1/*
2 * Copyright 2017, Data61
3 * Commonwealth Scientific and Industrial Research Organisation (CSIRO)
4 * ABN 41 687 119 230.
5 *
6 * This software may be distributed and modified according to the terms of
7 * the BSD 2-Clause license. Note that NO WARRANTY is provided.
8 * See "LICENSE_BSD2.txt" for details.
9 *
10 * @TAG(DATA61_BSD)
11 */
12
13#pragma once
14
15#include <unistd.h>
16
17typedef ssize_t mux_feature_t;
18typedef struct mux_sys mux_sys_t;
19
20#include <utils/arith.h>
21
22typedef enum mux_gpio_dir {
23    MUX_DIR_NOT_A_GPIO = 0,
24    MUX_DIR_GPIO_IN = BIT(0),
25    MUX_DIR_GPIO_OUT = BIT(1),
26    MUX_DIR_GPIO_BOTH = (MUX_DIR_GPIO_IN | MUX_DIR_GPIO_OUT)
27} mux_gpio_dir_t;
28
29struct mux_sys {
30    int (*feature_enable)(const mux_sys_t *mux, mux_feature_t, enum mux_gpio_dir);
31    int (*feature_disable)(const mux_sys_t *mux, mux_feature_t);
32    void *(*get_mux_vaddr)(const mux_sys_t *mux);
33    void *priv;
34};
35
36#include <platsupport/io.h>
37
38static inline int mux_sys_valid(const mux_sys_t *mux_sys)
39{
40    return mux_sys && mux_sys->priv;
41}
42
43/**
44 * Returns the vaddr of the mux controller so a driver can directly
45 * access the MUX controller and bypass the muxc.
46 */
47static inline void *mux_sys_get_vaddr(mux_sys_t *mux)
48{
49    return (mux && mux->get_mux_vaddr) ? mux->get_mux_vaddr(mux) : NULL;
50}
51
52/**
53 * Initialise (IO)MUX sub systems
54 * @param[in]  io_ops  collection of IO operations for the subsystem to use.
55 * @param[out] mux     On success, this will be filled with the appropriate
56 *                     subsystem data.
57 * @param[in]  dependencies     As an edge case, if this driver depends on some
58 *                              other set of drivers, you can pass in instances
59 *                              of those dependencies as a pointer or array of
60 *                              pointers here.
61 * @return             0 on success.
62 */
63int mux_sys_init(ps_io_ops_t *io_ops, void *dependencies, mux_sys_t *mux);
64
65/**
66 * Enable a SoC feature via the IO MUX
67 * @param[in] mux           A handle to the mux system
68 * @param[in] mux_feature   A SoC specific feature to enable.
69 * @param[in] mux_gpio_dir  If the signal being muxed out on the pin is a
70 *                          a GPIO signal, this might be required by your
71 *                          platform. For example, if your mux controller has
72 *                          input and output buffers, you would want to ensure
73 *                          that the output buffer on the pin is enabled if you
74 *                          plan to use the pin as a GPIO output.
75 *
76 *                          If the signal you're muxing out on the pin is not
77 *                          a GPIO controller, then you should use
78 *                          MUX_DIR_NOT_A_GPIO.
79 * @return                0 on success
80 */
81static inline int mux_feature_enable(const mux_sys_t *mux, mux_feature_t mux_feature,
82                                     enum mux_gpio_dir mux_gpio_dir)
83{
84    if (mux->feature_enable) {
85        return mux->feature_enable(mux, mux_feature, mux_gpio_dir);
86    } else {
87        return -ENOSYS;
88    }
89}
90
91/**
92 * Explicitly ensure that a certain controller's signals are not being driven
93 * out.
94 *
95 * This is useful if you need to ensure that no signals are output by the
96 * controller while it is being set up. In such a case you'd feature_disable()
97 * the signals, then initialize the controller, then feature_enable() the
98 * controller again.
99 *
100 * @param[in] mux         A handle to the mux system
101 * @param[in] mux_feature A SoC specific feature to enable.
102 * @return                0 on success
103 */
104static inline int mux_feature_disable(mux_sys_t *mux, mux_feature_t mux_feature)
105{
106    if (mux->feature_disable) {
107        return mux->feature_disable(mux, mux_feature);
108    } else {
109        return -ENOSYS;
110    }
111}
112