Angel Pons | 7c1d70e | 2020-04-04 18:51:19 +0200 | [diff] [blame] | 1 | /* SPDX-License-Identifier: GPL-2.0-only */ |
Taniya Das | 09c3bfe | 2019-08-07 11:34:57 +0530 | [diff] [blame] | 2 | |
Taniya Das | 09c3bfe | 2019-08-07 11:34:57 +0530 | [diff] [blame] | 3 | #include <assert.h> |
Julius Werner | 55009af | 2019-12-02 22:03:27 -0800 | [diff] [blame] | 4 | #include <device/mmio.h> |
Taniya Das | 09c3bfe | 2019-08-07 11:34:57 +0530 | [diff] [blame] | 5 | #include <types.h> |
| 6 | |
| 7 | #include <gpio.h> |
| 8 | |
| 9 | void gpio_configure(gpio_t gpio, uint32_t func, uint32_t pull, |
| 10 | uint32_t drive_str, uint32_t enable) |
| 11 | { |
| 12 | uint32_t reg_val; |
| 13 | struct tlmm_gpio *regs = (void *)(uintptr_t)gpio.addr; |
| 14 | |
| 15 | /* gpio pull only PULLNONE, PULLUP, KEEPER, PULLDOWN status */ |
| 16 | assert(pull <= GPIO_PULL_UP); |
| 17 | |
| 18 | reg_val = ((enable & GPIO_CFG_OE_BMSK) << GPIO_CFG_OE_SHFT) | |
| 19 | ((drive_str & GPIO_CFG_DRV_BMSK) << GPIO_CFG_DRV_SHFT) | |
| 20 | ((func & GPIO_CFG_FUNC_BMSK) << GPIO_CFG_FUNC_SHFT) | |
| 21 | ((pull & GPIO_CFG_PULL_BMSK) << GPIO_CFG_PULL_SHFT); |
| 22 | |
| 23 | write32(®s->cfg, reg_val); |
| 24 | } |
| 25 | |
| 26 | void gpio_set(gpio_t gpio, int value) |
| 27 | { |
| 28 | struct tlmm_gpio *regs = (void *)(uintptr_t)gpio.addr; |
| 29 | |
| 30 | write32(®s->in_out, (!!value) << GPIO_IO_OUT_SHFT); |
| 31 | } |
| 32 | |
| 33 | int gpio_get(gpio_t gpio) |
| 34 | { |
| 35 | struct tlmm_gpio *regs = (void *)(uintptr_t)gpio.addr; |
| 36 | |
| 37 | return ((read32(®s->in_out) >> GPIO_IO_IN_SHFT) & |
| 38 | GPIO_IO_IN_BMSK); |
| 39 | } |
| 40 | |
| 41 | void gpio_input_pulldown(gpio_t gpio) |
| 42 | { |
| 43 | gpio_configure(gpio, GPIO_FUNC_GPIO, |
| 44 | GPIO_PULL_DOWN, GPIO_2MA, GPIO_OUTPUT_DISABLE); |
| 45 | } |
| 46 | |
| 47 | void gpio_input_pullup(gpio_t gpio) |
| 48 | { |
| 49 | gpio_configure(gpio, GPIO_FUNC_GPIO, |
| 50 | GPIO_PULL_UP, GPIO_2MA, GPIO_OUTPUT_DISABLE); |
| 51 | } |
| 52 | |
| 53 | void gpio_input(gpio_t gpio) |
| 54 | { |
| 55 | gpio_configure(gpio, GPIO_FUNC_GPIO, |
| 56 | GPIO_NO_PULL, GPIO_2MA, GPIO_OUTPUT_DISABLE); |
| 57 | } |
| 58 | |
| 59 | void gpio_output(gpio_t gpio, int value) |
| 60 | { |
| 61 | gpio_set(gpio, value); |
| 62 | gpio_configure(gpio, GPIO_FUNC_GPIO, |
| 63 | GPIO_NO_PULL, GPIO_2MA, GPIO_OUTPUT_ENABLE); |
| 64 | } |
| 65 | |
| 66 | void gpio_input_irq(gpio_t gpio, enum gpio_irq_type type, uint32_t pull) |
| 67 | { |
| 68 | struct tlmm_gpio *regs = (void *)(uintptr_t)gpio.addr; |
| 69 | |
| 70 | gpio_configure(gpio, GPIO_FUNC_GPIO, |
| 71 | pull, GPIO_2MA, GPIO_OUTPUT_DISABLE); |
| 72 | |
Julius Werner | 55009af | 2019-12-02 22:03:27 -0800 | [diff] [blame] | 73 | clrsetbits32(®s->intr_cfg, GPIO_INTR_DECT_CTL_MASK << |
Taniya Das | 09c3bfe | 2019-08-07 11:34:57 +0530 | [diff] [blame] | 74 | GPIO_INTR_DECT_CTL_SHIFT, type << GPIO_INTR_DECT_CTL_SHIFT); |
Julius Werner | 55009af | 2019-12-02 22:03:27 -0800 | [diff] [blame] | 75 | clrsetbits32(®s->intr_cfg, GPIO_INTR_RAW_STATUS_ENABLE |
Taniya Das | 09c3bfe | 2019-08-07 11:34:57 +0530 | [diff] [blame] | 76 | << GPIO_INTR_RAW_STATUS_EN_SHIFT, GPIO_INTR_RAW_STATUS_ENABLE |
| 77 | << GPIO_INTR_RAW_STATUS_EN_SHIFT); |
| 78 | } |
| 79 | |
| 80 | int gpio_irq_status(gpio_t gpio) |
| 81 | { |
| 82 | struct tlmm_gpio *regs = (void *)(uintptr_t)gpio.addr; |
| 83 | |
| 84 | if (!(read32(®s->intr_status) & GPIO_INTR_STATUS_MASK)) |
| 85 | return 0; |
| 86 | |
| 87 | write32(®s->intr_status, GPIO_INTR_STATUS_DISABLE); |
| 88 | return 1; |
| 89 | } |