drv_gpio.c 10.4 KB
Newer Older
F
FuChao 已提交
1
/*
2
 * Copyright (c) 2006-2022, RT-Thread Development Team
F
FuChao 已提交
3 4 5 6 7 8 9 10
 *
 * SPDX-License-Identifier: Apache-2.0
 *
 * Change Logs:
 * Date           Author            Notes
 * 2020-12-27     iysheng           first version
 * 2021-01-01     iysheng           support exti interrupt
 * 2021-09-07     FuC               Suit for Vango V85xx
F
FuChao 已提交
11
 * 2021-09-09     ZhuXW             Add GPIO interrupt
F
FuChao 已提交
12 13 14 15 16 17 18
 */

#include <board.h>
#include "drv_gpio.h"

#ifdef RT_USING_PIN

19 20
#if defined(GPIOF)
#define __V85XX_PORT_MAX 6u
F
FuChao 已提交
21
#elif defined(GPIOE)
22
#define __V85XX_PORT_MAX 5u
F
FuChao 已提交
23
#elif defined(GPIOD)
24
#define __V85XX_PORT_MAX 4u
F
FuChao 已提交
25
#elif defined(GPIOC)
26
#define __V85XX_PORT_MAX 3u
F
FuChao 已提交
27
#elif defined(GPIOB)
28
#define __V85XX_PORT_MAX 2u
F
FuChao 已提交
29
#elif defined(GPIOA)
30
#define __V85XX_PORT_MAX 1u
F
FuChao 已提交
31
#else
32 33
#define __V85XX_PORT_MAX 0u
#error Unsupported V85XX GPIO peripheral.
F
FuChao 已提交
34 35
#endif

F
FuChao 已提交
36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61
#define PIN_V85XXPORT_MAX __V85XX_PORT_MAX
#define PIN_V85XXPORT_A   0u

static const struct pin_irq_map pin_irq_map[] =
{
#if defined(SOC_SERIES_V85XX)
    {GPIO_Pin_0,  PMU_IRQn},
    {GPIO_Pin_1,  PMU_IRQn},
    {GPIO_Pin_2,  PMU_IRQn},
    {GPIO_Pin_3,  PMU_IRQn},
    {GPIO_Pin_4,  PMU_IRQn},
    {GPIO_Pin_5,  PMU_IRQn},
    {GPIO_Pin_6,  PMU_IRQn},
    {GPIO_Pin_7,  PMU_IRQn},
    {GPIO_Pin_8,  PMU_IRQn},
    {GPIO_Pin_9,  PMU_IRQn},
    {GPIO_Pin_10, PMU_IRQn},
    {GPIO_Pin_11, PMU_IRQn},
    {GPIO_Pin_12, PMU_IRQn},
    {GPIO_Pin_13, PMU_IRQn},
    {GPIO_Pin_14, PMU_IRQn},
    {GPIO_Pin_15, PMU_IRQn},
#else
#error "Unsupported soc series"
#endif
};
F
FuChao 已提交
62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102

static struct rt_pin_irq_hdr pin_irq_hdr_tab[] =
{
    {-1, 0, RT_NULL, RT_NULL},
    {-1, 0, RT_NULL, RT_NULL},
    {-1, 0, RT_NULL, RT_NULL},
    {-1, 0, RT_NULL, RT_NULL},
    {-1, 0, RT_NULL, RT_NULL},
    {-1, 0, RT_NULL, RT_NULL},
    {-1, 0, RT_NULL, RT_NULL},
    {-1, 0, RT_NULL, RT_NULL},
    {-1, 0, RT_NULL, RT_NULL},
    {-1, 0, RT_NULL, RT_NULL},
    {-1, 0, RT_NULL, RT_NULL},
    {-1, 0, RT_NULL, RT_NULL},
    {-1, 0, RT_NULL, RT_NULL},
    {-1, 0, RT_NULL, RT_NULL},
    {-1, 0, RT_NULL, RT_NULL},
    {-1, 0, RT_NULL, RT_NULL},
};
static uint32_t pin_irq_enable_mask = 0;

#define ITEM_NUM(items) sizeof(items) / sizeof(items[0])

