1 /* 2 * Atmel PIO4 device driver 3 * 4 * Copyright (C) 2015 Atmel Corporation 5 * Wenyou.Yang <wenyou.yang@atmel.com> 6 * 7 * SPDX-License-Identifier: GPL-2.0+ 8 */ 9 #include <common.h> 10 #include <clk.h> 11 #include <dm.h> 12 #include <fdtdec.h> 13 #include <dm/root.h> 14 #include <asm/arch/hardware.h> 15 #include <asm/gpio.h> 16 #include <mach/gpio.h> 17 #include <mach/atmel_pio4.h> 18 19 DECLARE_GLOBAL_DATA_PTR; 20 21 static struct atmel_pio4_port *atmel_pio4_port_base(u32 port) 22 { 23 struct atmel_pio4_port *base = NULL; 24 25 switch (port) { 26 case AT91_PIO_PORTA: 27 base = (struct atmel_pio4_port *)ATMEL_BASE_PIOA; 28 break; 29 case AT91_PIO_PORTB: 30 base = (struct atmel_pio4_port *)ATMEL_BASE_PIOB; 31 break; 32 case AT91_PIO_PORTC: 33 base = (struct atmel_pio4_port *)ATMEL_BASE_PIOC; 34 break; 35 case AT91_PIO_PORTD: 36 base = (struct atmel_pio4_port *)ATMEL_BASE_PIOD; 37 break; 38 default: 39 printf("Error: Atmel PIO4: Failed to get PIO base of port#%d!\n", 40 port); 41 break; 42 } 43 44 return base; 45 } 46 47 static int atmel_pio4_config_io_func(u32 port, u32 pin, 48 u32 func, u32 use_pullup) 49 { 50 struct atmel_pio4_port *port_base; 51 u32 reg, mask; 52 53 if (pin >= ATMEL_PIO_NPINS_PER_BANK) 54 return -ENODEV; 55 56 port_base = atmel_pio4_port_base(port); 57 if (!port_base) 58 return -ENODEV; 59 60 mask = 1 << pin; 61 reg = func; 62 reg |= use_pullup ? ATMEL_PIO_PUEN_MASK : 0; 63 64 writel(mask, &port_base->mskr); 65 writel(reg, &port_base->cfgr); 66 67 return 0; 68 } 69 70 int atmel_pio4_set_gpio(u32 port, u32 pin, u32 use_pullup) 71 { 72 return atmel_pio4_config_io_func(port, pin, 73 ATMEL_PIO_CFGR_FUNC_GPIO, 74 use_pullup); 75 } 76 77 int atmel_pio4_set_a_periph(u32 port, u32 pin, u32 use_pullup) 78 { 79 return atmel_pio4_config_io_func(port, pin, 80 ATMEL_PIO_CFGR_FUNC_PERIPH_A, 81 use_pullup); 82 } 83 84 int atmel_pio4_set_b_periph(u32 port, u32 pin, u32 use_pullup) 85 { 86 return atmel_pio4_config_io_func(port, pin, 87 ATMEL_PIO_CFGR_FUNC_PERIPH_B, 88 use_pullup); 89 } 90 91 int atmel_pio4_set_c_periph(u32 port, u32 pin, u32 use_pullup) 92 { 93 return atmel_pio4_config_io_func(port, pin, 94 ATMEL_PIO_CFGR_FUNC_PERIPH_C, 95 use_pullup); 96 } 97 98 int atmel_pio4_set_d_periph(u32 port, u32 pin, u32 use_pullup) 99 { 100 return atmel_pio4_config_io_func(port, pin, 101 ATMEL_PIO_CFGR_FUNC_PERIPH_D, 102 use_pullup); 103 } 104 105 int atmel_pio4_set_e_periph(u32 port, u32 pin, u32 use_pullup) 106 { 107 return atmel_pio4_config_io_func(port, pin, 108 ATMEL_PIO_CFGR_FUNC_PERIPH_E, 109 use_pullup); 110 } 111 112 int atmel_pio4_set_f_periph(u32 port, u32 pin, u32 use_pullup) 113 { 114 return atmel_pio4_config_io_func(port, pin, 115 ATMEL_PIO_CFGR_FUNC_PERIPH_F, 116 use_pullup); 117 } 118 119 int atmel_pio4_set_g_periph(u32 port, u32 pin, u32 use_pullup) 120 { 121 return atmel_pio4_config_io_func(port, pin, 122 ATMEL_PIO_CFGR_FUNC_PERIPH_G, 123 use_pullup); 124 } 125 126 int atmel_pio4_set_pio_output(u32 port, u32 pin, u32 value) 127 { 128 struct atmel_pio4_port *port_base; 129 u32 reg, mask; 130 131 if (pin >= ATMEL_PIO_NPINS_PER_BANK) 132 return -ENODEV; 133 134 port_base = atmel_pio4_port_base(port); 135 if (!port_base) 136 return -ENODEV; 137 138 mask = 0x01 << pin; 139 reg = ATMEL_PIO_CFGR_FUNC_GPIO | ATMEL_PIO_DIR_MASK; 140 141 writel(mask, &port_base->mskr); 142 writel(reg, &port_base->cfgr); 143 144 if (value) 145 writel(mask, &port_base->sodr); 146 else 147 writel(mask, &port_base->codr); 148 149 return 0; 150 } 151 152 int atmel_pio4_get_pio_input(u32 port, u32 pin) 153 { 154 struct atmel_pio4_port *port_base; 155 u32 reg, mask; 156 157 if (pin >= ATMEL_PIO_NPINS_PER_BANK) 158 return -ENODEV; 159 160 port_base = atmel_pio4_port_base(port); 161 if (!port_base) 162 return -ENODEV; 163 164 mask = 0x01 << pin; 165 reg = ATMEL_PIO_CFGR_FUNC_GPIO; 166 167 writel(mask, &port_base->mskr); 168 writel(reg, &port_base->cfgr); 169 170 return (readl(&port_base->pdsr) & mask) ? 1 : 0; 171 } 172 173 #ifdef CONFIG_DM_GPIO 174 175 struct atmel_pioctrl_data { 176 u32 nbanks; 177 }; 178 179 struct atmel_pio4_platdata { 180 struct atmel_pio4_port *reg_base; 181 }; 182 183 static struct atmel_pio4_port *atmel_pio4_bank_base(struct udevice *dev, 184 u32 bank) 185 { 186 struct atmel_pio4_platdata *plat = dev_get_platdata(dev); 187 struct atmel_pio4_port *port_base = 188 (struct atmel_pio4_port *)((u32)plat->reg_base + 189 ATMEL_PIO_BANK_OFFSET * bank); 190 191 return port_base; 192 } 193 194 static int atmel_pio4_direction_input(struct udevice *dev, unsigned offset) 195 { 196 u32 bank = ATMEL_PIO_BANK(offset); 197 u32 line = ATMEL_PIO_LINE(offset); 198 struct atmel_pio4_port *port_base = atmel_pio4_bank_base(dev, bank); 199 u32 mask = BIT(line); 200 201 writel(mask, &port_base->mskr); 202 203 clrbits_le32(&port_base->cfgr, 204 ATMEL_PIO_CFGR_FUNC_MASK | ATMEL_PIO_DIR_MASK); 205 206 return 0; 207 } 208 209 static int atmel_pio4_direction_output(struct udevice *dev, 210 unsigned offset, int value) 211 { 212 u32 bank = ATMEL_PIO_BANK(offset); 213 u32 line = ATMEL_PIO_LINE(offset); 214 struct atmel_pio4_port *port_base = atmel_pio4_bank_base(dev, bank); 215 u32 mask = BIT(line); 216 217 writel(mask, &port_base->mskr); 218 219 clrsetbits_le32(&port_base->cfgr, 220 ATMEL_PIO_CFGR_FUNC_MASK, ATMEL_PIO_DIR_MASK); 221 222 if (value) 223 writel(mask, &port_base->sodr); 224 else 225 writel(mask, &port_base->codr); 226 227 return 0; 228 } 229 230 static int atmel_pio4_get_value(struct udevice *dev, unsigned offset) 231 { 232 u32 bank = ATMEL_PIO_BANK(offset); 233 u32 line = ATMEL_PIO_LINE(offset); 234 struct atmel_pio4_port *port_base = atmel_pio4_bank_base(dev, bank); 235 u32 mask = BIT(line); 236 237 return (readl(&port_base->pdsr) & mask) ? 1 : 0; 238 } 239 240 static int atmel_pio4_set_value(struct udevice *dev, 241 unsigned offset, int value) 242 { 243 u32 bank = ATMEL_PIO_BANK(offset); 244 u32 line = ATMEL_PIO_LINE(offset); 245 struct atmel_pio4_port *port_base = atmel_pio4_bank_base(dev, bank); 246 u32 mask = BIT(line); 247 248 if (value) 249 writel(mask, &port_base->sodr); 250 else 251 writel(mask, &port_base->codr); 252 253 return 0; 254 } 255 256 static int atmel_pio4_get_function(struct udevice *dev, unsigned offset) 257 { 258 u32 bank = ATMEL_PIO_BANK(offset); 259 u32 line = ATMEL_PIO_LINE(offset); 260 struct atmel_pio4_port *port_base = atmel_pio4_bank_base(dev, bank); 261 u32 mask = BIT(line); 262 263 writel(mask, &port_base->mskr); 264 265 return (readl(&port_base->cfgr) & 266 ATMEL_PIO_DIR_MASK) ? GPIOF_OUTPUT : GPIOF_INPUT; 267 } 268 269 static const struct dm_gpio_ops atmel_pio4_ops = { 270 .direction_input = atmel_pio4_direction_input, 271 .direction_output = atmel_pio4_direction_output, 272 .get_value = atmel_pio4_get_value, 273 .set_value = atmel_pio4_set_value, 274 .get_function = atmel_pio4_get_function, 275 }; 276 277 static int atmel_pio4_bind(struct udevice *dev) 278 { 279 return dm_scan_fdt_node(dev, gd->fdt_blob, dev->of_offset, false); 280 } 281 282 static int atmel_pio4_probe(struct udevice *dev) 283 { 284 struct atmel_pio4_platdata *plat = dev_get_platdata(dev); 285 struct gpio_dev_priv *uc_priv = dev_get_uclass_priv(dev); 286 struct atmel_pioctrl_data *pioctrl_data; 287 struct clk clk; 288 fdt_addr_t addr_base; 289 u32 nbanks; 290 int ret; 291 292 ret = clk_get_by_index(dev, 0, &clk); 293 if (ret) 294 return ret; 295 296 ret = clk_enable(&clk); 297 if (ret) 298 return ret; 299 300 clk_free(&clk); 301 302 addr_base = dev_get_addr(dev); 303 if (addr_base == FDT_ADDR_T_NONE) 304 return -EINVAL; 305 306 plat->reg_base = (struct atmel_pio4_port *)addr_base; 307 308 pioctrl_data = (struct atmel_pioctrl_data *)dev_get_driver_data(dev); 309 nbanks = pioctrl_data->nbanks; 310 311 uc_priv->bank_name = fdt_get_name(gd->fdt_blob, dev->of_offset, NULL); 312 uc_priv->gpio_count = nbanks * ATMEL_PIO_NPINS_PER_BANK; 313 314 return 0; 315 } 316 317 /* 318 * The number of banks can be different from a SoC to another one. 319 * We can have up to 16 banks. 320 */ 321 static const struct atmel_pioctrl_data atmel_sama5d2_pioctrl_data = { 322 .nbanks = 4, 323 }; 324 325 static const struct udevice_id atmel_pio4_ids[] = { 326 { 327 .compatible = "atmel,sama5d2-gpio", 328 .data = (ulong)&atmel_sama5d2_pioctrl_data, 329 }, 330 {} 331 }; 332 333 U_BOOT_DRIVER(gpio_atmel_pio4) = { 334 .name = "gpio_atmel_pio4", 335 .id = UCLASS_GPIO, 336 .ops = &atmel_pio4_ops, 337 .probe = atmel_pio4_probe, 338 .bind = atmel_pio4_bind, 339 .of_match = atmel_pio4_ids, 340 .platdata_auto_alloc_size = sizeof(struct atmel_pio4_platdata), 341 }; 342 343 #endif 344