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 void *priv;
46 };
47
48 /**
49 * @brief Defines the struct which represent a hardware GPIO pin.
50 *
51 * @since 1.0
52 */
53 struct GpioInfo {
54 struct GpioCntlr *cntlr;
55 char name[GPIO_NAME_LEN];
56 OsalSpinlock spin;
57 uint32_t irqSave;
58 struct GpioIrqRecord *irqRecord;
59 };
60
GpioInfoToLocal(struct GpioInfo * ginfo)61 static inline uint16_t GpioInfoToLocal(struct GpioInfo *ginfo)
62 {
63 return ginfo - &(ginfo->cntlr->ginfos[0]);
64 }
65
GpioInfoToGlobal(struct GpioInfo * ginfo)66 static inline uint16_t GpioInfoToGlobal(struct GpioInfo *ginfo)
67 {
68 return ginfo->cntlr->start + GpioInfoToLocal(ginfo);
69 }
70
71 /**
72 * @brief Defines the struct which represent a GPIO irq action.
73 *
74 * @since 1.0
75 */
76 struct GpioIrqRecord {
77 uint16_t mode;
78 GpioIrqFunc irqFunc;
79 GpioIrqFunc btmFunc;
80 void *irqData;
81 uint16_t global;
82 OsalSpinlock spin;
83 struct OsalSem sem;
84 struct OsalThread thread;
85 bool removed;
86 };
87
GpioIrqRecordTrigger(struct GpioIrqRecord * irqRecord)88 static inline void GpioIrqRecordTrigger(struct GpioIrqRecord *irqRecord)
89 {
90 if (irqRecord->irqFunc != NULL) {
91 (void)irqRecord->irqFunc(irqRecord->global, irqRecord->irqData);
92 }
93 if (irqRecord->btmFunc != NULL) {
94 (void)OsalSemPost(&irqRecord->sem);
95 }
96 }
97
GpioIrqRecordDestroy(struct GpioIrqRecord * irqRecord)98 static inline void GpioIrqRecordDestroy(struct GpioIrqRecord *irqRecord)
99 {
100 uint32_t irqSave;
101
102 if (irqRecord->btmFunc == NULL) {
103 OsalMemFree(irqRecord); // the last access to this record
104 } else {
105 (void)OsalSpinLockIrqSave(&irqRecord->spin, &irqSave);
106 irqRecord->removed = true;
107 (void)OsalSemPost(&irqRecord->sem); // this is the last post ...
108 (void)OsalSpinUnlockIrqRestore(&irqRecord->spin, &irqSave);
109 }
110 }
111
112 /**
113 * @brief Defines the struct which contains the hooks which a GPIO driver need to implement.
114 *
115 * @since 1.0
116 */
117 struct GpioMethod {
118 /** request exclusive access to an GPIO pin, optional */
119 int32_t (*request)(struct GpioCntlr *cntlr, uint16_t local);
120 /** release exclusive access to an GPIO pin, optional */
121 int32_t (*release)(struct GpioCntlr *cntlr, uint16_t local);
122 /** write the level value into a GPIO pin */
123 int32_t (*write)(struct GpioCntlr *cntlr, uint16_t local, uint16_t val);
124 /** read the level value of a GPIO pin */
125 int32_t (*read)(struct GpioCntlr *cntlr, uint16_t local, uint16_t *val);
126 /** set the direction for a GPIO pin */
127 int32_t (*setDir)(struct GpioCntlr *cntlr, uint16_t local, uint16_t dir);
128 /** get the direction of a GPIO pin */
129 int32_t (*getDir)(struct GpioCntlr *cntlr, uint16_t local, uint16_t *dir);
130 /** get the irq number of a GPIO pin, optional */
131 int32_t (*toIrq)(struct GpioCntlr *cntlr, uint16_t local, uint16_t *irq);
132 /** set the ISR function for a GPIO pin */
133 int32_t (*setIrq)(struct GpioCntlr *cntlr, uint16_t local, uint16_t mode);
134 /** unset the ISR function for a GPIO pin */
135 int32_t (*unsetIrq)(struct GpioCntlr *cntlr, uint16_t local);
136 /** enable a GPIO pin interrupt */
137 int32_t (*enableIrq)(struct GpioCntlr *cntlr, uint16_t local);
138 /** disable a GPIO pin interrupt */
139 int32_t (*disableIrq)(struct GpioCntlr *cntlr, uint16_t local);
140 };
141
142 /**
143 * @brief Add the Gpio Controller to HDF, and do some checking.
144 *
145 * @param cntlr Indicates the GPIO controller device.
146 *
147 * @return Returns 0 on success; returns a negative value otherwise.
148 * @since 1.0
149 */
150 int32_t GpioCntlrAdd(struct GpioCntlr *cntlr);
151
152 /**
153 * @brief Remove the Gpio Controller from HDF.
154 *
155 * @param cntlr Indicates the I2C controller device.
156 *
157 * @since 1.0
158 */
159 void GpioCntlrRemove(struct GpioCntlr *cntlr);
160
161 /**
162 * @brief Turn HdfDeviceObject to an GpioCntlr.
163 *
164 * @param device Indicates a HdfDeviceObject.
165 *
166 * @return Retrns the pointer of the GpioCntlr on success; returns NULL otherwise.
167 * @since 1.0
168 */
GpioCntlrFromHdfDev(struct HdfDeviceObject * device)169 static inline struct GpioCntlr *GpioCntlrFromHdfDev(struct HdfDeviceObject *device)
170 {
171 return (struct GpioCntlr *)PlatformDeviceFromHdfDev(device);
172 }
173
174 int32_t GpioCntlrWrite(struct GpioCntlr *cntlr, uint16_t local, uint16_t val);
175
176 int32_t GpioCntlrRead(struct GpioCntlr *cntlr, uint16_t local, uint16_t *val);
177
178 int32_t GpioCntlrSetDir(struct GpioCntlr *cntlr, uint16_t local, uint16_t dir);
179
180 int32_t GpioCntlrGetDir(struct GpioCntlr *cntlr, uint16_t local, uint16_t *dir);
181
182 int32_t GpioCntlrToIrq(struct GpioCntlr *cntlr, uint16_t local, uint16_t *irq);
183
184 int32_t GpioCntlrSetIrq(struct GpioCntlr *cntlr, uint16_t local, uint16_t mode, GpioIrqFunc func, void *arg);
185
186 int32_t GpioCntlrUnsetIrq(struct GpioCntlr *cntlr, uint16_t local, void *arg);
187
188 int32_t GpioCntlrEnableIrq(struct GpioCntlr *cntlr, uint16_t local);
189
190 int32_t GpioCntlrDisableIrq(struct GpioCntlr *cntlr, uint16_t local);
191
192 void GpioCntlrIrqCallback(struct GpioCntlr *cntlr, uint16_t local);
193
194 struct PlatformManager *GpioManagerGet(void);
195
196 struct GpioCntlr *GpioCntlrGetByGpio(uint16_t gpio);
197
GpioCntlrPut(struct GpioCntlr * cntlr)198 static inline void GpioCntlrPut(struct GpioCntlr *cntlr)
199 {
200 if (cntlr != NULL) {
201 PlatformDevicePut(&cntlr->device);
202 }
203 }
204
GpioCntlrGetLocal(struct GpioCntlr * cntlr,uint16_t gpio)205 static inline uint16_t GpioCntlrGetLocal(struct GpioCntlr *cntlr, uint16_t gpio)
206 {
207 return (cntlr == NULL) ? gpio : (gpio - cntlr->start);
208 }
209
210 #ifdef __cplusplus
211 #if __cplusplus
212 }
213 #endif
214 #endif /* __cplusplus */
215
216 #endif /* GPIO_CORE_H */
217