Angel Pons | e67ab18 | 2020-04-04 18:51:11 +0200 | [diff] [blame] | 1 | /* SPDX-License-Identifier: GPL-2.0-only */ |
Po Xu | f71f179 | 2018-07-16 18:41:49 +0800 | [diff] [blame] | 2 | |
Kyösti Mälkki | 13f6650 | 2019-03-03 08:01:05 +0200 | [diff] [blame] | 3 | #include <device/mmio.h> |
Po Xu | f71f179 | 2018-07-16 18:41:49 +0800 | [diff] [blame] | 4 | #include <gpio.h> |
Mengqi Zhang | 89b1753 | 2019-04-24 10:14:52 +0800 | [diff] [blame] | 5 | #include <assert.h> |
| 6 | #include <soc/spi.h> |
Po Xu | f71f179 | 2018-07-16 18:41:49 +0800 | [diff] [blame] | 7 | |
| 8 | enum { |
| 9 | EN_OFFSET = 0x60, |
| 10 | SEL_OFFSET = 0x80, |
jg_poxu | 9e21b2d | 2019-01-31 15:46:03 +0800 | [diff] [blame] | 11 | EH_RSEL_OFFSET = 0xF0, |
Mengqi Zhang | 89b1753 | 2019-04-24 10:14:52 +0800 | [diff] [blame] | 12 | GPIO_DRV0_OFFSET = 0xA0, |
Subrata Banik | 8e6d5f2 | 2020-08-30 13:51:44 +0530 | [diff] [blame] | 13 | GPIO_DRV1_OFFSET = 0xB0, |
Po Xu | f71f179 | 2018-07-16 18:41:49 +0800 | [diff] [blame] | 14 | }; |
| 15 | |
| 16 | static void gpio_set_pull_pupd(gpio_t gpio, enum pull_enable enable, |
| 17 | enum pull_select select) |
| 18 | { |
| 19 | void *reg = GPIO_TO_IOCFG_BASE(gpio.base) + gpio.offset; |
| 20 | int bit = gpio.bit; |
| 21 | |
| 22 | if (enable == GPIO_PULL_ENABLE) { |
| 23 | if (select == GPIO_PULL_DOWN) |
Julius Werner | 55009af | 2019-12-02 22:03:27 -0800 | [diff] [blame] | 24 | setbits32(reg, 1 << (bit + 2)); |
Po Xu | f71f179 | 2018-07-16 18:41:49 +0800 | [diff] [blame] | 25 | else |
Julius Werner | 55009af | 2019-12-02 22:03:27 -0800 | [diff] [blame] | 26 | clrbits32(reg, 1 << (bit + 2)); |
Po Xu | f71f179 | 2018-07-16 18:41:49 +0800 | [diff] [blame] | 27 | } |
| 28 | |
| 29 | if (enable == GPIO_PULL_ENABLE) |
Julius Werner | 55009af | 2019-12-02 22:03:27 -0800 | [diff] [blame] | 30 | clrsetbits32(reg, 3 << bit, 1 << bit); |
Po Xu | f71f179 | 2018-07-16 18:41:49 +0800 | [diff] [blame] | 31 | else |
Julius Werner | 55009af | 2019-12-02 22:03:27 -0800 | [diff] [blame] | 32 | clrbits32(reg, 3 << bit); |
Po Xu | f71f179 | 2018-07-16 18:41:49 +0800 | [diff] [blame] | 33 | } |
| 34 | |
| 35 | static void gpio_set_pull_en_sel(gpio_t gpio, enum pull_enable enable, |
| 36 | enum pull_select select) |
| 37 | { |
| 38 | void *reg = GPIO_TO_IOCFG_BASE(gpio.base) + gpio.offset; |
| 39 | int bit = gpio.bit; |
| 40 | |
| 41 | if (enable == GPIO_PULL_ENABLE) { |
| 42 | if (select == GPIO_PULL_DOWN) |
Julius Werner | 55009af | 2019-12-02 22:03:27 -0800 | [diff] [blame] | 43 | clrbits32(reg + SEL_OFFSET, 1 << bit); |
Po Xu | f71f179 | 2018-07-16 18:41:49 +0800 | [diff] [blame] | 44 | else |
Julius Werner | 55009af | 2019-12-02 22:03:27 -0800 | [diff] [blame] | 45 | setbits32(reg + SEL_OFFSET, 1 << bit); |
Po Xu | f71f179 | 2018-07-16 18:41:49 +0800 | [diff] [blame] | 46 | } |
| 47 | |
| 48 | if (enable == GPIO_PULL_ENABLE) |
Julius Werner | 55009af | 2019-12-02 22:03:27 -0800 | [diff] [blame] | 49 | setbits32(reg + EN_OFFSET, 1 << bit); |
Po Xu | f71f179 | 2018-07-16 18:41:49 +0800 | [diff] [blame] | 50 | else |
Julius Werner | 55009af | 2019-12-02 22:03:27 -0800 | [diff] [blame] | 51 | clrbits32(reg + EN_OFFSET, 1 << bit); |
Po Xu | f71f179 | 2018-07-16 18:41:49 +0800 | [diff] [blame] | 52 | } |
| 53 | |
| 54 | void gpio_set_pull(gpio_t gpio, enum pull_enable enable, |
| 55 | enum pull_select select) |
| 56 | { |
| 57 | if (gpio.flag) |
| 58 | gpio_set_pull_pupd(gpio, enable, select); |
| 59 | else |
| 60 | gpio_set_pull_en_sel(gpio, enable, select); |
| 61 | } |
jg_poxu | 9e21b2d | 2019-01-31 15:46:03 +0800 | [diff] [blame] | 62 | |
| 63 | enum { |
| 64 | EH_VAL = 0x0, |
| 65 | RSEL_VAL = 0x3, |
| 66 | EH_MASK = 0x7, |
| 67 | RSEL_MASK = 0x3, |
| 68 | SCL0_EH = 19, |
| 69 | SCL0_RSEL = 15, |
| 70 | SDA0_EH = 9, |
| 71 | SDA0_RSEL = 5, |
| 72 | SCL1_EH = 22, |
| 73 | SCL1_RSEL = 17, |
| 74 | SDA1_EH = 12, |
| 75 | SDA1_RSEL = 7, |
| 76 | SCL2_EH = 24, |
| 77 | SCL2_RSEL = 20, |
| 78 | SDA2_EH = 14, |
| 79 | SDA2_RSEL = 10, |
| 80 | SCL3_EH = 12, |
| 81 | SCL3_RSEL = 10, |
| 82 | SDA3_EH = 7, |
| 83 | SDA3_RSEL = 5, |
| 84 | SCL4_EH = 27, |
| 85 | SCL4_RSEL = 22, |
| 86 | SDA4_EH = 17, |
| 87 | SDA4_RSEL = 12, |
| 88 | SCL5_EH = 20, |
| 89 | SCL5_RSEL = 18, |
| 90 | SDA5_EH = 15, |
| 91 | SDA5_RSEL = 13, |
| 92 | }; |
| 93 | |
| 94 | #define I2C_EH_RSL_MASK(name) \ |
| 95 | (EH_MASK << name##_EH | RSEL_MASK << name##_RSEL) |
| 96 | |
| 97 | #define I2C_EH_RSL_VAL(name) \ |
| 98 | (EH_VAL << name##_EH | RSEL_VAL << name##_RSEL) |
| 99 | |
| 100 | void gpio_set_i2c_eh_rsel(void) |
| 101 | { |
Julius Werner | 55009af | 2019-12-02 22:03:27 -0800 | [diff] [blame] | 102 | clrsetbits32((void *)IOCFG_RB_BASE + EH_RSEL_OFFSET, |
jg_poxu | 9e21b2d | 2019-01-31 15:46:03 +0800 | [diff] [blame] | 103 | I2C_EH_RSL_MASK(SCL0) | I2C_EH_RSL_MASK(SDA0) | |
| 104 | I2C_EH_RSL_MASK(SCL1) | I2C_EH_RSL_MASK(SDA1), |
| 105 | I2C_EH_RSL_VAL(SCL0) | I2C_EH_RSL_VAL(SDA0) | |
| 106 | I2C_EH_RSL_VAL(SCL1) | I2C_EH_RSL_VAL(SDA1)); |
| 107 | |
Julius Werner | 55009af | 2019-12-02 22:03:27 -0800 | [diff] [blame] | 108 | clrsetbits32((void *)IOCFG_RM_BASE + EH_RSEL_OFFSET, |
jg_poxu | 9e21b2d | 2019-01-31 15:46:03 +0800 | [diff] [blame] | 109 | I2C_EH_RSL_MASK(SCL2) | I2C_EH_RSL_MASK(SDA2) | |
| 110 | I2C_EH_RSL_MASK(SCL4) | I2C_EH_RSL_MASK(SDA4), |
| 111 | I2C_EH_RSL_VAL(SCL2) | I2C_EH_RSL_VAL(SDA2) | |
| 112 | I2C_EH_RSL_VAL(SCL4) | I2C_EH_RSL_VAL(SDA4)); |
| 113 | |
Julius Werner | 55009af | 2019-12-02 22:03:27 -0800 | [diff] [blame] | 114 | clrsetbits32((void *)IOCFG_BL_BASE + EH_RSEL_OFFSET, |
jg_poxu | 9e21b2d | 2019-01-31 15:46:03 +0800 | [diff] [blame] | 115 | I2C_EH_RSL_MASK(SCL3) | I2C_EH_RSL_MASK(SDA3), |
| 116 | I2C_EH_RSL_VAL(SCL3) | I2C_EH_RSL_VAL(SDA3)); |
| 117 | |
Julius Werner | 55009af | 2019-12-02 22:03:27 -0800 | [diff] [blame] | 118 | clrsetbits32((void *)IOCFG_LB_BASE + EH_RSEL_OFFSET, |
jg_poxu | 9e21b2d | 2019-01-31 15:46:03 +0800 | [diff] [blame] | 119 | I2C_EH_RSL_MASK(SCL5) | I2C_EH_RSL_MASK(SDA5), |
| 120 | I2C_EH_RSL_VAL(SCL5) | I2C_EH_RSL_VAL(SDA5)); |
| 121 | } |
Mengqi Zhang | 89b1753 | 2019-04-24 10:14:52 +0800 | [diff] [blame] | 122 | |
| 123 | void gpio_set_spi_driving(unsigned int bus, enum spi_pad_mask pad_select, |
| 124 | unsigned int milliamps) |
| 125 | { |
| 126 | void *reg = NULL; |
| 127 | unsigned int reg_val = milliamps / 2 - 1, offset = 0; |
| 128 | |
| 129 | assert(bus < SPI_BUS_NUMBER); |
| 130 | assert(milliamps >= 2 && milliamps <= 16); |
| 131 | assert(pad_select <= SPI_PAD1_MASK); |
| 132 | |
| 133 | switch (bus) { |
| 134 | case 0: |
| 135 | reg = (void *)(IOCFG_RB_BASE + GPIO_DRV1_OFFSET); |
| 136 | offset = 0; |
| 137 | break; |
| 138 | case 1: |
| 139 | if (pad_select == SPI_PAD0_MASK) { |
| 140 | reg = (void *)(IOCFG_LM_BASE + GPIO_DRV0_OFFSET); |
| 141 | offset = 0; |
| 142 | } else if (pad_select == SPI_PAD1_MASK) { |
Julius Werner | 55009af | 2019-12-02 22:03:27 -0800 | [diff] [blame] | 143 | clrsetbits32((void *)IOCFG_RM_BASE + |
Mengqi Zhang | 89b1753 | 2019-04-24 10:14:52 +0800 | [diff] [blame] | 144 | GPIO_DRV0_OFFSET, 0xf | 0xf << 20, |
| 145 | reg_val | reg_val << 20); |
Julius Werner | 55009af | 2019-12-02 22:03:27 -0800 | [diff] [blame] | 146 | clrsetbits32((void *)IOCFG_RM_BASE + |
Mengqi Zhang | 89b1753 | 2019-04-24 10:14:52 +0800 | [diff] [blame] | 147 | GPIO_DRV1_OFFSET, 0xf << 16, |
| 148 | reg_val << 16); |
| 149 | return; |
| 150 | } |
| 151 | break; |
| 152 | case 2: |
Julius Werner | 55009af | 2019-12-02 22:03:27 -0800 | [diff] [blame] | 153 | clrsetbits32((void *)IOCFG_RM_BASE + GPIO_DRV0_OFFSET, |
Mengqi Zhang | 89b1753 | 2019-04-24 10:14:52 +0800 | [diff] [blame] | 154 | 0xf << 8 | 0xf << 12, |
| 155 | reg_val << 8 | reg_val << 12); |
| 156 | return; |
| 157 | case 3: |
| 158 | reg = (void *)(IOCFG_LM_BASE + GPIO_DRV0_OFFSET); |
| 159 | offset = 16; |
| 160 | break; |
| 161 | case 4: |
| 162 | reg = (void *)(IOCFG_LM_BASE + GPIO_DRV0_OFFSET); |
| 163 | offset = 12; |
| 164 | break; |
| 165 | case 5: |
| 166 | reg = (void *)(IOCFG_LM_BASE + GPIO_DRV0_OFFSET); |
| 167 | offset = 8; |
| 168 | break; |
| 169 | } |
| 170 | |
Julius Werner | 55009af | 2019-12-02 22:03:27 -0800 | [diff] [blame] | 171 | clrsetbits32(reg, 0xf << offset, reg_val << offset); |
Mengqi Zhang | 89b1753 | 2019-04-24 10:14:52 +0800 | [diff] [blame] | 172 | } |