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> 10*ee3311dbSWenyou Yang #include <clk.h> 112c62c56aSWenyou Yang #include <dm.h> 12*ee3311dbSWenyou Yang #include <fdtdec.h> 13*ee3311dbSWenyou Yang #include <dm/root.h> 142c62c56aSWenyou Yang #include <asm/arch/hardware.h> 15*ee3311dbSWenyou Yang #include <asm/gpio.h> 162c62c56aSWenyou Yang #include <mach/gpio.h> 172c62c56aSWenyou Yang #include <mach/atmel_pio4.h> 182c62c56aSWenyou Yang 19*ee3311dbSWenyou Yang DECLARE_GLOBAL_DATA_PTR; 20*ee3311dbSWenyou 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 174*ee3311dbSWenyou Yang 175*ee3311dbSWenyou Yang struct atmel_pioctrl_data { 176*ee3311dbSWenyou Yang u32 nbanks; 177*ee3311dbSWenyou Yang }; 178*ee3311dbSWenyou Yang 179*ee3311dbSWenyou Yang struct atmel_pio4_platdata { 180*ee3311dbSWenyou Yang struct atmel_pio4_port *reg_base; 181*ee3311dbSWenyou Yang }; 182*ee3311dbSWenyou Yang 183*ee3311dbSWenyou Yang static struct atmel_pio4_port *atmel_pio4_bank_base(struct udevice *dev, 184*ee3311dbSWenyou Yang u32 bank) 185*ee3311dbSWenyou Yang { 186*ee3311dbSWenyou Yang struct atmel_pio4_platdata *plat = dev_get_platdata(dev); 187*ee3311dbSWenyou Yang struct atmel_pio4_port *port_base = 188*ee3311dbSWenyou Yang (struct atmel_pio4_port *)((u32)plat->reg_base + 189*ee3311dbSWenyou Yang ATMEL_PIO_BANK_OFFSET * bank); 190*ee3311dbSWenyou Yang 191*ee3311dbSWenyou Yang return port_base; 192*ee3311dbSWenyou Yang } 193*ee3311dbSWenyou Yang 1942c62c56aSWenyou Yang static int atmel_pio4_direction_input(struct udevice *dev, unsigned offset) 1952c62c56aSWenyou Yang { 196*ee3311dbSWenyou Yang u32 bank = ATMEL_PIO_BANK(offset); 197*ee3311dbSWenyou Yang u32 line = ATMEL_PIO_LINE(offset); 198*ee3311dbSWenyou Yang struct atmel_pio4_port *port_base = atmel_pio4_bank_base(dev, bank); 199*ee3311dbSWenyou Yang u32 mask = BIT(line); 2002c62c56aSWenyou Yang 2012c62c56aSWenyou Yang writel(mask, &port_base->mskr); 202*ee3311dbSWenyou Yang 203*ee3311dbSWenyou Yang clrbits_le32(&port_base->cfgr, 204*ee3311dbSWenyou 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 { 212*ee3311dbSWenyou Yang u32 bank = ATMEL_PIO_BANK(offset); 213*ee3311dbSWenyou Yang u32 line = ATMEL_PIO_LINE(offset); 214*ee3311dbSWenyou Yang struct atmel_pio4_port *port_base = atmel_pio4_bank_base(dev, bank); 215*ee3311dbSWenyou Yang u32 mask = BIT(line); 2162c62c56aSWenyou Yang 2172c62c56aSWenyou Yang writel(mask, &port_base->mskr); 218*ee3311dbSWenyou Yang 219*ee3311dbSWenyou Yang clrsetbits_le32(&port_base->cfgr, 220*ee3311dbSWenyou 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 { 232*ee3311dbSWenyou Yang u32 bank = ATMEL_PIO_BANK(offset); 233*ee3311dbSWenyou Yang u32 line = ATMEL_PIO_LINE(offset); 234*ee3311dbSWenyou Yang struct atmel_pio4_port *port_base = atmel_pio4_bank_base(dev, bank); 235*ee3311dbSWenyou 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 { 243*ee3311dbSWenyou Yang u32 bank = ATMEL_PIO_BANK(offset); 244*ee3311dbSWenyou Yang u32 line = ATMEL_PIO_LINE(offset); 245*ee3311dbSWenyou Yang struct atmel_pio4_port *port_base = atmel_pio4_bank_base(dev, bank); 246*ee3311dbSWenyou 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 { 258*ee3311dbSWenyou Yang u32 bank = ATMEL_PIO_BANK(offset); 259*ee3311dbSWenyou Yang u32 line = ATMEL_PIO_LINE(offset); 260*ee3311dbSWenyou Yang struct atmel_pio4_port *port_base = atmel_pio4_bank_base(dev, bank); 261*ee3311dbSWenyou 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 277*ee3311dbSWenyou Yang static int atmel_pio4_bind(struct udevice *dev) 278*ee3311dbSWenyou Yang { 279*ee3311dbSWenyou Yang return dm_scan_fdt_node(dev, gd->fdt_blob, dev->of_offset, false); 280*ee3311dbSWenyou Yang } 281*ee3311dbSWenyou Yang 2822c62c56aSWenyou Yang static int atmel_pio4_probe(struct udevice *dev) 2832c62c56aSWenyou Yang { 284*ee3311dbSWenyou Yang struct atmel_pio4_platdata *plat = dev_get_platdata(dev); 2852c62c56aSWenyou Yang struct gpio_dev_priv *uc_priv = dev_get_uclass_priv(dev); 286*ee3311dbSWenyou Yang struct atmel_pioctrl_data *pioctrl_data; 287*ee3311dbSWenyou Yang struct udevice *dev_clk; 288*ee3311dbSWenyou Yang struct clk clk; 289*ee3311dbSWenyou Yang fdt_addr_t addr_base; 290*ee3311dbSWenyou Yang u32 nbanks; 291*ee3311dbSWenyou Yang int periph; 292*ee3311dbSWenyou Yang int ret; 2932c62c56aSWenyou Yang 294*ee3311dbSWenyou Yang ret = clk_get_by_index(dev, 0, &clk); 295*ee3311dbSWenyou Yang if (ret) 296*ee3311dbSWenyou Yang return ret; 297*ee3311dbSWenyou Yang 298*ee3311dbSWenyou Yang periph = fdtdec_get_uint(gd->fdt_blob, clk.dev->of_offset, "reg", -1); 299*ee3311dbSWenyou Yang if (periph < 0) 300*ee3311dbSWenyou Yang return -EINVAL; 301*ee3311dbSWenyou Yang 302*ee3311dbSWenyou Yang dev_clk = dev_get_parent(clk.dev); 303*ee3311dbSWenyou Yang ret = clk_request(dev_clk, &clk); 304*ee3311dbSWenyou Yang if (ret) 305*ee3311dbSWenyou Yang return ret; 306*ee3311dbSWenyou Yang 307*ee3311dbSWenyou Yang clk.id = periph; 308*ee3311dbSWenyou Yang ret = clk_enable(&clk); 309*ee3311dbSWenyou Yang if (ret) 310*ee3311dbSWenyou Yang return ret; 311*ee3311dbSWenyou Yang 312*ee3311dbSWenyou Yang clk_free(&clk); 313*ee3311dbSWenyou Yang 314*ee3311dbSWenyou Yang addr_base = dev_get_addr(dev); 315*ee3311dbSWenyou Yang if (addr_base == FDT_ADDR_T_NONE) 316*ee3311dbSWenyou Yang return -EINVAL; 317*ee3311dbSWenyou Yang 318*ee3311dbSWenyou Yang plat->reg_base = (struct atmel_pio4_port *)addr_base; 319*ee3311dbSWenyou Yang 320*ee3311dbSWenyou Yang pioctrl_data = (struct atmel_pioctrl_data *)dev_get_driver_data(dev); 321*ee3311dbSWenyou Yang nbanks = pioctrl_data->nbanks; 322*ee3311dbSWenyou Yang 323*ee3311dbSWenyou Yang uc_priv->bank_name = fdt_get_name(gd->fdt_blob, dev->of_offset, NULL); 324*ee3311dbSWenyou Yang uc_priv->gpio_count = nbanks * ATMEL_PIO_NPINS_PER_BANK; 3252c62c56aSWenyou Yang 3262c62c56aSWenyou Yang return 0; 3272c62c56aSWenyou Yang } 3282c62c56aSWenyou Yang 329*ee3311dbSWenyou Yang /* 330*ee3311dbSWenyou Yang * The number of banks can be different from a SoC to another one. 331*ee3311dbSWenyou Yang * We can have up to 16 banks. 332*ee3311dbSWenyou Yang */ 333*ee3311dbSWenyou Yang static const struct atmel_pioctrl_data atmel_sama5d2_pioctrl_data = { 334*ee3311dbSWenyou Yang .nbanks = 4, 335*ee3311dbSWenyou Yang }; 336*ee3311dbSWenyou Yang 337*ee3311dbSWenyou Yang static const struct udevice_id atmel_pio4_ids[] = { 338*ee3311dbSWenyou Yang { 339*ee3311dbSWenyou Yang .compatible = "atmel,sama5d2-gpio", 340*ee3311dbSWenyou Yang .data = (ulong)&atmel_sama5d2_pioctrl_data, 341*ee3311dbSWenyou Yang }, 342*ee3311dbSWenyou Yang {} 343*ee3311dbSWenyou Yang }; 344*ee3311dbSWenyou Yang 3452c62c56aSWenyou Yang U_BOOT_DRIVER(gpio_atmel_pio4) = { 3462c62c56aSWenyou Yang .name = "gpio_atmel_pio4", 3472c62c56aSWenyou Yang .id = UCLASS_GPIO, 3482c62c56aSWenyou Yang .ops = &atmel_pio4_ops, 3492c62c56aSWenyou Yang .probe = atmel_pio4_probe, 350*ee3311dbSWenyou Yang .bind = atmel_pio4_bind, 351*ee3311dbSWenyou Yang .of_match = atmel_pio4_ids, 352*ee3311dbSWenyou Yang .platdata_auto_alloc_size = sizeof(struct atmel_pio4_platdata), 3532c62c56aSWenyou Yang }; 354*ee3311dbSWenyou Yang 3552c62c56aSWenyou Yang #endif 356