static rt_base_t v85xx_pin_get(const char *name)
{
    rt_base_t pin = 0;
    int hw_port_num, hw_pin_num = 0;
    int i, name_len;

    name_len = rt_strlen(name);

    if ((name_len < 4) || (name_len >= 6))
    {
        return -RT_EINVAL;
    }
    if ((name[0] != 'P') || (name[2] != '.'))
    {
        return -RT_EINVAL;
    }

103
    if ((name[1] >= 'A') && (name[1] <= 'F'))
F
FuChao 已提交
104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127
    {
        hw_port_num = (int)(name[1] - 'A');
    }
    else
    {
        return -RT_EINVAL;
    }

    for (i = 3; i < name_len; i++)
    {
        hw_pin_num *= 10;
        hw_pin_num += name[i] - '0';
    }

    pin = PIN_NUM(hw_port_num, hw_pin_num);

    return pin;
}

static void v85xx_pin_write(rt_device_t dev, rt_base_t pin, rt_base_t value)
{
    GPIO_TypeDef *gpio_port;
    uint16_t gpio_pin;

F
FuChao 已提交
128
    if (PIN_PORT(pin) == PIN_V85XXPORT_A)
F
FuChao 已提交
129
    {
F
FuChao 已提交
130
        gpio_pin = PIN_V85XXPIN(pin);
F
FuChao 已提交
131

F
FuChao 已提交
132 133 134 135 136 137 138 139
        GPIOA_WriteBit(GPIOA, gpio_pin, (BitState)value);
    }
    else if (PIN_PORT(pin) < PIN_V85XXPORT_MAX)
    {
        gpio_port = PIN_V85XXPORT(pin);
        gpio_pin = PIN_V85XXPIN(pin);

        GPIOBToF_WriteBit(gpio_port, gpio_pin, (BitState)value);
F
FuChao 已提交
140 141 142 143 144 145 146 147 148
    }
}

static int v85xx_pin_read(rt_device_t dev, rt_base_t pin)
{
    GPIO_TypeDef *gpio_port;
    uint16_t gpio_pin;
    int value = PIN_LOW;

F
FuChao 已提交
149
    if (PIN_PORT(pin) == PIN_V85XXPORT_A)
F
FuChao 已提交
150
    {
F
FuChao 已提交
151 152 153 154 155 156 157 158
        gpio_pin = PIN_V85XXPIN(pin);
        value = GPIOA_ReadInputDataBit(GPIOA, gpio_pin);
    }
    else if (PIN_PORT(pin) < PIN_V85XXPORT_MAX)
    {
        gpio_port = PIN_V85XXPORT(pin);
        gpio_pin = PIN_V85XXPIN(pin);
        value = GPIOBToF_ReadInputDataBit(gpio_port, gpio_pin);
F
FuChao 已提交
159 160 161 162 163 164 165 166 167
    }

    return value;
}

static void v85xx_pin_mode(rt_device_t dev, rt_base_t pin, rt_base_t mode)
{
    GPIO_InitType GPIO_InitStruct = {0};

F
FuChao 已提交
168
    if (PIN_PORT(pin) >= PIN_V85XXPORT_MAX)
F
FuChao 已提交
169 170 171 172 173
    {
        return;
    }

    /* Configure GPIO_InitStructure */
F
FuChao 已提交
174
    GPIO_InitStruct.GPIO_Pin  = PIN_V85XXPIN(pin);
F
FuChao 已提交
175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197
    GPIO_InitStruct.GPIO_Mode = GPIO_Mode_INPUT;

    switch (mode)
    {
        case PIN_MODE_OUTPUT:
            GPIO_InitStruct.GPIO_Mode = GPIO_Mode_OUTPUT_CMOS;
            break;
        case PIN_MODE_INPUT:
            GPIO_InitStruct.GPIO_Mode = GPIO_Mode_INPUT;
            break;
        case PIN_MODE_INPUT_PULLUP:
            GPIO_InitStruct.GPIO_Mode = GPIO_Mode_INOUT_CMOS;
            break;
        case PIN_MODE_INPUT_PULLDOWN:
            GPIO_InitStruct.GPIO_Mode = GPIO_Mode_INOUT_OD;
            break;
        case PIN_MODE_OUTPUT_OD:
            GPIO_InitStruct.GPIO_Mode = GPIO_Mode_INOUT_OD;
            break;
        default:
            break;
    }

F
FuChao 已提交
198 199 200 201 202 203 204 205
    if (PIN_PORT(pin) == PIN_V85XXPORT_A)
    {
        GPIOA_Init(GPIOA, &GPIO_InitStruct);
    }
    else if (PIN_PORT(pin) < PIN_V85XXPORT_MAX)
    {
        GPIOBToF_Init(PIN_V85XXPORT(pin), &GPIO_InitStruct);
    }
F
FuChao 已提交
206 207 208 209 210 211 212 213 214 215 216 217 218 219 220
}

