1 /* 2 * ast_gpio.c - GPIO driver for the Aspeed SoC 3 * 4 * Copyright (C) ASPEED Technology Inc. 5 * Ryan Chen <ryan_chen@aspeedtech.com> 6 * 7 */ 8 #include <common.h> 9 #include <asm/io.h> 10 #include <asm/gpio.h> 11 12 #include <config.h> 13 #include <common.h> 14 #include <clk.h> 15 #include <dm.h> 16 #include <asm/io.h> 17 #include <linux/sizes.h> 18 19 struct aspeed_gpio_priv { 20 void *regs; 21 }; 22 23 struct aspeed_gpio_bank { 24 uint16_t val_regs; /* +0: Rd: read input value, Wr: set write latch 25 * +4: Rd/Wr: Direction (0=in, 1=out) 26 */ 27 uint16_t rdata_reg; /* Rd: read write latch, Wr: <none> */ 28 uint16_t irq_regs; 29 uint16_t debounce_regs; 30 uint16_t tolerance_regs; 31 uint16_t cmdsrc_regs; 32 const char names[4][3]; 33 }; 34 35 static const struct aspeed_gpio_bank aspeed_gpio_banks[] = { 36 { 37 .val_regs = 0x0000, 38 .rdata_reg = 0x00c0, 39 .irq_regs = 0x0008, 40 .debounce_regs = 0x0040, 41 .tolerance_regs = 0x001c, 42 .cmdsrc_regs = 0x0060, 43 .names = { "A", "B", "C", "D" }, 44 }, 45 { 46 .val_regs = 0x0020, 47 .rdata_reg = 0x00c4, 48 .irq_regs = 0x0028, 49 .debounce_regs = 0x0048, 50 .tolerance_regs = 0x003c, 51 .cmdsrc_regs = 0x0068, 52 .names = { "E", "F", "G", "H" }, 53 }, 54 { 55 .val_regs = 0x0070, 56 .rdata_reg = 0x00c8, 57 .irq_regs = 0x0098, 58 .debounce_regs = 0x00b0, 59 .tolerance_regs = 0x00ac, 60 .cmdsrc_regs = 0x0090, 61 .names = { "I", "J", "K", "L" }, 62 }, 63 { 64 .val_regs = 0x0078, 65 .rdata_reg = 0x00cc, 66 .irq_regs = 0x00e8, 67 .debounce_regs = 0x0100, 68 .tolerance_regs = 0x00fc, 69 .cmdsrc_regs = 0x00e0, 70 .names = { "M", "N", "O", "P" }, 71 }, 72 { 73 .val_regs = 0x0080, 74 .rdata_reg = 0x00d0, 75 .irq_regs = 0x0118, 76 .debounce_regs = 0x0130, 77 .tolerance_regs = 0x012c, 78 .cmdsrc_regs = 0x0110, 79 .names = { "Q", "R", "S", "T" }, 80 }, 81 { 82 .val_regs = 0x0088, 83 .rdata_reg = 0x00d4, 84 .irq_regs = 0x0148, 85 .debounce_regs = 0x0160, 86 .tolerance_regs = 0x015c, 87 .cmdsrc_regs = 0x0140, 88 .names = { "U", "V", "W", "X" }, 89 }, 90 { 91 .val_regs = 0x01E0, 92 .rdata_reg = 0x00d8, 93 .irq_regs = 0x0178, 94 .debounce_regs = 0x0190, 95 .tolerance_regs = 0x018c, 96 .cmdsrc_regs = 0x0170, 97 .names = { "Y", "Z", "AA", "AB" }, 98 }, 99 { 100 .val_regs = 0x01e8, 101 .rdata_reg = 0x00dc, 102 .irq_regs = 0x01a8, 103 .debounce_regs = 0x01c0, 104 .tolerance_regs = 0x01bc, 105 .cmdsrc_regs = 0x01a0, 106 .names = { "AC", "", "", "" }, 107 }, 108 }; 109 110 enum aspeed_gpio_reg { 111 reg_val, 112 reg_rdata, 113 reg_dir, 114 reg_irq_enable, 115 reg_irq_type0, 116 reg_irq_type1, 117 reg_irq_type2, 118 reg_irq_status, 119 reg_debounce_sel1, 120 reg_debounce_sel2, 121 reg_tolerance, 122 reg_cmdsrc0, 123 reg_cmdsrc1, 124 }; 125 126 #define GPIO_VAL_VALUE 0x00 127 #define GPIO_VAL_DIR 0x04 128 129 #define GPIO_IRQ_ENABLE 0x00 130 #define GPIO_IRQ_TYPE0 0x04 131 #define GPIO_IRQ_TYPE1 0x08 132 #define GPIO_IRQ_TYPE2 0x0c 133 #define GPIO_IRQ_STATUS 0x10 134 135 #define GPIO_DEBOUNCE_SEL1 0x00 136 #define GPIO_DEBOUNCE_SEL2 0x04 137 138 #define GPIO_CMDSRC_0 0x00 139 #define GPIO_CMDSRC_1 0x04 140 #define GPIO_CMDSRC_ARM 0 141 #define GPIO_CMDSRC_LPC 1 142 #define GPIO_CMDSRC_COLDFIRE 2 143 #define GPIO_CMDSRC_RESERVED 3 144 145 /* This will be resolved at compile time */ 146 static inline void __iomem *bank_reg(struct aspeed_gpio_priv *gpio, 147 const struct aspeed_gpio_bank *bank, 148 const enum aspeed_gpio_reg reg) 149 { 150 switch (reg) { 151 case reg_val: 152 return gpio->regs + bank->val_regs + GPIO_VAL_VALUE; 153 case reg_rdata: 154 return gpio->regs + bank->rdata_reg; 155 case reg_dir: 156 return gpio->regs + bank->val_regs + GPIO_VAL_DIR; 157 case reg_irq_enable: 158 return gpio->regs + bank->irq_regs + GPIO_IRQ_ENABLE; 159 case reg_irq_type0: 160 return gpio->regs + bank->irq_regs + GPIO_IRQ_TYPE0; 161 case reg_irq_type1: 162 return gpio->regs + bank->irq_regs + GPIO_IRQ_TYPE1; 163 case reg_irq_type2: 164 return gpio->regs + bank->irq_regs + GPIO_IRQ_TYPE2; 165 case reg_irq_status: 166 return gpio->regs + bank->irq_regs + GPIO_IRQ_STATUS; 167 case reg_debounce_sel1: 168 return gpio->regs + bank->debounce_regs + GPIO_DEBOUNCE_SEL1; 169 case reg_debounce_sel2: 170 return gpio->regs + bank->debounce_regs + GPIO_DEBOUNCE_SEL2; 171 case reg_tolerance: 172 return gpio->regs + bank->tolerance_regs; 173 case reg_cmdsrc0: 174 return gpio->regs + bank->cmdsrc_regs + GPIO_CMDSRC_0; 175 case reg_cmdsrc1: 176 return gpio->regs + bank->cmdsrc_regs + GPIO_CMDSRC_1; 177 } 178 BUG(); 179 } 180 181 #define GPIO_BANK(x) ((x) >> 5) 182 #define GPIO_OFFSET(x) ((x) & 0x1f) 183 #define GPIO_BIT(x) BIT(GPIO_OFFSET(x)) 184 185 static const struct aspeed_gpio_bank *to_bank(unsigned int offset) 186 { 187 unsigned int bank = GPIO_BANK(offset); 188 189 WARN_ON(bank >= ARRAY_SIZE(aspeed_gpio_banks)); 190 return &aspeed_gpio_banks[bank]; 191 } 192 193 static int 194 aspeed_gpio_direction_input(struct udevice *dev, unsigned offset) 195 { 196 struct aspeed_gpio_priv *priv = dev_get_priv(dev); 197 const struct aspeed_gpio_bank *bank = to_bank(offset); 198 u32 dir = readl(bank_reg(priv, bank, reg_dir)); 199 200 dir &= ~GPIO_BIT(offset); 201 writel(dir, bank_reg(priv, bank, reg_dir)); 202 203 return 0; 204 } 205 206 static int 207 aspeed_gpio_direction_output(struct udevice *dev, unsigned offset, 208 int value) 209 { 210 struct aspeed_gpio_priv *priv = dev_get_priv(dev); 211 const struct aspeed_gpio_bank *bank = to_bank(offset); 212 u32 dir = readl(bank_reg(priv, bank, reg_dir)); 213 u32 output = readl(bank_reg(priv, bank, reg_val)); 214 215 dir |= GPIO_BIT(offset); 216 writel(dir, bank_reg(priv, bank, reg_dir)); 217 218 if(value) 219 output |= GPIO_BIT(offset); 220 else 221 output &= ~GPIO_BIT(offset); 222 223 writel(output, bank_reg(priv, bank, reg_val)); 224 225 return 0; 226 } 227 228 229 static int aspeed_gpio_get_value(struct udevice *dev, unsigned offset) 230 { 231 struct aspeed_gpio_priv *priv = dev_get_priv(dev); 232 const struct aspeed_gpio_bank *bank = to_bank(offset); 233 234 return !!(readl(bank_reg(priv, bank, reg_val)) & GPIO_BIT(offset)); 235 } 236 237 static int aspeed_gpio_set_value(struct udevice *dev, unsigned offset, 238 int value) 239 { 240 241 struct aspeed_gpio_priv *priv = dev_get_priv(dev); 242 const struct aspeed_gpio_bank *bank = to_bank(offset); 243 u32 data = readl(bank_reg(priv, bank, reg_val)); 244 245 if (value) 246 data |= GPIO_BIT(offset); 247 else 248 data &= ~GPIO_BIT(offset); 249 250 writel(data, bank_reg(priv, bank, reg_val)); 251 252 return 0; 253 } 254 255 static int aspeed_gpio_get_function(struct udevice *dev, unsigned offset) 256 { 257 struct aspeed_gpio_priv *priv = dev_get_priv(dev); 258 const struct aspeed_gpio_bank *bank = to_bank(offset); 259 260 if(readl(bank_reg(priv, bank, reg_dir)) & GPIO_BIT(offset)) 261 return GPIOF_OUTPUT; 262 else 263 return GPIOF_INPUT; 264 } 265 266 static const struct dm_gpio_ops gpio_aspeed_ops = { 267 .direction_input = aspeed_gpio_direction_input, 268 .direction_output = aspeed_gpio_direction_output, 269 .get_value = aspeed_gpio_get_value, 270 .set_value = aspeed_gpio_set_value, 271 .get_function = aspeed_gpio_get_function, 272 }; 273 274 static int aspeed_gpio_probe(struct udevice *dev) 275 { 276 struct gpio_dev_priv *uc_priv = dev_get_uclass_priv(dev); 277 struct aspeed_gpio_priv *priv = dev_get_priv(dev); 278 ulong driver_data = dev_get_driver_data(dev); 279 280 uc_priv->bank_name = dev->name; 281 uc_priv->gpio_count = driver_data; 282 283 priv->regs = devfdt_get_addr_ptr(dev); 284 285 return 0; 286 } 287 288 static const struct udevice_id aspeed_gpio_ids[] = { 289 { .compatible = "aspeed,ast2500-gpio", .data = 232 }, 290 { .compatible = "aspeed,ast2600-gpio", .data = 208 }, 291 { } 292 }; 293 294 U_BOOT_DRIVER(gpio_aspeed) = { 295 .name = "gpio_aspeed", 296 .id = UCLASS_GPIO, 297 .of_match = aspeed_gpio_ids, 298 .ops = &gpio_aspeed_ops, 299 .probe = aspeed_gpio_probe, 300 .priv_auto_alloc_size = sizeof(struct aspeed_gpio_priv), 301 }; 302