// SPDX-License-Identifier: GPL-2.0-only
/*
* Driver for the Atmel PIO4 controller
*
* Copyright (C) 2015 Atmel,
* 2015 Ludovic Desroches <ludovic.desroches@atmel.com>
*/
#include <dt-bindings/pinctrl/at91.h>
#include <linux/clk.h>
#include <linux/gpio/driver.h>
#include <linux/interrupt.h>
#include <linux/io.h>
#include <linux/init.h>
#include <linux/of.h>
#include <linux/platform_device.h>
#include <linux/pinctrl/pinconf.h>
#include <linux/pinctrl/pinconf-generic.h>
#include <linux/pinctrl/pinctrl.h>
#include <linux/pinctrl/pinmux.h>
#include <linux/slab.h>
#include "core.h"
#include "pinconf.h"
#include "pinctrl-utils.h"
/*
* Warning:
* In order to not introduce confusion between Atmel PIO groups and pinctrl
* framework groups, Atmel PIO groups will be called banks, line is kept to
* designed the pin id into this bank.
*/
#define ATMEL_PIO_MSKR 0x0000
#define ATMEL_PIO_CFGR 0x0004
#define ATMEL_PIO_CFGR_FUNC_MASK GENMASK(2, 0)
#define ATMEL_PIO_DIR_MASK BIT(8)
#define ATMEL_PIO_PUEN_MASK BIT(9)
#define ATMEL_PIO_PDEN_MASK BIT(10)
#define ATMEL_PIO_IFEN_MASK BIT(12)
#define ATMEL_PIO_IFSCEN_MASK BIT(13)
#define ATMEL_PIO_OPD_MASK BIT(14)
#define ATMEL_PIO_SCHMITT_MASK BIT(15)
#define ATMEL_PIO_DRVSTR_MASK GENMASK(17, 16)
#define ATMEL_PIO_DRVSTR_OFFSET 16
#define ATMEL_PIO_CFGR_EVTSEL_MASK GENMASK(26, 24)
#define ATMEL_PIO_CFGR_EVTSEL_FALLING (0 << 24)
#define ATMEL_PIO_CFGR_EVTSEL_RISING (1 << 24)
#define ATMEL_PIO_CFGR_EVTSEL_BOTH (2 << 24)
#define ATMEL_PIO_CFGR_EVTSEL_LOW (3 << 24)
#define ATMEL_PIO_CFGR_EVTSEL_HIGH (4 << 24)
#define ATMEL_PIO_PDSR 0x0008
#define ATMEL_PIO_LOCKSR 0x000C
#define ATMEL_PIO_SODR 0x0010
#define ATMEL_PIO_CODR 0x0014
#define ATMEL_PIO_ODSR 0x0018
#define ATMEL_PIO_IER 0x0020
#define ATMEL_PIO_IDR 0x0024
#define ATMEL_PIO_IMR 0x0028
#define ATMEL_PIO_ISR 0x002C
#define ATMEL_PIO_IOFR 0x003C
#define ATMEL_PIO_NPINS_PER_BANK 32
#define ATMEL_PIO_BANK(pin_id) (pin_id / ATMEL_PIO_NPINS_PER_BANK)
#define ATMEL_PIO_LINE(pin_id) (pin_id % ATMEL_PIO_NPINS_PER_BANK)
#define ATMEL_PIO_BANK_OFFSET 0x40
#define ATMEL_GET_PIN_NO(pinfunc) ((pinfunc) & 0xff)
#define ATMEL_GET_PIN_FUNC(pinfunc) ((pinfunc >> 16) & 0xf)
#define ATMEL_GET_PIN_IOSET(pinfunc) ((pinfunc >> 20) & 0xf)
/* Custom pinconf parameters */
#define ATMEL_PIN_CONFIG_DRIVE_STRENGTH (PIN_CONFIG_END + 1)
struct atmel_pioctrl_data {
unsigned nbanks;
};
struct atmel_group {
const char *name;
u32 pin;
};
struct atmel_pin {
unsigned pin_id;
unsigned mux;
unsigned ioset;
unsigned bank;
unsigned line;
const char *device;
};
/**
* struct atmel_pioctrl - Atmel PIO controller (pinmux + gpio)
* @reg_base: base address of the controller.
* @clk: clock of the controller.
* @nbanks: number of PIO groups, it can vary depending on the SoC.
* @pinctrl_dev: pinctrl device registered.
* @groups: groups table to provide group name and pin in the group to pinctrl.
* @group_names: group names table to provide all the group/pin names to
* pinctrl or gpio.
* @pins: pins table used for both pinctrl and gpio. pin_id, bank and line
* fields are set at probe time. Other ones are set when parsing dt
* pinctrl.
* @npins: number of pins.
* @gpio_chip: gpio chip registered.
* @irq_domain: irq domain for the gpio controller.
* @irqs: table containing the hw irq number of the bank. The index of the
* table is the bank id.
* @dev: device entry for the Atmel PIO controller.
* @node: node of the Atmel PIO controller.
*/
struct atmel_pioctrl {
void __iomem *reg_base;
struct clk *clk;
unsigned nbanks;
struct pinctrl_dev *pinctrl_dev;
struct atmel_group *groups;
const char * const *group_names;
struct atmel_pin **pins;
unsigned npins;
struct gpio_chip *gpio_chip;
struct irq_domain *irq_domain;
int *irqs;
unsigned *pm_wakeup_sources;
struct {
u32 imr;
u32 odsr;
u32 cfgr[ATMEL_PIO_NPINS_PER_BANK];
} *pm_suspend_backup;
struct device *dev;
struct device_node *node;
};
static const char * const atmel_functions[] = {
"GPIO", "A", "B", "C", "D", "E", "F", "G"
};
static const struct pinconf_generic_params atmel_custom_bindings[] = {
{"atmel,drive-strength", ATMEL_PIN_CONFIG_DRIVE_STRENGTH, 0},
};
/* --- GPIO --- */
static unsigned int atmel_gpio_read(struct atmel_pioctrl *atmel_pioctrl,
unsigned int bank, unsigned int reg)
{
return readl_relaxed(atmel_pioctrl->reg_base
+ ATMEL_PIO_BANK_OFFSET * bank + reg);
}
static void atmel_gpio_write(struct atmel_pioctrl *atmel_pioctrl,
unsigned int bank, unsigned int reg,
unsigned int val)
{
writel_relaxed(val, atmel_pioctrl->reg_base
+ ATMEL_PIO_BANK_OFFSET * bank + reg);
}
static void atmel_gpio_irq_ack(struct irq_data *d)
{
/*
* Nothing to do, interrupt is cleared when reading the status
* register.
*/
}
static int atmel_gpio_irq_set_type(struct irq_data *d, unsigned type)
{
struct atmel_pioctrl *atmel_pioctrl = irq_data_get_irq_chip_data(d);
struct atmel_pin *pin = atmel_pioctrl->pins[d->hwirq];
unsigned reg;
atmel_gpio_write(atmel_pioctrl, pin->bank, ATMEL_PIO_MSKR,
BIT(pin->line));
reg = atmel_gpio_read(atmel_pioctrl, pin->bank, ATMEL_PIO_CFGR);
reg &= (~ATMEL_PIO_CFGR_EVTSEL_MASK);
switch (type) {
case IRQ_TYPE_EDGE_RISING:
irq_set_handler_locked(d, handle_edge_irq);
reg |= ATMEL_PIO_CFGR_EVTSEL_RISING;
break;
case IRQ_TYPE_EDGE_FALLING:
irq_set_handler_locked(d, handle_edge_irq);
reg |= ATMEL_PIO_CFGR_EVTSEL_FALLING;
break;
case IRQ_TYPE_EDGE_BOTH:
irq_set_handler_locked(d, handle_edge_irq);
reg