rt_inline rt_int32_t bit2bitno(rt_uint32_t bit)
{
    int i;
    for (i = 0; i < 32; i++)
    {
        if ((0x01 << i) == bit)
        {
            return i;
        }
    }
    return -1;
}

221 222 223 224 225 226 227

static rt_err_t v85xx_pin_attach_irq(struct rt_device *device, rt_int32_t pin,
                    rt_uint32_t mode, void (*hdr)(void *args), void *args)
{
    rt_base_t level;
    rt_int32_t irqindex = -1;

F
FuChao 已提交
228
    if (PIN_PORT(pin) > PIN_V85XXPORT_A)
229 230 231 232
    {
        return -RT_ENOSYS;
    }

F
FuChao 已提交
233 234 235 236 237
    irqindex = bit2bitno(PIN_V85XXPIN(pin));
    if (irqindex < 0 || irqindex >= ITEM_NUM(pin_irq_map))
    {
        return RT_ENOSYS;
    }
238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262

    level = rt_hw_interrupt_disable();
    if (pin_irq_hdr_tab[irqindex].pin == pin &&
        pin_irq_hdr_tab[irqindex].hdr == hdr &&
        pin_irq_hdr_tab[irqindex].mode == mode &&
        pin_irq_hdr_tab[irqindex].args == args)
    {
        rt_hw_interrupt_enable(level);
        return RT_EOK;
    }
    if (pin_irq_hdr_tab[irqindex].pin != -1)
    {
        rt_hw_interrupt_enable(level);
        return RT_EBUSY;
    }
    pin_irq_hdr_tab[irqindex].pin = pin;
    pin_irq_hdr_tab[irqindex].hdr = hdr;
    pin_irq_hdr_tab[irqindex].mode = mode;
    pin_irq_hdr_tab[irqindex].args = args;
    rt_hw_interrupt_enable(level);

    return RT_EOK;
}
static rt_err_t v85xx_pin_detach_irq(struct rt_device *device, rt_int32_t pin)
{
F
FuChao 已提交
263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287
    rt_base_t level;
    rt_int32_t irqindex = -1;

    if (PIN_PORT(pin) > PIN_V85XXPORT_A)
    {
        return -RT_ENOSYS;
    }

    irqindex = bit2bitno(PIN_V85XXPIN(pin));
    if (irqindex < 0 || irqindex >= ITEM_NUM(pin_irq_map))
    {
        return RT_ENOSYS;
    }

    level = rt_hw_interrupt_disable();
    if (pin_irq_hdr_tab[irqindex].pin == -1)
    {
        rt_hw_interrupt_enable(level);
        return RT_EOK;
    }
    pin_irq_hdr_tab[irqindex].pin = -1;
    pin_irq_hdr_tab[irqindex].hdr = RT_NULL;
    pin_irq_hdr_tab[irqindex].mode = 0;
    pin_irq_hdr_tab[irqindex].args = RT_NULL;
    rt_hw_interrupt_enable(level);
288 289 290 291 292

    return RT_EOK;
}
static rt_err_t v85xx_pin_irq_enable(struct rt_device *device, rt_base_t pin, rt_uint32_t enabled)
{
F
FuChao 已提交
293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312
    const struct pin_irq_map *irqmap;
    rt_base_t level;
    rt_int32_t irqindex = -1;
    GPIO_InitType GPIO_InitStruct = {0};

    if (PIN_PORT(pin) > PIN_V85XXPORT_A)
    {
        return -RT_ENOSYS;
    }

    GPIO_InitStruct.GPIO_Pin = PIN_V85XXPIN(pin);
    if (enabled == PIN_IRQ_ENABLE)
    {
        irqindex = bit2bitno(PIN_V85XXPIN(pin));
        if (irqindex < 0 || irqindex >= ITEM_NUM(pin_irq_map))
        {
            return RT_ENOSYS;
        }

        level = rt_hw_interrupt_disable();
313

F
FuChao 已提交
314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368
        if (pin_irq_hdr_tab[irqindex].pin == -1)
        {
            rt_hw_interrupt_enable(level);
            return RT_ENOSYS;
        }

        GPIO_InitStruct.GPIO_Mode = GPIO_Mode_INPUT;
        GPIO_InitStruct.GPIO_Pin  = PIN_V85XXPIN(pin);
        GPIOA_Init(GPIOA, &GPIO_InitStruct);

        irqmap = &pin_irq_map[irqindex];

        switch (pin_irq_hdr_tab[irqindex].mode)
        {
        case PIN_IRQ_MODE_RISING:
            PMU_WakeUpPinConfig(PIN_V85XXPIN(pin), IOA_RISING);
            break;
        case PIN_IRQ_MODE_FALLING:
            PMU_WakeUpPinConfig(PIN_V85XXPIN(pin), IOA_FALLING);
            break;
        case PIN_IRQ_MODE_RISING_FALLING:
            PMU_WakeUpPinConfig(PIN_V85XXPIN(pin), IOA_EDGEBOTH);
            break;
        case PIN_IRQ_MODE_HIGH_LEVEL:
            PMU_WakeUpPinConfig(PIN_V85XXPIN(pin), IOA_HIGH);
            break;
        case PIN_IRQ_MODE_LOW_LEVEL:
            PMU_WakeUpPinConfig(PIN_V85XXPIN(pin), IOA_LOW);
            break;
        default:
            break;
        }
        PMU_INTConfig(PMU_INT_IOAEN, ENABLE);

        NVIC_SetPriority(irqmap->irqno, 0);
        NVIC_EnableIRQ(irqmap->irqno);
        pin_irq_enable_mask |= irqmap->pinbit;

        rt_hw_interrupt_enable(level);
    }
    else if (enabled == PIN_IRQ_DISABLE)
    {

        level = rt_hw_interrupt_disable();

        PMU_INTConfig(PMU_INT_IOAEN, DISABLE);

        NVIC_DisableIRQ(irqmap->irqno);

        rt_hw_interrupt_enable(level);
    }
    else
    {
        return -RT_ENOSYS;
    }
369 370 371 372 373
    return RT_EOK;
}



