19c92ab61SThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only 277618084SLudovic Desroches /* 377618084SLudovic Desroches * Driver for the Atmel PIO4 controller 477618084SLudovic Desroches * 577618084SLudovic Desroches * Copyright (C) 2015 Atmel, 677618084SLudovic Desroches * 2015 Ludovic Desroches <ludovic.desroches@atmel.com> 777618084SLudovic Desroches */ 877618084SLudovic Desroches 9ff10e353SLudovic Desroches #include <dt-bindings/pinctrl/at91.h> 1077618084SLudovic Desroches #include <linux/clk.h> 1180036f88SLinus Walleij #include <linux/gpio/driver.h> 12de4e882fSLudovic Desroches #include <linux/interrupt.h> 1377618084SLudovic Desroches #include <linux/io.h> 14f703851aSPaul Gortmaker #include <linux/init.h> 1577618084SLudovic Desroches #include <linux/of.h> 1677618084SLudovic Desroches #include <linux/platform_device.h> 1777618084SLudovic Desroches #include <linux/pinctrl/pinconf.h> 1877618084SLudovic Desroches #include <linux/pinctrl/pinconf-generic.h> 1977618084SLudovic Desroches #include <linux/pinctrl/pinctrl.h> 2077618084SLudovic Desroches #include <linux/pinctrl/pinmux.h> 2177618084SLudovic Desroches #include <linux/slab.h> 2277618084SLudovic Desroches #include "core.h" 2377618084SLudovic Desroches #include "pinconf.h" 2477618084SLudovic Desroches #include "pinctrl-utils.h" 2577618084SLudovic Desroches 2677618084SLudovic Desroches /* 2777618084SLudovic Desroches * Warning: 2877618084SLudovic Desroches * In order to not introduce confusion between Atmel PIO groups and pinctrl 2977618084SLudovic Desroches * framework groups, Atmel PIO groups will be called banks, line is kept to 3077618084SLudovic Desroches * designed the pin id into this bank. 3177618084SLudovic Desroches */ 3277618084SLudovic Desroches 3377618084SLudovic Desroches #define ATMEL_PIO_MSKR 0x0000 3477618084SLudovic Desroches #define ATMEL_PIO_CFGR 0x0004 3577618084SLudovic Desroches #define ATMEL_PIO_CFGR_FUNC_MASK GENMASK(2, 0) 3677618084SLudovic Desroches #define ATMEL_PIO_DIR_MASK BIT(8) 3777618084SLudovic Desroches #define ATMEL_PIO_PUEN_MASK BIT(9) 3877618084SLudovic Desroches #define ATMEL_PIO_PDEN_MASK BIT(10) 3977618084SLudovic Desroches #define ATMEL_PIO_IFEN_MASK BIT(12) 4077618084SLudovic Desroches #define ATMEL_PIO_IFSCEN_MASK BIT(13) 4177618084SLudovic Desroches #define ATMEL_PIO_OPD_MASK BIT(14) 4277618084SLudovic Desroches #define ATMEL_PIO_SCHMITT_MASK BIT(15) 43ff10e353SLudovic Desroches #define ATMEL_PIO_DRVSTR_MASK GENMASK(17, 16) 44ff10e353SLudovic Desroches #define ATMEL_PIO_DRVSTR_OFFSET 16 4577618084SLudovic Desroches #define ATMEL_PIO_CFGR_EVTSEL_MASK GENMASK(26, 24) 4677618084SLudovic Desroches #define ATMEL_PIO_CFGR_EVTSEL_FALLING (0 << 24) 4777618084SLudovic Desroches #define ATMEL_PIO_CFGR_EVTSEL_RISING (1 << 24) 4877618084SLudovic Desroches #define ATMEL_PIO_CFGR_EVTSEL_BOTH (2 << 24) 4977618084SLudovic Desroches #define ATMEL_PIO_CFGR_EVTSEL_LOW (3 << 24) 5077618084SLudovic Desroches #define ATMEL_PIO_CFGR_EVTSEL_HIGH (4 << 24) 5177618084SLudovic Desroches #define ATMEL_PIO_PDSR 0x0008 5277618084SLudovic Desroches #define ATMEL_PIO_LOCKSR 0x000C 5377618084SLudovic Desroches #define ATMEL_PIO_SODR 0x0010 5477618084SLudovic Desroches #define ATMEL_PIO_CODR 0x0014 5577618084SLudovic Desroches #define ATMEL_PIO_ODSR 0x0018 5677618084SLudovic Desroches #define ATMEL_PIO_IER 0x0020 5777618084SLudovic Desroches #define ATMEL_PIO_IDR 0x0024 5877618084SLudovic Desroches #define ATMEL_PIO_IMR 0x0028 5977618084SLudovic Desroches #define ATMEL_PIO_ISR 0x002C 6077618084SLudovic Desroches #define ATMEL_PIO_IOFR 0x003C 6177618084SLudovic Desroches 6277618084SLudovic Desroches #define ATMEL_PIO_NPINS_PER_BANK 32 6377618084SLudovic Desroches #define ATMEL_PIO_BANK(pin_id) (pin_id / ATMEL_PIO_NPINS_PER_BANK) 6477618084SLudovic Desroches #define ATMEL_PIO_LINE(pin_id) (pin_id % ATMEL_PIO_NPINS_PER_BANK) 6577618084SLudovic Desroches #define ATMEL_PIO_BANK_OFFSET 0x40 6677618084SLudovic Desroches 6777618084SLudovic Desroches #define ATMEL_GET_PIN_NO(pinfunc) ((pinfunc) & 0xff) 6877618084SLudovic Desroches #define ATMEL_GET_PIN_FUNC(pinfunc) ((pinfunc >> 16) & 0xf) 6977618084SLudovic Desroches #define ATMEL_GET_PIN_IOSET(pinfunc) ((pinfunc >> 20) & 0xf) 7077618084SLudovic Desroches 71ff10e353SLudovic Desroches /* Custom pinconf parameters */ 72ff10e353SLudovic Desroches #define ATMEL_PIN_CONFIG_DRIVE_STRENGTH (PIN_CONFIG_END + 1) 73ff10e353SLudovic Desroches 7477618084SLudovic Desroches struct atmel_pioctrl_data { 7577618084SLudovic Desroches unsigned nbanks; 7677618084SLudovic Desroches }; 7777618084SLudovic Desroches 7877618084SLudovic Desroches struct atmel_group { 7977618084SLudovic Desroches const char *name; 8077618084SLudovic Desroches u32 pin; 8177618084SLudovic Desroches }; 8277618084SLudovic Desroches 8377618084SLudovic Desroches struct atmel_pin { 8477618084SLudovic Desroches unsigned pin_id; 8577618084SLudovic Desroches unsigned mux; 8677618084SLudovic Desroches unsigned ioset; 8777618084SLudovic Desroches unsigned bank; 8877618084SLudovic Desroches unsigned line; 8977618084SLudovic Desroches const char *device; 9077618084SLudovic Desroches }; 9177618084SLudovic Desroches 9277618084SLudovic Desroches /** 9377618084SLudovic Desroches * struct atmel_pioctrl - Atmel PIO controller (pinmux + gpio) 9477618084SLudovic Desroches * @reg_base: base address of the controller. 9577618084SLudovic Desroches * @clk: clock of the controller. 9677618084SLudovic Desroches * @nbanks: number of PIO groups, it can vary depending on the SoC. 9777618084SLudovic Desroches * @pinctrl_dev: pinctrl device registered. 9877618084SLudovic Desroches * @groups: groups table to provide group name and pin in the group to pinctrl. 9977618084SLudovic Desroches * @group_names: group names table to provide all the group/pin names to 10077618084SLudovic Desroches * pinctrl or gpio. 10177618084SLudovic Desroches * @pins: pins table used for both pinctrl and gpio. pin_id, bank and line 10277618084SLudovic Desroches * fields are set at probe time. Other ones are set when parsing dt 10377618084SLudovic Desroches * pinctrl. 10477618084SLudovic Desroches * @npins: number of pins. 10577618084SLudovic Desroches * @gpio_chip: gpio chip registered. 10677618084SLudovic Desroches * @irq_domain: irq domain for the gpio controller. 10777618084SLudovic Desroches * @irqs: table containing the hw irq number of the bank. The index of the 10877618084SLudovic Desroches * table is the bank id. 109*898503eeSLee Jones * @pm_wakeup_sources: bitmap of wakeup sources (lines) 110*898503eeSLee Jones * @pm_suspend_backup: backup/restore register values on suspend/resume 11177618084SLudovic Desroches * @dev: device entry for the Atmel PIO controller. 11277618084SLudovic Desroches * @node: node of the Atmel PIO controller. 11377618084SLudovic Desroches */ 11477618084SLudovic Desroches struct atmel_pioctrl { 11577618084SLudovic Desroches void __iomem *reg_base; 11677618084SLudovic Desroches struct clk *clk; 11777618084SLudovic Desroches unsigned nbanks; 11877618084SLudovic Desroches struct pinctrl_dev *pinctrl_dev; 11977618084SLudovic Desroches struct atmel_group *groups; 12077618084SLudovic Desroches const char * const *group_names; 12177618084SLudovic Desroches struct atmel_pin **pins; 12277618084SLudovic Desroches unsigned npins; 12377618084SLudovic Desroches struct gpio_chip *gpio_chip; 12477618084SLudovic Desroches struct irq_domain *irq_domain; 12577618084SLudovic Desroches int *irqs; 126de4e882fSLudovic Desroches unsigned *pm_wakeup_sources; 127ba9e7f27SAlexandre Belloni struct { 128ba9e7f27SAlexandre Belloni u32 imr; 129ba9e7f27SAlexandre Belloni u32 odsr; 130ba9e7f27SAlexandre Belloni u32 cfgr[ATMEL_PIO_NPINS_PER_BANK]; 131ba9e7f27SAlexandre Belloni } *pm_suspend_backup; 13277618084SLudovic Desroches struct device *dev; 13377618084SLudovic Desroches struct device_node *node; 13477618084SLudovic Desroches }; 13577618084SLudovic Desroches 13677618084SLudovic Desroches static const char * const atmel_functions[] = { 13777618084SLudovic Desroches "GPIO", "A", "B", "C", "D", "E", "F", "G" 13877618084SLudovic Desroches }; 13977618084SLudovic Desroches 140ff10e353SLudovic Desroches static const struct pinconf_generic_params atmel_custom_bindings[] = { 141ff10e353SLudovic Desroches {"atmel,drive-strength", ATMEL_PIN_CONFIG_DRIVE_STRENGTH, 0}, 142ff10e353SLudovic Desroches }; 143ff10e353SLudovic Desroches 14477618084SLudovic Desroches /* --- GPIO --- */ 14577618084SLudovic Desroches static unsigned int atmel_gpio_read(struct atmel_pioctrl *atmel_pioctrl, 14677618084SLudovic Desroches unsigned int bank, unsigned int reg) 14777618084SLudovic Desroches { 14877618084SLudovic Desroches return readl_relaxed(atmel_pioctrl->reg_base 14977618084SLudovic Desroches + ATMEL_PIO_BANK_OFFSET * bank + reg); 15077618084SLudovic Desroches } 15177618084SLudovic Desroches 15277618084SLudovic Desroches static void atmel_gpio_write(struct atmel_pioctrl *atmel_pioctrl, 15377618084SLudovic Desroches unsigned int bank, unsigned int reg, 15477618084SLudovic Desroches unsigned int val) 15577618084SLudovic Desroches { 15677618084SLudovic Desroches writel_relaxed(val, atmel_pioctrl->reg_base 15777618084SLudovic Desroches + ATMEL_PIO_BANK_OFFSET * bank + reg); 15877618084SLudovic Desroches } 15977618084SLudovic Desroches 16077618084SLudovic Desroches static void atmel_gpio_irq_ack(struct irq_data *d) 16177618084SLudovic Desroches { 16277618084SLudovic Desroches /* 16377618084SLudovic Desroches * Nothing to do, interrupt is cleared when reading the status 16477618084SLudovic Desroches * register. 16577618084SLudovic Desroches */ 16677618084SLudovic Desroches } 16777618084SLudovic Desroches 16877618084SLudovic Desroches static int atmel_gpio_irq_set_type(struct irq_data *d, unsigned type) 16977618084SLudovic Desroches { 17077618084SLudovic Desroches struct atmel_pioctrl *atmel_pioctrl = irq_data_get_irq_chip_data(d); 17177618084SLudovic Desroches struct atmel_pin *pin = atmel_pioctrl->pins[d->hwirq]; 17277618084SLudovic Desroches unsigned reg; 17377618084SLudovic Desroches 17477618084SLudovic Desroches atmel_gpio_write(atmel_pioctrl, pin->bank, ATMEL_PIO_MSKR, 17577618084SLudovic Desroches BIT(pin->line)); 17677618084SLudovic Desroches reg = atmel_gpio_read(atmel_pioctrl, pin->bank, ATMEL_PIO_CFGR); 17777618084SLudovic Desroches reg &= (~ATMEL_PIO_CFGR_EVTSEL_MASK); 17877618084SLudovic Desroches 17977618084SLudovic Desroches switch (type) { 18077618084SLudovic Desroches case IRQ_TYPE_EDGE_RISING: 1813fd550c6SLudovic Desroches irq_set_handler_locked(d, handle_edge_irq); 18277618084SLudovic Desroches reg |= ATMEL_PIO_CFGR_EVTSEL_RISING; 18377618084SLudovic Desroches break; 18477618084SLudovic Desroches case IRQ_TYPE_EDGE_FALLING: 1853fd550c6SLudovic Desroches irq_set_handler_locked(d, handle_edge_irq); 18677618084SLudovic Desroches reg |= ATMEL_PIO_CFGR_EVTSEL_FALLING; 18777618084SLudovic Desroches break; 18877618084SLudovic Desroches case IRQ_TYPE_EDGE_BOTH: 1893fd550c6SLudovic Desroches irq_set_handler_locked(d, handle_edge_irq); 19077618084SLudovic Desroches reg |= ATMEL_PIO_CFGR_EVTSEL_BOTH; 19177618084SLudovic Desroches break; 19277618084SLudovic Desroches case IRQ_TYPE_LEVEL_LOW: 1933fd550c6SLudovic Desroches irq_set_handler_locked(d, handle_level_irq); 19477618084SLudovic Desroches reg |= ATMEL_PIO_CFGR_EVTSEL_LOW; 19577618084SLudovic Desroches break; 19677618084SLudovic Desroches case IRQ_TYPE_LEVEL_HIGH: 1973fd550c6SLudovic Desroches irq_set_handler_locked(d, handle_level_irq); 19877618084SLudovic Desroches reg |= ATMEL_PIO_CFGR_EVTSEL_HIGH; 19977618084SLudovic Desroches break; 20077618084SLudovic Desroches case IRQ_TYPE_NONE: 20177618084SLudovic Desroches default: 20277618084SLudovic Desroches return -EINVAL; 20377618084SLudovic Desroches } 20477618084SLudovic Desroches 20577618084SLudovic Desroches atmel_gpio_write(atmel_pioctrl, pin->bank, ATMEL_PIO_CFGR, reg); 20677618084SLudovic Desroches 20777618084SLudovic Desroches return 0; 20877618084SLudovic Desroches } 20977618084SLudovic Desroches 21077618084SLudovic Desroches static void atmel_gpio_irq_mask(struct irq_data *d) 21177618084SLudovic Desroches { 21277618084SLudovic Desroches struct atmel_pioctrl *atmel_pioctrl = irq_data_get_irq_chip_data(d); 21377618084SLudovic Desroches struct atmel_pin *pin = atmel_pioctrl->pins[d->hwirq]; 21477618084SLudovic Desroches 21577618084SLudovic Desroches atmel_gpio_write(atmel_pioctrl, pin->bank, ATMEL_PIO_IDR, 21677618084SLudovic Desroches BIT(pin->line)); 21777618084SLudovic Desroches } 21877618084SLudovic Desroches 21977618084SLudovic Desroches static void atmel_gpio_irq_unmask(struct irq_data *d) 22077618084SLudovic Desroches { 22177618084SLudovic Desroches struct atmel_pioctrl *atmel_pioctrl = irq_data_get_irq_chip_data(d); 22277618084SLudovic Desroches struct atmel_pin *pin = atmel_pioctrl->pins[d->hwirq]; 22377618084SLudovic Desroches 22477618084SLudovic Desroches atmel_gpio_write(atmel_pioctrl, pin->bank, ATMEL_PIO_IER, 22577618084SLudovic Desroches BIT(pin->line)); 22677618084SLudovic Desroches } 22777618084SLudovic Desroches 228de4e882fSLudovic Desroches #ifdef CONFIG_PM_SLEEP 229de4e882fSLudovic Desroches 230de4e882fSLudovic Desroches static int atmel_gpio_irq_set_wake(struct irq_data *d, unsigned int on) 231de4e882fSLudovic Desroches { 232de4e882fSLudovic Desroches struct atmel_pioctrl *atmel_pioctrl = irq_data_get_irq_chip_data(d); 233de4e882fSLudovic Desroches int bank = ATMEL_PIO_BANK(d->hwirq); 234de4e882fSLudovic Desroches int line = ATMEL_PIO_LINE(d->hwirq); 235de4e882fSLudovic Desroches 236de4e882fSLudovic Desroches /* The gpio controller has one interrupt line per bank. */ 237de4e882fSLudovic Desroches irq_set_irq_wake(atmel_pioctrl->irqs[bank], on); 238de4e882fSLudovic Desroches 239de4e882fSLudovic Desroches if (on) 240de4e882fSLudovic Desroches atmel_pioctrl->pm_wakeup_sources[bank] |= BIT(line); 241de4e882fSLudovic Desroches else 242de4e882fSLudovic Desroches atmel_pioctrl->pm_wakeup_sources[bank] &= ~(BIT(line)); 243de4e882fSLudovic Desroches 244de4e882fSLudovic Desroches return 0; 245de4e882fSLudovic Desroches } 246de4e882fSLudovic Desroches #else 247de4e882fSLudovic Desroches #define atmel_gpio_irq_set_wake NULL 248de4e882fSLudovic Desroches #endif /* CONFIG_PM_SLEEP */ 249de4e882fSLudovic Desroches 25077618084SLudovic Desroches static struct irq_chip atmel_gpio_irq_chip = { 25177618084SLudovic Desroches .name = "GPIO", 25277618084SLudovic Desroches .irq_ack = atmel_gpio_irq_ack, 25377618084SLudovic Desroches .irq_mask = atmel_gpio_irq_mask, 25477618084SLudovic Desroches .irq_unmask = atmel_gpio_irq_unmask, 25577618084SLudovic Desroches .irq_set_type = atmel_gpio_irq_set_type, 256de4e882fSLudovic Desroches .irq_set_wake = atmel_gpio_irq_set_wake, 25777618084SLudovic Desroches }; 25877618084SLudovic Desroches 259e897b386SLinus Walleij static int atmel_gpio_to_irq(struct gpio_chip *chip, unsigned offset) 260e897b386SLinus Walleij { 261e897b386SLinus Walleij struct atmel_pioctrl *atmel_pioctrl = gpiochip_get_data(chip); 262e897b386SLinus Walleij 263e897b386SLinus Walleij return irq_find_mapping(atmel_pioctrl->irq_domain, offset); 264e897b386SLinus Walleij } 265e897b386SLinus Walleij 26689092fb0SLudovic Desroches static void atmel_gpio_irq_handler(struct irq_desc *desc) 26777618084SLudovic Desroches { 26889092fb0SLudovic Desroches unsigned int irq = irq_desc_get_irq(desc); 26989092fb0SLudovic Desroches struct atmel_pioctrl *atmel_pioctrl = irq_desc_get_handler_data(desc); 27077618084SLudovic Desroches struct irq_chip *chip = irq_desc_get_chip(desc); 27177618084SLudovic Desroches unsigned long isr; 27277618084SLudovic Desroches int n, bank = -1; 27377618084SLudovic Desroches 27477618084SLudovic Desroches /* Find from which bank is the irq received. */ 27577618084SLudovic Desroches for (n = 0; n < atmel_pioctrl->nbanks; n++) { 27677618084SLudovic Desroches if (atmel_pioctrl->irqs[n] == irq) { 27777618084SLudovic Desroches bank = n; 27877618084SLudovic Desroches break; 27977618084SLudovic Desroches } 28077618084SLudovic Desroches } 28177618084SLudovic Desroches 28277618084SLudovic Desroches if (bank < 0) { 28377618084SLudovic Desroches dev_err(atmel_pioctrl->dev, 28477618084SLudovic Desroches "no bank associated to irq %u\n", irq); 28577618084SLudovic Desroches return; 28677618084SLudovic Desroches } 28777618084SLudovic Desroches 28877618084SLudovic Desroches chained_irq_enter(chip, desc); 28977618084SLudovic Desroches 29077618084SLudovic Desroches for (;;) { 29177618084SLudovic Desroches isr = (unsigned long)atmel_gpio_read(atmel_pioctrl, bank, 29277618084SLudovic Desroches ATMEL_PIO_ISR); 29377618084SLudovic Desroches isr &= (unsigned long)atmel_gpio_read(atmel_pioctrl, bank, 29477618084SLudovic Desroches ATMEL_PIO_IMR); 29577618084SLudovic Desroches if (!isr) 29677618084SLudovic Desroches break; 29777618084SLudovic Desroches 29877618084SLudovic Desroches for_each_set_bit(n, &isr, BITS_PER_LONG) 299e897b386SLinus Walleij generic_handle_irq(atmel_gpio_to_irq( 300e897b386SLinus Walleij atmel_pioctrl->gpio_chip, 301e897b386SLinus Walleij bank * ATMEL_PIO_NPINS_PER_BANK + n)); 30277618084SLudovic Desroches } 30377618084SLudovic Desroches 30477618084SLudovic Desroches chained_irq_exit(chip, desc); 30577618084SLudovic Desroches } 30677618084SLudovic Desroches 30777618084SLudovic Desroches static int atmel_gpio_direction_input(struct gpio_chip *chip, unsigned offset) 30877618084SLudovic Desroches { 30980036f88SLinus Walleij struct atmel_pioctrl *atmel_pioctrl = gpiochip_get_data(chip); 31077618084SLudovic Desroches struct atmel_pin *pin = atmel_pioctrl->pins[offset]; 31177618084SLudovic Desroches unsigned reg; 31277618084SLudovic Desroches 31377618084SLudovic Desroches atmel_gpio_write(atmel_pioctrl, pin->bank, ATMEL_PIO_MSKR, 31477618084SLudovic Desroches BIT(pin->line)); 31577618084SLudovic Desroches reg = atmel_gpio_read(atmel_pioctrl, pin->bank, ATMEL_PIO_CFGR); 31677618084SLudovic Desroches reg &= ~ATMEL_PIO_DIR_MASK; 31777618084SLudovic Desroches atmel_gpio_write(atmel_pioctrl, pin->bank, ATMEL_PIO_CFGR, reg); 31877618084SLudovic Desroches 31977618084SLudovic Desroches return 0; 32077618084SLudovic Desroches } 32177618084SLudovic Desroches 32277618084SLudovic Desroches static int atmel_gpio_get(struct gpio_chip *chip, unsigned offset) 32377618084SLudovic Desroches { 32480036f88SLinus Walleij struct atmel_pioctrl *atmel_pioctrl = gpiochip_get_data(chip); 32577618084SLudovic Desroches struct atmel_pin *pin = atmel_pioctrl->pins[offset]; 32677618084SLudovic Desroches unsigned reg; 32777618084SLudovic Desroches 32877618084SLudovic Desroches reg = atmel_gpio_read(atmel_pioctrl, pin->bank, ATMEL_PIO_PDSR); 32977618084SLudovic Desroches 33077618084SLudovic Desroches return !!(reg & BIT(pin->line)); 33177618084SLudovic Desroches } 33277618084SLudovic Desroches 33309107a51SAlexandre Belloni static int atmel_gpio_get_multiple(struct gpio_chip *chip, unsigned long *mask, 33409107a51SAlexandre Belloni unsigned long *bits) 33509107a51SAlexandre Belloni { 33609107a51SAlexandre Belloni struct atmel_pioctrl *atmel_pioctrl = gpiochip_get_data(chip); 33709107a51SAlexandre Belloni unsigned int bank; 33809107a51SAlexandre Belloni 33909107a51SAlexandre Belloni bitmap_zero(bits, atmel_pioctrl->npins); 34009107a51SAlexandre Belloni 34109107a51SAlexandre Belloni for (bank = 0; bank < atmel_pioctrl->nbanks; bank++) { 34209107a51SAlexandre Belloni unsigned int word = bank; 34309107a51SAlexandre Belloni unsigned int offset = 0; 34409107a51SAlexandre Belloni unsigned int reg; 34509107a51SAlexandre Belloni 34609107a51SAlexandre Belloni #if ATMEL_PIO_NPINS_PER_BANK != BITS_PER_LONG 34709107a51SAlexandre Belloni word = BIT_WORD(bank * ATMEL_PIO_NPINS_PER_BANK); 34809107a51SAlexandre Belloni offset = bank * ATMEL_PIO_NPINS_PER_BANK % BITS_PER_LONG; 34909107a51SAlexandre Belloni #endif 35009107a51SAlexandre Belloni if (!mask[word]) 35109107a51SAlexandre Belloni continue; 35209107a51SAlexandre Belloni 35309107a51SAlexandre Belloni reg = atmel_gpio_read(atmel_pioctrl, bank, ATMEL_PIO_PDSR); 35409107a51SAlexandre Belloni bits[word] |= mask[word] & (reg << offset); 35509107a51SAlexandre Belloni } 35609107a51SAlexandre Belloni 35709107a51SAlexandre Belloni return 0; 35809107a51SAlexandre Belloni } 35909107a51SAlexandre Belloni 36077618084SLudovic Desroches static int atmel_gpio_direction_output(struct gpio_chip *chip, unsigned offset, 36177618084SLudovic Desroches int value) 36277618084SLudovic Desroches { 36380036f88SLinus Walleij struct atmel_pioctrl *atmel_pioctrl = gpiochip_get_data(chip); 36477618084SLudovic Desroches struct atmel_pin *pin = atmel_pioctrl->pins[offset]; 36577618084SLudovic Desroches unsigned reg; 36677618084SLudovic Desroches 36777618084SLudovic Desroches atmel_gpio_write(atmel_pioctrl, pin->bank, 36877618084SLudovic Desroches value ? ATMEL_PIO_SODR : ATMEL_PIO_CODR, 36977618084SLudovic Desroches BIT(pin->line)); 37077618084SLudovic Desroches 37177618084SLudovic Desroches atmel_gpio_write(atmel_pioctrl, pin->bank, ATMEL_PIO_MSKR, 37277618084SLudovic Desroches BIT(pin->line)); 37377618084SLudovic Desroches reg = atmel_gpio_read(atmel_pioctrl, pin->bank, ATMEL_PIO_CFGR); 37477618084SLudovic Desroches reg |= ATMEL_PIO_DIR_MASK; 37577618084SLudovic Desroches atmel_gpio_write(atmel_pioctrl, pin->bank, ATMEL_PIO_CFGR, reg); 37677618084SLudovic Desroches 37777618084SLudovic Desroches return 0; 37877618084SLudovic Desroches } 37977618084SLudovic Desroches 38077618084SLudovic Desroches static void atmel_gpio_set(struct gpio_chip *chip, unsigned offset, int val) 38177618084SLudovic Desroches { 38280036f88SLinus Walleij struct atmel_pioctrl *atmel_pioctrl = gpiochip_get_data(chip); 38377618084SLudovic Desroches struct atmel_pin *pin = atmel_pioctrl->pins[offset]; 38477618084SLudovic Desroches 38577618084SLudovic Desroches atmel_gpio_write(atmel_pioctrl, pin->bank, 38677618084SLudovic Desroches val ? ATMEL_PIO_SODR : ATMEL_PIO_CODR, 38777618084SLudovic Desroches BIT(pin->line)); 38877618084SLudovic Desroches } 38977618084SLudovic Desroches 39009107a51SAlexandre Belloni static void atmel_gpio_set_multiple(struct gpio_chip *chip, unsigned long *mask, 39109107a51SAlexandre Belloni unsigned long *bits) 39209107a51SAlexandre Belloni { 39309107a51SAlexandre Belloni struct atmel_pioctrl *atmel_pioctrl = gpiochip_get_data(chip); 39409107a51SAlexandre Belloni unsigned int bank; 39509107a51SAlexandre Belloni 39609107a51SAlexandre Belloni for (bank = 0; bank < atmel_pioctrl->nbanks; bank++) { 39709107a51SAlexandre Belloni unsigned int bitmask; 39809107a51SAlexandre Belloni unsigned int word = bank; 39909107a51SAlexandre Belloni 40009107a51SAlexandre Belloni /* 40109107a51SAlexandre Belloni * On a 64-bit platform, BITS_PER_LONG is 64 so it is necessary to iterate over 40209107a51SAlexandre Belloni * two 32bit words to handle the whole bitmask 40309107a51SAlexandre Belloni */ 40409107a51SAlexandre Belloni #if ATMEL_PIO_NPINS_PER_BANK != BITS_PER_LONG 40509107a51SAlexandre Belloni word = BIT_WORD(bank * ATMEL_PIO_NPINS_PER_BANK); 40609107a51SAlexandre Belloni #endif 40709107a51SAlexandre Belloni if (!mask[word]) 40809107a51SAlexandre Belloni continue; 40909107a51SAlexandre Belloni 41009107a51SAlexandre Belloni bitmask = mask[word] & bits[word]; 41109107a51SAlexandre Belloni atmel_gpio_write(atmel_pioctrl, bank, ATMEL_PIO_SODR, bitmask); 41209107a51SAlexandre Belloni 41309107a51SAlexandre Belloni bitmask = mask[word] & ~bits[word]; 41409107a51SAlexandre Belloni atmel_gpio_write(atmel_pioctrl, bank, ATMEL_PIO_CODR, bitmask); 41509107a51SAlexandre Belloni 41609107a51SAlexandre Belloni #if ATMEL_PIO_NPINS_PER_BANK != BITS_PER_LONG 41709107a51SAlexandre Belloni mask[word] >>= ATMEL_PIO_NPINS_PER_BANK; 41809107a51SAlexandre Belloni bits[word] >>= ATMEL_PIO_NPINS_PER_BANK; 41909107a51SAlexandre Belloni #endif 42009107a51SAlexandre Belloni } 42109107a51SAlexandre Belloni } 42209107a51SAlexandre Belloni 42377618084SLudovic Desroches static struct gpio_chip atmel_gpio_chip = { 42477618084SLudovic Desroches .direction_input = atmel_gpio_direction_input, 42577618084SLudovic Desroches .get = atmel_gpio_get, 42609107a51SAlexandre Belloni .get_multiple = atmel_gpio_get_multiple, 42777618084SLudovic Desroches .direction_output = atmel_gpio_direction_output, 42877618084SLudovic Desroches .set = atmel_gpio_set, 42909107a51SAlexandre Belloni .set_multiple = atmel_gpio_set_multiple, 43077618084SLudovic Desroches .to_irq = atmel_gpio_to_irq, 43177618084SLudovic Desroches .base = 0, 43277618084SLudovic Desroches }; 43377618084SLudovic Desroches 43477618084SLudovic Desroches /* --- PINCTRL --- */ 43577618084SLudovic Desroches static unsigned int atmel_pin_config_read(struct pinctrl_dev *pctldev, 43677618084SLudovic Desroches unsigned pin_id) 43777618084SLudovic Desroches { 43877618084SLudovic Desroches struct atmel_pioctrl *atmel_pioctrl = pinctrl_dev_get_drvdata(pctldev); 43977618084SLudovic Desroches unsigned bank = atmel_pioctrl->pins[pin_id]->bank; 44077618084SLudovic Desroches unsigned line = atmel_pioctrl->pins[pin_id]->line; 44177618084SLudovic Desroches void __iomem *addr = atmel_pioctrl->reg_base 44277618084SLudovic Desroches + bank * ATMEL_PIO_BANK_OFFSET; 44377618084SLudovic Desroches 44477618084SLudovic Desroches writel_relaxed(BIT(line), addr + ATMEL_PIO_MSKR); 44577618084SLudovic Desroches /* Have to set MSKR first, to access the right pin CFGR. */ 44677618084SLudovic Desroches wmb(); 44777618084SLudovic Desroches 44877618084SLudovic Desroches return readl_relaxed(addr + ATMEL_PIO_CFGR); 44977618084SLudovic Desroches } 45077618084SLudovic Desroches 45177618084SLudovic Desroches static void atmel_pin_config_write(struct pinctrl_dev *pctldev, 45277618084SLudovic Desroches unsigned pin_id, u32 conf) 45377618084SLudovic Desroches { 45477618084SLudovic Desroches struct atmel_pioctrl *atmel_pioctrl = pinctrl_dev_get_drvdata(pctldev); 45577618084SLudovic Desroches unsigned bank = atmel_pioctrl->pins[pin_id]->bank; 45677618084SLudovic Desroches unsigned line = atmel_pioctrl->pins[pin_id]->line; 45777618084SLudovic Desroches void __iomem *addr = atmel_pioctrl->reg_base 45877618084SLudovic Desroches + bank * ATMEL_PIO_BANK_OFFSET; 45977618084SLudovic Desroches 46077618084SLudovic Desroches writel_relaxed(BIT(line), addr + ATMEL_PIO_MSKR); 46177618084SLudovic Desroches /* Have to set MSKR first, to access the right pin CFGR. */ 46277618084SLudovic Desroches wmb(); 46377618084SLudovic Desroches writel_relaxed(conf, addr + ATMEL_PIO_CFGR); 46477618084SLudovic Desroches } 46577618084SLudovic Desroches 46677618084SLudovic Desroches static int atmel_pctl_get_groups_count(struct pinctrl_dev *pctldev) 46777618084SLudovic Desroches { 46877618084SLudovic Desroches struct atmel_pioctrl *atmel_pioctrl = pinctrl_dev_get_drvdata(pctldev); 46977618084SLudovic Desroches 47077618084SLudovic Desroches return atmel_pioctrl->npins; 47177618084SLudovic Desroches } 47277618084SLudovic Desroches 47377618084SLudovic Desroches static const char *atmel_pctl_get_group_name(struct pinctrl_dev *pctldev, 47477618084SLudovic Desroches unsigned selector) 47577618084SLudovic Desroches { 47677618084SLudovic Desroches struct atmel_pioctrl *atmel_pioctrl = pinctrl_dev_get_drvdata(pctldev); 47777618084SLudovic Desroches 47877618084SLudovic Desroches return atmel_pioctrl->groups[selector].name; 47977618084SLudovic Desroches } 48077618084SLudovic Desroches 48177618084SLudovic Desroches static int atmel_pctl_get_group_pins(struct pinctrl_dev *pctldev, 48277618084SLudovic Desroches unsigned selector, const unsigned **pins, 48377618084SLudovic Desroches unsigned *num_pins) 48477618084SLudovic Desroches { 48577618084SLudovic Desroches struct atmel_pioctrl *atmel_pioctrl = pinctrl_dev_get_drvdata(pctldev); 48677618084SLudovic Desroches 48777618084SLudovic Desroches *pins = (unsigned *)&atmel_pioctrl->groups[selector].pin; 48877618084SLudovic Desroches *num_pins = 1; 48977618084SLudovic Desroches 49077618084SLudovic Desroches return 0; 49177618084SLudovic Desroches } 49277618084SLudovic Desroches 493682d68b8SBen Dooks static struct atmel_group * 494682d68b8SBen Dooks atmel_pctl_find_group_by_pin(struct pinctrl_dev *pctldev, unsigned pin) 49577618084SLudovic Desroches { 49677618084SLudovic Desroches struct atmel_pioctrl *atmel_pioctrl = pinctrl_dev_get_drvdata(pctldev); 49777618084SLudovic Desroches int i; 49877618084SLudovic Desroches 49977618084SLudovic Desroches for (i = 0; i < atmel_pioctrl->npins; i++) { 50077618084SLudovic Desroches struct atmel_group *grp = atmel_pioctrl->groups + i; 50177618084SLudovic Desroches 50277618084SLudovic Desroches if (grp->pin == pin) 50377618084SLudovic Desroches return grp; 50477618084SLudovic Desroches } 50577618084SLudovic Desroches 50677618084SLudovic Desroches return NULL; 50777618084SLudovic Desroches } 50877618084SLudovic Desroches 50977618084SLudovic Desroches static int atmel_pctl_xlate_pinfunc(struct pinctrl_dev *pctldev, 51077618084SLudovic Desroches struct device_node *np, 51177618084SLudovic Desroches u32 pinfunc, const char **grp_name, 51277618084SLudovic Desroches const char **func_name) 51377618084SLudovic Desroches { 51477618084SLudovic Desroches struct atmel_pioctrl *atmel_pioctrl = pinctrl_dev_get_drvdata(pctldev); 51577618084SLudovic Desroches unsigned pin_id, func_id; 51677618084SLudovic Desroches struct atmel_group *grp; 51777618084SLudovic Desroches 51877618084SLudovic Desroches pin_id = ATMEL_GET_PIN_NO(pinfunc); 51977618084SLudovic Desroches func_id = ATMEL_GET_PIN_FUNC(pinfunc); 52077618084SLudovic Desroches 52177618084SLudovic Desroches if (func_id >= ARRAY_SIZE(atmel_functions)) 52277618084SLudovic Desroches return -EINVAL; 52377618084SLudovic Desroches 52477618084SLudovic Desroches *func_name = atmel_functions[func_id]; 52577618084SLudovic Desroches 52677618084SLudovic Desroches grp = atmel_pctl_find_group_by_pin(pctldev, pin_id); 52777618084SLudovic Desroches if (!grp) 52877618084SLudovic Desroches return -EINVAL; 52977618084SLudovic Desroches *grp_name = grp->name; 53077618084SLudovic Desroches 53177618084SLudovic Desroches atmel_pioctrl->pins[pin_id]->mux = func_id; 53277618084SLudovic Desroches atmel_pioctrl->pins[pin_id]->ioset = ATMEL_GET_PIN_IOSET(pinfunc); 53377618084SLudovic Desroches /* Want the device name not the group one. */ 53477618084SLudovic Desroches if (np->parent == atmel_pioctrl->node) 53577618084SLudovic Desroches atmel_pioctrl->pins[pin_id]->device = np->name; 53677618084SLudovic Desroches else 53777618084SLudovic Desroches atmel_pioctrl->pins[pin_id]->device = np->parent->name; 53877618084SLudovic Desroches 53977618084SLudovic Desroches return 0; 54077618084SLudovic Desroches } 54177618084SLudovic Desroches 54277618084SLudovic Desroches static int atmel_pctl_dt_subnode_to_map(struct pinctrl_dev *pctldev, 54377618084SLudovic Desroches struct device_node *np, 54477618084SLudovic Desroches struct pinctrl_map **map, 54577618084SLudovic Desroches unsigned *reserved_maps, 54677618084SLudovic Desroches unsigned *num_maps) 54777618084SLudovic Desroches { 54877618084SLudovic Desroches unsigned num_pins, num_configs, reserve; 54977618084SLudovic Desroches unsigned long *configs; 55077618084SLudovic Desroches struct property *pins; 55177618084SLudovic Desroches u32 pinfunc; 55277618084SLudovic Desroches int ret, i; 55377618084SLudovic Desroches 55477618084SLudovic Desroches pins = of_find_property(np, "pinmux", NULL); 55577618084SLudovic Desroches if (!pins) 55677618084SLudovic Desroches return -EINVAL; 55777618084SLudovic Desroches 55877618084SLudovic Desroches ret = pinconf_generic_parse_dt_config(np, pctldev, &configs, 55977618084SLudovic Desroches &num_configs); 56077618084SLudovic Desroches if (ret < 0) { 561f5292d06SRob Herring dev_err(pctldev->dev, "%pOF: could not parse node property\n", 562f5292d06SRob Herring np); 56377618084SLudovic Desroches return ret; 56477618084SLudovic Desroches } 56577618084SLudovic Desroches 56677618084SLudovic Desroches num_pins = pins->length / sizeof(u32); 56777618084SLudovic Desroches if (!num_pins) { 568f5292d06SRob Herring dev_err(pctldev->dev, "no pins found in node %pOF\n", np); 569e43d2b75SLudovic Desroches ret = -EINVAL; 570e43d2b75SLudovic Desroches goto exit; 57177618084SLudovic Desroches } 57277618084SLudovic Desroches 57377618084SLudovic Desroches /* 57477618084SLudovic Desroches * Reserve maps, at least there is a mux map and an optional conf 57577618084SLudovic Desroches * map for each pin. 57677618084SLudovic Desroches */ 57777618084SLudovic Desroches reserve = 1; 578b97760aeSDan Carpenter if (num_configs) 57977618084SLudovic Desroches reserve++; 58077618084SLudovic Desroches reserve *= num_pins; 58177618084SLudovic Desroches ret = pinctrl_utils_reserve_map(pctldev, map, reserved_maps, num_maps, 58277618084SLudovic Desroches reserve); 58377618084SLudovic Desroches if (ret < 0) 584e43d2b75SLudovic Desroches goto exit; 58577618084SLudovic Desroches 58677618084SLudovic Desroches for (i = 0; i < num_pins; i++) { 58777618084SLudovic Desroches const char *group, *func; 58877618084SLudovic Desroches 58977618084SLudovic Desroches ret = of_property_read_u32_index(np, "pinmux", i, &pinfunc); 59077618084SLudovic Desroches if (ret) 591e43d2b75SLudovic Desroches goto exit; 59277618084SLudovic Desroches 59377618084SLudovic Desroches ret = atmel_pctl_xlate_pinfunc(pctldev, np, pinfunc, &group, 59477618084SLudovic Desroches &func); 59577618084SLudovic Desroches if (ret) 596e43d2b75SLudovic Desroches goto exit; 59777618084SLudovic Desroches 59877618084SLudovic Desroches pinctrl_utils_add_map_mux(pctldev, map, reserved_maps, num_maps, 59977618084SLudovic Desroches group, func); 60077618084SLudovic Desroches 601b97760aeSDan Carpenter if (num_configs) { 60277618084SLudovic Desroches ret = pinctrl_utils_add_map_configs(pctldev, map, 60377618084SLudovic Desroches reserved_maps, num_maps, group, 60477618084SLudovic Desroches configs, num_configs, 60577618084SLudovic Desroches PIN_MAP_TYPE_CONFIGS_GROUP); 60677618084SLudovic Desroches if (ret < 0) 607e43d2b75SLudovic Desroches goto exit; 60877618084SLudovic Desroches } 60977618084SLudovic Desroches } 61077618084SLudovic Desroches 611e43d2b75SLudovic Desroches exit: 612e43d2b75SLudovic Desroches kfree(configs); 613e43d2b75SLudovic Desroches return ret; 61477618084SLudovic Desroches } 61577618084SLudovic Desroches 61677618084SLudovic Desroches static int atmel_pctl_dt_node_to_map(struct pinctrl_dev *pctldev, 61777618084SLudovic Desroches struct device_node *np_config, 61877618084SLudovic Desroches struct pinctrl_map **map, 61977618084SLudovic Desroches unsigned *num_maps) 62077618084SLudovic Desroches { 62177618084SLudovic Desroches struct device_node *np; 62277618084SLudovic Desroches unsigned reserved_maps; 62377618084SLudovic Desroches int ret; 62477618084SLudovic Desroches 62577618084SLudovic Desroches *map = NULL; 62677618084SLudovic Desroches *num_maps = 0; 62777618084SLudovic Desroches reserved_maps = 0; 62877618084SLudovic Desroches 62977618084SLudovic Desroches /* 63077618084SLudovic Desroches * If all the pins of a device have the same configuration (or no one), 63177618084SLudovic Desroches * it is useless to add a subnode, so directly parse node referenced by 63277618084SLudovic Desroches * phandle. 63377618084SLudovic Desroches */ 63477618084SLudovic Desroches ret = atmel_pctl_dt_subnode_to_map(pctldev, np_config, map, 63577618084SLudovic Desroches &reserved_maps, num_maps); 63677618084SLudovic Desroches if (ret) { 63777618084SLudovic Desroches for_each_child_of_node(np_config, np) { 63877618084SLudovic Desroches ret = atmel_pctl_dt_subnode_to_map(pctldev, np, map, 63977618084SLudovic Desroches &reserved_maps, num_maps); 64021816364SJulia Lawall if (ret < 0) { 64121816364SJulia Lawall of_node_put(np); 64277618084SLudovic Desroches break; 64377618084SLudovic Desroches } 64477618084SLudovic Desroches } 64521816364SJulia Lawall } 64677618084SLudovic Desroches 64777618084SLudovic Desroches if (ret < 0) { 648d32f7fd3SIrina Tirdea pinctrl_utils_free_map(pctldev, *map, *num_maps); 649f5292d06SRob Herring dev_err(pctldev->dev, "can't create maps for node %pOF\n", 650f5292d06SRob Herring np_config); 65177618084SLudovic Desroches } 65277618084SLudovic Desroches 65377618084SLudovic Desroches return ret; 65477618084SLudovic Desroches } 65577618084SLudovic Desroches 65677618084SLudovic Desroches static const struct pinctrl_ops atmel_pctlops = { 65777618084SLudovic Desroches .get_groups_count = atmel_pctl_get_groups_count, 65877618084SLudovic Desroches .get_group_name = atmel_pctl_get_group_name, 65977618084SLudovic Desroches .get_group_pins = atmel_pctl_get_group_pins, 66077618084SLudovic Desroches .dt_node_to_map = atmel_pctl_dt_node_to_map, 661d32f7fd3SIrina Tirdea .dt_free_map = pinctrl_utils_free_map, 66277618084SLudovic Desroches }; 66377618084SLudovic Desroches 66477618084SLudovic Desroches static int atmel_pmx_get_functions_count(struct pinctrl_dev *pctldev) 66577618084SLudovic Desroches { 66677618084SLudovic Desroches return ARRAY_SIZE(atmel_functions); 66777618084SLudovic Desroches } 66877618084SLudovic Desroches 66977618084SLudovic Desroches static const char *atmel_pmx_get_function_name(struct pinctrl_dev *pctldev, 67077618084SLudovic Desroches unsigned selector) 67177618084SLudovic Desroches { 67277618084SLudovic Desroches return atmel_functions[selector]; 67377618084SLudovic Desroches } 67477618084SLudovic Desroches 67577618084SLudovic Desroches static int atmel_pmx_get_function_groups(struct pinctrl_dev *pctldev, 67677618084SLudovic Desroches unsigned selector, 67777618084SLudovic Desroches const char * const **groups, 67877618084SLudovic Desroches unsigned * const num_groups) 67977618084SLudovic Desroches { 68077618084SLudovic Desroches struct atmel_pioctrl *atmel_pioctrl = pinctrl_dev_get_drvdata(pctldev); 68177618084SLudovic Desroches 68277618084SLudovic Desroches *groups = atmel_pioctrl->group_names; 68377618084SLudovic Desroches *num_groups = atmel_pioctrl->npins; 68477618084SLudovic Desroches 68577618084SLudovic Desroches return 0; 68677618084SLudovic Desroches } 68777618084SLudovic Desroches 68877618084SLudovic Desroches static int atmel_pmx_set_mux(struct pinctrl_dev *pctldev, 68977618084SLudovic Desroches unsigned function, 69077618084SLudovic Desroches unsigned group) 69177618084SLudovic Desroches { 69277618084SLudovic Desroches struct atmel_pioctrl *atmel_pioctrl = pinctrl_dev_get_drvdata(pctldev); 69377618084SLudovic Desroches unsigned pin; 69477618084SLudovic Desroches u32 conf; 69577618084SLudovic Desroches 69677618084SLudovic Desroches dev_dbg(pctldev->dev, "enable function %s group %s\n", 69777618084SLudovic Desroches atmel_functions[function], atmel_pioctrl->groups[group].name); 69877618084SLudovic Desroches 69977618084SLudovic Desroches pin = atmel_pioctrl->groups[group].pin; 70077618084SLudovic Desroches conf = atmel_pin_config_read(pctldev, pin); 70177618084SLudovic Desroches conf &= (~ATMEL_PIO_CFGR_FUNC_MASK); 70277618084SLudovic Desroches conf |= (function & ATMEL_PIO_CFGR_FUNC_MASK); 70377618084SLudovic Desroches dev_dbg(pctldev->dev, "pin: %u, conf: 0x%08x\n", pin, conf); 70477618084SLudovic Desroches atmel_pin_config_write(pctldev, pin, conf); 70577618084SLudovic Desroches 70677618084SLudovic Desroches return 0; 70777618084SLudovic Desroches } 70877618084SLudovic Desroches 70977618084SLudovic Desroches static const struct pinmux_ops atmel_pmxops = { 71077618084SLudovic Desroches .get_functions_count = atmel_pmx_get_functions_count, 71177618084SLudovic Desroches .get_function_name = atmel_pmx_get_function_name, 71277618084SLudovic Desroches .get_function_groups = atmel_pmx_get_function_groups, 71377618084SLudovic Desroches .set_mux = atmel_pmx_set_mux, 71477618084SLudovic Desroches }; 71577618084SLudovic Desroches 71677618084SLudovic Desroches static int atmel_conf_pin_config_group_get(struct pinctrl_dev *pctldev, 71777618084SLudovic Desroches unsigned group, 71877618084SLudovic Desroches unsigned long *config) 71977618084SLudovic Desroches { 72077618084SLudovic Desroches struct atmel_pioctrl *atmel_pioctrl = pinctrl_dev_get_drvdata(pctldev); 72177618084SLudovic Desroches unsigned param = pinconf_to_config_param(*config), arg = 0; 72277618084SLudovic Desroches struct atmel_group *grp = atmel_pioctrl->groups + group; 72377618084SLudovic Desroches unsigned pin_id = grp->pin; 72477618084SLudovic Desroches u32 res; 72577618084SLudovic Desroches 72677618084SLudovic Desroches res = atmel_pin_config_read(pctldev, pin_id); 72777618084SLudovic Desroches 72877618084SLudovic Desroches switch (param) { 72977618084SLudovic Desroches case PIN_CONFIG_BIAS_PULL_UP: 73077618084SLudovic Desroches if (!(res & ATMEL_PIO_PUEN_MASK)) 73177618084SLudovic Desroches return -EINVAL; 73277618084SLudovic Desroches arg = 1; 73377618084SLudovic Desroches break; 73477618084SLudovic Desroches case PIN_CONFIG_BIAS_PULL_DOWN: 73577618084SLudovic Desroches if ((res & ATMEL_PIO_PUEN_MASK) || 73677618084SLudovic Desroches (!(res & ATMEL_PIO_PDEN_MASK))) 73777618084SLudovic Desroches return -EINVAL; 73877618084SLudovic Desroches arg = 1; 73977618084SLudovic Desroches break; 74077618084SLudovic Desroches case PIN_CONFIG_BIAS_DISABLE: 74177618084SLudovic Desroches if ((res & ATMEL_PIO_PUEN_MASK) || 74277618084SLudovic Desroches ((res & ATMEL_PIO_PDEN_MASK))) 74377618084SLudovic Desroches return -EINVAL; 74477618084SLudovic Desroches arg = 1; 74577618084SLudovic Desroches break; 74677618084SLudovic Desroches case PIN_CONFIG_DRIVE_OPEN_DRAIN: 74777618084SLudovic Desroches if (!(res & ATMEL_PIO_OPD_MASK)) 74877618084SLudovic Desroches return -EINVAL; 74977618084SLudovic Desroches arg = 1; 75077618084SLudovic Desroches break; 75177618084SLudovic Desroches case PIN_CONFIG_INPUT_SCHMITT_ENABLE: 75277618084SLudovic Desroches if (!(res & ATMEL_PIO_SCHMITT_MASK)) 75377618084SLudovic Desroches return -EINVAL; 75477618084SLudovic Desroches arg = 1; 75577618084SLudovic Desroches break; 756ff10e353SLudovic Desroches case ATMEL_PIN_CONFIG_DRIVE_STRENGTH: 757ff10e353SLudovic Desroches if (!(res & ATMEL_PIO_DRVSTR_MASK)) 758ff10e353SLudovic Desroches return -EINVAL; 759ff10e353SLudovic Desroches arg = (res & ATMEL_PIO_DRVSTR_MASK) >> ATMEL_PIO_DRVSTR_OFFSET; 760ff10e353SLudovic Desroches break; 76177618084SLudovic Desroches default: 76277618084SLudovic Desroches return -ENOTSUPP; 76377618084SLudovic Desroches } 76477618084SLudovic Desroches 76577618084SLudovic Desroches *config = pinconf_to_config_packed(param, arg); 76677618084SLudovic Desroches return 0; 76777618084SLudovic Desroches } 76877618084SLudovic Desroches 76977618084SLudovic Desroches static int atmel_conf_pin_config_group_set(struct pinctrl_dev *pctldev, 77077618084SLudovic Desroches unsigned group, 77177618084SLudovic Desroches unsigned long *configs, 77277618084SLudovic Desroches unsigned num_configs) 77377618084SLudovic Desroches { 77477618084SLudovic Desroches struct atmel_pioctrl *atmel_pioctrl = pinctrl_dev_get_drvdata(pctldev); 77577618084SLudovic Desroches struct atmel_group *grp = atmel_pioctrl->groups + group; 77677618084SLudovic Desroches unsigned bank, pin, pin_id = grp->pin; 77777618084SLudovic Desroches u32 mask, conf = 0; 77877618084SLudovic Desroches int i; 77977618084SLudovic Desroches 78077618084SLudovic Desroches conf = atmel_pin_config_read(pctldev, pin_id); 78177618084SLudovic Desroches 78277618084SLudovic Desroches for (i = 0; i < num_configs; i++) { 78377618084SLudovic Desroches unsigned param = pinconf_to_config_param(configs[i]); 78477618084SLudovic Desroches unsigned arg = pinconf_to_config_argument(configs[i]); 78577618084SLudovic Desroches 78677618084SLudovic Desroches dev_dbg(pctldev->dev, "%s: pin=%u, config=0x%lx\n", 78777618084SLudovic Desroches __func__, pin_id, configs[i]); 78877618084SLudovic Desroches 78977618084SLudovic Desroches switch (param) { 79077618084SLudovic Desroches case PIN_CONFIG_BIAS_DISABLE: 79177618084SLudovic Desroches conf &= (~ATMEL_PIO_PUEN_MASK); 79277618084SLudovic Desroches conf &= (~ATMEL_PIO_PDEN_MASK); 79377618084SLudovic Desroches break; 79477618084SLudovic Desroches case PIN_CONFIG_BIAS_PULL_UP: 79577618084SLudovic Desroches conf |= ATMEL_PIO_PUEN_MASK; 7965305a7b7SLudovic Desroches conf &= (~ATMEL_PIO_PDEN_MASK); 79777618084SLudovic Desroches break; 79877618084SLudovic Desroches case PIN_CONFIG_BIAS_PULL_DOWN: 79977618084SLudovic Desroches conf |= ATMEL_PIO_PDEN_MASK; 8005305a7b7SLudovic Desroches conf &= (~ATMEL_PIO_PUEN_MASK); 80177618084SLudovic Desroches break; 80277618084SLudovic Desroches case PIN_CONFIG_DRIVE_OPEN_DRAIN: 80377618084SLudovic Desroches if (arg == 0) 80477618084SLudovic Desroches conf &= (~ATMEL_PIO_OPD_MASK); 80577618084SLudovic Desroches else 80677618084SLudovic Desroches conf |= ATMEL_PIO_OPD_MASK; 80777618084SLudovic Desroches break; 80877618084SLudovic Desroches case PIN_CONFIG_INPUT_SCHMITT_ENABLE: 80977618084SLudovic Desroches if (arg == 0) 81077618084SLudovic Desroches conf |= ATMEL_PIO_SCHMITT_MASK; 81177618084SLudovic Desroches else 81277618084SLudovic Desroches conf &= (~ATMEL_PIO_SCHMITT_MASK); 81377618084SLudovic Desroches break; 81477618084SLudovic Desroches case PIN_CONFIG_INPUT_DEBOUNCE: 81577618084SLudovic Desroches if (arg == 0) { 81677618084SLudovic Desroches conf &= (~ATMEL_PIO_IFEN_MASK); 81777618084SLudovic Desroches conf &= (~ATMEL_PIO_IFSCEN_MASK); 81877618084SLudovic Desroches } else { 81977618084SLudovic Desroches /* 82077618084SLudovic Desroches * We don't care about the debounce value for several reasons: 82177618084SLudovic Desroches * - can't have different debounce periods inside a same group, 82277618084SLudovic Desroches * - the register to configure this period is a secure register. 82377618084SLudovic Desroches * The debouncing filter can filter a pulse with a duration of less 82477618084SLudovic Desroches * than 1/2 slow clock period. 82577618084SLudovic Desroches */ 82677618084SLudovic Desroches conf |= ATMEL_PIO_IFEN_MASK; 82777618084SLudovic Desroches conf |= ATMEL_PIO_IFSCEN_MASK; 82877618084SLudovic Desroches } 82977618084SLudovic Desroches break; 83077618084SLudovic Desroches case PIN_CONFIG_OUTPUT: 83177618084SLudovic Desroches conf |= ATMEL_PIO_DIR_MASK; 83277618084SLudovic Desroches bank = ATMEL_PIO_BANK(pin_id); 83377618084SLudovic Desroches pin = ATMEL_PIO_LINE(pin_id); 83477618084SLudovic Desroches mask = 1 << pin; 83577618084SLudovic Desroches 83677618084SLudovic Desroches if (arg == 0) { 83777618084SLudovic Desroches writel_relaxed(mask, atmel_pioctrl->reg_base + 83877618084SLudovic Desroches bank * ATMEL_PIO_BANK_OFFSET + 83977618084SLudovic Desroches ATMEL_PIO_CODR); 84077618084SLudovic Desroches } else { 84177618084SLudovic Desroches writel_relaxed(mask, atmel_pioctrl->reg_base + 84277618084SLudovic Desroches bank * ATMEL_PIO_BANK_OFFSET + 84377618084SLudovic Desroches ATMEL_PIO_SODR); 84477618084SLudovic Desroches } 84577618084SLudovic Desroches break; 846ff10e353SLudovic Desroches case ATMEL_PIN_CONFIG_DRIVE_STRENGTH: 847ff10e353SLudovic Desroches switch (arg) { 848ff10e353SLudovic Desroches case ATMEL_PIO_DRVSTR_LO: 849ff10e353SLudovic Desroches case ATMEL_PIO_DRVSTR_ME: 850ff10e353SLudovic Desroches case ATMEL_PIO_DRVSTR_HI: 851ff10e353SLudovic Desroches conf &= (~ATMEL_PIO_DRVSTR_MASK); 852ff10e353SLudovic Desroches conf |= arg << ATMEL_PIO_DRVSTR_OFFSET; 853ff10e353SLudovic Desroches break; 854ff10e353SLudovic Desroches default: 855ff10e353SLudovic Desroches dev_warn(pctldev->dev, "drive strength not updated (incorrect value)\n"); 856ff10e353SLudovic Desroches } 857ff10e353SLudovic Desroches break; 85877618084SLudovic Desroches default: 85977618084SLudovic Desroches dev_warn(pctldev->dev, 86077618084SLudovic Desroches "unsupported configuration parameter: %u\n", 86177618084SLudovic Desroches param); 86277618084SLudovic Desroches continue; 86377618084SLudovic Desroches } 86477618084SLudovic Desroches } 86577618084SLudovic Desroches 86677618084SLudovic Desroches dev_dbg(pctldev->dev, "%s: reg=0x%08x\n", __func__, conf); 86777618084SLudovic Desroches atmel_pin_config_write(pctldev, pin_id, conf); 86877618084SLudovic Desroches 86977618084SLudovic Desroches return 0; 87077618084SLudovic Desroches } 87177618084SLudovic Desroches 87277618084SLudovic Desroches static void atmel_conf_pin_config_dbg_show(struct pinctrl_dev *pctldev, 87377618084SLudovic Desroches struct seq_file *s, unsigned pin_id) 87477618084SLudovic Desroches { 87577618084SLudovic Desroches struct atmel_pioctrl *atmel_pioctrl = pinctrl_dev_get_drvdata(pctldev); 87677618084SLudovic Desroches u32 conf; 87777618084SLudovic Desroches 87877618084SLudovic Desroches if (!atmel_pioctrl->pins[pin_id]->device) 87977618084SLudovic Desroches return; 88077618084SLudovic Desroches 88177618084SLudovic Desroches if (atmel_pioctrl->pins[pin_id]) 88277618084SLudovic Desroches seq_printf(s, " (%s, ioset %u) ", 88377618084SLudovic Desroches atmel_pioctrl->pins[pin_id]->device, 88477618084SLudovic Desroches atmel_pioctrl->pins[pin_id]->ioset); 88577618084SLudovic Desroches 88677618084SLudovic Desroches conf = atmel_pin_config_read(pctldev, pin_id); 88777618084SLudovic Desroches if (conf & ATMEL_PIO_PUEN_MASK) 88877618084SLudovic Desroches seq_printf(s, "%s ", "pull-up"); 88977618084SLudovic Desroches if (conf & ATMEL_PIO_PDEN_MASK) 89077618084SLudovic Desroches seq_printf(s, "%s ", "pull-down"); 89177618084SLudovic Desroches if (conf & ATMEL_PIO_IFEN_MASK) 89277618084SLudovic Desroches seq_printf(s, "%s ", "debounce"); 89377618084SLudovic Desroches if (conf & ATMEL_PIO_OPD_MASK) 89477618084SLudovic Desroches seq_printf(s, "%s ", "open-drain"); 89577618084SLudovic Desroches if (conf & ATMEL_PIO_SCHMITT_MASK) 89677618084SLudovic Desroches seq_printf(s, "%s ", "schmitt"); 897ff10e353SLudovic Desroches if (conf & ATMEL_PIO_DRVSTR_MASK) { 898ff10e353SLudovic Desroches switch ((conf & ATMEL_PIO_DRVSTR_MASK) >> ATMEL_PIO_DRVSTR_OFFSET) { 899ff10e353SLudovic Desroches case ATMEL_PIO_DRVSTR_ME: 900ff10e353SLudovic Desroches seq_printf(s, "%s ", "medium-drive"); 901ff10e353SLudovic Desroches break; 902ff10e353SLudovic Desroches case ATMEL_PIO_DRVSTR_HI: 903ff10e353SLudovic Desroches seq_printf(s, "%s ", "high-drive"); 904ff10e353SLudovic Desroches break; 905ff10e353SLudovic Desroches /* ATMEL_PIO_DRVSTR_LO and 0 which is the default value at reset */ 906ff10e353SLudovic Desroches default: 907ff10e353SLudovic Desroches seq_printf(s, "%s ", "low-drive"); 908ff10e353SLudovic Desroches } 909ff10e353SLudovic Desroches } 91077618084SLudovic Desroches } 91177618084SLudovic Desroches 91277618084SLudovic Desroches static const struct pinconf_ops atmel_confops = { 91377618084SLudovic Desroches .pin_config_group_get = atmel_conf_pin_config_group_get, 91477618084SLudovic Desroches .pin_config_group_set = atmel_conf_pin_config_group_set, 91577618084SLudovic Desroches .pin_config_dbg_show = atmel_conf_pin_config_dbg_show, 91677618084SLudovic Desroches }; 91777618084SLudovic Desroches 91877618084SLudovic Desroches static struct pinctrl_desc atmel_pinctrl_desc = { 91977618084SLudovic Desroches .name = "atmel_pinctrl", 92077618084SLudovic Desroches .confops = &atmel_confops, 92177618084SLudovic Desroches .pctlops = &atmel_pctlops, 92277618084SLudovic Desroches .pmxops = &atmel_pmxops, 92377618084SLudovic Desroches }; 92477618084SLudovic Desroches 9256be2a3a0SArnd Bergmann static int __maybe_unused atmel_pctrl_suspend(struct device *dev) 926de4e882fSLudovic Desroches { 9271ccb0426SWolfram Sang struct atmel_pioctrl *atmel_pioctrl = dev_get_drvdata(dev); 928ba9e7f27SAlexandre Belloni int i, j; 929de4e882fSLudovic Desroches 930de4e882fSLudovic Desroches /* 931de4e882fSLudovic Desroches * For each bank, save IMR to restore it later and disable all GPIO 932de4e882fSLudovic Desroches * interrupts excepting the ones marked as wakeup sources. 933de4e882fSLudovic Desroches */ 934de4e882fSLudovic Desroches for (i = 0; i < atmel_pioctrl->nbanks; i++) { 935ba9e7f27SAlexandre Belloni atmel_pioctrl->pm_suspend_backup[i].imr = 936de4e882fSLudovic Desroches atmel_gpio_read(atmel_pioctrl, i, ATMEL_PIO_IMR); 937de4e882fSLudovic Desroches atmel_gpio_write(atmel_pioctrl, i, ATMEL_PIO_IDR, 938de4e882fSLudovic Desroches ~atmel_pioctrl->pm_wakeup_sources[i]); 939ba9e7f27SAlexandre Belloni atmel_pioctrl->pm_suspend_backup[i].odsr = 940ba9e7f27SAlexandre Belloni atmel_gpio_read(atmel_pioctrl, i, ATMEL_PIO_ODSR); 941ba9e7f27SAlexandre Belloni for (j = 0; j < ATMEL_PIO_NPINS_PER_BANK; j++) { 942ba9e7f27SAlexandre Belloni atmel_gpio_write(atmel_pioctrl, i, 943ba9e7f27SAlexandre Belloni ATMEL_PIO_MSKR, BIT(j)); 944ba9e7f27SAlexandre Belloni atmel_pioctrl->pm_suspend_backup[i].cfgr[j] = 945ba9e7f27SAlexandre Belloni atmel_gpio_read(atmel_pioctrl, i, 946ba9e7f27SAlexandre Belloni ATMEL_PIO_CFGR); 947ba9e7f27SAlexandre Belloni } 948de4e882fSLudovic Desroches } 949de4e882fSLudovic Desroches 950de4e882fSLudovic Desroches return 0; 951de4e882fSLudovic Desroches } 952de4e882fSLudovic Desroches 9536be2a3a0SArnd Bergmann static int __maybe_unused atmel_pctrl_resume(struct device *dev) 954de4e882fSLudovic Desroches { 9551ccb0426SWolfram Sang struct atmel_pioctrl *atmel_pioctrl = dev_get_drvdata(dev); 956ba9e7f27SAlexandre Belloni int i, j; 957de4e882fSLudovic Desroches 958ba9e7f27SAlexandre Belloni for (i = 0; i < atmel_pioctrl->nbanks; i++) { 959de4e882fSLudovic Desroches atmel_gpio_write(atmel_pioctrl, i, ATMEL_PIO_IER, 960ba9e7f27SAlexandre Belloni atmel_pioctrl->pm_suspend_backup[i].imr); 961ba9e7f27SAlexandre Belloni atmel_gpio_write(atmel_pioctrl, i, ATMEL_PIO_SODR, 962ba9e7f27SAlexandre Belloni atmel_pioctrl->pm_suspend_backup[i].odsr); 963ba9e7f27SAlexandre Belloni for (j = 0; j < ATMEL_PIO_NPINS_PER_BANK; j++) { 964ba9e7f27SAlexandre Belloni atmel_gpio_write(atmel_pioctrl, i, 965ba9e7f27SAlexandre Belloni ATMEL_PIO_MSKR, BIT(j)); 966ba9e7f27SAlexandre Belloni atmel_gpio_write(atmel_pioctrl, i, ATMEL_PIO_CFGR, 967ba9e7f27SAlexandre Belloni atmel_pioctrl->pm_suspend_backup[i].cfgr[j]); 968ba9e7f27SAlexandre Belloni } 969ba9e7f27SAlexandre Belloni } 970de4e882fSLudovic Desroches 971de4e882fSLudovic Desroches return 0; 972de4e882fSLudovic Desroches } 973de4e882fSLudovic Desroches 974de4e882fSLudovic Desroches static const struct dev_pm_ops atmel_pctrl_pm_ops = { 975de4e882fSLudovic Desroches SET_SYSTEM_SLEEP_PM_OPS(atmel_pctrl_suspend, atmel_pctrl_resume) 976de4e882fSLudovic Desroches }; 977de4e882fSLudovic Desroches 97877618084SLudovic Desroches /* 97977618084SLudovic Desroches * The number of banks can be different from a SoC to another one. 98077618084SLudovic Desroches * We can have up to 16 banks. 98177618084SLudovic Desroches */ 98277618084SLudovic Desroches static const struct atmel_pioctrl_data atmel_sama5d2_pioctrl_data = { 98377618084SLudovic Desroches .nbanks = 4, 98477618084SLudovic Desroches }; 98577618084SLudovic Desroches 98677618084SLudovic Desroches static const struct of_device_id atmel_pctrl_of_match[] = { 98777618084SLudovic Desroches { 98877618084SLudovic Desroches .compatible = "atmel,sama5d2-pinctrl", 98977618084SLudovic Desroches .data = &atmel_sama5d2_pioctrl_data, 99077618084SLudovic Desroches }, { 99177618084SLudovic Desroches /* sentinel */ 99277618084SLudovic Desroches } 99377618084SLudovic Desroches }; 99477618084SLudovic Desroches 99577618084SLudovic Desroches static int atmel_pinctrl_probe(struct platform_device *pdev) 99677618084SLudovic Desroches { 99777618084SLudovic Desroches struct device *dev = &pdev->dev; 99877618084SLudovic Desroches struct pinctrl_pin_desc *pin_desc; 99977618084SLudovic Desroches const char **group_names; 100077618084SLudovic Desroches const struct of_device_id *match; 100177618084SLudovic Desroches int i, ret; 100277618084SLudovic Desroches struct resource *res; 100377618084SLudovic Desroches struct atmel_pioctrl *atmel_pioctrl; 10048b74c7d3SJulia Lawall const struct atmel_pioctrl_data *atmel_pioctrl_data; 100577618084SLudovic Desroches 100677618084SLudovic Desroches atmel_pioctrl = devm_kzalloc(dev, sizeof(*atmel_pioctrl), GFP_KERNEL); 100777618084SLudovic Desroches if (!atmel_pioctrl) 100877618084SLudovic Desroches return -ENOMEM; 100977618084SLudovic Desroches atmel_pioctrl->dev = dev; 101077618084SLudovic Desroches atmel_pioctrl->node = dev->of_node; 101177618084SLudovic Desroches platform_set_drvdata(pdev, atmel_pioctrl); 101277618084SLudovic Desroches 101377618084SLudovic Desroches match = of_match_node(atmel_pctrl_of_match, dev->of_node); 101477618084SLudovic Desroches if (!match) { 101577618084SLudovic Desroches dev_err(dev, "unknown compatible string\n"); 101677618084SLudovic Desroches return -ENODEV; 101777618084SLudovic Desroches } 10188b74c7d3SJulia Lawall atmel_pioctrl_data = match->data; 101977618084SLudovic Desroches atmel_pioctrl->nbanks = atmel_pioctrl_data->nbanks; 102077618084SLudovic Desroches atmel_pioctrl->npins = atmel_pioctrl->nbanks * ATMEL_PIO_NPINS_PER_BANK; 102177618084SLudovic Desroches 10224b024225SYueHaibing atmel_pioctrl->reg_base = devm_platform_ioremap_resource(pdev, 0); 102377618084SLudovic Desroches if (IS_ERR(atmel_pioctrl->reg_base)) 1024b5d9ff10STiezhu Yang return PTR_ERR(atmel_pioctrl->reg_base); 102577618084SLudovic Desroches 102677618084SLudovic Desroches atmel_pioctrl->clk = devm_clk_get(dev, NULL); 102777618084SLudovic Desroches if (IS_ERR(atmel_pioctrl->clk)) { 102877618084SLudovic Desroches dev_err(dev, "failed to get clock\n"); 102977618084SLudovic Desroches return PTR_ERR(atmel_pioctrl->clk); 103077618084SLudovic Desroches } 103177618084SLudovic Desroches 1032a86854d0SKees Cook atmel_pioctrl->pins = devm_kcalloc(dev, 1033a86854d0SKees Cook atmel_pioctrl->npins, 1034a86854d0SKees Cook sizeof(*atmel_pioctrl->pins), 1035a86854d0SKees Cook GFP_KERNEL); 103677618084SLudovic Desroches if (!atmel_pioctrl->pins) 103777618084SLudovic Desroches return -ENOMEM; 103877618084SLudovic Desroches 1039a86854d0SKees Cook pin_desc = devm_kcalloc(dev, atmel_pioctrl->npins, sizeof(*pin_desc), 1040a86854d0SKees Cook GFP_KERNEL); 104177618084SLudovic Desroches if (!pin_desc) 104277618084SLudovic Desroches return -ENOMEM; 104377618084SLudovic Desroches atmel_pinctrl_desc.pins = pin_desc; 104477618084SLudovic Desroches atmel_pinctrl_desc.npins = atmel_pioctrl->npins; 1045ff10e353SLudovic Desroches atmel_pinctrl_desc.num_custom_params = ARRAY_SIZE(atmel_custom_bindings); 1046ff10e353SLudovic Desroches atmel_pinctrl_desc.custom_params = atmel_custom_bindings; 104777618084SLudovic Desroches 104877618084SLudovic Desroches /* One pin is one group since a pin can achieve all functions. */ 1049a86854d0SKees Cook group_names = devm_kcalloc(dev, 1050a86854d0SKees Cook atmel_pioctrl->npins, sizeof(*group_names), 1051a86854d0SKees Cook GFP_KERNEL); 105277618084SLudovic Desroches if (!group_names) 105377618084SLudovic Desroches return -ENOMEM; 105477618084SLudovic Desroches atmel_pioctrl->group_names = group_names; 105577618084SLudovic Desroches 1056a86854d0SKees Cook atmel_pioctrl->groups = devm_kcalloc(&pdev->dev, 1057a86854d0SKees Cook atmel_pioctrl->npins, sizeof(*atmel_pioctrl->groups), 105877618084SLudovic Desroches GFP_KERNEL); 105977618084SLudovic Desroches if (!atmel_pioctrl->groups) 106077618084SLudovic Desroches return -ENOMEM; 106177618084SLudovic Desroches for (i = 0 ; i < atmel_pioctrl->npins; i++) { 106277618084SLudovic Desroches struct atmel_group *group = atmel_pioctrl->groups + i; 106377618084SLudovic Desroches unsigned bank = ATMEL_PIO_BANK(i); 106477618084SLudovic Desroches unsigned line = ATMEL_PIO_LINE(i); 106577618084SLudovic Desroches 106677618084SLudovic Desroches atmel_pioctrl->pins[i] = devm_kzalloc(dev, 106777618084SLudovic Desroches sizeof(**atmel_pioctrl->pins), GFP_KERNEL); 106877618084SLudovic Desroches if (!atmel_pioctrl->pins[i]) 106977618084SLudovic Desroches return -ENOMEM; 107077618084SLudovic Desroches 107177618084SLudovic Desroches atmel_pioctrl->pins[i]->pin_id = i; 107277618084SLudovic Desroches atmel_pioctrl->pins[i]->bank = bank; 107377618084SLudovic Desroches atmel_pioctrl->pins[i]->line = line; 107477618084SLudovic Desroches 107577618084SLudovic Desroches pin_desc[i].number = i; 107677618084SLudovic Desroches /* Pin naming convention: P(bank_name)(bank_pin_number). */ 107777618084SLudovic Desroches pin_desc[i].name = kasprintf(GFP_KERNEL, "P%c%d", 107877618084SLudovic Desroches bank + 'A', line); 107977618084SLudovic Desroches 108077618084SLudovic Desroches group->name = group_names[i] = pin_desc[i].name; 108177618084SLudovic Desroches group->pin = pin_desc[i].number; 108277618084SLudovic Desroches 108377618084SLudovic Desroches dev_dbg(dev, "pin_id=%u, bank=%u, line=%u", i, bank, line); 108477618084SLudovic Desroches } 108577618084SLudovic Desroches 108677618084SLudovic Desroches atmel_pioctrl->gpio_chip = &atmel_gpio_chip; 108777618084SLudovic Desroches atmel_pioctrl->gpio_chip->of_node = dev->of_node; 108877618084SLudovic Desroches atmel_pioctrl->gpio_chip->ngpio = atmel_pioctrl->npins; 108977618084SLudovic Desroches atmel_pioctrl->gpio_chip->label = dev_name(dev); 109058383c78SLinus Walleij atmel_pioctrl->gpio_chip->parent = dev; 109177618084SLudovic Desroches atmel_pioctrl->gpio_chip->names = atmel_pioctrl->group_names; 109277618084SLudovic Desroches 1093a86854d0SKees Cook atmel_pioctrl->pm_wakeup_sources = devm_kcalloc(dev, 1094a86854d0SKees Cook atmel_pioctrl->nbanks, 1095a86854d0SKees Cook sizeof(*atmel_pioctrl->pm_wakeup_sources), 1096a86854d0SKees Cook GFP_KERNEL); 1097de4e882fSLudovic Desroches if (!atmel_pioctrl->pm_wakeup_sources) 1098de4e882fSLudovic Desroches return -ENOMEM; 1099de4e882fSLudovic Desroches 1100a86854d0SKees Cook atmel_pioctrl->pm_suspend_backup = devm_kcalloc(dev, 1101a86854d0SKees Cook atmel_pioctrl->nbanks, 1102a86854d0SKees Cook sizeof(*atmel_pioctrl->pm_suspend_backup), 1103a86854d0SKees Cook GFP_KERNEL); 1104de4e882fSLudovic Desroches if (!atmel_pioctrl->pm_suspend_backup) 1105de4e882fSLudovic Desroches return -ENOMEM; 1106de4e882fSLudovic Desroches 1107a86854d0SKees Cook atmel_pioctrl->irqs = devm_kcalloc(dev, 1108a86854d0SKees Cook atmel_pioctrl->nbanks, 1109a86854d0SKees Cook sizeof(*atmel_pioctrl->irqs), 1110a86854d0SKees Cook GFP_KERNEL); 111177618084SLudovic Desroches if (!atmel_pioctrl->irqs) 111277618084SLudovic Desroches return -ENOMEM; 111377618084SLudovic Desroches 111477618084SLudovic Desroches /* There is one controller but each bank has its own irq line. */ 111577618084SLudovic Desroches for (i = 0; i < atmel_pioctrl->nbanks; i++) { 111677618084SLudovic Desroches res = platform_get_resource(pdev, IORESOURCE_IRQ, i); 111777618084SLudovic Desroches if (!res) { 111877618084SLudovic Desroches dev_err(dev, "missing irq resource for group %c\n", 111977618084SLudovic Desroches 'A' + i); 112077618084SLudovic Desroches return -EINVAL; 112177618084SLudovic Desroches } 112277618084SLudovic Desroches atmel_pioctrl->irqs[i] = res->start; 112377618084SLudovic Desroches irq_set_chained_handler(res->start, atmel_gpio_irq_handler); 112477618084SLudovic Desroches irq_set_handler_data(res->start, atmel_pioctrl); 112532844138SArnd Bergmann dev_dbg(dev, "bank %i: irq=%pr\n", i, res); 112677618084SLudovic Desroches } 112777618084SLudovic Desroches 112877618084SLudovic Desroches atmel_pioctrl->irq_domain = irq_domain_add_linear(dev->of_node, 112977618084SLudovic Desroches atmel_pioctrl->gpio_chip->ngpio, 113077618084SLudovic Desroches &irq_domain_simple_ops, NULL); 113177618084SLudovic Desroches if (!atmel_pioctrl->irq_domain) { 113277618084SLudovic Desroches dev_err(dev, "can't add the irq domain\n"); 113377618084SLudovic Desroches return -ENODEV; 113477618084SLudovic Desroches } 113577618084SLudovic Desroches atmel_pioctrl->irq_domain->name = "atmel gpio"; 113677618084SLudovic Desroches 113777618084SLudovic Desroches for (i = 0; i < atmel_pioctrl->npins; i++) { 113877618084SLudovic Desroches int irq = irq_create_mapping(atmel_pioctrl->irq_domain, i); 113977618084SLudovic Desroches 114077618084SLudovic Desroches irq_set_chip_and_handler(irq, &atmel_gpio_irq_chip, 114177618084SLudovic Desroches handle_simple_irq); 114277618084SLudovic Desroches irq_set_chip_data(irq, atmel_pioctrl); 114377618084SLudovic Desroches dev_dbg(dev, 114477618084SLudovic Desroches "atmel gpio irq domain: hwirq: %d, linux irq: %d\n", 114577618084SLudovic Desroches i, irq); 114677618084SLudovic Desroches } 114777618084SLudovic Desroches 114877618084SLudovic Desroches ret = clk_prepare_enable(atmel_pioctrl->clk); 114977618084SLudovic Desroches if (ret) { 115077618084SLudovic Desroches dev_err(dev, "failed to prepare and enable clock\n"); 115177618084SLudovic Desroches goto clk_prepare_enable_error; 115277618084SLudovic Desroches } 115377618084SLudovic Desroches 11545d3fc884SLaxman Dewangan atmel_pioctrl->pinctrl_dev = devm_pinctrl_register(&pdev->dev, 11555d3fc884SLaxman Dewangan &atmel_pinctrl_desc, 115677618084SLudovic Desroches atmel_pioctrl); 11575d3fc884SLaxman Dewangan if (IS_ERR(atmel_pioctrl->pinctrl_dev)) { 11585d3fc884SLaxman Dewangan ret = PTR_ERR(atmel_pioctrl->pinctrl_dev); 115977618084SLudovic Desroches dev_err(dev, "pinctrl registration failed\n"); 11605d3fc884SLaxman Dewangan goto clk_unprep; 116177618084SLudovic Desroches } 116277618084SLudovic Desroches 116380036f88SLinus Walleij ret = gpiochip_add_data(atmel_pioctrl->gpio_chip, atmel_pioctrl); 116477618084SLudovic Desroches if (ret) { 116577618084SLudovic Desroches dev_err(dev, "failed to add gpiochip\n"); 11665d3fc884SLaxman Dewangan goto clk_unprep; 116777618084SLudovic Desroches } 116877618084SLudovic Desroches 116977618084SLudovic Desroches ret = gpiochip_add_pin_range(atmel_pioctrl->gpio_chip, dev_name(dev), 117077618084SLudovic Desroches 0, 0, atmel_pioctrl->gpio_chip->ngpio); 117177618084SLudovic Desroches if (ret) { 117277618084SLudovic Desroches dev_err(dev, "failed to add gpio pin range\n"); 117377618084SLudovic Desroches goto gpiochip_add_pin_range_error; 117477618084SLudovic Desroches } 117577618084SLudovic Desroches 117677618084SLudovic Desroches dev_info(&pdev->dev, "atmel pinctrl initialized\n"); 117777618084SLudovic Desroches 117877618084SLudovic Desroches return 0; 117977618084SLudovic Desroches 118077618084SLudovic Desroches gpiochip_add_pin_range_error: 118177618084SLudovic Desroches gpiochip_remove(atmel_pioctrl->gpio_chip); 118277618084SLudovic Desroches 11835d3fc884SLaxman Dewangan clk_unprep: 11845d3fc884SLaxman Dewangan clk_disable_unprepare(atmel_pioctrl->clk); 11855d3fc884SLaxman Dewangan 11865d3fc884SLaxman Dewangan clk_prepare_enable_error: 11875d3fc884SLaxman Dewangan irq_domain_remove(atmel_pioctrl->irq_domain); 11885d3fc884SLaxman Dewangan 118977618084SLudovic Desroches return ret; 119077618084SLudovic Desroches } 119177618084SLudovic Desroches 119277618084SLudovic Desroches static struct platform_driver atmel_pinctrl_driver = { 119377618084SLudovic Desroches .driver = { 119477618084SLudovic Desroches .name = "pinctrl-at91-pio4", 119577618084SLudovic Desroches .of_match_table = atmel_pctrl_of_match, 1196de4e882fSLudovic Desroches .pm = &atmel_pctrl_pm_ops, 1197f703851aSPaul Gortmaker .suppress_bind_attrs = true, 119877618084SLudovic Desroches }, 119977618084SLudovic Desroches .probe = atmel_pinctrl_probe, 120077618084SLudovic Desroches }; 1201f703851aSPaul Gortmaker builtin_platform_driver(atmel_pinctrl_driver); 1202