• 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     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