1 /*
2 * Copyright (c) 2022 HPMicro
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #include <stdlib.h>
17 #include <stdio.h>
18 #include "device_resource_if.h"
19 #include "hdf_device_desc.h"
20 #include "hdf_log.h"
21 #include "osal_mem.h"
22 #include "gpio_if.h"
23 #include "gpio_core.h"
24 #include <hpm_gpio_drv.h>
25 #include <los_interrupt.h>
26
27 #define HDF_LOG_TAG HPMICRO_GPIO_HDF
28
29 struct HPMGpioDevice {
30 uint32_t base;
31 const char *name;
32 uint32_t port_num;
33 uint32_t irq_num;
34 };
35
36
Write(struct GpioCntlr * ctl,uint16_t local,uint16_t val)37 static int32_t Write(struct GpioCntlr *ctl, uint16_t local, uint16_t val)
38 {
39 struct HPMGpioDevice *hpmGpioDev = (struct HPMGpioDevice *)ctl->priv;
40 GPIO_Type *base = (GPIO_Type *)hpmGpioDev->base;
41 uint32_t port_num = hpmGpioDev->port_num;
42
43 gpio_write_pin(base, port_num, local, (val == GPIO_VAL_LOW) ? 0 : 1);
44
45 return HDF_SUCCESS;
46 }
47
Read(struct GpioCntlr * ctl,uint16_t local,uint16_t * val)48 static int32_t Read(struct GpioCntlr *ctl, uint16_t local, uint16_t *val)
49 {
50 struct HPMGpioDevice *hpmGpioDev = (struct HPMGpioDevice *)ctl->priv;
51 GPIO_Type *base = (GPIO_Type *)hpmGpioDev->base;
52 uint32_t port_num = hpmGpioDev->port_num;
53
54 if (gpio_read_pin(base, port_num, local)) {
55 *val = GPIO_VAL_HIGH;
56 } else {
57 *val = GPIO_VAL_LOW;
58 }
59
60 return HDF_SUCCESS;
61 }
62
SetDir(struct GpioCntlr * ctl,uint16_t local,uint16_t dir)63 int32_t SetDir(struct GpioCntlr *ctl, uint16_t local, uint16_t dir)
64 {
65 struct HPMGpioDevice *hpmGpioDev = (struct HPMGpioDevice *)ctl->priv;
66 GPIO_Type *base = (GPIO_Type *)hpmGpioDev->base;
67 uint32_t port_num = hpmGpioDev->port_num;
68
69 if (dir == GPIO_DIR_IN) {
70 gpio_set_pin_input(base, port_num, local);
71 } else {
72 gpio_set_pin_output(base, port_num, local);
73 }
74 HDF_LOGD("GPIO: [%s-%hu] SetDir [%hu]", hpmGpioDev->name, local, dir);
75 return HDF_SUCCESS;
76 }
77
GetDir(struct GpioCntlr * ctl,uint16_t local,uint16_t * dir)78 int32_t GetDir(struct GpioCntlr *ctl, uint16_t local, uint16_t *dir)
79 {
80 return HDF_SUCCESS;
81 }
82
SetIrq(struct GpioCntlr * ctl,uint16_t local,uint16_t mode)83 static int32_t SetIrq(struct GpioCntlr *ctl, uint16_t local, uint16_t mode)
84 {
85 struct HPMGpioDevice *hpmGpioDev = (struct HPMGpioDevice *)ctl->priv;
86 GPIO_Type *base = (GPIO_Type *)hpmGpioDev->base;
87 uint32_t port_num = hpmGpioDev->port_num;
88
89 if (mode & GPIO_IRQ_TRIGGER_RISING) {
90 gpio_config_pin_interrupt(base, port_num, local, gpio_interrupt_trigger_edge_rising);
91 } else if (mode & GPIO_IRQ_TRIGGER_FALLING) {
92 gpio_config_pin_interrupt(base, port_num, local, gpio_interrupt_trigger_edge_falling);
93 } else if (mode & GPIO_IRQ_TRIGGER_HIGH) {
94 gpio_config_pin_interrupt(base, port_num, local, gpio_interrupt_trigger_level_high);
95 } else if (mode & GPIO_IRQ_TRIGGER_LOW) {
96 gpio_config_pin_interrupt(base, port_num, local, gpio_interrupt_trigger_level_low);
97 } else {
98
99 }
100
101 return HDF_SUCCESS;
102 }
103
UnsetIrq(struct GpioCntlr * ctl,uint16_t local)104 static int32_t UnsetIrq(struct GpioCntlr *ctl, uint16_t local)
105 {
106 return HDF_SUCCESS;
107 }
108
EnableIrq(struct GpioCntlr * ctl,uint16_t local)109 static int32_t EnableIrq(struct GpioCntlr *ctl, uint16_t local)
110 {
111 struct HPMGpioDevice *hpmGpioDev = (struct HPMGpioDevice *)ctl->priv;
112 GPIO_Type *base = (GPIO_Type *)hpmGpioDev->base;
113 uint32_t port_num = hpmGpioDev->port_num;
114
115 gpio_enable_pin_interrupt(base, port_num, local);
116
117 return HDF_SUCCESS;
118 }
119
DisableIrq(struct GpioCntlr * ctl,uint16_t local)120 static int32_t DisableIrq(struct GpioCntlr *ctl, uint16_t local)
121 {
122 struct HPMGpioDevice *hpmGpioDev = (struct HPMGpioDevice *)ctl->priv;
123 GPIO_Type *base = (GPIO_Type *)hpmGpioDev->base;
124 uint32_t port_num = hpmGpioDev->port_num;
125
126 gpio_disable_pin_interrupt(base, port_num, local);
127
128 return HDF_SUCCESS;
129 }
130
131 static struct GpioMethod gpioOps = {
132 .write = Write,
133 .read = Read,
134 .setDir = SetDir,
135 .getDir = GetDir,
136 .setIrq = SetIrq,
137 .unsetIrq = UnsetIrq,
138 .enableIrq = EnableIrq,
139 .disableIrq = DisableIrq,
140 };
141
GpioHcsResurceInit(struct GpioCntlr * ctl)142 static int32_t GpioHcsResurceInit(struct GpioCntlr *ctl)
143 {
144 int ret = HDF_SUCCESS;
145 struct HdfDeviceObject *device = ctl->device.hdfDev;
146 struct HPMGpioDevice *hpmGpioDev = (struct HPMGpioDevice *)ctl->priv;
147
148 struct DeviceResourceIface *dri = DeviceResourceGetIfaceInstance(HDF_CONFIG_SOURCE);
149 if (dri == NULL) {
150 HDF_LOGE("get DeviceResourceIface Failed!!!");
151 return HDF_FAILURE;
152 }
153
154 dri->GetUint32(device->property, "base", &hpmGpioDev->base, 0);
155 dri->GetString(device->property, "name", &hpmGpioDev->name, NULL);
156 dri->GetUint32(device->property, "port_num", &hpmGpioDev->port_num, 0);
157 dri->GetUint32(device->property, "irq_num", &hpmGpioDev->irq_num, 0);
158 dri->GetUint16(device->property, "count", &ctl->count, 0);
159 ctl->start = ctl->count * hpmGpioDev->port_num;
160
161 HDF_LOGI("GPIO: base: 0x%X", hpmGpioDev->base);
162 HDF_LOGI("GPIO: name: %s", hpmGpioDev->name);
163 HDF_LOGI("GPIO: port_num: %u", hpmGpioDev->port_num);
164 HDF_LOGI("GPIO: irq_num: %u", hpmGpioDev->irq_num);
165 HDF_LOGI("GPIO: count: %u", ctl->count);
166 HDF_LOGI("GPIO: start: %u", ctl->start);
167
168 return ret;
169 }
170
hpm_gpio_isr(VOID * parm)171 static __attribute__((section(".interrupt.text"))) VOID hpm_gpio_isr(VOID *parm)
172 {
173 struct GpioCntlr *ctl = (struct GpioCntlr *)parm;
174 struct HPMGpioDevice *hpmGpioDev = (struct HPMGpioDevice *)ctl->priv;
175 GPIO_Type *base = (GPIO_Type *)hpmGpioDev->base;
176 uint32_t port_num = hpmGpioDev->port_num;
177
178 for (uint32_t local = 0; local < ctl->count; local++) {
179 if (gpio_check_clear_interrupt_flag(base, port_num, local)) {
180 GpioCntlrIrqCallback(ctl, local);
181 }
182 }
183 }
184
GpioDriverBind(struct HdfDeviceObject * device)185 static int32_t GpioDriverBind(struct HdfDeviceObject *device)
186 {
187 HDF_LOGI("Bind: It's not to be run");
188 return HDF_SUCCESS;
189 }
190
GpioDriverInit(struct HdfDeviceObject * device)191 static int32_t GpioDriverInit(struct HdfDeviceObject *device)
192 {
193 int32_t ret = HDF_SUCCESS;
194 struct HPMGpioDevice *hpmGpioDev;
195 struct GpioCntlr *ctl = (struct GpioCntlr *)OsalMemCalloc(sizeof(struct GpioCntlr) + sizeof(struct HPMGpioDevice));
196 ctl->priv = (char *)ctl + sizeof(struct GpioCntlr);
197 hpmGpioDev = (struct HPMGpioDevice *)ctl->priv;
198 ctl->ops = &gpioOps;
199
200 PlatformDeviceSetHdfDev(&ctl->device, device);
201
202 ret = GpioHcsResurceInit(ctl);
203 if (ret) {
204 HDF_LOGE("Init: GpioHcsResurceInit Failed!!!\n");
205 goto ERROR;
206 }
207
208 ret = GpioCntlrAdd(ctl);
209 if (ret) {
210 HDF_LOGE("Init: GpioCntlrAdd Fualed, name: %s!!!\n", hpmGpioDev->name);
211 goto ERROR;
212 }
213
214 HwiIrqParam irqParam;
215 irqParam.pDevId = ctl;
216 LOS_HwiCreate(HPM2LITEOS_IRQ(hpmGpioDev->irq_num), 1, 0, (HWI_PROC_FUNC)hpm_gpio_isr, &irqParam);
217 LOS_HwiEnable(HPM2LITEOS_IRQ(hpmGpioDev->irq_num));
218
219 HDF_LOGI("Init");
220
221 return ret;
222
223 ERROR:
224 OsalMemFree(ctl);
225 return ret;
226 }
227
GpioDriverRelease(struct HdfDeviceObject * device)228 static void GpioDriverRelease(struct HdfDeviceObject *device)
229 {
230 if (device == NULL) {
231 return;
232 }
233
234 struct GpioCntlr *ctl = GpioCntlrFromHdfDev(device);
235 if (ctl) {
236 OsalMemFree(ctl);
237 }
238 HDF_LOGI("Release");
239 return;
240 }
241
242
243 struct HdfDriverEntry g_gpioDriverEntry = {
244 .moduleVersion = 1,
245 .moduleName = "HPMICRO_GPIO_MODULE_HDF",
246 .Bind = GpioDriverBind,
247 .Init = GpioDriverInit,
248 .Release = GpioDriverRelease,
249 };
250
251 HDF_INIT(g_gpioDriverEntry);
252