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