1 /*
2 * Copyright (c) 2020-2021 Huawei Device Co., Ltd.
3 *
4 * HDF is dual licensed: you can use it either under the terms of
5 * the GPL, or the BSD license, at your option.
6 * See the LICENSE file in the root of this repository for complete details.
7 */
8
9 #ifndef GPIO_CORE_H
10 #define GPIO_CORE_H
11
12 #include "gpio_if.h"
13 #include "hdf_base.h"
14 #include "hdf_device_desc.h"
15 #include "hdf_dlist.h"
16 #include "osal_mem.h"
17 #include "osal_spinlock.h"
18 #include "platform_core.h"
19
20 #ifdef __cplusplus
21 #if __cplusplus
22 extern "C" {
23 #endif
24 #endif /* __cplusplus */
25
26 struct GpioCntlr;
27 struct GpioMethod;
28 struct GpioInfo;
29 struct GpioIrqRecord;
30
31 #define GPIO_NUM_MAX 0xFFFF
32 #define GPIO_NAME_LEN 16
33
34 /**
35 * @brief Defines the struct which represent a hardware GPIO controller.
36 *
37 * @since 1.0
38 */
39 struct GpioCntlr {
40 struct PlatformDevice device;
41 struct GpioMethod *ops;
42 uint16_t start;
43 uint16_t count;
44 struct GpioInfo *ginfos;
45 bool isAutoAlloced;
46 void *priv;
47 };
48
49 /**
50 * @brief Defines the struct which represent a hardware GPIO pin.
51 *
52 * @since 1.0
53 */
54 struct GpioInfo {
55 struct GpioCntlr *cntlr;
56 char name[GPIO_NAME_LEN];
57 OsalSpinlock spin;
58 uint32_t irqSave;
59 struct GpioIrqRecord *irqRecord;
60 };
61
GpioInfoToLocal(struct GpioInfo * ginfo)62 static inline uint16_t GpioInfoToLocal(struct GpioInfo *ginfo)
63 {
64 return ginfo - &(ginfo->cntlr->ginfos[0]);
65 }
66
GpioInfoToGlobal(struct GpioInfo * ginfo)67 static inline uint16_t GpioInfoToGlobal(struct GpioInfo *ginfo)
68 {
69 return ginfo->cntlr->start + GpioInfoToLocal(ginfo);
70 }
71
72 /**
73 * @brief Defines the struct which represent a GPIO irq action.
74 *
75 * @since 1.0
76 */
77 struct GpioIrqRecord {
78 uint16_t mode;
79 GpioIrqFunc irqFunc;
80 GpioIrqFunc btmFunc;
81 void *irqData;
82 uint16_t global;
83 OsalSpinlock spin;
84 struct OsalSem sem;
85 struct OsalThread thread;
86 bool removed;
87 };
88
GpioIrqRecordTrigger(struct GpioIrqRecord * irqRecord)89 static inline void GpioIrqRecordTrigger(struct GpioIrqRecord *irqRecord)
90 {
91 if (irqRecord->irqFunc != NULL) {
92 (void)irqRecord->irqFunc(irqRecord->global, irqRecord->irqData);
93 }
94 if (irqRecord->btmFunc != NULL) {
95 (void)OsalSemPost(&irqRecord->sem);
96 }
97 }
98
GpioIrqRecordDestroy(struct GpioIrqRecord * irqRecord)99 static inline void GpioIrqRecordDestroy(struct GpioIrqRecord *irqRecord)
100 {
101 uint32_t irqSave;
102
103 if (irqRecord->btmFunc == NULL) {
104 OsalMemFree(irqRecord); // the last access to this record
105 } else {
106 (void)OsalSpinLockIrqSave(&irqRecord->spin, &irqSave);
107 irqRecord->removed = true;
108 (void)OsalSemPost(&irqRecord->sem); // this is the last post ...
109 (void)OsalSpinUnlockIrqRestore(&irqRecord->spin, &irqSave);
110 }
111 }
112
113 /**
114 * @brief Defines the struct which contains the hooks which a GPIO driver need to implement.
115 *
116 * @since 1.0
117 */
118 struct GpioMethod {
119 /** request exclusive access to an GPIO pin, optional */
120 int32_t (*request)(struct GpioCntlr *cntlr, uint16_t local);
121 /** release exclusive access to an GPIO pin, optional */
122 int32_t (*release)(struct GpioCntlr *cntlr, uint16_t local);
123 /** write the level value into a GPIO pin */
124 int32_t (*write)(struct GpioCntlr *cntlr, uint16_t local, uint16_t val);
125 /** read the level value of a GPIO pin */
126 int32_t (*read)(struct GpioCntlr *cntlr, uint16_t local, uint16_t *val);
127 /** set the direction for a GPIO pin */
128 int32_t (*setDir)(struct GpioCntlr *cntlr, uint16_t local, uint16_t dir);
129 /** get the direction of a GPIO pin */
130 int32_t (*getDir)(struct GpioCntlr *cntlr, uint16_t local, uint16_t *dir);
131 /** get the irq number of a GPIO pin, optional */
132 int32_t (*toIrq)(struct GpioCntlr *cntlr, uint16_t local, uint16_t *irq);
133 /** set the ISR function for a GPIO pin */
134 int32_t (*setIrq)(struct GpioCntlr *cntlr, uint16_t local, uint16_t mode);
135 /** unset the ISR function for a GPIO pin */
136 int32_t (*unsetIrq)(struct GpioCntlr *cntlr, uint16_t local);
137 /** enable a GPIO pin interrupt */
138 int32_t (*enableIrq)(struct GpioCntlr *cntlr, uint16_t local);
139 /** disable a GPIO pin interrupt */
140 int32_t (*disableIrq)(struct GpioCntlr *cntlr, uint16_t local);
141 };
142
143 /**
144 * @brief Add the Gpio Controller to HDF, and do some checking.
145 *
146 * @param cntlr Indicates the GPIO controller device.
147 *
148 * @return Returns 0 on success; returns a negative value otherwise.
149 * @since 1.0
150 */
151 int32_t GpioCntlrAdd(struct GpioCntlr *cntlr);
152
153 /**
154 * @brief Remove the Gpio Controller from HDF.
155 *
156 * @param cntlr Indicates the I2C controller device.
157 *
158 * @since 1.0
159 */
160 void GpioCntlrRemove(struct GpioCntlr *cntlr);
161
162 /**
163 * @brief Turn HdfDeviceObject to an GpioCntlr.
164 *
165 * @param device Indicates a HdfDeviceObject.
166 *
167 * @return Retrns the pointer of the GpioCntlr on success; returns NULL otherwise.
168 * @since 1.0
169 */
GpioCntlrFromHdfDev(const struct HdfDeviceObject * device)170 static inline struct GpioCntlr *GpioCntlrFromHdfDev(const struct HdfDeviceObject *device)
171 {
172 return (struct GpioCntlr *)PlatformDeviceFromHdfDev(device);
173 }
174
175 int32_t GpioCntlrWrite(struct GpioCntlr *cntlr, uint16_t local, uint16_t val);
176
177 int32_t GpioCntlrRead(struct GpioCntlr *cntlr, uint16_t local, uint16_t *val);
178
179 int32_t GpioCntlrSetDir(struct GpioCntlr *cntlr, uint16_t local, uint16_t dir);
180
181 int32_t GpioCntlrGetDir(struct GpioCntlr *cntlr, uint16_t local, uint16_t *dir);
182
183 int32_t GpioCntlrToIrq(struct GpioCntlr *cntlr, uint16_t local, uint16_t *irq);
184
185 int32_t GpioCntlrSetIrq(struct GpioCntlr *cntlr, uint16_t local, uint16_t mode, GpioIrqFunc func, void *arg);
186
187 int32_t GpioCntlrUnsetIrq(struct GpioCntlr *cntlr, uint16_t local, void *arg);
188
189 int32_t GpioCntlrEnableIrq(struct GpioCntlr *cntlr, uint16_t local);
190
191 int32_t GpioCntlrDisableIrq(struct GpioCntlr *cntlr, uint16_t local);
192
193 void GpioCntlrIrqCallback(struct GpioCntlr *cntlr, uint16_t local);
194
195 int32_t GpioCntlrGetNumByGpioName(struct GpioCntlr *cntlr, const char *gpioName);
196
197 struct GpioCntlr *GpioCntlrGetByGpioName(const char *gpioName);
198
199 struct PlatformManager *GpioManagerGet(void);
200
201 struct GpioCntlr *GpioCntlrGetByGpio(uint16_t gpio);
202
GpioCntlrPut(struct GpioCntlr * cntlr)203 static inline void GpioCntlrPut(struct GpioCntlr *cntlr)
204 {
205 if (cntlr != NULL) {
206 PlatformDevicePut(&cntlr->device);
207 }
208 }
209
GpioCntlrGetLocal(struct GpioCntlr * cntlr,uint16_t gpio)210 static inline uint16_t GpioCntlrGetLocal(struct GpioCntlr *cntlr, uint16_t gpio)
211 {
212 return (cntlr == NULL) ? gpio : (gpio - cntlr->start);
213 }
214
215 #ifdef __cplusplus
216 #if __cplusplus
217 }
218 #endif
219 #endif /* __cplusplus */
220
221 #endif /* GPIO_CORE_H */
222