177618084SLudovic Desroches /* 277618084SLudovic Desroches * Driver for the Atmel PIO4 controller 377618084SLudovic Desroches * 477618084SLudovic Desroches * Copyright (C) 2015 Atmel, 577618084SLudovic Desroches * 2015 Ludovic Desroches <ludovic.desroches@atmel.com> 677618084SLudovic Desroches * 777618084SLudovic Desroches * This software is licensed under the terms of the GNU General Public 877618084SLudovic Desroches * License version 2, as published by the Free Software Foundation, and 977618084SLudovic Desroches * may be copied, distributed, and modified under those terms. 1077618084SLudovic Desroches * 1177618084SLudovic Desroches * This program is distributed in the hope that it will be useful, 1277618084SLudovic Desroches * but WITHOUT ANY WARRANTY; without even the implied warranty of 1377618084SLudovic Desroches * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 1477618084SLudovic Desroches * GNU General Public License for more details. 1577618084SLudovic Desroches */ 1677618084SLudovic Desroches 1777618084SLudovic Desroches #include <linux/clk.h> 18*80036f88SLinus Walleij #include <linux/gpio/driver.h> 19*80036f88SLinus Walleij /* FIXME: needed for gpio_to_irq(), get rid of this */ 2077618084SLudovic Desroches #include <linux/gpio.h> 21de4e882fSLudovic Desroches #include <linux/interrupt.h> 2277618084SLudovic Desroches #include <linux/io.h> 2377618084SLudovic Desroches #include <linux/module.h> 2477618084SLudovic Desroches #include <linux/of.h> 2577618084SLudovic Desroches #include <linux/platform_device.h> 2677618084SLudovic Desroches #include <linux/pinctrl/pinconf.h> 2777618084SLudovic Desroches #include <linux/pinctrl/pinconf-generic.h> 2877618084SLudovic Desroches #include <linux/pinctrl/pinctrl.h> 2977618084SLudovic Desroches #include <linux/pinctrl/pinmux.h> 3077618084SLudovic Desroches #include <linux/slab.h> 3177618084SLudovic Desroches #include "core.h" 3277618084SLudovic Desroches #include "pinconf.h" 3377618084SLudovic Desroches #include "pinctrl-utils.h" 3477618084SLudovic Desroches 3577618084SLudovic Desroches /* 3677618084SLudovic Desroches * Warning: 3777618084SLudovic Desroches * In order to not introduce confusion between Atmel PIO groups and pinctrl 3877618084SLudovic Desroches * framework groups, Atmel PIO groups will be called banks, line is kept to 3977618084SLudovic Desroches * designed the pin id into this bank. 4077618084SLudovic Desroches */ 4177618084SLudovic Desroches 4277618084SLudovic Desroches #define ATMEL_PIO_MSKR 0x0000 4377618084SLudovic Desroches #define ATMEL_PIO_CFGR 0x0004 4477618084SLudovic Desroches #define ATMEL_PIO_CFGR_FUNC_MASK GENMASK(2, 0) 4577618084SLudovic Desroches #define ATMEL_PIO_DIR_MASK BIT(8) 4677618084SLudovic Desroches #define ATMEL_PIO_PUEN_MASK BIT(9) 4777618084SLudovic Desroches #define ATMEL_PIO_PDEN_MASK BIT(10) 4877618084SLudovic Desroches #define ATMEL_PIO_IFEN_MASK BIT(12) 4977618084SLudovic Desroches #define ATMEL_PIO_IFSCEN_MASK BIT(13) 5077618084SLudovic Desroches #define ATMEL_PIO_OPD_MASK BIT(14) 5177618084SLudovic Desroches #define ATMEL_PIO_SCHMITT_MASK BIT(15) 5277618084SLudovic Desroches #define ATMEL_PIO_CFGR_EVTSEL_MASK GENMASK(26, 24) 5377618084SLudovic Desroches #define ATMEL_PIO_CFGR_EVTSEL_FALLING (0 << 24) 5477618084SLudovic Desroches #define ATMEL_PIO_CFGR_EVTSEL_RISING (1 << 24) 5577618084SLudovic Desroches #define ATMEL_PIO_CFGR_EVTSEL_BOTH (2 << 24) 5677618084SLudovic Desroches #define ATMEL_PIO_CFGR_EVTSEL_LOW (3 << 24) 5777618084SLudovic Desroches #define ATMEL_PIO_CFGR_EVTSEL_HIGH (4 << 24) 5877618084SLudovic Desroches #define ATMEL_PIO_PDSR 0x0008 5977618084SLudovic Desroches #define ATMEL_PIO_LOCKSR 0x000C 6077618084SLudovic Desroches #define ATMEL_PIO_SODR 0x0010 6177618084SLudovic Desroches #define ATMEL_PIO_CODR 0x0014 6277618084SLudovic Desroches #define ATMEL_PIO_ODSR 0x0018 6377618084SLudovic Desroches #define ATMEL_PIO_IER 0x0020 6477618084SLudovic Desroches #define ATMEL_PIO_IDR 0x0024 6577618084SLudovic Desroches #define ATMEL_PIO_IMR 0x0028 6677618084SLudovic Desroches #define ATMEL_PIO_ISR 0x002C 6777618084SLudovic Desroches #define ATMEL_PIO_IOFR 0x003C 6877618084SLudovic Desroches 6977618084SLudovic Desroches #define ATMEL_PIO_NPINS_PER_BANK 32 7077618084SLudovic Desroches #define ATMEL_PIO_BANK(pin_id) (pin_id / ATMEL_PIO_NPINS_PER_BANK) 7177618084SLudovic Desroches #define ATMEL_PIO_LINE(pin_id) (pin_id % ATMEL_PIO_NPINS_PER_BANK) 7277618084SLudovic Desroches #define ATMEL_PIO_BANK_OFFSET 0x40 7377618084SLudovic Desroches 7477618084SLudovic Desroches #define ATMEL_GET_PIN_NO(pinfunc) ((pinfunc) & 0xff) 7577618084SLudovic Desroches #define ATMEL_GET_PIN_FUNC(pinfunc) ((pinfunc >> 16) & 0xf) 7677618084SLudovic Desroches #define ATMEL_GET_PIN_IOSET(pinfunc) ((pinfunc >> 20) & 0xf) 7777618084SLudovic Desroches 7877618084SLudovic Desroches struct atmel_pioctrl_data { 7977618084SLudovic Desroches unsigned nbanks; 8077618084SLudovic Desroches }; 8177618084SLudovic Desroches 8277618084SLudovic Desroches struct atmel_group { 8377618084SLudovic Desroches const char *name; 8477618084SLudovic Desroches u32 pin; 8577618084SLudovic Desroches }; 8677618084SLudovic Desroches 8777618084SLudovic Desroches struct atmel_pin { 8877618084SLudovic Desroches unsigned pin_id; 8977618084SLudovic Desroches unsigned mux; 9077618084SLudovic Desroches unsigned ioset; 9177618084SLudovic Desroches unsigned bank; 9277618084SLudovic Desroches unsigned line; 9377618084SLudovic Desroches const char *device; 9477618084SLudovic Desroches }; 9577618084SLudovic Desroches 9677618084SLudovic Desroches /** 9777618084SLudovic Desroches * struct atmel_pioctrl - Atmel PIO controller (pinmux + gpio) 9877618084SLudovic Desroches * @reg_base: base address of the controller. 9977618084SLudovic Desroches * @clk: clock of the controller. 10077618084SLudovic Desroches * @nbanks: number of PIO groups, it can vary depending on the SoC. 10177618084SLudovic Desroches * @pinctrl_dev: pinctrl device registered. 10277618084SLudovic Desroches * @groups: groups table to provide group name and pin in the group to pinctrl. 10377618084SLudovic Desroches * @group_names: group names table to provide all the group/pin names to 10477618084SLudovic Desroches * pinctrl or gpio. 10577618084SLudovic Desroches * @pins: pins table used for both pinctrl and gpio. pin_id, bank and line 10677618084SLudovic Desroches * fields are set at probe time. Other ones are set when parsing dt 10777618084SLudovic Desroches * pinctrl. 10877618084SLudovic Desroches * @npins: number of pins. 10977618084SLudovic Desroches * @gpio_chip: gpio chip registered. 11077618084SLudovic Desroches * @irq_domain: irq domain for the gpio controller. 11177618084SLudovic Desroches * @irqs: table containing the hw irq number of the bank. The index of the 11277618084SLudovic Desroches * table is the bank id. 11377618084SLudovic Desroches * @dev: device entry for the Atmel PIO controller. 11477618084SLudovic Desroches * @node: node of the Atmel PIO controller. 11577618084SLudovic Desroches */ 11677618084SLudovic Desroches struct atmel_pioctrl { 11777618084SLudovic Desroches void __iomem *reg_base; 11877618084SLudovic Desroches struct clk *clk; 11977618084SLudovic Desroches unsigned nbanks; 12077618084SLudovic Desroches struct pinctrl_dev *pinctrl_dev; 12177618084SLudovic Desroches struct atmel_group *groups; 12277618084SLudovic Desroches const char * const *group_names; 12377618084SLudovic Desroches struct atmel_pin **pins; 12477618084SLudovic Desroches unsigned npins; 12577618084SLudovic Desroches struct gpio_chip *gpio_chip; 12677618084SLudovic Desroches struct irq_domain *irq_domain; 12777618084SLudovic Desroches int *irqs; 128de4e882fSLudovic Desroches unsigned *pm_wakeup_sources; 129de4e882fSLudovic Desroches unsigned *pm_suspend_backup; 13077618084SLudovic Desroches struct device *dev; 13177618084SLudovic Desroches struct device_node *node; 13277618084SLudovic Desroches }; 13377618084SLudovic Desroches 13477618084SLudovic Desroches static const char * const atmel_functions[] = { 13577618084SLudovic Desroches "GPIO", "A", "B", "C", "D", "E", "F", "G" 13677618084SLudovic Desroches }; 13777618084SLudovic Desroches 13877618084SLudovic Desroches /* --- GPIO --- */ 13977618084SLudovic Desroches static unsigned int atmel_gpio_read(struct atmel_pioctrl *atmel_pioctrl, 14077618084SLudovic Desroches unsigned int bank, unsigned int reg) 14177618084SLudovic Desroches { 14277618084SLudovic Desroches return readl_relaxed(atmel_pioctrl->reg_base 14377618084SLudovic Desroches + ATMEL_PIO_BANK_OFFSET * bank + reg); 14477618084SLudovic Desroches } 14577618084SLudovic Desroches 14677618084SLudovic Desroches static void atmel_gpio_write(struct atmel_pioctrl *atmel_pioctrl, 14777618084SLudovic Desroches unsigned int bank, unsigned int reg, 14877618084SLudovic Desroches unsigned int val) 14977618084SLudovic Desroches { 15077618084SLudovic Desroches writel_relaxed(val, atmel_pioctrl->reg_base 15177618084SLudovic Desroches + ATMEL_PIO_BANK_OFFSET * bank + reg); 15277618084SLudovic Desroches } 15377618084SLudovic Desroches 15477618084SLudovic Desroches static void atmel_gpio_irq_ack(struct irq_data *d) 15577618084SLudovic Desroches { 15677618084SLudovic Desroches /* 15777618084SLudovic Desroches * Nothing to do, interrupt is cleared when reading the status 15877618084SLudovic Desroches * register. 15977618084SLudovic Desroches */ 16077618084SLudovic Desroches } 16177618084SLudovic Desroches 16277618084SLudovic Desroches static int atmel_gpio_irq_set_type(struct irq_data *d, unsigned type) 16377618084SLudovic Desroches { 16477618084SLudovic Desroches struct atmel_pioctrl *atmel_pioctrl = irq_data_get_irq_chip_data(d); 16577618084SLudovic Desroches struct atmel_pin *pin = atmel_pioctrl->pins[d->hwirq]; 16677618084SLudovic Desroches unsigned reg; 16777618084SLudovic Desroches 16877618084SLudovic Desroches atmel_gpio_write(atmel_pioctrl, pin->bank, ATMEL_PIO_MSKR, 16977618084SLudovic Desroches BIT(pin->line)); 17077618084SLudovic Desroches reg = atmel_gpio_read(atmel_pioctrl, pin->bank, ATMEL_PIO_CFGR); 17177618084SLudovic Desroches reg &= (~ATMEL_PIO_CFGR_EVTSEL_MASK); 17277618084SLudovic Desroches 17377618084SLudovic Desroches switch (type) { 17477618084SLudovic Desroches case IRQ_TYPE_EDGE_RISING: 1753fd550c6SLudovic Desroches irq_set_handler_locked(d, handle_edge_irq); 17677618084SLudovic Desroches reg |= ATMEL_PIO_CFGR_EVTSEL_RISING; 17777618084SLudovic Desroches break; 17877618084SLudovic Desroches case IRQ_TYPE_EDGE_FALLING: 1793fd550c6SLudovic Desroches irq_set_handler_locked(d, handle_edge_irq); 18077618084SLudovic Desroches reg |= ATMEL_PIO_CFGR_EVTSEL_FALLING; 18177618084SLudovic Desroches break; 18277618084SLudovic Desroches case IRQ_TYPE_EDGE_BOTH: 1833fd550c6SLudovic Desroches irq_set_handler_locked(d, handle_edge_irq); 18477618084SLudovic Desroches reg |= ATMEL_PIO_CFGR_EVTSEL_BOTH; 18577618084SLudovic Desroches break; 18677618084SLudovic Desroches case IRQ_TYPE_LEVEL_LOW: 1873fd550c6SLudovic Desroches irq_set_handler_locked(d, handle_level_irq); 18877618084SLudovic Desroches reg |= ATMEL_PIO_CFGR_EVTSEL_LOW; 18977618084SLudovic Desroches break; 19077618084SLudovic Desroches case IRQ_TYPE_LEVEL_HIGH: 1913fd550c6SLudovic Desroches irq_set_handler_locked(d, handle_level_irq); 19277618084SLudovic Desroches reg |= ATMEL_PIO_CFGR_EVTSEL_HIGH; 19377618084SLudovic Desroches break; 19477618084SLudovic Desroches case IRQ_TYPE_NONE: 19577618084SLudovic Desroches default: 19677618084SLudovic Desroches return -EINVAL; 19777618084SLudovic Desroches } 19877618084SLudovic Desroches 19977618084SLudovic Desroches atmel_gpio_write(atmel_pioctrl, pin->bank, ATMEL_PIO_CFGR, reg); 20077618084SLudovic Desroches 20177618084SLudovic Desroches return 0; 20277618084SLudovic Desroches } 20377618084SLudovic Desroches 20477618084SLudovic Desroches static void atmel_gpio_irq_mask(struct irq_data *d) 20577618084SLudovic Desroches { 20677618084SLudovic Desroches struct atmel_pioctrl *atmel_pioctrl = irq_data_get_irq_chip_data(d); 20777618084SLudovic Desroches struct atmel_pin *pin = atmel_pioctrl->pins[d->hwirq]; 20877618084SLudovic Desroches 20977618084SLudovic Desroches atmel_gpio_write(atmel_pioctrl, pin->bank, ATMEL_PIO_IDR, 21077618084SLudovic Desroches BIT(pin->line)); 21177618084SLudovic Desroches } 21277618084SLudovic Desroches 21377618084SLudovic Desroches static void atmel_gpio_irq_unmask(struct irq_data *d) 21477618084SLudovic Desroches { 21577618084SLudovic Desroches struct atmel_pioctrl *atmel_pioctrl = irq_data_get_irq_chip_data(d); 21677618084SLudovic Desroches struct atmel_pin *pin = atmel_pioctrl->pins[d->hwirq]; 21777618084SLudovic Desroches 21877618084SLudovic Desroches atmel_gpio_write(atmel_pioctrl, pin->bank, ATMEL_PIO_IER, 21977618084SLudovic Desroches BIT(pin->line)); 22077618084SLudovic Desroches } 22177618084SLudovic Desroches 222de4e882fSLudovic Desroches #ifdef CONFIG_PM_SLEEP 223de4e882fSLudovic Desroches 224de4e882fSLudovic Desroches static int atmel_gpio_irq_set_wake(struct irq_data *d, unsigned int on) 225de4e882fSLudovic Desroches { 226de4e882fSLudovic Desroches struct atmel_pioctrl *atmel_pioctrl = irq_data_get_irq_chip_data(d); 227de4e882fSLudovic Desroches int bank = ATMEL_PIO_BANK(d->hwirq); 228de4e882fSLudovic Desroches int line = ATMEL_PIO_LINE(d->hwirq); 229de4e882fSLudovic Desroches 230de4e882fSLudovic Desroches /* The gpio controller has one interrupt line per bank. */ 231de4e882fSLudovic Desroches irq_set_irq_wake(atmel_pioctrl->irqs[bank], on); 232de4e882fSLudovic Desroches 233de4e882fSLudovic Desroches if (on) 234de4e882fSLudovic Desroches atmel_pioctrl->pm_wakeup_sources[bank] |= BIT(line); 235de4e882fSLudovic Desroches else 236de4e882fSLudovic Desroches atmel_pioctrl->pm_wakeup_sources[bank] &= ~(BIT(line)); 237de4e882fSLudovic Desroches 238de4e882fSLudovic Desroches return 0; 239de4e882fSLudovic Desroches } 240de4e882fSLudovic Desroches #else 241de4e882fSLudovic Desroches #define atmel_gpio_irq_set_wake NULL 242de4e882fSLudovic Desroches #endif /* CONFIG_PM_SLEEP */ 243de4e882fSLudovic Desroches 24477618084SLudovic Desroches static struct irq_chip atmel_gpio_irq_chip = { 24577618084SLudovic Desroches .name = "GPIO", 24677618084SLudovic Desroches .irq_ack = atmel_gpio_irq_ack, 24777618084SLudovic Desroches .irq_mask = atmel_gpio_irq_mask, 24877618084SLudovic Desroches .irq_unmask = atmel_gpio_irq_unmask, 24977618084SLudovic Desroches .irq_set_type = atmel_gpio_irq_set_type, 250de4e882fSLudovic Desroches .irq_set_wake = atmel_gpio_irq_set_wake, 25177618084SLudovic Desroches }; 25277618084SLudovic Desroches 25389092fb0SLudovic Desroches static void atmel_gpio_irq_handler(struct irq_desc *desc) 25477618084SLudovic Desroches { 25589092fb0SLudovic Desroches unsigned int irq = irq_desc_get_irq(desc); 25689092fb0SLudovic Desroches struct atmel_pioctrl *atmel_pioctrl = irq_desc_get_handler_data(desc); 25777618084SLudovic Desroches struct irq_chip *chip = irq_desc_get_chip(desc); 25877618084SLudovic Desroches unsigned long isr; 25977618084SLudovic Desroches int n, bank = -1; 26077618084SLudovic Desroches 26177618084SLudovic Desroches /* Find from which bank is the irq received. */ 26277618084SLudovic Desroches for (n = 0; n < atmel_pioctrl->nbanks; n++) { 26377618084SLudovic Desroches if (atmel_pioctrl->irqs[n] == irq) { 26477618084SLudovic Desroches bank = n; 26577618084SLudovic Desroches break; 26677618084SLudovic Desroches } 26777618084SLudovic Desroches } 26877618084SLudovic Desroches 26977618084SLudovic Desroches if (bank < 0) { 27077618084SLudovic Desroches dev_err(atmel_pioctrl->dev, 27177618084SLudovic Desroches "no bank associated to irq %u\n", irq); 27277618084SLudovic Desroches return; 27377618084SLudovic Desroches } 27477618084SLudovic Desroches 27577618084SLudovic Desroches chained_irq_enter(chip, desc); 27677618084SLudovic Desroches 27777618084SLudovic Desroches for (;;) { 27877618084SLudovic Desroches isr = (unsigned long)atmel_gpio_read(atmel_pioctrl, bank, 27977618084SLudovic Desroches ATMEL_PIO_ISR); 28077618084SLudovic Desroches isr &= (unsigned long)atmel_gpio_read(atmel_pioctrl, bank, 28177618084SLudovic Desroches ATMEL_PIO_IMR); 28277618084SLudovic Desroches if (!isr) 28377618084SLudovic Desroches break; 28477618084SLudovic Desroches 28577618084SLudovic Desroches for_each_set_bit(n, &isr, BITS_PER_LONG) 28677618084SLudovic Desroches generic_handle_irq(gpio_to_irq(bank * 28777618084SLudovic Desroches ATMEL_PIO_NPINS_PER_BANK + n)); 28877618084SLudovic Desroches } 28977618084SLudovic Desroches 29077618084SLudovic Desroches chained_irq_exit(chip, desc); 29177618084SLudovic Desroches } 29277618084SLudovic Desroches 29377618084SLudovic Desroches static int atmel_gpio_direction_input(struct gpio_chip *chip, unsigned offset) 29477618084SLudovic Desroches { 295*80036f88SLinus Walleij struct atmel_pioctrl *atmel_pioctrl = gpiochip_get_data(chip); 29677618084SLudovic Desroches struct atmel_pin *pin = atmel_pioctrl->pins[offset]; 29777618084SLudovic Desroches unsigned reg; 29877618084SLudovic Desroches 29977618084SLudovic Desroches atmel_gpio_write(atmel_pioctrl, pin->bank, ATMEL_PIO_MSKR, 30077618084SLudovic Desroches BIT(pin->line)); 30177618084SLudovic Desroches reg = atmel_gpio_read(atmel_pioctrl, pin->bank, ATMEL_PIO_CFGR); 30277618084SLudovic Desroches reg &= ~ATMEL_PIO_DIR_MASK; 30377618084SLudovic Desroches atmel_gpio_write(atmel_pioctrl, pin->bank, ATMEL_PIO_CFGR, reg); 30477618084SLudovic Desroches 30577618084SLudovic Desroches return 0; 30677618084SLudovic Desroches } 30777618084SLudovic Desroches 30877618084SLudovic Desroches static int atmel_gpio_get(struct gpio_chip *chip, unsigned offset) 30977618084SLudovic Desroches { 310*80036f88SLinus Walleij struct atmel_pioctrl *atmel_pioctrl = gpiochip_get_data(chip); 31177618084SLudovic Desroches struct atmel_pin *pin = atmel_pioctrl->pins[offset]; 31277618084SLudovic Desroches unsigned reg; 31377618084SLudovic Desroches 31477618084SLudovic Desroches reg = atmel_gpio_read(atmel_pioctrl, pin->bank, ATMEL_PIO_PDSR); 31577618084SLudovic Desroches 31677618084SLudovic Desroches return !!(reg & BIT(pin->line)); 31777618084SLudovic Desroches } 31877618084SLudovic Desroches 31977618084SLudovic Desroches static int atmel_gpio_direction_output(struct gpio_chip *chip, unsigned offset, 32077618084SLudovic Desroches int value) 32177618084SLudovic Desroches { 322*80036f88SLinus Walleij struct atmel_pioctrl *atmel_pioctrl = gpiochip_get_data(chip); 32377618084SLudovic Desroches struct atmel_pin *pin = atmel_pioctrl->pins[offset]; 32477618084SLudovic Desroches unsigned reg; 32577618084SLudovic Desroches 32677618084SLudovic Desroches atmel_gpio_write(atmel_pioctrl, pin->bank, 32777618084SLudovic Desroches value ? ATMEL_PIO_SODR : ATMEL_PIO_CODR, 32877618084SLudovic Desroches BIT(pin->line)); 32977618084SLudovic Desroches 33077618084SLudovic Desroches atmel_gpio_write(atmel_pioctrl, pin->bank, ATMEL_PIO_MSKR, 33177618084SLudovic Desroches BIT(pin->line)); 33277618084SLudovic Desroches reg = atmel_gpio_read(atmel_pioctrl, pin->bank, ATMEL_PIO_CFGR); 33377618084SLudovic Desroches reg |= ATMEL_PIO_DIR_MASK; 33477618084SLudovic Desroches atmel_gpio_write(atmel_pioctrl, pin->bank, ATMEL_PIO_CFGR, reg); 33577618084SLudovic Desroches 33677618084SLudovic Desroches return 0; 33777618084SLudovic Desroches } 33877618084SLudovic Desroches 33977618084SLudovic Desroches static void atmel_gpio_set(struct gpio_chip *chip, unsigned offset, int val) 34077618084SLudovic Desroches { 341*80036f88SLinus Walleij struct atmel_pioctrl *atmel_pioctrl = gpiochip_get_data(chip); 34277618084SLudovic Desroches struct atmel_pin *pin = atmel_pioctrl->pins[offset]; 34377618084SLudovic Desroches 34477618084SLudovic Desroches atmel_gpio_write(atmel_pioctrl, pin->bank, 34577618084SLudovic Desroches val ? ATMEL_PIO_SODR : ATMEL_PIO_CODR, 34677618084SLudovic Desroches BIT(pin->line)); 34777618084SLudovic Desroches } 34877618084SLudovic Desroches 34977618084SLudovic Desroches static int atmel_gpio_to_irq(struct gpio_chip *chip, unsigned offset) 35077618084SLudovic Desroches { 351*80036f88SLinus Walleij struct atmel_pioctrl *atmel_pioctrl = gpiochip_get_data(chip); 35277618084SLudovic Desroches 35377618084SLudovic Desroches return irq_find_mapping(atmel_pioctrl->irq_domain, offset); 35477618084SLudovic Desroches } 35577618084SLudovic Desroches 35677618084SLudovic Desroches static struct gpio_chip atmel_gpio_chip = { 35777618084SLudovic Desroches .direction_input = atmel_gpio_direction_input, 35877618084SLudovic Desroches .get = atmel_gpio_get, 35977618084SLudovic Desroches .direction_output = atmel_gpio_direction_output, 36077618084SLudovic Desroches .set = atmel_gpio_set, 36177618084SLudovic Desroches .to_irq = atmel_gpio_to_irq, 36277618084SLudovic Desroches .base = 0, 36377618084SLudovic Desroches }; 36477618084SLudovic Desroches 36577618084SLudovic Desroches /* --- PINCTRL --- */ 36677618084SLudovic Desroches static unsigned int atmel_pin_config_read(struct pinctrl_dev *pctldev, 36777618084SLudovic Desroches unsigned pin_id) 36877618084SLudovic Desroches { 36977618084SLudovic Desroches struct atmel_pioctrl *atmel_pioctrl = pinctrl_dev_get_drvdata(pctldev); 37077618084SLudovic Desroches unsigned bank = atmel_pioctrl->pins[pin_id]->bank; 37177618084SLudovic Desroches unsigned line = atmel_pioctrl->pins[pin_id]->line; 37277618084SLudovic Desroches void __iomem *addr = atmel_pioctrl->reg_base 37377618084SLudovic Desroches + bank * ATMEL_PIO_BANK_OFFSET; 37477618084SLudovic Desroches 37577618084SLudovic Desroches writel_relaxed(BIT(line), addr + ATMEL_PIO_MSKR); 37677618084SLudovic Desroches /* Have to set MSKR first, to access the right pin CFGR. */ 37777618084SLudovic Desroches wmb(); 37877618084SLudovic Desroches 37977618084SLudovic Desroches return readl_relaxed(addr + ATMEL_PIO_CFGR); 38077618084SLudovic Desroches } 38177618084SLudovic Desroches 38277618084SLudovic Desroches static void atmel_pin_config_write(struct pinctrl_dev *pctldev, 38377618084SLudovic Desroches unsigned pin_id, u32 conf) 38477618084SLudovic Desroches { 38577618084SLudovic Desroches struct atmel_pioctrl *atmel_pioctrl = pinctrl_dev_get_drvdata(pctldev); 38677618084SLudovic Desroches unsigned bank = atmel_pioctrl->pins[pin_id]->bank; 38777618084SLudovic Desroches unsigned line = atmel_pioctrl->pins[pin_id]->line; 38877618084SLudovic Desroches void __iomem *addr = atmel_pioctrl->reg_base 38977618084SLudovic Desroches + bank * ATMEL_PIO_BANK_OFFSET; 39077618084SLudovic Desroches 39177618084SLudovic Desroches writel_relaxed(BIT(line), addr + ATMEL_PIO_MSKR); 39277618084SLudovic Desroches /* Have to set MSKR first, to access the right pin CFGR. */ 39377618084SLudovic Desroches wmb(); 39477618084SLudovic Desroches writel_relaxed(conf, addr + ATMEL_PIO_CFGR); 39577618084SLudovic Desroches } 39677618084SLudovic Desroches 39777618084SLudovic Desroches static int atmel_pctl_get_groups_count(struct pinctrl_dev *pctldev) 39877618084SLudovic Desroches { 39977618084SLudovic Desroches struct atmel_pioctrl *atmel_pioctrl = pinctrl_dev_get_drvdata(pctldev); 40077618084SLudovic Desroches 40177618084SLudovic Desroches return atmel_pioctrl->npins; 40277618084SLudovic Desroches } 40377618084SLudovic Desroches 40477618084SLudovic Desroches static const char *atmel_pctl_get_group_name(struct pinctrl_dev *pctldev, 40577618084SLudovic Desroches unsigned selector) 40677618084SLudovic Desroches { 40777618084SLudovic Desroches struct atmel_pioctrl *atmel_pioctrl = pinctrl_dev_get_drvdata(pctldev); 40877618084SLudovic Desroches 40977618084SLudovic Desroches return atmel_pioctrl->groups[selector].name; 41077618084SLudovic Desroches } 41177618084SLudovic Desroches 41277618084SLudovic Desroches static int atmel_pctl_get_group_pins(struct pinctrl_dev *pctldev, 41377618084SLudovic Desroches unsigned selector, const unsigned **pins, 41477618084SLudovic Desroches unsigned *num_pins) 41577618084SLudovic Desroches { 41677618084SLudovic Desroches struct atmel_pioctrl *atmel_pioctrl = pinctrl_dev_get_drvdata(pctldev); 41777618084SLudovic Desroches 41877618084SLudovic Desroches *pins = (unsigned *)&atmel_pioctrl->groups[selector].pin; 41977618084SLudovic Desroches *num_pins = 1; 42077618084SLudovic Desroches 42177618084SLudovic Desroches return 0; 42277618084SLudovic Desroches } 42377618084SLudovic Desroches 42477618084SLudovic Desroches struct atmel_group *atmel_pctl_find_group_by_pin(struct pinctrl_dev *pctldev, 42577618084SLudovic Desroches unsigned pin) 42677618084SLudovic Desroches { 42777618084SLudovic Desroches struct atmel_pioctrl *atmel_pioctrl = pinctrl_dev_get_drvdata(pctldev); 42877618084SLudovic Desroches int i; 42977618084SLudovic Desroches 43077618084SLudovic Desroches for (i = 0; i < atmel_pioctrl->npins; i++) { 43177618084SLudovic Desroches struct atmel_group *grp = atmel_pioctrl->groups + i; 43277618084SLudovic Desroches 43377618084SLudovic Desroches if (grp->pin == pin) 43477618084SLudovic Desroches return grp; 43577618084SLudovic Desroches } 43677618084SLudovic Desroches 43777618084SLudovic Desroches return NULL; 43877618084SLudovic Desroches } 43977618084SLudovic Desroches 44077618084SLudovic Desroches static int atmel_pctl_xlate_pinfunc(struct pinctrl_dev *pctldev, 44177618084SLudovic Desroches struct device_node *np, 44277618084SLudovic Desroches u32 pinfunc, const char **grp_name, 44377618084SLudovic Desroches const char **func_name) 44477618084SLudovic Desroches { 44577618084SLudovic Desroches struct atmel_pioctrl *atmel_pioctrl = pinctrl_dev_get_drvdata(pctldev); 44677618084SLudovic Desroches unsigned pin_id, func_id; 44777618084SLudovic Desroches struct atmel_group *grp; 44877618084SLudovic Desroches 44977618084SLudovic Desroches pin_id = ATMEL_GET_PIN_NO(pinfunc); 45077618084SLudovic Desroches func_id = ATMEL_GET_PIN_FUNC(pinfunc); 45177618084SLudovic Desroches 45277618084SLudovic Desroches if (func_id >= ARRAY_SIZE(atmel_functions)) 45377618084SLudovic Desroches return -EINVAL; 45477618084SLudovic Desroches 45577618084SLudovic Desroches *func_name = atmel_functions[func_id]; 45677618084SLudovic Desroches 45777618084SLudovic Desroches grp = atmel_pctl_find_group_by_pin(pctldev, pin_id); 45877618084SLudovic Desroches if (!grp) 45977618084SLudovic Desroches return -EINVAL; 46077618084SLudovic Desroches *grp_name = grp->name; 46177618084SLudovic Desroches 46277618084SLudovic Desroches atmel_pioctrl->pins[pin_id]->mux = func_id; 46377618084SLudovic Desroches atmel_pioctrl->pins[pin_id]->ioset = ATMEL_GET_PIN_IOSET(pinfunc); 46477618084SLudovic Desroches /* Want the device name not the group one. */ 46577618084SLudovic Desroches if (np->parent == atmel_pioctrl->node) 46677618084SLudovic Desroches atmel_pioctrl->pins[pin_id]->device = np->name; 46777618084SLudovic Desroches else 46877618084SLudovic Desroches atmel_pioctrl->pins[pin_id]->device = np->parent->name; 46977618084SLudovic Desroches 47077618084SLudovic Desroches return 0; 47177618084SLudovic Desroches } 47277618084SLudovic Desroches 47377618084SLudovic Desroches static int atmel_pctl_dt_subnode_to_map(struct pinctrl_dev *pctldev, 47477618084SLudovic Desroches struct device_node *np, 47577618084SLudovic Desroches struct pinctrl_map **map, 47677618084SLudovic Desroches unsigned *reserved_maps, 47777618084SLudovic Desroches unsigned *num_maps) 47877618084SLudovic Desroches { 47977618084SLudovic Desroches unsigned num_pins, num_configs, reserve; 48077618084SLudovic Desroches unsigned long *configs; 48177618084SLudovic Desroches struct property *pins; 48277618084SLudovic Desroches bool has_config; 48377618084SLudovic Desroches u32 pinfunc; 48477618084SLudovic Desroches int ret, i; 48577618084SLudovic Desroches 48677618084SLudovic Desroches pins = of_find_property(np, "pinmux", NULL); 48777618084SLudovic Desroches if (!pins) 48877618084SLudovic Desroches return -EINVAL; 48977618084SLudovic Desroches 49077618084SLudovic Desroches ret = pinconf_generic_parse_dt_config(np, pctldev, &configs, 49177618084SLudovic Desroches &num_configs); 49277618084SLudovic Desroches if (ret < 0) { 49377618084SLudovic Desroches dev_err(pctldev->dev, "%s: could not parse node property\n", 49477618084SLudovic Desroches of_node_full_name(np)); 49577618084SLudovic Desroches return ret; 49677618084SLudovic Desroches } 49777618084SLudovic Desroches 49877618084SLudovic Desroches if (num_configs) 49977618084SLudovic Desroches has_config = true; 50077618084SLudovic Desroches 50177618084SLudovic Desroches num_pins = pins->length / sizeof(u32); 50277618084SLudovic Desroches if (!num_pins) { 50377618084SLudovic Desroches dev_err(pctldev->dev, "no pins found in node %s\n", 50477618084SLudovic Desroches of_node_full_name(np)); 50577618084SLudovic Desroches return -EINVAL; 50677618084SLudovic Desroches } 50777618084SLudovic Desroches 50877618084SLudovic Desroches /* 50977618084SLudovic Desroches * Reserve maps, at least there is a mux map and an optional conf 51077618084SLudovic Desroches * map for each pin. 51177618084SLudovic Desroches */ 51277618084SLudovic Desroches reserve = 1; 51377618084SLudovic Desroches if (has_config && num_pins >= 1) 51477618084SLudovic Desroches reserve++; 51577618084SLudovic Desroches reserve *= num_pins; 51677618084SLudovic Desroches ret = pinctrl_utils_reserve_map(pctldev, map, reserved_maps, num_maps, 51777618084SLudovic Desroches reserve); 51877618084SLudovic Desroches if (ret < 0) 51977618084SLudovic Desroches return ret; 52077618084SLudovic Desroches 52177618084SLudovic Desroches for (i = 0; i < num_pins; i++) { 52277618084SLudovic Desroches const char *group, *func; 52377618084SLudovic Desroches 52477618084SLudovic Desroches ret = of_property_read_u32_index(np, "pinmux", i, &pinfunc); 52577618084SLudovic Desroches if (ret) 52677618084SLudovic Desroches return ret; 52777618084SLudovic Desroches 52877618084SLudovic Desroches ret = atmel_pctl_xlate_pinfunc(pctldev, np, pinfunc, &group, 52977618084SLudovic Desroches &func); 53077618084SLudovic Desroches if (ret) 53177618084SLudovic Desroches return ret; 53277618084SLudovic Desroches 53377618084SLudovic Desroches pinctrl_utils_add_map_mux(pctldev, map, reserved_maps, num_maps, 53477618084SLudovic Desroches group, func); 53577618084SLudovic Desroches 53677618084SLudovic Desroches if (has_config) { 53777618084SLudovic Desroches ret = pinctrl_utils_add_map_configs(pctldev, map, 53877618084SLudovic Desroches reserved_maps, num_maps, group, 53977618084SLudovic Desroches configs, num_configs, 54077618084SLudovic Desroches PIN_MAP_TYPE_CONFIGS_GROUP); 54177618084SLudovic Desroches if (ret < 0) 54277618084SLudovic Desroches return ret; 54377618084SLudovic Desroches } 54477618084SLudovic Desroches } 54577618084SLudovic Desroches 54677618084SLudovic Desroches return 0; 54777618084SLudovic Desroches } 54877618084SLudovic Desroches 54977618084SLudovic Desroches static int atmel_pctl_dt_node_to_map(struct pinctrl_dev *pctldev, 55077618084SLudovic Desroches struct device_node *np_config, 55177618084SLudovic Desroches struct pinctrl_map **map, 55277618084SLudovic Desroches unsigned *num_maps) 55377618084SLudovic Desroches { 55477618084SLudovic Desroches struct device_node *np; 55577618084SLudovic Desroches unsigned reserved_maps; 55677618084SLudovic Desroches int ret; 55777618084SLudovic Desroches 55877618084SLudovic Desroches *map = NULL; 55977618084SLudovic Desroches *num_maps = 0; 56077618084SLudovic Desroches reserved_maps = 0; 56177618084SLudovic Desroches 56277618084SLudovic Desroches /* 56377618084SLudovic Desroches * If all the pins of a device have the same configuration (or no one), 56477618084SLudovic Desroches * it is useless to add a subnode, so directly parse node referenced by 56577618084SLudovic Desroches * phandle. 56677618084SLudovic Desroches */ 56777618084SLudovic Desroches ret = atmel_pctl_dt_subnode_to_map(pctldev, np_config, map, 56877618084SLudovic Desroches &reserved_maps, num_maps); 56977618084SLudovic Desroches if (ret) { 57077618084SLudovic Desroches for_each_child_of_node(np_config, np) { 57177618084SLudovic Desroches ret = atmel_pctl_dt_subnode_to_map(pctldev, np, map, 57277618084SLudovic Desroches &reserved_maps, num_maps); 57377618084SLudovic Desroches if (ret < 0) 57477618084SLudovic Desroches break; 57577618084SLudovic Desroches } 57677618084SLudovic Desroches } 57777618084SLudovic Desroches 57877618084SLudovic Desroches if (ret < 0) { 57977618084SLudovic Desroches pinctrl_utils_dt_free_map(pctldev, *map, *num_maps); 58077618084SLudovic Desroches dev_err(pctldev->dev, "can't create maps for node %s\n", 58177618084SLudovic Desroches np_config->full_name); 58277618084SLudovic Desroches } 58377618084SLudovic Desroches 58477618084SLudovic Desroches return ret; 58577618084SLudovic Desroches } 58677618084SLudovic Desroches 58777618084SLudovic Desroches static const struct pinctrl_ops atmel_pctlops = { 58877618084SLudovic Desroches .get_groups_count = atmel_pctl_get_groups_count, 58977618084SLudovic Desroches .get_group_name = atmel_pctl_get_group_name, 59077618084SLudovic Desroches .get_group_pins = atmel_pctl_get_group_pins, 59177618084SLudovic Desroches .dt_node_to_map = atmel_pctl_dt_node_to_map, 59277618084SLudovic Desroches .dt_free_map = pinctrl_utils_dt_free_map, 59377618084SLudovic Desroches }; 59477618084SLudovic Desroches 59577618084SLudovic Desroches static int atmel_pmx_get_functions_count(struct pinctrl_dev *pctldev) 59677618084SLudovic Desroches { 59777618084SLudovic Desroches return ARRAY_SIZE(atmel_functions); 59877618084SLudovic Desroches } 59977618084SLudovic Desroches 60077618084SLudovic Desroches static const char *atmel_pmx_get_function_name(struct pinctrl_dev *pctldev, 60177618084SLudovic Desroches unsigned selector) 60277618084SLudovic Desroches { 60377618084SLudovic Desroches return atmel_functions[selector]; 60477618084SLudovic Desroches } 60577618084SLudovic Desroches 60677618084SLudovic Desroches static int atmel_pmx_get_function_groups(struct pinctrl_dev *pctldev, 60777618084SLudovic Desroches unsigned selector, 60877618084SLudovic Desroches const char * const **groups, 60977618084SLudovic Desroches unsigned * const num_groups) 61077618084SLudovic Desroches { 61177618084SLudovic Desroches struct atmel_pioctrl *atmel_pioctrl = pinctrl_dev_get_drvdata(pctldev); 61277618084SLudovic Desroches 61377618084SLudovic Desroches *groups = atmel_pioctrl->group_names; 61477618084SLudovic Desroches *num_groups = atmel_pioctrl->npins; 61577618084SLudovic Desroches 61677618084SLudovic Desroches return 0; 61777618084SLudovic Desroches } 61877618084SLudovic Desroches 61977618084SLudovic Desroches static int atmel_pmx_set_mux(struct pinctrl_dev *pctldev, 62077618084SLudovic Desroches unsigned function, 62177618084SLudovic Desroches unsigned group) 62277618084SLudovic Desroches { 62377618084SLudovic Desroches struct atmel_pioctrl *atmel_pioctrl = pinctrl_dev_get_drvdata(pctldev); 62477618084SLudovic Desroches unsigned pin; 62577618084SLudovic Desroches u32 conf; 62677618084SLudovic Desroches 62777618084SLudovic Desroches dev_dbg(pctldev->dev, "enable function %s group %s\n", 62877618084SLudovic Desroches atmel_functions[function], atmel_pioctrl->groups[group].name); 62977618084SLudovic Desroches 63077618084SLudovic Desroches pin = atmel_pioctrl->groups[group].pin; 63177618084SLudovic Desroches conf = atmel_pin_config_read(pctldev, pin); 63277618084SLudovic Desroches conf &= (~ATMEL_PIO_CFGR_FUNC_MASK); 63377618084SLudovic Desroches conf |= (function & ATMEL_PIO_CFGR_FUNC_MASK); 63477618084SLudovic Desroches dev_dbg(pctldev->dev, "pin: %u, conf: 0x%08x\n", pin, conf); 63577618084SLudovic Desroches atmel_pin_config_write(pctldev, pin, conf); 63677618084SLudovic Desroches 63777618084SLudovic Desroches return 0; 63877618084SLudovic Desroches } 63977618084SLudovic Desroches 64077618084SLudovic Desroches static const struct pinmux_ops atmel_pmxops = { 64177618084SLudovic Desroches .get_functions_count = atmel_pmx_get_functions_count, 64277618084SLudovic Desroches .get_function_name = atmel_pmx_get_function_name, 64377618084SLudovic Desroches .get_function_groups = atmel_pmx_get_function_groups, 64477618084SLudovic Desroches .set_mux = atmel_pmx_set_mux, 64577618084SLudovic Desroches }; 64677618084SLudovic Desroches 64777618084SLudovic Desroches static int atmel_conf_pin_config_group_get(struct pinctrl_dev *pctldev, 64877618084SLudovic Desroches unsigned group, 64977618084SLudovic Desroches unsigned long *config) 65077618084SLudovic Desroches { 65177618084SLudovic Desroches struct atmel_pioctrl *atmel_pioctrl = pinctrl_dev_get_drvdata(pctldev); 65277618084SLudovic Desroches unsigned param = pinconf_to_config_param(*config), arg = 0; 65377618084SLudovic Desroches struct atmel_group *grp = atmel_pioctrl->groups + group; 65477618084SLudovic Desroches unsigned pin_id = grp->pin; 65577618084SLudovic Desroches u32 res; 65677618084SLudovic Desroches 65777618084SLudovic Desroches res = atmel_pin_config_read(pctldev, pin_id); 65877618084SLudovic Desroches 65977618084SLudovic Desroches switch (param) { 66077618084SLudovic Desroches case PIN_CONFIG_BIAS_PULL_UP: 66177618084SLudovic Desroches if (!(res & ATMEL_PIO_PUEN_MASK)) 66277618084SLudovic Desroches return -EINVAL; 66377618084SLudovic Desroches arg = 1; 66477618084SLudovic Desroches break; 66577618084SLudovic Desroches case PIN_CONFIG_BIAS_PULL_DOWN: 66677618084SLudovic Desroches if ((res & ATMEL_PIO_PUEN_MASK) || 66777618084SLudovic Desroches (!(res & ATMEL_PIO_PDEN_MASK))) 66877618084SLudovic Desroches return -EINVAL; 66977618084SLudovic Desroches arg = 1; 67077618084SLudovic Desroches break; 67177618084SLudovic Desroches case PIN_CONFIG_BIAS_DISABLE: 67277618084SLudovic Desroches if ((res & ATMEL_PIO_PUEN_MASK) || 67377618084SLudovic Desroches ((res & ATMEL_PIO_PDEN_MASK))) 67477618084SLudovic Desroches return -EINVAL; 67577618084SLudovic Desroches arg = 1; 67677618084SLudovic Desroches break; 67777618084SLudovic Desroches case PIN_CONFIG_DRIVE_OPEN_DRAIN: 67877618084SLudovic Desroches if (!(res & ATMEL_PIO_OPD_MASK)) 67977618084SLudovic Desroches return -EINVAL; 68077618084SLudovic Desroches arg = 1; 68177618084SLudovic Desroches break; 68277618084SLudovic Desroches case PIN_CONFIG_INPUT_SCHMITT_ENABLE: 68377618084SLudovic Desroches if (!(res & ATMEL_PIO_SCHMITT_MASK)) 68477618084SLudovic Desroches return -EINVAL; 68577618084SLudovic Desroches arg = 1; 68677618084SLudovic Desroches break; 68777618084SLudovic Desroches default: 68877618084SLudovic Desroches return -ENOTSUPP; 68977618084SLudovic Desroches } 69077618084SLudovic Desroches 69177618084SLudovic Desroches *config = pinconf_to_config_packed(param, arg); 69277618084SLudovic Desroches return 0; 69377618084SLudovic Desroches } 69477618084SLudovic Desroches 69577618084SLudovic Desroches static int atmel_conf_pin_config_group_set(struct pinctrl_dev *pctldev, 69677618084SLudovic Desroches unsigned group, 69777618084SLudovic Desroches unsigned long *configs, 69877618084SLudovic Desroches unsigned num_configs) 69977618084SLudovic Desroches { 70077618084SLudovic Desroches struct atmel_pioctrl *atmel_pioctrl = pinctrl_dev_get_drvdata(pctldev); 70177618084SLudovic Desroches struct atmel_group *grp = atmel_pioctrl->groups + group; 70277618084SLudovic Desroches unsigned bank, pin, pin_id = grp->pin; 70377618084SLudovic Desroches u32 mask, conf = 0; 70477618084SLudovic Desroches int i; 70577618084SLudovic Desroches 70677618084SLudovic Desroches conf = atmel_pin_config_read(pctldev, pin_id); 70777618084SLudovic Desroches 70877618084SLudovic Desroches for (i = 0; i < num_configs; i++) { 70977618084SLudovic Desroches unsigned param = pinconf_to_config_param(configs[i]); 71077618084SLudovic Desroches unsigned arg = pinconf_to_config_argument(configs[i]); 71177618084SLudovic Desroches 71277618084SLudovic Desroches dev_dbg(pctldev->dev, "%s: pin=%u, config=0x%lx\n", 71377618084SLudovic Desroches __func__, pin_id, configs[i]); 71477618084SLudovic Desroches 71577618084SLudovic Desroches switch (param) { 71677618084SLudovic Desroches case PIN_CONFIG_BIAS_DISABLE: 71777618084SLudovic Desroches conf &= (~ATMEL_PIO_PUEN_MASK); 71877618084SLudovic Desroches conf &= (~ATMEL_PIO_PDEN_MASK); 71977618084SLudovic Desroches break; 72077618084SLudovic Desroches case PIN_CONFIG_BIAS_PULL_UP: 72177618084SLudovic Desroches conf |= ATMEL_PIO_PUEN_MASK; 72277618084SLudovic Desroches break; 72377618084SLudovic Desroches case PIN_CONFIG_BIAS_PULL_DOWN: 72477618084SLudovic Desroches conf |= ATMEL_PIO_PDEN_MASK; 72577618084SLudovic Desroches break; 72677618084SLudovic Desroches case PIN_CONFIG_DRIVE_OPEN_DRAIN: 72777618084SLudovic Desroches if (arg == 0) 72877618084SLudovic Desroches conf &= (~ATMEL_PIO_OPD_MASK); 72977618084SLudovic Desroches else 73077618084SLudovic Desroches conf |= ATMEL_PIO_OPD_MASK; 73177618084SLudovic Desroches break; 73277618084SLudovic Desroches case PIN_CONFIG_INPUT_SCHMITT_ENABLE: 73377618084SLudovic Desroches if (arg == 0) 73477618084SLudovic Desroches conf |= ATMEL_PIO_SCHMITT_MASK; 73577618084SLudovic Desroches else 73677618084SLudovic Desroches conf &= (~ATMEL_PIO_SCHMITT_MASK); 73777618084SLudovic Desroches break; 73877618084SLudovic Desroches case PIN_CONFIG_INPUT_DEBOUNCE: 73977618084SLudovic Desroches if (arg == 0) { 74077618084SLudovic Desroches conf &= (~ATMEL_PIO_IFEN_MASK); 74177618084SLudovic Desroches conf &= (~ATMEL_PIO_IFSCEN_MASK); 74277618084SLudovic Desroches } else { 74377618084SLudovic Desroches /* 74477618084SLudovic Desroches * We don't care about the debounce value for several reasons: 74577618084SLudovic Desroches * - can't have different debounce periods inside a same group, 74677618084SLudovic Desroches * - the register to configure this period is a secure register. 74777618084SLudovic Desroches * The debouncing filter can filter a pulse with a duration of less 74877618084SLudovic Desroches * than 1/2 slow clock period. 74977618084SLudovic Desroches */ 75077618084SLudovic Desroches conf |= ATMEL_PIO_IFEN_MASK; 75177618084SLudovic Desroches conf |= ATMEL_PIO_IFSCEN_MASK; 75277618084SLudovic Desroches } 75377618084SLudovic Desroches break; 75477618084SLudovic Desroches case PIN_CONFIG_OUTPUT: 75577618084SLudovic Desroches conf |= ATMEL_PIO_DIR_MASK; 75677618084SLudovic Desroches bank = ATMEL_PIO_BANK(pin_id); 75777618084SLudovic Desroches pin = ATMEL_PIO_LINE(pin_id); 75877618084SLudovic Desroches mask = 1 << pin; 75977618084SLudovic Desroches 76077618084SLudovic Desroches if (arg == 0) { 76177618084SLudovic Desroches writel_relaxed(mask, atmel_pioctrl->reg_base + 76277618084SLudovic Desroches bank * ATMEL_PIO_BANK_OFFSET + 76377618084SLudovic Desroches ATMEL_PIO_CODR); 76477618084SLudovic Desroches } else { 76577618084SLudovic Desroches writel_relaxed(mask, atmel_pioctrl->reg_base + 76677618084SLudovic Desroches bank * ATMEL_PIO_BANK_OFFSET + 76777618084SLudovic Desroches ATMEL_PIO_SODR); 76877618084SLudovic Desroches } 76977618084SLudovic Desroches break; 77077618084SLudovic Desroches default: 77177618084SLudovic Desroches dev_warn(pctldev->dev, 77277618084SLudovic Desroches "unsupported configuration parameter: %u\n", 77377618084SLudovic Desroches param); 77477618084SLudovic Desroches continue; 77577618084SLudovic Desroches } 77677618084SLudovic Desroches } 77777618084SLudovic Desroches 77877618084SLudovic Desroches dev_dbg(pctldev->dev, "%s: reg=0x%08x\n", __func__, conf); 77977618084SLudovic Desroches atmel_pin_config_write(pctldev, pin_id, conf); 78077618084SLudovic Desroches 78177618084SLudovic Desroches return 0; 78277618084SLudovic Desroches } 78377618084SLudovic Desroches 78477618084SLudovic Desroches static void atmel_conf_pin_config_dbg_show(struct pinctrl_dev *pctldev, 78577618084SLudovic Desroches struct seq_file *s, unsigned pin_id) 78677618084SLudovic Desroches { 78777618084SLudovic Desroches struct atmel_pioctrl *atmel_pioctrl = pinctrl_dev_get_drvdata(pctldev); 78877618084SLudovic Desroches u32 conf; 78977618084SLudovic Desroches 79077618084SLudovic Desroches if (!atmel_pioctrl->pins[pin_id]->device) 79177618084SLudovic Desroches return; 79277618084SLudovic Desroches 79377618084SLudovic Desroches if (atmel_pioctrl->pins[pin_id]) 79477618084SLudovic Desroches seq_printf(s, " (%s, ioset %u) ", 79577618084SLudovic Desroches atmel_pioctrl->pins[pin_id]->device, 79677618084SLudovic Desroches atmel_pioctrl->pins[pin_id]->ioset); 79777618084SLudovic Desroches 79877618084SLudovic Desroches conf = atmel_pin_config_read(pctldev, pin_id); 79977618084SLudovic Desroches if (conf & ATMEL_PIO_PUEN_MASK) 80077618084SLudovic Desroches seq_printf(s, "%s ", "pull-up"); 80177618084SLudovic Desroches if (conf & ATMEL_PIO_PDEN_MASK) 80277618084SLudovic Desroches seq_printf(s, "%s ", "pull-down"); 80377618084SLudovic Desroches if (conf & ATMEL_PIO_IFEN_MASK) 80477618084SLudovic Desroches seq_printf(s, "%s ", "debounce"); 80577618084SLudovic Desroches if (conf & ATMEL_PIO_OPD_MASK) 80677618084SLudovic Desroches seq_printf(s, "%s ", "open-drain"); 80777618084SLudovic Desroches if (conf & ATMEL_PIO_SCHMITT_MASK) 80877618084SLudovic Desroches seq_printf(s, "%s ", "schmitt"); 80977618084SLudovic Desroches } 81077618084SLudovic Desroches 81177618084SLudovic Desroches static const struct pinconf_ops atmel_confops = { 81277618084SLudovic Desroches .pin_config_group_get = atmel_conf_pin_config_group_get, 81377618084SLudovic Desroches .pin_config_group_set = atmel_conf_pin_config_group_set, 81477618084SLudovic Desroches .pin_config_dbg_show = atmel_conf_pin_config_dbg_show, 81577618084SLudovic Desroches }; 81677618084SLudovic Desroches 81777618084SLudovic Desroches static struct pinctrl_desc atmel_pinctrl_desc = { 81877618084SLudovic Desroches .name = "atmel_pinctrl", 81977618084SLudovic Desroches .confops = &atmel_confops, 82077618084SLudovic Desroches .pctlops = &atmel_pctlops, 82177618084SLudovic Desroches .pmxops = &atmel_pmxops, 82277618084SLudovic Desroches }; 82377618084SLudovic Desroches 824de4e882fSLudovic Desroches static int atmel_pctrl_suspend(struct device *dev) 825de4e882fSLudovic Desroches { 826de4e882fSLudovic Desroches struct platform_device *pdev = to_platform_device(dev); 827de4e882fSLudovic Desroches struct atmel_pioctrl *atmel_pioctrl = platform_get_drvdata(pdev); 828de4e882fSLudovic Desroches int i; 829de4e882fSLudovic Desroches 830de4e882fSLudovic Desroches /* 831de4e882fSLudovic Desroches * For each bank, save IMR to restore it later and disable all GPIO 832de4e882fSLudovic Desroches * interrupts excepting the ones marked as wakeup sources. 833de4e882fSLudovic Desroches */ 834de4e882fSLudovic Desroches for (i = 0; i < atmel_pioctrl->nbanks; i++) { 835de4e882fSLudovic Desroches atmel_pioctrl->pm_suspend_backup[i] = 836de4e882fSLudovic Desroches atmel_gpio_read(atmel_pioctrl, i, ATMEL_PIO_IMR); 837de4e882fSLudovic Desroches atmel_gpio_write(atmel_pioctrl, i, ATMEL_PIO_IDR, 838de4e882fSLudovic Desroches ~atmel_pioctrl->pm_wakeup_sources[i]); 839de4e882fSLudovic Desroches } 840de4e882fSLudovic Desroches 841de4e882fSLudovic Desroches return 0; 842de4e882fSLudovic Desroches } 843de4e882fSLudovic Desroches 844de4e882fSLudovic Desroches static int atmel_pctrl_resume(struct device *dev) 845de4e882fSLudovic Desroches { 846de4e882fSLudovic Desroches struct platform_device *pdev = to_platform_device(dev); 847de4e882fSLudovic Desroches struct atmel_pioctrl *atmel_pioctrl = platform_get_drvdata(pdev); 848de4e882fSLudovic Desroches int i; 849de4e882fSLudovic Desroches 850de4e882fSLudovic Desroches for (i = 0; i < atmel_pioctrl->nbanks; i++) 851de4e882fSLudovic Desroches atmel_gpio_write(atmel_pioctrl, i, ATMEL_PIO_IER, 852de4e882fSLudovic Desroches atmel_pioctrl->pm_suspend_backup[i]); 853de4e882fSLudovic Desroches 854de4e882fSLudovic Desroches return 0; 855de4e882fSLudovic Desroches } 856de4e882fSLudovic Desroches 857de4e882fSLudovic Desroches static const struct dev_pm_ops atmel_pctrl_pm_ops = { 858de4e882fSLudovic Desroches SET_SYSTEM_SLEEP_PM_OPS(atmel_pctrl_suspend, atmel_pctrl_resume) 859de4e882fSLudovic Desroches }; 860de4e882fSLudovic Desroches 86177618084SLudovic Desroches /* 86277618084SLudovic Desroches * The number of banks can be different from a SoC to another one. 86377618084SLudovic Desroches * We can have up to 16 banks. 86477618084SLudovic Desroches */ 86577618084SLudovic Desroches static const struct atmel_pioctrl_data atmel_sama5d2_pioctrl_data = { 86677618084SLudovic Desroches .nbanks = 4, 86777618084SLudovic Desroches }; 86877618084SLudovic Desroches 86977618084SLudovic Desroches static const struct of_device_id atmel_pctrl_of_match[] = { 87077618084SLudovic Desroches { 87177618084SLudovic Desroches .compatible = "atmel,sama5d2-pinctrl", 87277618084SLudovic Desroches .data = &atmel_sama5d2_pioctrl_data, 87377618084SLudovic Desroches }, { 87477618084SLudovic Desroches /* sentinel */ 87577618084SLudovic Desroches } 87677618084SLudovic Desroches }; 87777618084SLudovic Desroches MODULE_DEVICE_TABLE(of, atmel_pctrl_of_match); 87877618084SLudovic Desroches 87977618084SLudovic Desroches static int atmel_pinctrl_probe(struct platform_device *pdev) 88077618084SLudovic Desroches { 88177618084SLudovic Desroches struct device *dev = &pdev->dev; 88277618084SLudovic Desroches struct pinctrl_pin_desc *pin_desc; 88377618084SLudovic Desroches const char **group_names; 88477618084SLudovic Desroches const struct of_device_id *match; 88577618084SLudovic Desroches int i, ret; 88677618084SLudovic Desroches struct resource *res; 88777618084SLudovic Desroches struct atmel_pioctrl *atmel_pioctrl; 88877618084SLudovic Desroches struct atmel_pioctrl_data *atmel_pioctrl_data; 88977618084SLudovic Desroches 89077618084SLudovic Desroches atmel_pioctrl = devm_kzalloc(dev, sizeof(*atmel_pioctrl), GFP_KERNEL); 89177618084SLudovic Desroches if (!atmel_pioctrl) 89277618084SLudovic Desroches return -ENOMEM; 89377618084SLudovic Desroches atmel_pioctrl->dev = dev; 89477618084SLudovic Desroches atmel_pioctrl->node = dev->of_node; 89577618084SLudovic Desroches platform_set_drvdata(pdev, atmel_pioctrl); 89677618084SLudovic Desroches 89777618084SLudovic Desroches match = of_match_node(atmel_pctrl_of_match, dev->of_node); 89877618084SLudovic Desroches if (!match) { 89977618084SLudovic Desroches dev_err(dev, "unknown compatible string\n"); 90077618084SLudovic Desroches return -ENODEV; 90177618084SLudovic Desroches } 90277618084SLudovic Desroches atmel_pioctrl_data = (struct atmel_pioctrl_data *)match->data; 90377618084SLudovic Desroches atmel_pioctrl->nbanks = atmel_pioctrl_data->nbanks; 90477618084SLudovic Desroches atmel_pioctrl->npins = atmel_pioctrl->nbanks * ATMEL_PIO_NPINS_PER_BANK; 90577618084SLudovic Desroches 90677618084SLudovic Desroches res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 90777618084SLudovic Desroches if (!res) { 90877618084SLudovic Desroches dev_err(dev, "unable to get atmel pinctrl resource\n"); 90977618084SLudovic Desroches return -EINVAL; 91077618084SLudovic Desroches } 91177618084SLudovic Desroches atmel_pioctrl->reg_base = devm_ioremap_resource(dev, res); 91277618084SLudovic Desroches if (IS_ERR(atmel_pioctrl->reg_base)) 91377618084SLudovic Desroches return -EINVAL; 91477618084SLudovic Desroches 91577618084SLudovic Desroches atmel_pioctrl->clk = devm_clk_get(dev, NULL); 91677618084SLudovic Desroches if (IS_ERR(atmel_pioctrl->clk)) { 91777618084SLudovic Desroches dev_err(dev, "failed to get clock\n"); 91877618084SLudovic Desroches return PTR_ERR(atmel_pioctrl->clk); 91977618084SLudovic Desroches } 92077618084SLudovic Desroches 92177618084SLudovic Desroches atmel_pioctrl->pins = devm_kzalloc(dev, sizeof(*atmel_pioctrl->pins) 92277618084SLudovic Desroches * atmel_pioctrl->npins, GFP_KERNEL); 92377618084SLudovic Desroches if (!atmel_pioctrl->pins) 92477618084SLudovic Desroches return -ENOMEM; 92577618084SLudovic Desroches 92677618084SLudovic Desroches pin_desc = devm_kzalloc(dev, sizeof(*pin_desc) 92777618084SLudovic Desroches * atmel_pioctrl->npins, GFP_KERNEL); 92877618084SLudovic Desroches if (!pin_desc) 92977618084SLudovic Desroches return -ENOMEM; 93077618084SLudovic Desroches atmel_pinctrl_desc.pins = pin_desc; 93177618084SLudovic Desroches atmel_pinctrl_desc.npins = atmel_pioctrl->npins; 93277618084SLudovic Desroches 93377618084SLudovic Desroches /* One pin is one group since a pin can achieve all functions. */ 93477618084SLudovic Desroches group_names = devm_kzalloc(dev, sizeof(*group_names) 93577618084SLudovic Desroches * atmel_pioctrl->npins, GFP_KERNEL); 93677618084SLudovic Desroches if (!group_names) 93777618084SLudovic Desroches return -ENOMEM; 93877618084SLudovic Desroches atmel_pioctrl->group_names = group_names; 93977618084SLudovic Desroches 94077618084SLudovic Desroches atmel_pioctrl->groups = devm_kzalloc(&pdev->dev, 94177618084SLudovic Desroches sizeof(*atmel_pioctrl->groups) * atmel_pioctrl->npins, 94277618084SLudovic Desroches GFP_KERNEL); 94377618084SLudovic Desroches if (!atmel_pioctrl->groups) 94477618084SLudovic Desroches return -ENOMEM; 94577618084SLudovic Desroches for (i = 0 ; i < atmel_pioctrl->npins; i++) { 94677618084SLudovic Desroches struct atmel_group *group = atmel_pioctrl->groups + i; 94777618084SLudovic Desroches unsigned bank = ATMEL_PIO_BANK(i); 94877618084SLudovic Desroches unsigned line = ATMEL_PIO_LINE(i); 94977618084SLudovic Desroches 95077618084SLudovic Desroches atmel_pioctrl->pins[i] = devm_kzalloc(dev, 95177618084SLudovic Desroches sizeof(**atmel_pioctrl->pins), GFP_KERNEL); 95277618084SLudovic Desroches if (!atmel_pioctrl->pins[i]) 95377618084SLudovic Desroches return -ENOMEM; 95477618084SLudovic Desroches 95577618084SLudovic Desroches atmel_pioctrl->pins[i]->pin_id = i; 95677618084SLudovic Desroches atmel_pioctrl->pins[i]->bank = bank; 95777618084SLudovic Desroches atmel_pioctrl->pins[i]->line = line; 95877618084SLudovic Desroches 95977618084SLudovic Desroches pin_desc[i].number = i; 96077618084SLudovic Desroches /* Pin naming convention: P(bank_name)(bank_pin_number). */ 96177618084SLudovic Desroches pin_desc[i].name = kasprintf(GFP_KERNEL, "P%c%d", 96277618084SLudovic Desroches bank + 'A', line); 96377618084SLudovic Desroches 96477618084SLudovic Desroches group->name = group_names[i] = pin_desc[i].name; 96577618084SLudovic Desroches group->pin = pin_desc[i].number; 96677618084SLudovic Desroches 96777618084SLudovic Desroches dev_dbg(dev, "pin_id=%u, bank=%u, line=%u", i, bank, line); 96877618084SLudovic Desroches } 96977618084SLudovic Desroches 97077618084SLudovic Desroches atmel_pioctrl->gpio_chip = &atmel_gpio_chip; 97177618084SLudovic Desroches atmel_pioctrl->gpio_chip->of_node = dev->of_node; 97277618084SLudovic Desroches atmel_pioctrl->gpio_chip->ngpio = atmel_pioctrl->npins; 97377618084SLudovic Desroches atmel_pioctrl->gpio_chip->label = dev_name(dev); 97458383c78SLinus Walleij atmel_pioctrl->gpio_chip->parent = dev; 97577618084SLudovic Desroches atmel_pioctrl->gpio_chip->names = atmel_pioctrl->group_names; 97677618084SLudovic Desroches 977de4e882fSLudovic Desroches atmel_pioctrl->pm_wakeup_sources = devm_kzalloc(dev, 978de4e882fSLudovic Desroches sizeof(*atmel_pioctrl->pm_wakeup_sources) 979de4e882fSLudovic Desroches * atmel_pioctrl->nbanks, GFP_KERNEL); 980de4e882fSLudovic Desroches if (!atmel_pioctrl->pm_wakeup_sources) 981de4e882fSLudovic Desroches return -ENOMEM; 982de4e882fSLudovic Desroches 983de4e882fSLudovic Desroches atmel_pioctrl->pm_suspend_backup = devm_kzalloc(dev, 984de4e882fSLudovic Desroches sizeof(*atmel_pioctrl->pm_suspend_backup) 985de4e882fSLudovic Desroches * atmel_pioctrl->nbanks, GFP_KERNEL); 986de4e882fSLudovic Desroches if (!atmel_pioctrl->pm_suspend_backup) 987de4e882fSLudovic Desroches return -ENOMEM; 988de4e882fSLudovic Desroches 98977618084SLudovic Desroches atmel_pioctrl->irqs = devm_kzalloc(dev, sizeof(*atmel_pioctrl->irqs) 99077618084SLudovic Desroches * atmel_pioctrl->nbanks, GFP_KERNEL); 99177618084SLudovic Desroches if (!atmel_pioctrl->irqs) 99277618084SLudovic Desroches return -ENOMEM; 99377618084SLudovic Desroches 99477618084SLudovic Desroches /* There is one controller but each bank has its own irq line. */ 99577618084SLudovic Desroches for (i = 0; i < atmel_pioctrl->nbanks; i++) { 99677618084SLudovic Desroches res = platform_get_resource(pdev, IORESOURCE_IRQ, i); 99777618084SLudovic Desroches if (!res) { 99877618084SLudovic Desroches dev_err(dev, "missing irq resource for group %c\n", 99977618084SLudovic Desroches 'A' + i); 100077618084SLudovic Desroches return -EINVAL; 100177618084SLudovic Desroches } 100277618084SLudovic Desroches atmel_pioctrl->irqs[i] = res->start; 100377618084SLudovic Desroches irq_set_chained_handler(res->start, atmel_gpio_irq_handler); 100477618084SLudovic Desroches irq_set_handler_data(res->start, atmel_pioctrl); 100577618084SLudovic Desroches dev_dbg(dev, "bank %i: hwirq=%u\n", i, res->start); 100677618084SLudovic Desroches } 100777618084SLudovic Desroches 100877618084SLudovic Desroches atmel_pioctrl->irq_domain = irq_domain_add_linear(dev->of_node, 100977618084SLudovic Desroches atmel_pioctrl->gpio_chip->ngpio, 101077618084SLudovic Desroches &irq_domain_simple_ops, NULL); 101177618084SLudovic Desroches if (!atmel_pioctrl->irq_domain) { 101277618084SLudovic Desroches dev_err(dev, "can't add the irq domain\n"); 101377618084SLudovic Desroches return -ENODEV; 101477618084SLudovic Desroches } 101577618084SLudovic Desroches atmel_pioctrl->irq_domain->name = "atmel gpio"; 101677618084SLudovic Desroches 101777618084SLudovic Desroches for (i = 0; i < atmel_pioctrl->npins; i++) { 101877618084SLudovic Desroches int irq = irq_create_mapping(atmel_pioctrl->irq_domain, i); 101977618084SLudovic Desroches 102077618084SLudovic Desroches irq_set_chip_and_handler(irq, &atmel_gpio_irq_chip, 102177618084SLudovic Desroches handle_simple_irq); 102277618084SLudovic Desroches irq_set_chip_data(irq, atmel_pioctrl); 102377618084SLudovic Desroches dev_dbg(dev, 102477618084SLudovic Desroches "atmel gpio irq domain: hwirq: %d, linux irq: %d\n", 102577618084SLudovic Desroches i, irq); 102677618084SLudovic Desroches } 102777618084SLudovic Desroches 102877618084SLudovic Desroches ret = clk_prepare_enable(atmel_pioctrl->clk); 102977618084SLudovic Desroches if (ret) { 103077618084SLudovic Desroches dev_err(dev, "failed to prepare and enable clock\n"); 103177618084SLudovic Desroches goto clk_prepare_enable_error; 103277618084SLudovic Desroches } 103377618084SLudovic Desroches 103477618084SLudovic Desroches atmel_pioctrl->pinctrl_dev = pinctrl_register(&atmel_pinctrl_desc, 103577618084SLudovic Desroches &pdev->dev, 103677618084SLudovic Desroches atmel_pioctrl); 103777618084SLudovic Desroches if (!atmel_pioctrl->pinctrl_dev) { 103877618084SLudovic Desroches dev_err(dev, "pinctrl registration failed\n"); 103977618084SLudovic Desroches goto pinctrl_register_error; 104077618084SLudovic Desroches } 104177618084SLudovic Desroches 1042*80036f88SLinus Walleij ret = gpiochip_add_data(atmel_pioctrl->gpio_chip, atmel_pioctrl); 104377618084SLudovic Desroches if (ret) { 104477618084SLudovic Desroches dev_err(dev, "failed to add gpiochip\n"); 104577618084SLudovic Desroches goto gpiochip_add_error; 104677618084SLudovic Desroches } 104777618084SLudovic Desroches 104877618084SLudovic Desroches ret = gpiochip_add_pin_range(atmel_pioctrl->gpio_chip, dev_name(dev), 104977618084SLudovic Desroches 0, 0, atmel_pioctrl->gpio_chip->ngpio); 105077618084SLudovic Desroches if (ret) { 105177618084SLudovic Desroches dev_err(dev, "failed to add gpio pin range\n"); 105277618084SLudovic Desroches goto gpiochip_add_pin_range_error; 105377618084SLudovic Desroches } 105477618084SLudovic Desroches 105577618084SLudovic Desroches dev_info(&pdev->dev, "atmel pinctrl initialized\n"); 105677618084SLudovic Desroches 105777618084SLudovic Desroches return 0; 105877618084SLudovic Desroches 105977618084SLudovic Desroches clk_prepare_enable_error: 106077618084SLudovic Desroches irq_domain_remove(atmel_pioctrl->irq_domain); 106177618084SLudovic Desroches pinctrl_register_error: 106277618084SLudovic Desroches clk_disable_unprepare(atmel_pioctrl->clk); 106377618084SLudovic Desroches gpiochip_add_error: 106477618084SLudovic Desroches pinctrl_unregister(atmel_pioctrl->pinctrl_dev); 106577618084SLudovic Desroches gpiochip_add_pin_range_error: 106677618084SLudovic Desroches gpiochip_remove(atmel_pioctrl->gpio_chip); 106777618084SLudovic Desroches 106877618084SLudovic Desroches return ret; 106977618084SLudovic Desroches } 107077618084SLudovic Desroches 107177618084SLudovic Desroches int atmel_pinctrl_remove(struct platform_device *pdev) 107277618084SLudovic Desroches { 107377618084SLudovic Desroches struct atmel_pioctrl *atmel_pioctrl = platform_get_drvdata(pdev); 107477618084SLudovic Desroches 107577618084SLudovic Desroches irq_domain_remove(atmel_pioctrl->irq_domain); 107677618084SLudovic Desroches clk_disable_unprepare(atmel_pioctrl->clk); 107777618084SLudovic Desroches pinctrl_unregister(atmel_pioctrl->pinctrl_dev); 107877618084SLudovic Desroches gpiochip_remove(atmel_pioctrl->gpio_chip); 107977618084SLudovic Desroches 108077618084SLudovic Desroches return 0; 108177618084SLudovic Desroches } 108277618084SLudovic Desroches 108377618084SLudovic Desroches static struct platform_driver atmel_pinctrl_driver = { 108477618084SLudovic Desroches .driver = { 108577618084SLudovic Desroches .name = "pinctrl-at91-pio4", 108677618084SLudovic Desroches .of_match_table = atmel_pctrl_of_match, 1087de4e882fSLudovic Desroches .pm = &atmel_pctrl_pm_ops, 108877618084SLudovic Desroches }, 108977618084SLudovic Desroches .probe = atmel_pinctrl_probe, 109077618084SLudovic Desroches .remove = atmel_pinctrl_remove, 109177618084SLudovic Desroches }; 109277618084SLudovic Desroches module_platform_driver(atmel_pinctrl_driver); 109377618084SLudovic Desroches 109477618084SLudovic Desroches MODULE_AUTHOR(Ludovic Desroches <ludovic.desroches@atmel.com>); 109577618084SLudovic Desroches MODULE_DESCRIPTION("Atmel PIO4 pinctrl driver"); 109677618084SLudovic Desroches MODULE_LICENSE("GPL v2"); 1097