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