12c62c56aSWenyou Yang /* 22c62c56aSWenyou Yang * Atmel PIO4 device driver 32c62c56aSWenyou Yang * 42c62c56aSWenyou Yang * Copyright (C) 2015 Atmel Corporation 52c62c56aSWenyou Yang * Wenyou.Yang <wenyou.yang@atmel.com> 62c62c56aSWenyou Yang * 72c62c56aSWenyou Yang * SPDX-License-Identifier: GPL-2.0+ 82c62c56aSWenyou Yang */ 92c62c56aSWenyou Yang #include <common.h> 10ee3311dbSWenyou Yang #include <clk.h> 112c62c56aSWenyou Yang #include <dm.h> 12ee3311dbSWenyou Yang #include <fdtdec.h> 13ee3311dbSWenyou Yang #include <dm/root.h> 142c62c56aSWenyou Yang #include <asm/arch/hardware.h> 15ee3311dbSWenyou Yang #include <asm/gpio.h> 162c62c56aSWenyou Yang #include <mach/gpio.h> 172c62c56aSWenyou Yang #include <mach/atmel_pio4.h> 182c62c56aSWenyou Yang 19ee3311dbSWenyou Yang DECLARE_GLOBAL_DATA_PTR; 20ee3311dbSWenyou Yang 212c62c56aSWenyou Yang static struct atmel_pio4_port *atmel_pio4_port_base(u32 port) 222c62c56aSWenyou Yang { 232c62c56aSWenyou Yang struct atmel_pio4_port *base = NULL; 242c62c56aSWenyou Yang 252c62c56aSWenyou Yang switch (port) { 262c62c56aSWenyou Yang case AT91_PIO_PORTA: 272c62c56aSWenyou Yang base = (struct atmel_pio4_port *)ATMEL_BASE_PIOA; 282c62c56aSWenyou Yang break; 292c62c56aSWenyou Yang case AT91_PIO_PORTB: 302c62c56aSWenyou Yang base = (struct atmel_pio4_port *)ATMEL_BASE_PIOB; 312c62c56aSWenyou Yang break; 322c62c56aSWenyou Yang case AT91_PIO_PORTC: 332c62c56aSWenyou Yang base = (struct atmel_pio4_port *)ATMEL_BASE_PIOC; 342c62c56aSWenyou Yang break; 352c62c56aSWenyou Yang case AT91_PIO_PORTD: 362c62c56aSWenyou Yang base = (struct atmel_pio4_port *)ATMEL_BASE_PIOD; 372c62c56aSWenyou Yang break; 382c62c56aSWenyou Yang default: 392c62c56aSWenyou Yang printf("Error: Atmel PIO4: Failed to get PIO base of port#%d!\n", 402c62c56aSWenyou Yang port); 412c62c56aSWenyou Yang break; 422c62c56aSWenyou Yang } 432c62c56aSWenyou Yang 442c62c56aSWenyou Yang return base; 452c62c56aSWenyou Yang } 462c62c56aSWenyou Yang 472c62c56aSWenyou Yang static int atmel_pio4_config_io_func(u32 port, u32 pin, 482c62c56aSWenyou Yang u32 func, u32 use_pullup) 492c62c56aSWenyou Yang { 502c62c56aSWenyou Yang struct atmel_pio4_port *port_base; 512c62c56aSWenyou Yang u32 reg, mask; 522c62c56aSWenyou Yang 5346ed9381SWenyou Yang if (pin >= ATMEL_PIO_NPINS_PER_BANK) 542c62c56aSWenyou Yang return -ENODEV; 552c62c56aSWenyou Yang 562c62c56aSWenyou Yang port_base = atmel_pio4_port_base(port); 572c62c56aSWenyou Yang if (!port_base) 582c62c56aSWenyou Yang return -ENODEV; 592c62c56aSWenyou Yang 602c62c56aSWenyou Yang mask = 1 << pin; 612c62c56aSWenyou Yang reg = func; 6246ed9381SWenyou Yang reg |= use_pullup ? ATMEL_PIO_PUEN_MASK : 0; 632c62c56aSWenyou Yang 642c62c56aSWenyou Yang writel(mask, &port_base->mskr); 652c62c56aSWenyou Yang writel(reg, &port_base->cfgr); 662c62c56aSWenyou Yang 672c62c56aSWenyou Yang return 0; 682c62c56aSWenyou Yang } 692c62c56aSWenyou Yang 702c62c56aSWenyou Yang int atmel_pio4_set_gpio(u32 port, u32 pin, u32 use_pullup) 712c62c56aSWenyou Yang { 722c62c56aSWenyou Yang return atmel_pio4_config_io_func(port, pin, 7346ed9381SWenyou Yang ATMEL_PIO_CFGR_FUNC_GPIO, 742c62c56aSWenyou Yang use_pullup); 752c62c56aSWenyou Yang } 762c62c56aSWenyou Yang 772c62c56aSWenyou Yang int atmel_pio4_set_a_periph(u32 port, u32 pin, u32 use_pullup) 782c62c56aSWenyou Yang { 792c62c56aSWenyou Yang return atmel_pio4_config_io_func(port, pin, 8046ed9381SWenyou Yang ATMEL_PIO_CFGR_FUNC_PERIPH_A, 812c62c56aSWenyou Yang use_pullup); 822c62c56aSWenyou Yang } 832c62c56aSWenyou Yang 842c62c56aSWenyou Yang int atmel_pio4_set_b_periph(u32 port, u32 pin, u32 use_pullup) 852c62c56aSWenyou Yang { 862c62c56aSWenyou Yang return atmel_pio4_config_io_func(port, pin, 8746ed9381SWenyou Yang ATMEL_PIO_CFGR_FUNC_PERIPH_B, 882c62c56aSWenyou Yang use_pullup); 892c62c56aSWenyou Yang } 902c62c56aSWenyou Yang 912c62c56aSWenyou Yang int atmel_pio4_set_c_periph(u32 port, u32 pin, u32 use_pullup) 922c62c56aSWenyou Yang { 932c62c56aSWenyou Yang return atmel_pio4_config_io_func(port, pin, 9446ed9381SWenyou Yang ATMEL_PIO_CFGR_FUNC_PERIPH_C, 952c62c56aSWenyou Yang use_pullup); 962c62c56aSWenyou Yang } 972c62c56aSWenyou Yang 982c62c56aSWenyou Yang int atmel_pio4_set_d_periph(u32 port, u32 pin, u32 use_pullup) 992c62c56aSWenyou Yang { 1002c62c56aSWenyou Yang return atmel_pio4_config_io_func(port, pin, 10146ed9381SWenyou Yang ATMEL_PIO_CFGR_FUNC_PERIPH_D, 1022c62c56aSWenyou Yang use_pullup); 1032c62c56aSWenyou Yang } 1042c62c56aSWenyou Yang 1052c62c56aSWenyou Yang int atmel_pio4_set_e_periph(u32 port, u32 pin, u32 use_pullup) 1062c62c56aSWenyou Yang { 1072c62c56aSWenyou Yang return atmel_pio4_config_io_func(port, pin, 10846ed9381SWenyou Yang ATMEL_PIO_CFGR_FUNC_PERIPH_E, 1092c62c56aSWenyou Yang use_pullup); 1102c62c56aSWenyou Yang } 1112c62c56aSWenyou Yang 1122c62c56aSWenyou Yang int atmel_pio4_set_f_periph(u32 port, u32 pin, u32 use_pullup) 1132c62c56aSWenyou Yang { 1142c62c56aSWenyou Yang return atmel_pio4_config_io_func(port, pin, 11546ed9381SWenyou Yang ATMEL_PIO_CFGR_FUNC_PERIPH_F, 1162c62c56aSWenyou Yang use_pullup); 1172c62c56aSWenyou Yang } 1182c62c56aSWenyou Yang 1192c62c56aSWenyou Yang int atmel_pio4_set_g_periph(u32 port, u32 pin, u32 use_pullup) 1202c62c56aSWenyou Yang { 1212c62c56aSWenyou Yang return atmel_pio4_config_io_func(port, pin, 12246ed9381SWenyou Yang ATMEL_PIO_CFGR_FUNC_PERIPH_G, 1232c62c56aSWenyou Yang use_pullup); 1242c62c56aSWenyou Yang } 1252c62c56aSWenyou Yang 1262c62c56aSWenyou Yang int atmel_pio4_set_pio_output(u32 port, u32 pin, u32 value) 1272c62c56aSWenyou Yang { 1282c62c56aSWenyou Yang struct atmel_pio4_port *port_base; 1292c62c56aSWenyou Yang u32 reg, mask; 1302c62c56aSWenyou Yang 13146ed9381SWenyou Yang if (pin >= ATMEL_PIO_NPINS_PER_BANK) 1322c62c56aSWenyou Yang return -ENODEV; 1332c62c56aSWenyou Yang 1342c62c56aSWenyou Yang port_base = atmel_pio4_port_base(port); 1352c62c56aSWenyou Yang if (!port_base) 1362c62c56aSWenyou Yang return -ENODEV; 1372c62c56aSWenyou Yang 1382c62c56aSWenyou Yang mask = 0x01 << pin; 13946ed9381SWenyou Yang reg = ATMEL_PIO_CFGR_FUNC_GPIO | ATMEL_PIO_DIR_MASK; 1402c62c56aSWenyou Yang 1412c62c56aSWenyou Yang writel(mask, &port_base->mskr); 1422c62c56aSWenyou Yang writel(reg, &port_base->cfgr); 1432c62c56aSWenyou Yang 1442c62c56aSWenyou Yang if (value) 1452c62c56aSWenyou Yang writel(mask, &port_base->sodr); 1462c62c56aSWenyou Yang else 1472c62c56aSWenyou Yang writel(mask, &port_base->codr); 1482c62c56aSWenyou Yang 1492c62c56aSWenyou Yang return 0; 1502c62c56aSWenyou Yang } 1512c62c56aSWenyou Yang 1522c62c56aSWenyou Yang int atmel_pio4_get_pio_input(u32 port, u32 pin) 1532c62c56aSWenyou Yang { 1542c62c56aSWenyou Yang struct atmel_pio4_port *port_base; 1552c62c56aSWenyou Yang u32 reg, mask; 1562c62c56aSWenyou Yang 15746ed9381SWenyou Yang if (pin >= ATMEL_PIO_NPINS_PER_BANK) 1582c62c56aSWenyou Yang return -ENODEV; 1592c62c56aSWenyou Yang 1602c62c56aSWenyou Yang port_base = atmel_pio4_port_base(port); 1612c62c56aSWenyou Yang if (!port_base) 1622c62c56aSWenyou Yang return -ENODEV; 1632c62c56aSWenyou Yang 1642c62c56aSWenyou Yang mask = 0x01 << pin; 16546ed9381SWenyou Yang reg = ATMEL_PIO_CFGR_FUNC_GPIO; 1662c62c56aSWenyou Yang 1672c62c56aSWenyou Yang writel(mask, &port_base->mskr); 1682c62c56aSWenyou Yang writel(reg, &port_base->cfgr); 1692c62c56aSWenyou Yang 1702c62c56aSWenyou Yang return (readl(&port_base->pdsr) & mask) ? 1 : 0; 1712c62c56aSWenyou Yang } 1722c62c56aSWenyou Yang 1732c62c56aSWenyou Yang #ifdef CONFIG_DM_GPIO 174ee3311dbSWenyou Yang 175ee3311dbSWenyou Yang struct atmel_pioctrl_data { 176ee3311dbSWenyou Yang u32 nbanks; 177ee3311dbSWenyou Yang }; 178ee3311dbSWenyou Yang 179ee3311dbSWenyou Yang struct atmel_pio4_platdata { 180ee3311dbSWenyou Yang struct atmel_pio4_port *reg_base; 181ee3311dbSWenyou Yang }; 182ee3311dbSWenyou Yang 183ee3311dbSWenyou Yang static struct atmel_pio4_port *atmel_pio4_bank_base(struct udevice *dev, 184ee3311dbSWenyou Yang u32 bank) 185ee3311dbSWenyou Yang { 186ee3311dbSWenyou Yang struct atmel_pio4_platdata *plat = dev_get_platdata(dev); 187ee3311dbSWenyou Yang struct atmel_pio4_port *port_base = 188ee3311dbSWenyou Yang (struct atmel_pio4_port *)((u32)plat->reg_base + 189ee3311dbSWenyou Yang ATMEL_PIO_BANK_OFFSET * bank); 190ee3311dbSWenyou Yang 191ee3311dbSWenyou Yang return port_base; 192ee3311dbSWenyou Yang } 193ee3311dbSWenyou Yang 1942c62c56aSWenyou Yang static int atmel_pio4_direction_input(struct udevice *dev, unsigned offset) 1952c62c56aSWenyou Yang { 196ee3311dbSWenyou Yang u32 bank = ATMEL_PIO_BANK(offset); 197ee3311dbSWenyou Yang u32 line = ATMEL_PIO_LINE(offset); 198ee3311dbSWenyou Yang struct atmel_pio4_port *port_base = atmel_pio4_bank_base(dev, bank); 199ee3311dbSWenyou Yang u32 mask = BIT(line); 2002c62c56aSWenyou Yang 2012c62c56aSWenyou Yang writel(mask, &port_base->mskr); 202ee3311dbSWenyou Yang 203ee3311dbSWenyou Yang clrbits_le32(&port_base->cfgr, 204ee3311dbSWenyou Yang ATMEL_PIO_CFGR_FUNC_MASK | ATMEL_PIO_DIR_MASK); 2052c62c56aSWenyou Yang 2062c62c56aSWenyou Yang return 0; 2072c62c56aSWenyou Yang } 2082c62c56aSWenyou Yang 2092c62c56aSWenyou Yang static int atmel_pio4_direction_output(struct udevice *dev, 2102c62c56aSWenyou Yang unsigned offset, int value) 2112c62c56aSWenyou Yang { 212ee3311dbSWenyou Yang u32 bank = ATMEL_PIO_BANK(offset); 213ee3311dbSWenyou Yang u32 line = ATMEL_PIO_LINE(offset); 214ee3311dbSWenyou Yang struct atmel_pio4_port *port_base = atmel_pio4_bank_base(dev, bank); 215ee3311dbSWenyou Yang u32 mask = BIT(line); 2162c62c56aSWenyou Yang 2172c62c56aSWenyou Yang writel(mask, &port_base->mskr); 218ee3311dbSWenyou Yang 219ee3311dbSWenyou Yang clrsetbits_le32(&port_base->cfgr, 220ee3311dbSWenyou Yang ATMEL_PIO_CFGR_FUNC_MASK, ATMEL_PIO_DIR_MASK); 2212c62c56aSWenyou Yang 2222c62c56aSWenyou Yang if (value) 2232c62c56aSWenyou Yang writel(mask, &port_base->sodr); 2242c62c56aSWenyou Yang else 2252c62c56aSWenyou Yang writel(mask, &port_base->codr); 2262c62c56aSWenyou Yang 2272c62c56aSWenyou Yang return 0; 2282c62c56aSWenyou Yang } 2292c62c56aSWenyou Yang 2302c62c56aSWenyou Yang static int atmel_pio4_get_value(struct udevice *dev, unsigned offset) 2312c62c56aSWenyou Yang { 232ee3311dbSWenyou Yang u32 bank = ATMEL_PIO_BANK(offset); 233ee3311dbSWenyou Yang u32 line = ATMEL_PIO_LINE(offset); 234ee3311dbSWenyou Yang struct atmel_pio4_port *port_base = atmel_pio4_bank_base(dev, bank); 235ee3311dbSWenyou Yang u32 mask = BIT(line); 2362c62c56aSWenyou Yang 2372c62c56aSWenyou Yang return (readl(&port_base->pdsr) & mask) ? 1 : 0; 2382c62c56aSWenyou Yang } 2392c62c56aSWenyou Yang 2402c62c56aSWenyou Yang static int atmel_pio4_set_value(struct udevice *dev, 2412c62c56aSWenyou Yang unsigned offset, int value) 2422c62c56aSWenyou Yang { 243ee3311dbSWenyou Yang u32 bank = ATMEL_PIO_BANK(offset); 244ee3311dbSWenyou Yang u32 line = ATMEL_PIO_LINE(offset); 245ee3311dbSWenyou Yang struct atmel_pio4_port *port_base = atmel_pio4_bank_base(dev, bank); 246ee3311dbSWenyou Yang u32 mask = BIT(line); 2472c62c56aSWenyou Yang 2482c62c56aSWenyou Yang if (value) 2492c62c56aSWenyou Yang writel(mask, &port_base->sodr); 2502c62c56aSWenyou Yang else 2512c62c56aSWenyou Yang writel(mask, &port_base->codr); 2522c62c56aSWenyou Yang 2532c62c56aSWenyou Yang return 0; 2542c62c56aSWenyou Yang } 2552c62c56aSWenyou Yang 2562c62c56aSWenyou Yang static int atmel_pio4_get_function(struct udevice *dev, unsigned offset) 2572c62c56aSWenyou Yang { 258ee3311dbSWenyou Yang u32 bank = ATMEL_PIO_BANK(offset); 259ee3311dbSWenyou Yang u32 line = ATMEL_PIO_LINE(offset); 260ee3311dbSWenyou Yang struct atmel_pio4_port *port_base = atmel_pio4_bank_base(dev, bank); 261ee3311dbSWenyou Yang u32 mask = BIT(line); 2622c62c56aSWenyou Yang 2632c62c56aSWenyou Yang writel(mask, &port_base->mskr); 2642c62c56aSWenyou Yang 2652c62c56aSWenyou Yang return (readl(&port_base->cfgr) & 26646ed9381SWenyou Yang ATMEL_PIO_DIR_MASK) ? GPIOF_OUTPUT : GPIOF_INPUT; 2672c62c56aSWenyou Yang } 2682c62c56aSWenyou Yang 2692c62c56aSWenyou Yang static const struct dm_gpio_ops atmel_pio4_ops = { 2702c62c56aSWenyou Yang .direction_input = atmel_pio4_direction_input, 2712c62c56aSWenyou Yang .direction_output = atmel_pio4_direction_output, 2722c62c56aSWenyou Yang .get_value = atmel_pio4_get_value, 2732c62c56aSWenyou Yang .set_value = atmel_pio4_set_value, 2742c62c56aSWenyou Yang .get_function = atmel_pio4_get_function, 2752c62c56aSWenyou Yang }; 2762c62c56aSWenyou Yang 277ee3311dbSWenyou Yang static int atmel_pio4_bind(struct udevice *dev) 278ee3311dbSWenyou Yang { 279e160f7d4SSimon Glass return dm_scan_fdt_node(dev, gd->fdt_blob, dev_of_offset(dev), false); 280ee3311dbSWenyou Yang } 281ee3311dbSWenyou Yang 2822c62c56aSWenyou Yang static int atmel_pio4_probe(struct udevice *dev) 2832c62c56aSWenyou Yang { 284ee3311dbSWenyou Yang struct atmel_pio4_platdata *plat = dev_get_platdata(dev); 2852c62c56aSWenyou Yang struct gpio_dev_priv *uc_priv = dev_get_uclass_priv(dev); 286ee3311dbSWenyou Yang struct atmel_pioctrl_data *pioctrl_data; 287ee3311dbSWenyou Yang struct clk clk; 288ee3311dbSWenyou Yang fdt_addr_t addr_base; 289ee3311dbSWenyou Yang u32 nbanks; 290ee3311dbSWenyou Yang int ret; 2912c62c56aSWenyou Yang 292ee3311dbSWenyou Yang ret = clk_get_by_index(dev, 0, &clk); 293ee3311dbSWenyou Yang if (ret) 294ee3311dbSWenyou Yang return ret; 295ee3311dbSWenyou Yang 296ee3311dbSWenyou Yang ret = clk_enable(&clk); 297ee3311dbSWenyou Yang if (ret) 298ee3311dbSWenyou Yang return ret; 299ee3311dbSWenyou Yang 300ee3311dbSWenyou Yang clk_free(&clk); 301ee3311dbSWenyou Yang 302*a821c4afSSimon Glass addr_base = devfdt_get_addr(dev); 303ee3311dbSWenyou Yang if (addr_base == FDT_ADDR_T_NONE) 304ee3311dbSWenyou Yang return -EINVAL; 305ee3311dbSWenyou Yang 306ee3311dbSWenyou Yang plat->reg_base = (struct atmel_pio4_port *)addr_base; 307ee3311dbSWenyou Yang 308ee3311dbSWenyou Yang pioctrl_data = (struct atmel_pioctrl_data *)dev_get_driver_data(dev); 309ee3311dbSWenyou Yang nbanks = pioctrl_data->nbanks; 310ee3311dbSWenyou Yang 311e160f7d4SSimon Glass uc_priv->bank_name = fdt_get_name(gd->fdt_blob, dev_of_offset(dev), 312e160f7d4SSimon Glass NULL); 313ee3311dbSWenyou Yang uc_priv->gpio_count = nbanks * ATMEL_PIO_NPINS_PER_BANK; 3142c62c56aSWenyou Yang 3152c62c56aSWenyou Yang return 0; 3162c62c56aSWenyou Yang } 3172c62c56aSWenyou Yang 318ee3311dbSWenyou Yang /* 319ee3311dbSWenyou Yang * The number of banks can be different from a SoC to another one. 320ee3311dbSWenyou Yang * We can have up to 16 banks. 321ee3311dbSWenyou Yang */ 322ee3311dbSWenyou Yang static const struct atmel_pioctrl_data atmel_sama5d2_pioctrl_data = { 323ee3311dbSWenyou Yang .nbanks = 4, 324ee3311dbSWenyou Yang }; 325ee3311dbSWenyou Yang 326ee3311dbSWenyou Yang static const struct udevice_id atmel_pio4_ids[] = { 327ee3311dbSWenyou Yang { 328ee3311dbSWenyou Yang .compatible = "atmel,sama5d2-gpio", 329ee3311dbSWenyou Yang .data = (ulong)&atmel_sama5d2_pioctrl_data, 330ee3311dbSWenyou Yang }, 331ee3311dbSWenyou Yang {} 332ee3311dbSWenyou Yang }; 333ee3311dbSWenyou Yang 3342c62c56aSWenyou Yang U_BOOT_DRIVER(gpio_atmel_pio4) = { 3352c62c56aSWenyou Yang .name = "gpio_atmel_pio4", 3362c62c56aSWenyou Yang .id = UCLASS_GPIO, 3372c62c56aSWenyou Yang .ops = &atmel_pio4_ops, 3382c62c56aSWenyou Yang .probe = atmel_pio4_probe, 339ee3311dbSWenyou Yang .bind = atmel_pio4_bind, 340ee3311dbSWenyou Yang .of_match = atmel_pio4_ids, 341ee3311dbSWenyou Yang .platdata_auto_alloc_size = sizeof(struct atmel_pio4_platdata), 3422c62c56aSWenyou Yang }; 343ee3311dbSWenyou Yang 3442c62c56aSWenyou Yang #endif 345