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