• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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