F
FuChao 已提交
374 375 376 377 378
const static struct rt_pin_ops _v85xx_pin_ops =
{
    v85xx_pin_mode,
    v85xx_pin_write,
    v85xx_pin_read,
379 380 381 382
    v85xx_pin_attach_irq,
    v85xx_pin_detach_irq,
    v85xx_pin_irq_enable,
    v85xx_pin_get,
F
FuChao 已提交
383 384 385 386 387 388 389 390 391 392
};

rt_inline void pin_irq_hdr(int irqno)
{
    if (pin_irq_hdr_tab[irqno].hdr)
    {
        pin_irq_hdr_tab[irqno].hdr(pin_irq_hdr_tab[irqno].args);
    }
}

F
FuChao 已提交
393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418

void v85xx_pin_exti_irqhandler()
{
    rt_base_t intsts=0;
    int i=0;

    intsts = PMU_GetIOAAllINTStatus();
    for(i=0; i<16; i++)
    {
        if((1<<i) & intsts)
        {
            PMU_ClearIOAINTStatus(1<<i);
            pin_irq_hdr(bit2bitno(1<<i));
            return;
        }
    }
}

void PMU_IRQHandler()
{
    rt_interrupt_enter();
    v85xx_pin_exti_irqhandler();
    rt_interrupt_leave();
}


F
FuChao 已提交
419 420 421 422 423
int rt_hw_pin_init(void)
{
  GPIO_InitType GPIO_InitStruct;
  GPIO_InitStruct.GPIO_Mode = GPIO_Mode_INPUT;
  GPIO_InitStruct.GPIO_Pin = GPIO_Pin_All;
424

F
FuChao 已提交
425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442
#if defined(GPIOF)
    GPIOBToF_Init(GPIOF, &GPIO_InitStruct);
#endif
#if defined(GPIOE)
    GPIOBToF_Init(GPIOE, &GPIO_InitStruct);
#endif
#if defined(GPIOD)
    GPIOBToF_Init(GPIOD, &GPIO_InitStruct);
#endif
#if defined(GPIOC)
    GPIOBToF_Init(GPIOC, &GPIO_InitStruct);
#endif
#if defined(GPIOB)
    GPIOBToF_Init(GPIOB, &GPIO_InitStruct);
#endif
#if defined(GPIOA)
    GPIOA_Init(GPIOA, &GPIO_InitStruct);
#endif
443

F
FuChao 已提交
444 445 446 447
    return rt_device_pin_register("pin", &_v85xx_pin_ops, RT_NULL);
}
INIT_BOARD_EXPORT(rt_hw_pin_init);
#endif /* RT_USING_PIN */