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> 102c62c56aSWenyou Yang #include <dm.h> 112c62c56aSWenyou Yang #include <asm/arch/hardware.h> 122c62c56aSWenyou Yang #include <mach/gpio.h> 132c62c56aSWenyou Yang #include <mach/atmel_pio4.h> 142c62c56aSWenyou Yang 152c62c56aSWenyou Yang static struct atmel_pio4_port *atmel_pio4_port_base(u32 port) 162c62c56aSWenyou Yang { 172c62c56aSWenyou Yang struct atmel_pio4_port *base = NULL; 182c62c56aSWenyou Yang 192c62c56aSWenyou Yang switch (port) { 202c62c56aSWenyou Yang case AT91_PIO_PORTA: 212c62c56aSWenyou Yang base = (struct atmel_pio4_port *)ATMEL_BASE_PIOA; 222c62c56aSWenyou Yang break; 232c62c56aSWenyou Yang case AT91_PIO_PORTB: 242c62c56aSWenyou Yang base = (struct atmel_pio4_port *)ATMEL_BASE_PIOB; 252c62c56aSWenyou Yang break; 262c62c56aSWenyou Yang case AT91_PIO_PORTC: 272c62c56aSWenyou Yang base = (struct atmel_pio4_port *)ATMEL_BASE_PIOC; 282c62c56aSWenyou Yang break; 292c62c56aSWenyou Yang case AT91_PIO_PORTD: 302c62c56aSWenyou Yang base = (struct atmel_pio4_port *)ATMEL_BASE_PIOD; 312c62c56aSWenyou Yang break; 322c62c56aSWenyou Yang default: 332c62c56aSWenyou Yang printf("Error: Atmel PIO4: Failed to get PIO base of port#%d!\n", 342c62c56aSWenyou Yang port); 352c62c56aSWenyou Yang break; 362c62c56aSWenyou Yang } 372c62c56aSWenyou Yang 382c62c56aSWenyou Yang return base; 392c62c56aSWenyou Yang } 402c62c56aSWenyou Yang 412c62c56aSWenyou Yang static int atmel_pio4_config_io_func(u32 port, u32 pin, 422c62c56aSWenyou Yang u32 func, u32 use_pullup) 432c62c56aSWenyou Yang { 442c62c56aSWenyou Yang struct atmel_pio4_port *port_base; 452c62c56aSWenyou Yang u32 reg, mask; 462c62c56aSWenyou Yang 47*46ed9381SWenyou Yang if (pin >= ATMEL_PIO_NPINS_PER_BANK) 482c62c56aSWenyou Yang return -ENODEV; 492c62c56aSWenyou Yang 502c62c56aSWenyou Yang port_base = atmel_pio4_port_base(port); 512c62c56aSWenyou Yang if (!port_base) 522c62c56aSWenyou Yang return -ENODEV; 532c62c56aSWenyou Yang 542c62c56aSWenyou Yang mask = 1 << pin; 552c62c56aSWenyou Yang reg = func; 56*46ed9381SWenyou Yang reg |= use_pullup ? ATMEL_PIO_PUEN_MASK : 0; 572c62c56aSWenyou Yang 582c62c56aSWenyou Yang writel(mask, &port_base->mskr); 592c62c56aSWenyou Yang writel(reg, &port_base->cfgr); 602c62c56aSWenyou Yang 612c62c56aSWenyou Yang return 0; 622c62c56aSWenyou Yang } 632c62c56aSWenyou Yang 642c62c56aSWenyou Yang int atmel_pio4_set_gpio(u32 port, u32 pin, u32 use_pullup) 652c62c56aSWenyou Yang { 662c62c56aSWenyou Yang return atmel_pio4_config_io_func(port, pin, 67*46ed9381SWenyou Yang ATMEL_PIO_CFGR_FUNC_GPIO, 682c62c56aSWenyou Yang use_pullup); 692c62c56aSWenyou Yang } 702c62c56aSWenyou Yang 712c62c56aSWenyou Yang int atmel_pio4_set_a_periph(u32 port, u32 pin, u32 use_pullup) 722c62c56aSWenyou Yang { 732c62c56aSWenyou Yang return atmel_pio4_config_io_func(port, pin, 74*46ed9381SWenyou Yang ATMEL_PIO_CFGR_FUNC_PERIPH_A, 752c62c56aSWenyou Yang use_pullup); 762c62c56aSWenyou Yang } 772c62c56aSWenyou Yang 782c62c56aSWenyou Yang int atmel_pio4_set_b_periph(u32 port, u32 pin, u32 use_pullup) 792c62c56aSWenyou Yang { 802c62c56aSWenyou Yang return atmel_pio4_config_io_func(port, pin, 81*46ed9381SWenyou Yang ATMEL_PIO_CFGR_FUNC_PERIPH_B, 822c62c56aSWenyou Yang use_pullup); 832c62c56aSWenyou Yang } 842c62c56aSWenyou Yang 852c62c56aSWenyou Yang int atmel_pio4_set_c_periph(u32 port, u32 pin, u32 use_pullup) 862c62c56aSWenyou Yang { 872c62c56aSWenyou Yang return atmel_pio4_config_io_func(port, pin, 88*46ed9381SWenyou Yang ATMEL_PIO_CFGR_FUNC_PERIPH_C, 892c62c56aSWenyou Yang use_pullup); 902c62c56aSWenyou Yang } 912c62c56aSWenyou Yang 922c62c56aSWenyou Yang int atmel_pio4_set_d_periph(u32 port, u32 pin, u32 use_pullup) 932c62c56aSWenyou Yang { 942c62c56aSWenyou Yang return atmel_pio4_config_io_func(port, pin, 95*46ed9381SWenyou Yang ATMEL_PIO_CFGR_FUNC_PERIPH_D, 962c62c56aSWenyou Yang use_pullup); 972c62c56aSWenyou Yang } 982c62c56aSWenyou Yang 992c62c56aSWenyou Yang int atmel_pio4_set_e_periph(u32 port, u32 pin, u32 use_pullup) 1002c62c56aSWenyou Yang { 1012c62c56aSWenyou Yang return atmel_pio4_config_io_func(port, pin, 102*46ed9381SWenyou Yang ATMEL_PIO_CFGR_FUNC_PERIPH_E, 1032c62c56aSWenyou Yang use_pullup); 1042c62c56aSWenyou Yang } 1052c62c56aSWenyou Yang 1062c62c56aSWenyou Yang int atmel_pio4_set_f_periph(u32 port, u32 pin, u32 use_pullup) 1072c62c56aSWenyou Yang { 1082c62c56aSWenyou Yang return atmel_pio4_config_io_func(port, pin, 109*46ed9381SWenyou Yang ATMEL_PIO_CFGR_FUNC_PERIPH_F, 1102c62c56aSWenyou Yang use_pullup); 1112c62c56aSWenyou Yang } 1122c62c56aSWenyou Yang 1132c62c56aSWenyou Yang int atmel_pio4_set_g_periph(u32 port, u32 pin, u32 use_pullup) 1142c62c56aSWenyou Yang { 1152c62c56aSWenyou Yang return atmel_pio4_config_io_func(port, pin, 116*46ed9381SWenyou Yang ATMEL_PIO_CFGR_FUNC_PERIPH_G, 1172c62c56aSWenyou Yang use_pullup); 1182c62c56aSWenyou Yang } 1192c62c56aSWenyou Yang 1202c62c56aSWenyou Yang int atmel_pio4_set_pio_output(u32 port, u32 pin, u32 value) 1212c62c56aSWenyou Yang { 1222c62c56aSWenyou Yang struct atmel_pio4_port *port_base; 1232c62c56aSWenyou Yang u32 reg, mask; 1242c62c56aSWenyou Yang 125*46ed9381SWenyou Yang if (pin >= ATMEL_PIO_NPINS_PER_BANK) 1262c62c56aSWenyou Yang return -ENODEV; 1272c62c56aSWenyou Yang 1282c62c56aSWenyou Yang port_base = atmel_pio4_port_base(port); 1292c62c56aSWenyou Yang if (!port_base) 1302c62c56aSWenyou Yang return -ENODEV; 1312c62c56aSWenyou Yang 1322c62c56aSWenyou Yang mask = 0x01 << pin; 133*46ed9381SWenyou Yang reg = ATMEL_PIO_CFGR_FUNC_GPIO | ATMEL_PIO_DIR_MASK; 1342c62c56aSWenyou Yang 1352c62c56aSWenyou Yang writel(mask, &port_base->mskr); 1362c62c56aSWenyou Yang writel(reg, &port_base->cfgr); 1372c62c56aSWenyou Yang 1382c62c56aSWenyou Yang if (value) 1392c62c56aSWenyou Yang writel(mask, &port_base->sodr); 1402c62c56aSWenyou Yang else 1412c62c56aSWenyou Yang writel(mask, &port_base->codr); 1422c62c56aSWenyou Yang 1432c62c56aSWenyou Yang return 0; 1442c62c56aSWenyou Yang } 1452c62c56aSWenyou Yang 1462c62c56aSWenyou Yang int atmel_pio4_get_pio_input(u32 port, u32 pin) 1472c62c56aSWenyou Yang { 1482c62c56aSWenyou Yang struct atmel_pio4_port *port_base; 1492c62c56aSWenyou Yang u32 reg, mask; 1502c62c56aSWenyou Yang 151*46ed9381SWenyou Yang if (pin >= ATMEL_PIO_NPINS_PER_BANK) 1522c62c56aSWenyou Yang return -ENODEV; 1532c62c56aSWenyou Yang 1542c62c56aSWenyou Yang port_base = atmel_pio4_port_base(port); 1552c62c56aSWenyou Yang if (!port_base) 1562c62c56aSWenyou Yang return -ENODEV; 1572c62c56aSWenyou Yang 1582c62c56aSWenyou Yang mask = 0x01 << pin; 159*46ed9381SWenyou Yang reg = ATMEL_PIO_CFGR_FUNC_GPIO; 1602c62c56aSWenyou Yang 1612c62c56aSWenyou Yang writel(mask, &port_base->mskr); 1622c62c56aSWenyou Yang writel(reg, &port_base->cfgr); 1632c62c56aSWenyou Yang 1642c62c56aSWenyou Yang return (readl(&port_base->pdsr) & mask) ? 1 : 0; 1652c62c56aSWenyou Yang } 1662c62c56aSWenyou Yang 1672c62c56aSWenyou Yang #ifdef CONFIG_DM_GPIO 1682c62c56aSWenyou Yang static int atmel_pio4_direction_input(struct udevice *dev, unsigned offset) 1692c62c56aSWenyou Yang { 1702c62c56aSWenyou Yang struct at91_port_platdata *plat = dev_get_platdata(dev); 1712c62c56aSWenyou Yang struct atmel_pio4_port *port_base = (atmel_pio4_port *)plat->base_addr; 1722c62c56aSWenyou Yang u32 mask = 0x01 << offset; 173*46ed9381SWenyou Yang u32 reg = ATMEL_PIO_CFGR_FUNC_GPIO; 1742c62c56aSWenyou Yang 1752c62c56aSWenyou Yang writel(mask, &port_base->mskr); 1762c62c56aSWenyou Yang writel(reg, &port_base->cfgr); 1772c62c56aSWenyou Yang 1782c62c56aSWenyou Yang return 0; 1792c62c56aSWenyou Yang } 1802c62c56aSWenyou Yang 1812c62c56aSWenyou Yang static int atmel_pio4_direction_output(struct udevice *dev, 1822c62c56aSWenyou Yang unsigned offset, int value) 1832c62c56aSWenyou Yang { 1842c62c56aSWenyou Yang struct at91_port_platdata *plat = dev_get_platdata(dev); 1852c62c56aSWenyou Yang struct atmel_pio4_port *port_base = (atmel_pio4_port *)plat->base_addr; 1862c62c56aSWenyou Yang u32 mask = 0x01 << offset; 187*46ed9381SWenyou Yang u32 reg = ATMEL_PIO_CFGR_FUNC_GPIO | ATMEL_PIO_DIR_MASK; 1882c62c56aSWenyou Yang 1892c62c56aSWenyou Yang writel(mask, &port_base->mskr); 1902c62c56aSWenyou Yang writel(reg, &port_base->cfgr); 1912c62c56aSWenyou Yang 1922c62c56aSWenyou Yang if (value) 1932c62c56aSWenyou Yang writel(mask, &port_base->sodr); 1942c62c56aSWenyou Yang else 1952c62c56aSWenyou Yang writel(mask, &port_base->codr); 1962c62c56aSWenyou Yang 1972c62c56aSWenyou Yang return 0; 1982c62c56aSWenyou Yang } 1992c62c56aSWenyou Yang 2002c62c56aSWenyou Yang static int atmel_pio4_get_value(struct udevice *dev, unsigned offset) 2012c62c56aSWenyou Yang { 2022c62c56aSWenyou Yang struct at91_port_platdata *plat = dev_get_platdata(dev); 2032c62c56aSWenyou Yang struct atmel_pio4_port *port_base = (atmel_pio4_port *)plat->base_addr; 2042c62c56aSWenyou Yang u32 mask = 0x01 << offset; 2052c62c56aSWenyou Yang 2062c62c56aSWenyou Yang return (readl(&port_base->pdsr) & mask) ? 1 : 0; 2072c62c56aSWenyou Yang } 2082c62c56aSWenyou Yang 2092c62c56aSWenyou Yang static int atmel_pio4_set_value(struct udevice *dev, 2102c62c56aSWenyou Yang unsigned offset, int value) 2112c62c56aSWenyou Yang { 2122c62c56aSWenyou Yang struct at91_port_platdata *plat = dev_get_platdata(dev); 2132c62c56aSWenyou Yang struct atmel_pio4_port *port_base = (atmel_pio4_port *)plat->base_addr; 2142c62c56aSWenyou Yang u32 mask = 0x01 << offset; 2152c62c56aSWenyou Yang 2162c62c56aSWenyou Yang if (value) 2172c62c56aSWenyou Yang writel(mask, &port_base->sodr); 2182c62c56aSWenyou Yang else 2192c62c56aSWenyou Yang writel(mask, &port_base->codr); 2202c62c56aSWenyou Yang 2212c62c56aSWenyou Yang return 0; 2222c62c56aSWenyou Yang } 2232c62c56aSWenyou Yang 2242c62c56aSWenyou Yang static int atmel_pio4_get_function(struct udevice *dev, unsigned offset) 2252c62c56aSWenyou Yang { 2262c62c56aSWenyou Yang struct at91_port_platdata *plat = dev_get_platdata(dev); 2272c62c56aSWenyou Yang struct atmel_pio4_port *port_base = (atmel_pio4_port *)plat->base_addr; 2282c62c56aSWenyou Yang u32 mask = 0x01 << offset; 2292c62c56aSWenyou Yang 2302c62c56aSWenyou Yang writel(mask, &port_base->mskr); 2312c62c56aSWenyou Yang 2322c62c56aSWenyou Yang return (readl(&port_base->cfgr) & 233*46ed9381SWenyou Yang ATMEL_PIO_DIR_MASK) ? GPIOF_OUTPUT : GPIOF_INPUT; 2342c62c56aSWenyou Yang } 2352c62c56aSWenyou Yang 2362c62c56aSWenyou Yang static const struct dm_gpio_ops atmel_pio4_ops = { 2372c62c56aSWenyou Yang .direction_input = atmel_pio4_direction_input, 2382c62c56aSWenyou Yang .direction_output = atmel_pio4_direction_output, 2392c62c56aSWenyou Yang .get_value = atmel_pio4_get_value, 2402c62c56aSWenyou Yang .set_value = atmel_pio4_set_value, 2412c62c56aSWenyou Yang .get_function = atmel_pio4_get_function, 2422c62c56aSWenyou Yang }; 2432c62c56aSWenyou Yang 2442c62c56aSWenyou Yang static int atmel_pio4_probe(struct udevice *dev) 2452c62c56aSWenyou Yang { 2462c62c56aSWenyou Yang struct at91_port_platdata *plat = dev_get_platdata(dev); 2472c62c56aSWenyou Yang struct gpio_dev_priv *uc_priv = dev_get_uclass_priv(dev); 2482c62c56aSWenyou Yang 2492c62c56aSWenyou Yang uc_priv->bank_name = plat->bank_name; 250*46ed9381SWenyou Yang uc_priv->gpio_count = ATMEL_PIO_NPINS_PER_BANK; 2512c62c56aSWenyou Yang 2522c62c56aSWenyou Yang return 0; 2532c62c56aSWenyou Yang } 2542c62c56aSWenyou Yang 2552c62c56aSWenyou Yang U_BOOT_DRIVER(gpio_atmel_pio4) = { 2562c62c56aSWenyou Yang .name = "gpio_atmel_pio4", 2572c62c56aSWenyou Yang .id = UCLASS_GPIO, 2582c62c56aSWenyou Yang .ops = &atmel_pio4_ops, 2592c62c56aSWenyou Yang .probe = atmel_pio4_probe, 2602c62c56aSWenyou Yang }; 2612c62c56aSWenyou Yang #endif 262