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 static int aspeed_gpio_get_value(struct udevice *dev, unsigned offset) 229 { 230 struct aspeed_gpio_priv *priv = dev_get_priv(dev); 231 const struct aspeed_gpio_bank *bank = to_bank(offset); 232 233 return !!(readl(bank_reg(priv, bank, reg_val)) & GPIO_BIT(offset)); 234 } 235 236 static int aspeed_gpio_set_value(struct udevice *dev, unsigned offset, 237 int value) 238 { 239 240 struct aspeed_gpio_priv *priv = dev_get_priv(dev); 241 const struct aspeed_gpio_bank *bank = to_bank(offset); 242 u32 data = readl(bank_reg(priv, bank, reg_val)); 243 244 if (value) 245 data |= GPIO_BIT(offset); 246 else 247 data &= ~GPIO_BIT(offset); 248 249 writel(data, bank_reg(priv, bank, reg_val)); 250 251 return 0; 252 } 253 254 static int aspeed_gpio_get_function(struct udevice *dev, unsigned offset) 255 { 256 struct aspeed_gpio_priv *priv = dev_get_priv(dev); 257 const struct aspeed_gpio_bank *bank = to_bank(offset); 258 259 if(readl(bank_reg(priv, bank, reg_dir)) & GPIO_BIT(offset)) 260 return GPIOF_OUTPUT; 261 else 262 return GPIOF_INPUT; 263 } 264 265 static const struct dm_gpio_ops gpio_aspeed_ops = { 266 .direction_input = aspeed_gpio_direction_input, 267 .direction_output = aspeed_gpio_direction_output, 268 .get_value = aspeed_gpio_get_value, 269 .set_value = aspeed_gpio_set_value, 270 .get_function = aspeed_gpio_get_function, 271 }; 272 273 static int aspeed_gpio_probe(struct udevice *dev) 274 { 275 struct gpio_dev_priv *uc_priv = dev_get_uclass_priv(dev); 276 struct aspeed_gpio_priv *priv = dev_get_priv(dev); 277 278 uc_priv->bank_name = dev->name; 279 ofnode_read_u32(dev_ofnode(dev), "ngpios", &uc_priv->gpio_count); 280 priv->regs = devfdt_get_addr_ptr(dev); 281 282 return 0; 283 } 284 285 static const struct udevice_id aspeed_gpio_ids[] = { 286 { .compatible = "aspeed,ast2500-gpio", }, 287 { .compatible = "aspeed,ast2600-gpio", }, 288 { } 289 }; 290 291 U_BOOT_DRIVER(gpio_aspeed) = { 292 .name = "gpio_aspeed", 293 .id = UCLASS_GPIO, 294 .of_match = aspeed_gpio_ids, 295 .ops = &gpio_aspeed_ops, 296 .probe = aspeed_gpio_probe, 297 .priv_auto_alloc_size = sizeof(struct aspeed_gpio_priv), 298 }; 299