mirror of
https://github.com/AetherDroid/android_kernel_samsung_on5xelte.git
synced 2025-09-08 17:18:05 -04:00
Fixed MTP to work with TWRP
This commit is contained in:
commit
f6dfaef42e
50820 changed files with 20846062 additions and 0 deletions
56
drivers/pinctrl/spear/Kconfig
Normal file
56
drivers/pinctrl/spear/Kconfig
Normal file
|
@ -0,0 +1,56 @@
|
|||
#
|
||||
# ST Microelectronics SPEAr PINCTRL drivers
|
||||
#
|
||||
|
||||
if PLAT_SPEAR
|
||||
|
||||
config PINCTRL_SPEAR
|
||||
bool
|
||||
depends on OF
|
||||
select PINMUX
|
||||
help
|
||||
This enables pin control drivers for SPEAr Platform
|
||||
|
||||
config PINCTRL_SPEAR3XX
|
||||
bool
|
||||
depends on ARCH_SPEAR3XX
|
||||
select PINCTRL_SPEAR
|
||||
|
||||
config PINCTRL_SPEAR300
|
||||
bool "ST Microelectronics SPEAr300 SoC pin controller driver"
|
||||
depends on MACH_SPEAR300
|
||||
select PINCTRL_SPEAR3XX
|
||||
|
||||
config PINCTRL_SPEAR310
|
||||
bool "ST Microelectronics SPEAr310 SoC pin controller driver"
|
||||
depends on MACH_SPEAR310
|
||||
select PINCTRL_SPEAR3XX
|
||||
select PINCTRL_SPEAR_PLGPIO
|
||||
|
||||
config PINCTRL_SPEAR320
|
||||
bool "ST Microelectronics SPEAr320 SoC pin controller driver"
|
||||
depends on MACH_SPEAR320
|
||||
select PINCTRL_SPEAR3XX
|
||||
select PINCTRL_SPEAR_PLGPIO
|
||||
|
||||
config PINCTRL_SPEAR1310
|
||||
bool "ST Microelectronics SPEAr1310 SoC pin controller driver"
|
||||
depends on MACH_SPEAR1310
|
||||
select PINCTRL_SPEAR
|
||||
select PINCTRL_SPEAR_PLGPIO
|
||||
|
||||
config PINCTRL_SPEAR1340
|
||||
bool "ST Microelectronics SPEAr1340 SoC pin controller driver"
|
||||
depends on MACH_SPEAR1340
|
||||
select PINCTRL_SPEAR
|
||||
select PINCTRL_SPEAR_PLGPIO
|
||||
|
||||
config PINCTRL_SPEAR_PLGPIO
|
||||
bool "SPEAr SoC PLGPIO Controller"
|
||||
depends on GPIOLIB && PINCTRL_SPEAR
|
||||
select GPIOLIB_IRQCHIP
|
||||
help
|
||||
Say yes here to support PLGPIO controller on ST Microelectronics SPEAr
|
||||
SoCs.
|
||||
|
||||
endif
|
10
drivers/pinctrl/spear/Makefile
Normal file
10
drivers/pinctrl/spear/Makefile
Normal file
|
@ -0,0 +1,10 @@
|
|||
# SPEAr pinmux support
|
||||
|
||||
obj-$(CONFIG_PINCTRL_SPEAR_PLGPIO) += pinctrl-plgpio.o
|
||||
obj-$(CONFIG_PINCTRL_SPEAR) += pinctrl-spear.o
|
||||
obj-$(CONFIG_PINCTRL_SPEAR3XX) += pinctrl-spear3xx.o
|
||||
obj-$(CONFIG_PINCTRL_SPEAR300) += pinctrl-spear300.o
|
||||
obj-$(CONFIG_PINCTRL_SPEAR310) += pinctrl-spear310.o
|
||||
obj-$(CONFIG_PINCTRL_SPEAR320) += pinctrl-spear320.o
|
||||
obj-$(CONFIG_PINCTRL_SPEAR1310) += pinctrl-spear1310.o
|
||||
obj-$(CONFIG_PINCTRL_SPEAR1340) += pinctrl-spear1340.o
|
728
drivers/pinctrl/spear/pinctrl-plgpio.c
Normal file
728
drivers/pinctrl/spear/pinctrl-plgpio.c
Normal file
|
@ -0,0 +1,728 @@
|
|||
/*
|
||||
* SPEAr platform PLGPIO driver
|
||||
*
|
||||
* Copyright (C) 2012 ST Microelectronics
|
||||
* Viresh Kumar <viresh.kumar@linaro.org>
|
||||
*
|
||||
* This file is licensed under the terms of the GNU General Public
|
||||
* License version 2. This program is licensed "as is" without any
|
||||
* warranty of any kind, whether express or implied.
|
||||
*/
|
||||
|
||||
#include <linux/clk.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/gpio/driver.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_platform.h>
|
||||
#include <linux/pinctrl/consumer.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/pm.h>
|
||||
#include <linux/spinlock.h>
|
||||
|
||||
#define MAX_GPIO_PER_REG 32
|
||||
#define PIN_OFFSET(pin) (pin % MAX_GPIO_PER_REG)
|
||||
#define REG_OFFSET(base, reg, pin) (base + reg + (pin / MAX_GPIO_PER_REG) \
|
||||
* sizeof(int *))
|
||||
|
||||
/*
|
||||
* plgpio pins in all machines are not one to one mapped, bitwise with registers
|
||||
* bits. These set of macros define register masks for which below functions
|
||||
* (pin_to_offset and offset_to_pin) are required to be called.
|
||||
*/
|
||||
#define PTO_ENB_REG 0x001
|
||||
#define PTO_WDATA_REG 0x002
|
||||
#define PTO_DIR_REG 0x004
|
||||
#define PTO_IE_REG 0x008
|
||||
#define PTO_RDATA_REG 0x010
|
||||
#define PTO_MIS_REG 0x020
|
||||
|
||||
struct plgpio_regs {
|
||||
u32 enb; /* enable register */
|
||||
u32 wdata; /* write data register */
|
||||
u32 dir; /* direction set register */
|
||||
u32 rdata; /* read data register */
|
||||
u32 ie; /* interrupt enable register */
|
||||
u32 mis; /* mask interrupt status register */
|
||||
u32 eit; /* edge interrupt type */
|
||||
};
|
||||
|
||||
/*
|
||||
* struct plgpio: plgpio driver specific structure
|
||||
*
|
||||
* lock: lock for guarding gpio registers
|
||||
* base: base address of plgpio block
|
||||
* chip: gpio framework specific chip information structure
|
||||
* p2o: function ptr for pin to offset conversion. This is required only for
|
||||
* machines where mapping b/w pin and offset is not 1-to-1.
|
||||
* o2p: function ptr for offset to pin conversion. This is required only for
|
||||
* machines where mapping b/w pin and offset is not 1-to-1.
|
||||
* p2o_regs: mask of registers for which p2o and o2p are applicable
|
||||
* regs: register offsets
|
||||
* csave_regs: context save registers for standby/sleep/hibernate cases
|
||||
*/
|
||||
struct plgpio {
|
||||
spinlock_t lock;
|
||||
void __iomem *base;
|
||||
struct clk *clk;
|
||||
struct gpio_chip chip;
|
||||
int (*p2o)(int pin); /* pin_to_offset */
|
||||
int (*o2p)(int offset); /* offset_to_pin */
|
||||
u32 p2o_regs;
|
||||
struct plgpio_regs regs;
|
||||
#ifdef CONFIG_PM_SLEEP
|
||||
struct plgpio_regs *csave_regs;
|
||||
#endif
|
||||
};
|
||||
|
||||
/* register manipulation inline functions */
|
||||
static inline u32 is_plgpio_set(void __iomem *base, u32 pin, u32 reg)
|
||||
{
|
||||
u32 offset = PIN_OFFSET(pin);
|
||||
void __iomem *reg_off = REG_OFFSET(base, reg, pin);
|
||||
u32 val = readl_relaxed(reg_off);
|
||||
|
||||
return !!(val & (1 << offset));
|
||||
}
|
||||
|
||||
static inline void plgpio_reg_set(void __iomem *base, u32 pin, u32 reg)
|
||||
{
|
||||
u32 offset = PIN_OFFSET(pin);
|
||||
void __iomem *reg_off = REG_OFFSET(base, reg, pin);
|
||||
u32 val = readl_relaxed(reg_off);
|
||||
|
||||
writel_relaxed(val | (1 << offset), reg_off);
|
||||
}
|
||||
|
||||
static inline void plgpio_reg_reset(void __iomem *base, u32 pin, u32 reg)
|
||||
{
|
||||
u32 offset = PIN_OFFSET(pin);
|
||||
void __iomem *reg_off = REG_OFFSET(base, reg, pin);
|
||||
u32 val = readl_relaxed(reg_off);
|
||||
|
||||
writel_relaxed(val & ~(1 << offset), reg_off);
|
||||
}
|
||||
|
||||
/* gpio framework specific routines */
|
||||
static int plgpio_direction_input(struct gpio_chip *chip, unsigned offset)
|
||||
{
|
||||
struct plgpio *plgpio = container_of(chip, struct plgpio, chip);
|
||||
unsigned long flags;
|
||||
|
||||
/* get correct offset for "offset" pin */
|
||||
if (plgpio->p2o && (plgpio->p2o_regs & PTO_DIR_REG)) {
|
||||
offset = plgpio->p2o(offset);
|
||||
if (offset == -1)
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
spin_lock_irqsave(&plgpio->lock, flags);
|
||||
plgpio_reg_set(plgpio->base, offset, plgpio->regs.dir);
|
||||
spin_unlock_irqrestore(&plgpio->lock, flags);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int plgpio_direction_output(struct gpio_chip *chip, unsigned offset,
|
||||
int value)
|
||||
{
|
||||
struct plgpio *plgpio = container_of(chip, struct plgpio, chip);
|
||||
unsigned long flags;
|
||||
unsigned dir_offset = offset, wdata_offset = offset, tmp;
|
||||
|
||||
/* get correct offset for "offset" pin */
|
||||
if (plgpio->p2o && (plgpio->p2o_regs & (PTO_DIR_REG | PTO_WDATA_REG))) {
|
||||
tmp = plgpio->p2o(offset);
|
||||
if (tmp == -1)
|
||||
return -EINVAL;
|
||||
|
||||
if (plgpio->p2o_regs & PTO_DIR_REG)
|
||||
dir_offset = tmp;
|
||||
if (plgpio->p2o_regs & PTO_WDATA_REG)
|
||||
wdata_offset = tmp;
|
||||
}
|
||||
|
||||
spin_lock_irqsave(&plgpio->lock, flags);
|
||||
if (value)
|
||||
plgpio_reg_set(plgpio->base, wdata_offset,
|
||||
plgpio->regs.wdata);
|
||||
else
|
||||
plgpio_reg_reset(plgpio->base, wdata_offset,
|
||||
plgpio->regs.wdata);
|
||||
|
||||
plgpio_reg_reset(plgpio->base, dir_offset, plgpio->regs.dir);
|
||||
spin_unlock_irqrestore(&plgpio->lock, flags);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int plgpio_get_value(struct gpio_chip *chip, unsigned offset)
|
||||
{
|
||||
struct plgpio *plgpio = container_of(chip, struct plgpio, chip);
|
||||
|
||||
if (offset >= chip->ngpio)
|
||||
return -EINVAL;
|
||||
|
||||
/* get correct offset for "offset" pin */
|
||||
if (plgpio->p2o && (plgpio->p2o_regs & PTO_RDATA_REG)) {
|
||||
offset = plgpio->p2o(offset);
|
||||
if (offset == -1)
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return is_plgpio_set(plgpio->base, offset, plgpio->regs.rdata);
|
||||
}
|
||||
|
||||
static void plgpio_set_value(struct gpio_chip *chip, unsigned offset, int value)
|
||||
{
|
||||
struct plgpio *plgpio = container_of(chip, struct plgpio, chip);
|
||||
|
||||
if (offset >= chip->ngpio)
|
||||
return;
|
||||
|
||||
/* get correct offset for "offset" pin */
|
||||
if (plgpio->p2o && (plgpio->p2o_regs & PTO_WDATA_REG)) {
|
||||
offset = plgpio->p2o(offset);
|
||||
if (offset == -1)
|
||||
return;
|
||||
}
|
||||
|
||||
if (value)
|
||||
plgpio_reg_set(plgpio->base, offset, plgpio->regs.wdata);
|
||||
else
|
||||
plgpio_reg_reset(plgpio->base, offset, plgpio->regs.wdata);
|
||||
}
|
||||
|
||||
static int plgpio_request(struct gpio_chip *chip, unsigned offset)
|
||||
{
|
||||
struct plgpio *plgpio = container_of(chip, struct plgpio, chip);
|
||||
int gpio = chip->base + offset;
|
||||
unsigned long flags;
|
||||
int ret = 0;
|
||||
|
||||
if (offset >= chip->ngpio)
|
||||
return -EINVAL;
|
||||
|
||||
ret = pinctrl_request_gpio(gpio);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
if (!IS_ERR(plgpio->clk)) {
|
||||
ret = clk_enable(plgpio->clk);
|
||||
if (ret)
|
||||
goto err0;
|
||||
}
|
||||
|
||||
if (plgpio->regs.enb == -1)
|
||||
return 0;
|
||||
|
||||
/*
|
||||
* put gpio in IN mode before enabling it. This make enabling gpio safe
|
||||
*/
|
||||
ret = plgpio_direction_input(chip, offset);
|
||||
if (ret)
|
||||
goto err1;
|
||||
|
||||
/* get correct offset for "offset" pin */
|
||||
if (plgpio->p2o && (plgpio->p2o_regs & PTO_ENB_REG)) {
|
||||
offset = plgpio->p2o(offset);
|
||||
if (offset == -1) {
|
||||
ret = -EINVAL;
|
||||
goto err1;
|
||||
}
|
||||
}
|
||||
|
||||
spin_lock_irqsave(&plgpio->lock, flags);
|
||||
plgpio_reg_set(plgpio->base, offset, plgpio->regs.enb);
|
||||
spin_unlock_irqrestore(&plgpio->lock, flags);
|
||||
return 0;
|
||||
|
||||
err1:
|
||||
if (!IS_ERR(plgpio->clk))
|
||||
clk_disable(plgpio->clk);
|
||||
err0:
|
||||
pinctrl_free_gpio(gpio);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void plgpio_free(struct gpio_chip *chip, unsigned offset)
|
||||
{
|
||||
struct plgpio *plgpio = container_of(chip, struct plgpio, chip);
|
||||
int gpio = chip->base + offset;
|
||||
unsigned long flags;
|
||||
|
||||
if (offset >= chip->ngpio)
|
||||
return;
|
||||
|
||||
if (plgpio->regs.enb == -1)
|
||||
goto disable_clk;
|
||||
|
||||
/* get correct offset for "offset" pin */
|
||||
if (plgpio->p2o && (plgpio->p2o_regs & PTO_ENB_REG)) {
|
||||
offset = plgpio->p2o(offset);
|
||||
if (offset == -1)
|
||||
return;
|
||||
}
|
||||
|
||||
spin_lock_irqsave(&plgpio->lock, flags);
|
||||
plgpio_reg_reset(plgpio->base, offset, plgpio->regs.enb);
|
||||
spin_unlock_irqrestore(&plgpio->lock, flags);
|
||||
|
||||
disable_clk:
|
||||
if (!IS_ERR(plgpio->clk))
|
||||
clk_disable(plgpio->clk);
|
||||
|
||||
pinctrl_free_gpio(gpio);
|
||||
}
|
||||
|
||||
/* PLGPIO IRQ */
|
||||
static void plgpio_irq_disable(struct irq_data *d)
|
||||
{
|
||||
struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
|
||||
struct plgpio *plgpio = container_of(gc, struct plgpio, chip);
|
||||
int offset = d->hwirq;
|
||||
unsigned long flags;
|
||||
|
||||
/* get correct offset for "offset" pin */
|
||||
if (plgpio->p2o && (plgpio->p2o_regs & PTO_IE_REG)) {
|
||||
offset = plgpio->p2o(offset);
|
||||
if (offset == -1)
|
||||
return;
|
||||
}
|
||||
|
||||
spin_lock_irqsave(&plgpio->lock, flags);
|
||||
plgpio_reg_set(plgpio->base, offset, plgpio->regs.ie);
|
||||
spin_unlock_irqrestore(&plgpio->lock, flags);
|
||||
}
|
||||
|
||||
static void plgpio_irq_enable(struct irq_data *d)
|
||||
{
|
||||
struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
|
||||
struct plgpio *plgpio = container_of(gc, struct plgpio, chip);
|
||||
int offset = d->hwirq;
|
||||
unsigned long flags;
|
||||
|
||||
/* get correct offset for "offset" pin */
|
||||
if (plgpio->p2o && (plgpio->p2o_regs & PTO_IE_REG)) {
|
||||
offset = plgpio->p2o(offset);
|
||||
if (offset == -1)
|
||||
return;
|
||||
}
|
||||
|
||||
spin_lock_irqsave(&plgpio->lock, flags);
|
||||
plgpio_reg_reset(plgpio->base, offset, plgpio->regs.ie);
|
||||
spin_unlock_irqrestore(&plgpio->lock, flags);
|
||||
}
|
||||
|
||||
static int plgpio_irq_set_type(struct irq_data *d, unsigned trigger)
|
||||
{
|
||||
struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
|
||||
struct plgpio *plgpio = container_of(gc, struct plgpio, chip);
|
||||
int offset = d->hwirq;
|
||||
void __iomem *reg_off;
|
||||
unsigned int supported_type = 0, val;
|
||||
|
||||
if (offset >= plgpio->chip.ngpio)
|
||||
return -EINVAL;
|
||||
|
||||
if (plgpio->regs.eit == -1)
|
||||
supported_type = IRQ_TYPE_LEVEL_HIGH;
|
||||
else
|
||||
supported_type = IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING;
|
||||
|
||||
if (!(trigger & supported_type))
|
||||
return -EINVAL;
|
||||
|
||||
if (plgpio->regs.eit == -1)
|
||||
return 0;
|
||||
|
||||
reg_off = REG_OFFSET(plgpio->base, plgpio->regs.eit, offset);
|
||||
val = readl_relaxed(reg_off);
|
||||
|
||||
offset = PIN_OFFSET(offset);
|
||||
if (trigger & IRQ_TYPE_EDGE_RISING)
|
||||
writel_relaxed(val | (1 << offset), reg_off);
|
||||
else
|
||||
writel_relaxed(val & ~(1 << offset), reg_off);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct irq_chip plgpio_irqchip = {
|
||||
.name = "PLGPIO",
|
||||
.irq_enable = plgpio_irq_enable,
|
||||
.irq_disable = plgpio_irq_disable,
|
||||
.irq_set_type = plgpio_irq_set_type,
|
||||
};
|
||||
|
||||
static void plgpio_irq_handler(unsigned irq, struct irq_desc *desc)
|
||||
{
|
||||
struct gpio_chip *gc = irq_desc_get_handler_data(desc);
|
||||
struct plgpio *plgpio = container_of(gc, struct plgpio, chip);
|
||||
struct irq_chip *irqchip = irq_desc_get_chip(desc);
|
||||
int regs_count, count, pin, offset, i = 0;
|
||||
unsigned long pending;
|
||||
|
||||
count = plgpio->chip.ngpio;
|
||||
regs_count = DIV_ROUND_UP(count, MAX_GPIO_PER_REG);
|
||||
|
||||
chained_irq_enter(irqchip, desc);
|
||||
/* check all plgpio MIS registers for a possible interrupt */
|
||||
for (; i < regs_count; i++) {
|
||||
pending = readl_relaxed(plgpio->base + plgpio->regs.mis +
|
||||
i * sizeof(int *));
|
||||
if (!pending)
|
||||
continue;
|
||||
|
||||
/* clear interrupts */
|
||||
writel_relaxed(~pending, plgpio->base + plgpio->regs.mis +
|
||||
i * sizeof(int *));
|
||||
/*
|
||||
* clear extra bits in last register having gpios < MAX/REG
|
||||
* ex: Suppose there are max 102 plgpios. then last register
|
||||
* must have only (102 - MAX_GPIO_PER_REG * 3) = 6 relevant bits
|
||||
* so, we must not take other 28 bits into consideration for
|
||||
* checking interrupt. so clear those bits.
|
||||
*/
|
||||
count = count - i * MAX_GPIO_PER_REG;
|
||||
if (count < MAX_GPIO_PER_REG)
|
||||
pending &= (1 << count) - 1;
|
||||
|
||||
for_each_set_bit(offset, &pending, MAX_GPIO_PER_REG) {
|
||||
/* get correct pin for "offset" */
|
||||
if (plgpio->o2p && (plgpio->p2o_regs & PTO_MIS_REG)) {
|
||||
pin = plgpio->o2p(offset);
|
||||
if (pin == -1)
|
||||
continue;
|
||||
} else
|
||||
pin = offset;
|
||||
|
||||
/* get correct irq line number */
|
||||
pin = i * MAX_GPIO_PER_REG + pin;
|
||||
generic_handle_irq(
|
||||
irq_find_mapping(gc->irqdomain, pin));
|
||||
}
|
||||
}
|
||||
chained_irq_exit(irqchip, desc);
|
||||
}
|
||||
|
||||
/*
|
||||
* pin to offset and offset to pin converter functions
|
||||
*
|
||||
* In spear310 there is inconsistency among bit positions in plgpio regiseters,
|
||||
* for different plgpio pins. For example: for pin 27, bit offset is 23, pin
|
||||
* 28-33 are not supported, pin 95 has offset bit 95, bit 100 has offset bit 1
|
||||
*/
|
||||
static int spear310_p2o(int pin)
|
||||
{
|
||||
int offset = pin;
|
||||
|
||||
if (pin <= 27)
|
||||
offset += 4;
|
||||
else if (pin <= 33)
|
||||
offset = -1;
|
||||
else if (pin <= 97)
|
||||
offset -= 2;
|
||||
else if (pin <= 101)
|
||||
offset = 101 - pin;
|
||||
else
|
||||
offset = -1;
|
||||
|
||||
return offset;
|
||||
}
|
||||
|
||||
static int spear310_o2p(int offset)
|
||||
{
|
||||
if (offset <= 3)
|
||||
return 101 - offset;
|
||||
else if (offset <= 31)
|
||||
return offset - 4;
|
||||
else
|
||||
return offset + 2;
|
||||
}
|
||||
|
||||
static int plgpio_probe_dt(struct platform_device *pdev, struct plgpio *plgpio)
|
||||
{
|
||||
struct device_node *np = pdev->dev.of_node;
|
||||
int ret = -EINVAL;
|
||||
u32 val;
|
||||
|
||||
if (of_machine_is_compatible("st,spear310")) {
|
||||
plgpio->p2o = spear310_p2o;
|
||||
plgpio->o2p = spear310_o2p;
|
||||
plgpio->p2o_regs = PTO_WDATA_REG | PTO_DIR_REG | PTO_IE_REG |
|
||||
PTO_RDATA_REG | PTO_MIS_REG;
|
||||
}
|
||||
|
||||
if (!of_property_read_u32(np, "st-plgpio,ngpio", &val)) {
|
||||
plgpio->chip.ngpio = val;
|
||||
} else {
|
||||
dev_err(&pdev->dev, "DT: Invalid ngpio field\n");
|
||||
goto end;
|
||||
}
|
||||
|
||||
if (!of_property_read_u32(np, "st-plgpio,enb-reg", &val))
|
||||
plgpio->regs.enb = val;
|
||||
else
|
||||
plgpio->regs.enb = -1;
|
||||
|
||||
if (!of_property_read_u32(np, "st-plgpio,wdata-reg", &val)) {
|
||||
plgpio->regs.wdata = val;
|
||||
} else {
|
||||
dev_err(&pdev->dev, "DT: Invalid wdata reg\n");
|
||||
goto end;
|
||||
}
|
||||
|
||||
if (!of_property_read_u32(np, "st-plgpio,dir-reg", &val)) {
|
||||
plgpio->regs.dir = val;
|
||||
} else {
|
||||
dev_err(&pdev->dev, "DT: Invalid dir reg\n");
|
||||
goto end;
|
||||
}
|
||||
|
||||
if (!of_property_read_u32(np, "st-plgpio,ie-reg", &val)) {
|
||||
plgpio->regs.ie = val;
|
||||
} else {
|
||||
dev_err(&pdev->dev, "DT: Invalid ie reg\n");
|
||||
goto end;
|
||||
}
|
||||
|
||||
if (!of_property_read_u32(np, "st-plgpio,rdata-reg", &val)) {
|
||||
plgpio->regs.rdata = val;
|
||||
} else {
|
||||
dev_err(&pdev->dev, "DT: Invalid rdata reg\n");
|
||||
goto end;
|
||||
}
|
||||
|
||||
if (!of_property_read_u32(np, "st-plgpio,mis-reg", &val)) {
|
||||
plgpio->regs.mis = val;
|
||||
} else {
|
||||
dev_err(&pdev->dev, "DT: Invalid mis reg\n");
|
||||
goto end;
|
||||
}
|
||||
|
||||
if (!of_property_read_u32(np, "st-plgpio,eit-reg", &val))
|
||||
plgpio->regs.eit = val;
|
||||
else
|
||||
plgpio->regs.eit = -1;
|
||||
|
||||
return 0;
|
||||
|
||||
end:
|
||||
return ret;
|
||||
}
|
||||
static int plgpio_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct plgpio *plgpio;
|
||||
struct resource *res;
|
||||
int ret, irq;
|
||||
|
||||
plgpio = devm_kzalloc(&pdev->dev, sizeof(*plgpio), GFP_KERNEL);
|
||||
if (!plgpio) {
|
||||
dev_err(&pdev->dev, "memory allocation fail\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||
plgpio->base = devm_ioremap_resource(&pdev->dev, res);
|
||||
if (IS_ERR(plgpio->base))
|
||||
return PTR_ERR(plgpio->base);
|
||||
|
||||
ret = plgpio_probe_dt(pdev, plgpio);
|
||||
if (ret) {
|
||||
dev_err(&pdev->dev, "DT probe failed\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
plgpio->clk = devm_clk_get(&pdev->dev, NULL);
|
||||
if (IS_ERR(plgpio->clk))
|
||||
dev_warn(&pdev->dev, "clk_get() failed, work without it\n");
|
||||
|
||||
#ifdef CONFIG_PM_SLEEP
|
||||
plgpio->csave_regs = devm_kzalloc(&pdev->dev,
|
||||
sizeof(*plgpio->csave_regs) *
|
||||
DIV_ROUND_UP(plgpio->chip.ngpio, MAX_GPIO_PER_REG),
|
||||
GFP_KERNEL);
|
||||
if (!plgpio->csave_regs) {
|
||||
dev_err(&pdev->dev, "csave registers memory allocation fail\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
#endif
|
||||
|
||||
platform_set_drvdata(pdev, plgpio);
|
||||
spin_lock_init(&plgpio->lock);
|
||||
|
||||
plgpio->chip.base = -1;
|
||||
plgpio->chip.request = plgpio_request;
|
||||
plgpio->chip.free = plgpio_free;
|
||||
plgpio->chip.direction_input = plgpio_direction_input;
|
||||
plgpio->chip.direction_output = plgpio_direction_output;
|
||||
plgpio->chip.get = plgpio_get_value;
|
||||
plgpio->chip.set = plgpio_set_value;
|
||||
plgpio->chip.label = dev_name(&pdev->dev);
|
||||
plgpio->chip.dev = &pdev->dev;
|
||||
plgpio->chip.owner = THIS_MODULE;
|
||||
plgpio->chip.of_node = pdev->dev.of_node;
|
||||
|
||||
if (!IS_ERR(plgpio->clk)) {
|
||||
ret = clk_prepare(plgpio->clk);
|
||||
if (ret) {
|
||||
dev_err(&pdev->dev, "clk prepare failed\n");
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
ret = gpiochip_add(&plgpio->chip);
|
||||
if (ret) {
|
||||
dev_err(&pdev->dev, "unable to add gpio chip\n");
|
||||
goto unprepare_clk;
|
||||
}
|
||||
|
||||
irq = platform_get_irq(pdev, 0);
|
||||
if (irq < 0) {
|
||||
dev_info(&pdev->dev, "PLGPIO registered without IRQs\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
ret = gpiochip_irqchip_add(&plgpio->chip,
|
||||
&plgpio_irqchip,
|
||||
0,
|
||||
handle_simple_irq,
|
||||
IRQ_TYPE_NONE);
|
||||
if (ret) {
|
||||
dev_err(&pdev->dev, "failed to add irqchip to gpiochip\n");
|
||||
goto remove_gpiochip;
|
||||
}
|
||||
|
||||
gpiochip_set_chained_irqchip(&plgpio->chip,
|
||||
&plgpio_irqchip,
|
||||
irq,
|
||||
plgpio_irq_handler);
|
||||
|
||||
dev_info(&pdev->dev, "PLGPIO registered with IRQs\n");
|
||||
|
||||
return 0;
|
||||
|
||||
remove_gpiochip:
|
||||
dev_info(&pdev->dev, "Remove gpiochip\n");
|
||||
gpiochip_remove(&plgpio->chip);
|
||||
unprepare_clk:
|
||||
if (!IS_ERR(plgpio->clk))
|
||||
clk_unprepare(plgpio->clk);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_PM_SLEEP
|
||||
static int plgpio_suspend(struct device *dev)
|
||||
{
|
||||
struct plgpio *plgpio = dev_get_drvdata(dev);
|
||||
int i, reg_count = DIV_ROUND_UP(plgpio->chip.ngpio, MAX_GPIO_PER_REG);
|
||||
void __iomem *off;
|
||||
|
||||
for (i = 0; i < reg_count; i++) {
|
||||
off = plgpio->base + i * sizeof(int *);
|
||||
|
||||
if (plgpio->regs.enb != -1)
|
||||
plgpio->csave_regs[i].enb =
|
||||
readl_relaxed(plgpio->regs.enb + off);
|
||||
if (plgpio->regs.eit != -1)
|
||||
plgpio->csave_regs[i].eit =
|
||||
readl_relaxed(plgpio->regs.eit + off);
|
||||
plgpio->csave_regs[i].wdata = readl_relaxed(plgpio->regs.wdata +
|
||||
off);
|
||||
plgpio->csave_regs[i].dir = readl_relaxed(plgpio->regs.dir +
|
||||
off);
|
||||
plgpio->csave_regs[i].ie = readl_relaxed(plgpio->regs.ie + off);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* This is used to correct the values in end registers. End registers contain
|
||||
* extra bits that might be used for other purpose in platform. So, we shouldn't
|
||||
* overwrite these bits. This macro, reads given register again, preserves other
|
||||
* bit values (non-plgpio bits), and retain captured value (plgpio bits).
|
||||
*/
|
||||
#define plgpio_prepare_reg(__reg, _off, _mask, _tmp) \
|
||||
{ \
|
||||
_tmp = readl_relaxed(plgpio->regs.__reg + _off); \
|
||||
_tmp &= ~_mask; \
|
||||
plgpio->csave_regs[i].__reg = \
|
||||
_tmp | (plgpio->csave_regs[i].__reg & _mask); \
|
||||
}
|
||||
|
||||
static int plgpio_resume(struct device *dev)
|
||||
{
|
||||
struct plgpio *plgpio = dev_get_drvdata(dev);
|
||||
int i, reg_count = DIV_ROUND_UP(plgpio->chip.ngpio, MAX_GPIO_PER_REG);
|
||||
void __iomem *off;
|
||||
u32 mask, tmp;
|
||||
|
||||
for (i = 0; i < reg_count; i++) {
|
||||
off = plgpio->base + i * sizeof(int *);
|
||||
|
||||
if (i == reg_count - 1) {
|
||||
mask = (1 << (plgpio->chip.ngpio - i *
|
||||
MAX_GPIO_PER_REG)) - 1;
|
||||
|
||||
if (plgpio->regs.enb != -1)
|
||||
plgpio_prepare_reg(enb, off, mask, tmp);
|
||||
|
||||
if (plgpio->regs.eit != -1)
|
||||
plgpio_prepare_reg(eit, off, mask, tmp);
|
||||
|
||||
plgpio_prepare_reg(wdata, off, mask, tmp);
|
||||
plgpio_prepare_reg(dir, off, mask, tmp);
|
||||
plgpio_prepare_reg(ie, off, mask, tmp);
|
||||
}
|
||||
|
||||
writel_relaxed(plgpio->csave_regs[i].wdata, plgpio->regs.wdata +
|
||||
off);
|
||||
writel_relaxed(plgpio->csave_regs[i].dir, plgpio->regs.dir +
|
||||
off);
|
||||
|
||||
if (plgpio->regs.eit != -1)
|
||||
writel_relaxed(plgpio->csave_regs[i].eit,
|
||||
plgpio->regs.eit + off);
|
||||
|
||||
writel_relaxed(plgpio->csave_regs[i].ie, plgpio->regs.ie + off);
|
||||
|
||||
if (plgpio->regs.enb != -1)
|
||||
writel_relaxed(plgpio->csave_regs[i].enb,
|
||||
plgpio->regs.enb + off);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
static SIMPLE_DEV_PM_OPS(plgpio_dev_pm_ops, plgpio_suspend, plgpio_resume);
|
||||
|
||||
static const struct of_device_id plgpio_of_match[] = {
|
||||
{ .compatible = "st,spear-plgpio" },
|
||||
{}
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, plgpio_of_match);
|
||||
|
||||
static struct platform_driver plgpio_driver = {
|
||||
.probe = plgpio_probe,
|
||||
.driver = {
|
||||
.owner = THIS_MODULE,
|
||||
.name = "spear-plgpio",
|
||||
.pm = &plgpio_dev_pm_ops,
|
||||
.of_match_table = plgpio_of_match,
|
||||
},
|
||||
};
|
||||
|
||||
static int __init plgpio_init(void)
|
||||
{
|
||||
return platform_driver_register(&plgpio_driver);
|
||||
}
|
||||
subsys_initcall(plgpio_init);
|
||||
|
||||
MODULE_AUTHOR("Viresh Kumar <viresh.kumar@linaro.org>");
|
||||
MODULE_DESCRIPTION("ST Microlectronics SPEAr PLGPIO driver");
|
||||
MODULE_LICENSE("GPL");
|
414
drivers/pinctrl/spear/pinctrl-spear.c
Normal file
414
drivers/pinctrl/spear/pinctrl-spear.c
Normal file
|
@ -0,0 +1,414 @@
|
|||
/*
|
||||
* Driver for the ST Microelectronics SPEAr pinmux
|
||||
*
|
||||
* Copyright (C) 2012 ST Microelectronics
|
||||
* Viresh Kumar <viresh.linux@gmail.com>
|
||||
*
|
||||
* Inspired from:
|
||||
* - U300 Pinctl drivers
|
||||
* - Tegra Pinctl drivers
|
||||
*
|
||||
* This file is licensed under the terms of the GNU General Public
|
||||
* License version 2. This program is licensed "as is" without any
|
||||
* warranty of any kind, whether express or implied.
|
||||
*/
|
||||
|
||||
#include <linux/err.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_address.h>
|
||||
#include <linux/of_gpio.h>
|
||||
#include <linux/pinctrl/machine.h>
|
||||
#include <linux/pinctrl/pinctrl.h>
|
||||
#include <linux/pinctrl/pinmux.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/slab.h>
|
||||
|
||||
#include "pinctrl-spear.h"
|
||||
|
||||
#define DRIVER_NAME "spear-pinmux"
|
||||
|
||||
static void muxregs_endisable(struct spear_pmx *pmx,
|
||||
struct spear_muxreg *muxregs, u8 count, bool enable)
|
||||
{
|
||||
struct spear_muxreg *muxreg;
|
||||
u32 val, temp, j;
|
||||
|
||||
for (j = 0; j < count; j++) {
|
||||
muxreg = &muxregs[j];
|
||||
|
||||
val = pmx_readl(pmx, muxreg->reg);
|
||||
val &= ~muxreg->mask;
|
||||
|
||||
if (enable)
|
||||
temp = muxreg->val;
|
||||
else
|
||||
temp = ~muxreg->val;
|
||||
|
||||
val |= muxreg->mask & temp;
|
||||
pmx_writel(pmx, val, muxreg->reg);
|
||||
}
|
||||
}
|
||||
|
||||
static int set_mode(struct spear_pmx *pmx, int mode)
|
||||
{
|
||||
struct spear_pmx_mode *pmx_mode = NULL;
|
||||
int i;
|
||||
u32 val;
|
||||
|
||||
if (!pmx->machdata->pmx_modes || !pmx->machdata->npmx_modes)
|
||||
return -EINVAL;
|
||||
|
||||
for (i = 0; i < pmx->machdata->npmx_modes; i++) {
|
||||
if (pmx->machdata->pmx_modes[i]->mode == (1 << mode)) {
|
||||
pmx_mode = pmx->machdata->pmx_modes[i];
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!pmx_mode)
|
||||
return -EINVAL;
|
||||
|
||||
val = pmx_readl(pmx, pmx_mode->reg);
|
||||
val &= ~pmx_mode->mask;
|
||||
val |= pmx_mode->val;
|
||||
pmx_writel(pmx, val, pmx_mode->reg);
|
||||
|
||||
pmx->machdata->mode = pmx_mode->mode;
|
||||
dev_info(pmx->dev, "Configured Mode: %s with id: %x\n\n",
|
||||
pmx_mode->name ? pmx_mode->name : "no_name",
|
||||
pmx_mode->reg);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void pmx_init_gpio_pingroup_addr(struct spear_gpio_pingroup *gpio_pingroup,
|
||||
unsigned count, u16 reg)
|
||||
{
|
||||
int i, j;
|
||||
|
||||
for (i = 0; i < count; i++)
|
||||
for (j = 0; j < gpio_pingroup[i].nmuxregs; j++)
|
||||
gpio_pingroup[i].muxregs[j].reg = reg;
|
||||
}
|
||||
|
||||
void pmx_init_addr(struct spear_pinctrl_machdata *machdata, u16 reg)
|
||||
{
|
||||
struct spear_pingroup *pgroup;
|
||||
struct spear_modemux *modemux;
|
||||
int i, j, group;
|
||||
|
||||
for (group = 0; group < machdata->ngroups; group++) {
|
||||
pgroup = machdata->groups[group];
|
||||
|
||||
for (i = 0; i < pgroup->nmodemuxs; i++) {
|
||||
modemux = &pgroup->modemuxs[i];
|
||||
|
||||
for (j = 0; j < modemux->nmuxregs; j++)
|
||||
if (modemux->muxregs[j].reg == 0xFFFF)
|
||||
modemux->muxregs[j].reg = reg;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static int spear_pinctrl_get_groups_cnt(struct pinctrl_dev *pctldev)
|
||||
{
|
||||
struct spear_pmx *pmx = pinctrl_dev_get_drvdata(pctldev);
|
||||
|
||||
return pmx->machdata->ngroups;
|
||||
}
|
||||
|
||||
static const char *spear_pinctrl_get_group_name(struct pinctrl_dev *pctldev,
|
||||
unsigned group)
|
||||
{
|
||||
struct spear_pmx *pmx = pinctrl_dev_get_drvdata(pctldev);
|
||||
|
||||
return pmx->machdata->groups[group]->name;
|
||||
}
|
||||
|
||||
static int spear_pinctrl_get_group_pins(struct pinctrl_dev *pctldev,
|
||||
unsigned group, const unsigned **pins, unsigned *num_pins)
|
||||
{
|
||||
struct spear_pmx *pmx = pinctrl_dev_get_drvdata(pctldev);
|
||||
|
||||
*pins = pmx->machdata->groups[group]->pins;
|
||||
*num_pins = pmx->machdata->groups[group]->npins;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void spear_pinctrl_pin_dbg_show(struct pinctrl_dev *pctldev,
|
||||
struct seq_file *s, unsigned offset)
|
||||
{
|
||||
seq_printf(s, " " DRIVER_NAME);
|
||||
}
|
||||
|
||||
static int spear_pinctrl_dt_node_to_map(struct pinctrl_dev *pctldev,
|
||||
struct device_node *np_config,
|
||||
struct pinctrl_map **map,
|
||||
unsigned *num_maps)
|
||||
{
|
||||
struct spear_pmx *pmx = pinctrl_dev_get_drvdata(pctldev);
|
||||
struct device_node *np;
|
||||
struct property *prop;
|
||||
const char *function, *group;
|
||||
int ret, index = 0, count = 0;
|
||||
|
||||
/* calculate number of maps required */
|
||||
for_each_child_of_node(np_config, np) {
|
||||
ret = of_property_read_string(np, "st,function", &function);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
ret = of_property_count_strings(np, "st,pins");
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
count += ret;
|
||||
}
|
||||
|
||||
if (!count) {
|
||||
dev_err(pmx->dev, "No child nodes passed via DT\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
*map = kzalloc(sizeof(**map) * count, GFP_KERNEL);
|
||||
if (!*map)
|
||||
return -ENOMEM;
|
||||
|
||||
for_each_child_of_node(np_config, np) {
|
||||
of_property_read_string(np, "st,function", &function);
|
||||
of_property_for_each_string(np, "st,pins", prop, group) {
|
||||
(*map)[index].type = PIN_MAP_TYPE_MUX_GROUP;
|
||||
(*map)[index].data.mux.group = group;
|
||||
(*map)[index].data.mux.function = function;
|
||||
index++;
|
||||
}
|
||||
}
|
||||
|
||||
*num_maps = count;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void spear_pinctrl_dt_free_map(struct pinctrl_dev *pctldev,
|
||||
struct pinctrl_map *map,
|
||||
unsigned num_maps)
|
||||
{
|
||||
kfree(map);
|
||||
}
|
||||
|
||||
static const struct pinctrl_ops spear_pinctrl_ops = {
|
||||
.get_groups_count = spear_pinctrl_get_groups_cnt,
|
||||
.get_group_name = spear_pinctrl_get_group_name,
|
||||
.get_group_pins = spear_pinctrl_get_group_pins,
|
||||
.pin_dbg_show = spear_pinctrl_pin_dbg_show,
|
||||
.dt_node_to_map = spear_pinctrl_dt_node_to_map,
|
||||
.dt_free_map = spear_pinctrl_dt_free_map,
|
||||
};
|
||||
|
||||
static int spear_pinctrl_get_funcs_count(struct pinctrl_dev *pctldev)
|
||||
{
|
||||
struct spear_pmx *pmx = pinctrl_dev_get_drvdata(pctldev);
|
||||
|
||||
return pmx->machdata->nfunctions;
|
||||
}
|
||||
|
||||
static const char *spear_pinctrl_get_func_name(struct pinctrl_dev *pctldev,
|
||||
unsigned function)
|
||||
{
|
||||
struct spear_pmx *pmx = pinctrl_dev_get_drvdata(pctldev);
|
||||
|
||||
return pmx->machdata->functions[function]->name;
|
||||
}
|
||||
|
||||
static int spear_pinctrl_get_func_groups(struct pinctrl_dev *pctldev,
|
||||
unsigned function, const char *const **groups,
|
||||
unsigned * const ngroups)
|
||||
{
|
||||
struct spear_pmx *pmx = pinctrl_dev_get_drvdata(pctldev);
|
||||
|
||||
*groups = pmx->machdata->functions[function]->groups;
|
||||
*ngroups = pmx->machdata->functions[function]->ngroups;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int spear_pinctrl_endisable(struct pinctrl_dev *pctldev,
|
||||
unsigned function, unsigned group, bool enable)
|
||||
{
|
||||
struct spear_pmx *pmx = pinctrl_dev_get_drvdata(pctldev);
|
||||
const struct spear_pingroup *pgroup;
|
||||
const struct spear_modemux *modemux;
|
||||
int i;
|
||||
bool found = false;
|
||||
|
||||
pgroup = pmx->machdata->groups[group];
|
||||
|
||||
for (i = 0; i < pgroup->nmodemuxs; i++) {
|
||||
modemux = &pgroup->modemuxs[i];
|
||||
|
||||
/* SoC have any modes */
|
||||
if (pmx->machdata->modes_supported) {
|
||||
if (!(pmx->machdata->mode & modemux->modes))
|
||||
continue;
|
||||
}
|
||||
|
||||
found = true;
|
||||
muxregs_endisable(pmx, modemux->muxregs, modemux->nmuxregs,
|
||||
enable);
|
||||
}
|
||||
|
||||
if (!found) {
|
||||
dev_err(pmx->dev, "pinmux group: %s not supported\n",
|
||||
pgroup->name);
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int spear_pinctrl_set_mux(struct pinctrl_dev *pctldev, unsigned function,
|
||||
unsigned group)
|
||||
{
|
||||
return spear_pinctrl_endisable(pctldev, function, group, true);
|
||||
}
|
||||
|
||||
/* gpio with pinmux */
|
||||
static struct spear_gpio_pingroup *get_gpio_pingroup(struct spear_pmx *pmx,
|
||||
unsigned pin)
|
||||
{
|
||||
struct spear_gpio_pingroup *gpio_pingroup;
|
||||
int i, j;
|
||||
|
||||
if (!pmx->machdata->gpio_pingroups)
|
||||
return NULL;
|
||||
|
||||
for (i = 0; i < pmx->machdata->ngpio_pingroups; i++) {
|
||||
gpio_pingroup = &pmx->machdata->gpio_pingroups[i];
|
||||
|
||||
for (j = 0; j < gpio_pingroup->npins; j++) {
|
||||
if (gpio_pingroup->pins[j] == pin)
|
||||
return gpio_pingroup;
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static int gpio_request_endisable(struct pinctrl_dev *pctldev,
|
||||
struct pinctrl_gpio_range *range, unsigned offset, bool enable)
|
||||
{
|
||||
struct spear_pmx *pmx = pinctrl_dev_get_drvdata(pctldev);
|
||||
struct spear_pinctrl_machdata *machdata = pmx->machdata;
|
||||
struct spear_gpio_pingroup *gpio_pingroup;
|
||||
|
||||
/*
|
||||
* Some SoC have configuration options applicable to group of pins,
|
||||
* rather than a single pin.
|
||||
*/
|
||||
gpio_pingroup = get_gpio_pingroup(pmx, offset);
|
||||
if (gpio_pingroup)
|
||||
muxregs_endisable(pmx, gpio_pingroup->muxregs,
|
||||
gpio_pingroup->nmuxregs, enable);
|
||||
|
||||
/*
|
||||
* SoC may need some extra configurations, or configurations for single
|
||||
* pin
|
||||
*/
|
||||
if (machdata->gpio_request_endisable)
|
||||
machdata->gpio_request_endisable(pmx, offset, enable);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int gpio_request_enable(struct pinctrl_dev *pctldev,
|
||||
struct pinctrl_gpio_range *range, unsigned offset)
|
||||
{
|
||||
return gpio_request_endisable(pctldev, range, offset, true);
|
||||
}
|
||||
|
||||
static void gpio_disable_free(struct pinctrl_dev *pctldev,
|
||||
struct pinctrl_gpio_range *range, unsigned offset)
|
||||
{
|
||||
gpio_request_endisable(pctldev, range, offset, false);
|
||||
}
|
||||
|
||||
static const struct pinmux_ops spear_pinmux_ops = {
|
||||
.get_functions_count = spear_pinctrl_get_funcs_count,
|
||||
.get_function_name = spear_pinctrl_get_func_name,
|
||||
.get_function_groups = spear_pinctrl_get_func_groups,
|
||||
.set_mux = spear_pinctrl_set_mux,
|
||||
.gpio_request_enable = gpio_request_enable,
|
||||
.gpio_disable_free = gpio_disable_free,
|
||||
};
|
||||
|
||||
static struct pinctrl_desc spear_pinctrl_desc = {
|
||||
.name = DRIVER_NAME,
|
||||
.pctlops = &spear_pinctrl_ops,
|
||||
.pmxops = &spear_pinmux_ops,
|
||||
.owner = THIS_MODULE,
|
||||
};
|
||||
|
||||
int spear_pinctrl_probe(struct platform_device *pdev,
|
||||
struct spear_pinctrl_machdata *machdata)
|
||||
{
|
||||
struct device_node *np = pdev->dev.of_node;
|
||||
struct resource *res;
|
||||
struct spear_pmx *pmx;
|
||||
|
||||
if (!machdata)
|
||||
return -ENODEV;
|
||||
|
||||
pmx = devm_kzalloc(&pdev->dev, sizeof(*pmx), GFP_KERNEL);
|
||||
if (!pmx) {
|
||||
dev_err(&pdev->dev, "Can't alloc spear_pmx\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||
pmx->vbase = devm_ioremap_resource(&pdev->dev, res);
|
||||
if (IS_ERR(pmx->vbase))
|
||||
return PTR_ERR(pmx->vbase);
|
||||
|
||||
pmx->dev = &pdev->dev;
|
||||
pmx->machdata = machdata;
|
||||
|
||||
/* configure mode, if supported by SoC */
|
||||
if (machdata->modes_supported) {
|
||||
int mode = 0;
|
||||
|
||||
if (of_property_read_u32(np, "st,pinmux-mode", &mode)) {
|
||||
dev_err(&pdev->dev, "OF: pinmux mode not passed\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (set_mode(pmx, mode)) {
|
||||
dev_err(&pdev->dev, "OF: Couldn't configure mode: %x\n",
|
||||
mode);
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
|
||||
platform_set_drvdata(pdev, pmx);
|
||||
|
||||
spear_pinctrl_desc.pins = machdata->pins;
|
||||
spear_pinctrl_desc.npins = machdata->npins;
|
||||
|
||||
pmx->pctl = pinctrl_register(&spear_pinctrl_desc, &pdev->dev, pmx);
|
||||
if (!pmx->pctl) {
|
||||
dev_err(&pdev->dev, "Couldn't register pinctrl driver\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int spear_pinctrl_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct spear_pmx *pmx = platform_get_drvdata(pdev);
|
||||
|
||||
pinctrl_unregister(pmx->pctl);
|
||||
|
||||
return 0;
|
||||
}
|
452
drivers/pinctrl/spear/pinctrl-spear.h
Normal file
452
drivers/pinctrl/spear/pinctrl-spear.h
Normal file
|
@ -0,0 +1,452 @@
|
|||
/*
|
||||
* Driver header file for the ST Microelectronics SPEAr pinmux
|
||||
*
|
||||
* Copyright (C) 2012 ST Microelectronics
|
||||
* Viresh Kumar <viresh.linux@gmail.com>
|
||||
*
|
||||
* This file is licensed under the terms of the GNU General Public
|
||||
* License version 2. This program is licensed "as is" without any
|
||||
* warranty of any kind, whether express or implied.
|
||||
*/
|
||||
|
||||
#ifndef __PINMUX_SPEAR_H__
|
||||
#define __PINMUX_SPEAR_H__
|
||||
|
||||
#include <linux/gpio.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/pinctrl/pinctrl.h>
|
||||
#include <linux/types.h>
|
||||
|
||||
struct platform_device;
|
||||
struct device;
|
||||
struct spear_pmx;
|
||||
|
||||
/**
|
||||
* struct spear_pmx_mode - SPEAr pmx mode
|
||||
* @name: name of pmx mode
|
||||
* @mode: mode id
|
||||
* @reg: register for configuring this mode
|
||||
* @mask: mask of this mode in reg
|
||||
* @val: val to be configured at reg after doing (val & mask)
|
||||
*/
|
||||
struct spear_pmx_mode {
|
||||
const char *const name;
|
||||
u16 mode;
|
||||
u16 reg;
|
||||
u16 mask;
|
||||
u32 val;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct spear_muxreg - SPEAr mux reg configuration
|
||||
* @reg: register offset
|
||||
* @mask: mask bits
|
||||
* @val: val to be written on mask bits
|
||||
*/
|
||||
struct spear_muxreg {
|
||||
u16 reg;
|
||||
u32 mask;
|
||||
u32 val;
|
||||
};
|
||||
|
||||
struct spear_gpio_pingroup {
|
||||
const unsigned *pins;
|
||||
unsigned npins;
|
||||
struct spear_muxreg *muxregs;
|
||||
u8 nmuxregs;
|
||||
};
|
||||
|
||||
/* ste: set to enable */
|
||||
#define DEFINE_MUXREG(__pins, __muxreg, __mask, __ste) \
|
||||
static struct spear_muxreg __pins##_muxregs[] = { \
|
||||
{ \
|
||||
.reg = __muxreg, \
|
||||
.mask = __mask, \
|
||||
.val = __ste ? __mask : 0, \
|
||||
}, \
|
||||
}
|
||||
|
||||
#define DEFINE_2_MUXREG(__pins, __muxreg1, __muxreg2, __mask, __ste1, __ste2) \
|
||||
static struct spear_muxreg __pins##_muxregs[] = { \
|
||||
{ \
|
||||
.reg = __muxreg1, \
|
||||
.mask = __mask, \
|
||||
.val = __ste1 ? __mask : 0, \
|
||||
}, { \
|
||||
.reg = __muxreg2, \
|
||||
.mask = __mask, \
|
||||
.val = __ste2 ? __mask : 0, \
|
||||
}, \
|
||||
}
|
||||
|
||||
#define GPIO_PINGROUP(__pins) \
|
||||
{ \
|
||||
.pins = __pins, \
|
||||
.npins = ARRAY_SIZE(__pins), \
|
||||
.muxregs = __pins##_muxregs, \
|
||||
.nmuxregs = ARRAY_SIZE(__pins##_muxregs), \
|
||||
}
|
||||
|
||||
/**
|
||||
* struct spear_modemux - SPEAr mode mux configuration
|
||||
* @modes: mode ids supported by this group of muxregs
|
||||
* @nmuxregs: number of muxreg configurations to be done for modes
|
||||
* @muxregs: array of muxreg configurations to be done for modes
|
||||
*/
|
||||
struct spear_modemux {
|
||||
u16 modes;
|
||||
u8 nmuxregs;
|
||||
struct spear_muxreg *muxregs;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct spear_pingroup - SPEAr pin group configurations
|
||||
* @name: name of pin group
|
||||
* @pins: array containing pin numbers
|
||||
* @npins: size of pins array
|
||||
* @modemuxs: array of modemux configurations for this pin group
|
||||
* @nmodemuxs: size of array modemuxs
|
||||
*
|
||||
* A representation of a group of pins in the SPEAr pin controller. Each group
|
||||
* allows some parameter or parameters to be configured.
|
||||
*/
|
||||
struct spear_pingroup {
|
||||
const char *name;
|
||||
const unsigned *pins;
|
||||
unsigned npins;
|
||||
struct spear_modemux *modemuxs;
|
||||
unsigned nmodemuxs;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct spear_function - SPEAr pinctrl mux function
|
||||
* @name: The name of the function, exported to pinctrl core.
|
||||
* @groups: An array of pin groups that may select this function.
|
||||
* @ngroups: The number of entries in @groups.
|
||||
*/
|
||||
struct spear_function {
|
||||
const char *name;
|
||||
const char *const *groups;
|
||||
unsigned ngroups;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct spear_pinctrl_machdata - SPEAr pin controller machine driver
|
||||
* configuration
|
||||
* @pins: An array describing all pins the pin controller affects.
|
||||
* All pins which are also GPIOs must be listed first within the *array,
|
||||
* and be numbered identically to the GPIO controller's *numbering.
|
||||
* @npins: The numbmer of entries in @pins.
|
||||
* @functions: An array describing all mux functions the SoC supports.
|
||||
* @nfunctions: The numbmer of entries in @functions.
|
||||
* @groups: An array describing all pin groups the pin SoC supports.
|
||||
* @ngroups: The numbmer of entries in @groups.
|
||||
* @gpio_pingroups: gpio pingroups
|
||||
* @ngpio_pingroups: gpio pingroups count
|
||||
*
|
||||
* @modes_supported: Does SoC support modes
|
||||
* @mode: mode configured from probe
|
||||
* @pmx_modes: array of modes supported by SoC
|
||||
* @npmx_modes: number of entries in pmx_modes.
|
||||
*/
|
||||
struct spear_pinctrl_machdata {
|
||||
const struct pinctrl_pin_desc *pins;
|
||||
unsigned npins;
|
||||
struct spear_function **functions;
|
||||
unsigned nfunctions;
|
||||
struct spear_pingroup **groups;
|
||||
unsigned ngroups;
|
||||
struct spear_gpio_pingroup *gpio_pingroups;
|
||||
void (*gpio_request_endisable)(struct spear_pmx *pmx, int offset,
|
||||
bool enable);
|
||||
unsigned ngpio_pingroups;
|
||||
|
||||
bool modes_supported;
|
||||
u16 mode;
|
||||
struct spear_pmx_mode **pmx_modes;
|
||||
unsigned npmx_modes;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct spear_pmx - SPEAr pinctrl mux
|
||||
* @dev: pointer to struct dev of platform_device registered
|
||||
* @pctl: pointer to struct pinctrl_dev
|
||||
* @machdata: pointer to SoC or machine specific structure
|
||||
* @vbase: virtual base address of pinmux controller
|
||||
*/
|
||||
struct spear_pmx {
|
||||
struct device *dev;
|
||||
struct pinctrl_dev *pctl;
|
||||
struct spear_pinctrl_machdata *machdata;
|
||||
void __iomem *vbase;
|
||||
};
|
||||
|
||||
/* exported routines */
|
||||
static inline u32 pmx_readl(struct spear_pmx *pmx, u32 reg)
|
||||
{
|
||||
return readl_relaxed(pmx->vbase + reg);
|
||||
}
|
||||
|
||||
static inline void pmx_writel(struct spear_pmx *pmx, u32 val, u32 reg)
|
||||
{
|
||||
writel_relaxed(val, pmx->vbase + reg);
|
||||
}
|
||||
|
||||
void pmx_init_addr(struct spear_pinctrl_machdata *machdata, u16 reg);
|
||||
void pmx_init_gpio_pingroup_addr(struct spear_gpio_pingroup *gpio_pingroup,
|
||||
unsigned count, u16 reg);
|
||||
int spear_pinctrl_probe(struct platform_device *pdev,
|
||||
struct spear_pinctrl_machdata *machdata);
|
||||
int spear_pinctrl_remove(struct platform_device *pdev);
|
||||
|
||||
#define SPEAR_PIN_0_TO_101 \
|
||||
PINCTRL_PIN(0, "PLGPIO0"), \
|
||||
PINCTRL_PIN(1, "PLGPIO1"), \
|
||||
PINCTRL_PIN(2, "PLGPIO2"), \
|
||||
PINCTRL_PIN(3, "PLGPIO3"), \
|
||||
PINCTRL_PIN(4, "PLGPIO4"), \
|
||||
PINCTRL_PIN(5, "PLGPIO5"), \
|
||||
PINCTRL_PIN(6, "PLGPIO6"), \
|
||||
PINCTRL_PIN(7, "PLGPIO7"), \
|
||||
PINCTRL_PIN(8, "PLGPIO8"), \
|
||||
PINCTRL_PIN(9, "PLGPIO9"), \
|
||||
PINCTRL_PIN(10, "PLGPIO10"), \
|
||||
PINCTRL_PIN(11, "PLGPIO11"), \
|
||||
PINCTRL_PIN(12, "PLGPIO12"), \
|
||||
PINCTRL_PIN(13, "PLGPIO13"), \
|
||||
PINCTRL_PIN(14, "PLGPIO14"), \
|
||||
PINCTRL_PIN(15, "PLGPIO15"), \
|
||||
PINCTRL_PIN(16, "PLGPIO16"), \
|
||||
PINCTRL_PIN(17, "PLGPIO17"), \
|
||||
PINCTRL_PIN(18, "PLGPIO18"), \
|
||||
PINCTRL_PIN(19, "PLGPIO19"), \
|
||||
PINCTRL_PIN(20, "PLGPIO20"), \
|
||||
PINCTRL_PIN(21, "PLGPIO21"), \
|
||||
PINCTRL_PIN(22, "PLGPIO22"), \
|
||||
PINCTRL_PIN(23, "PLGPIO23"), \
|
||||
PINCTRL_PIN(24, "PLGPIO24"), \
|
||||
PINCTRL_PIN(25, "PLGPIO25"), \
|
||||
PINCTRL_PIN(26, "PLGPIO26"), \
|
||||
PINCTRL_PIN(27, "PLGPIO27"), \
|
||||
PINCTRL_PIN(28, "PLGPIO28"), \
|
||||
PINCTRL_PIN(29, "PLGPIO29"), \
|
||||
PINCTRL_PIN(30, "PLGPIO30"), \
|
||||
PINCTRL_PIN(31, "PLGPIO31"), \
|
||||
PINCTRL_PIN(32, "PLGPIO32"), \
|
||||
PINCTRL_PIN(33, "PLGPIO33"), \
|
||||
PINCTRL_PIN(34, "PLGPIO34"), \
|
||||
PINCTRL_PIN(35, "PLGPIO35"), \
|
||||
PINCTRL_PIN(36, "PLGPIO36"), \
|
||||
PINCTRL_PIN(37, "PLGPIO37"), \
|
||||
PINCTRL_PIN(38, "PLGPIO38"), \
|
||||
PINCTRL_PIN(39, "PLGPIO39"), \
|
||||
PINCTRL_PIN(40, "PLGPIO40"), \
|
||||
PINCTRL_PIN(41, "PLGPIO41"), \
|
||||
PINCTRL_PIN(42, "PLGPIO42"), \
|
||||
PINCTRL_PIN(43, "PLGPIO43"), \
|
||||
PINCTRL_PIN(44, "PLGPIO44"), \
|
||||
PINCTRL_PIN(45, "PLGPIO45"), \
|
||||
PINCTRL_PIN(46, "PLGPIO46"), \
|
||||
PINCTRL_PIN(47, "PLGPIO47"), \
|
||||
PINCTRL_PIN(48, "PLGPIO48"), \
|
||||
PINCTRL_PIN(49, "PLGPIO49"), \
|
||||
PINCTRL_PIN(50, "PLGPIO50"), \
|
||||
PINCTRL_PIN(51, "PLGPIO51"), \
|
||||
PINCTRL_PIN(52, "PLGPIO52"), \
|
||||
PINCTRL_PIN(53, "PLGPIO53"), \
|
||||
PINCTRL_PIN(54, "PLGPIO54"), \
|
||||
PINCTRL_PIN(55, "PLGPIO55"), \
|
||||
PINCTRL_PIN(56, "PLGPIO56"), \
|
||||
PINCTRL_PIN(57, "PLGPIO57"), \
|
||||
PINCTRL_PIN(58, "PLGPIO58"), \
|
||||
PINCTRL_PIN(59, "PLGPIO59"), \
|
||||
PINCTRL_PIN(60, "PLGPIO60"), \
|
||||
PINCTRL_PIN(61, "PLGPIO61"), \
|
||||
PINCTRL_PIN(62, "PLGPIO62"), \
|
||||
PINCTRL_PIN(63, "PLGPIO63"), \
|
||||
PINCTRL_PIN(64, "PLGPIO64"), \
|
||||
PINCTRL_PIN(65, "PLGPIO65"), \
|
||||
PINCTRL_PIN(66, "PLGPIO66"), \
|
||||
PINCTRL_PIN(67, "PLGPIO67"), \
|
||||
PINCTRL_PIN(68, "PLGPIO68"), \
|
||||
PINCTRL_PIN(69, "PLGPIO69"), \
|
||||
PINCTRL_PIN(70, "PLGPIO70"), \
|
||||
PINCTRL_PIN(71, "PLGPIO71"), \
|
||||
PINCTRL_PIN(72, "PLGPIO72"), \
|
||||
PINCTRL_PIN(73, "PLGPIO73"), \
|
||||
PINCTRL_PIN(74, "PLGPIO74"), \
|
||||
PINCTRL_PIN(75, "PLGPIO75"), \
|
||||
PINCTRL_PIN(76, "PLGPIO76"), \
|
||||
PINCTRL_PIN(77, "PLGPIO77"), \
|
||||
PINCTRL_PIN(78, "PLGPIO78"), \
|
||||
PINCTRL_PIN(79, "PLGPIO79"), \
|
||||
PINCTRL_PIN(80, "PLGPIO80"), \
|
||||
PINCTRL_PIN(81, "PLGPIO81"), \
|
||||
PINCTRL_PIN(82, "PLGPIO82"), \
|
||||
PINCTRL_PIN(83, "PLGPIO83"), \
|
||||
PINCTRL_PIN(84, "PLGPIO84"), \
|
||||
PINCTRL_PIN(85, "PLGPIO85"), \
|
||||
PINCTRL_PIN(86, "PLGPIO86"), \
|
||||
PINCTRL_PIN(87, "PLGPIO87"), \
|
||||
PINCTRL_PIN(88, "PLGPIO88"), \
|
||||
PINCTRL_PIN(89, "PLGPIO89"), \
|
||||
PINCTRL_PIN(90, "PLGPIO90"), \
|
||||
PINCTRL_PIN(91, "PLGPIO91"), \
|
||||
PINCTRL_PIN(92, "PLGPIO92"), \
|
||||
PINCTRL_PIN(93, "PLGPIO93"), \
|
||||
PINCTRL_PIN(94, "PLGPIO94"), \
|
||||
PINCTRL_PIN(95, "PLGPIO95"), \
|
||||
PINCTRL_PIN(96, "PLGPIO96"), \
|
||||
PINCTRL_PIN(97, "PLGPIO97"), \
|
||||
PINCTRL_PIN(98, "PLGPIO98"), \
|
||||
PINCTRL_PIN(99, "PLGPIO99"), \
|
||||
PINCTRL_PIN(100, "PLGPIO100"), \
|
||||
PINCTRL_PIN(101, "PLGPIO101")
|
||||
|
||||
#define SPEAR_PIN_102_TO_245 \
|
||||
PINCTRL_PIN(102, "PLGPIO102"), \
|
||||
PINCTRL_PIN(103, "PLGPIO103"), \
|
||||
PINCTRL_PIN(104, "PLGPIO104"), \
|
||||
PINCTRL_PIN(105, "PLGPIO105"), \
|
||||
PINCTRL_PIN(106, "PLGPIO106"), \
|
||||
PINCTRL_PIN(107, "PLGPIO107"), \
|
||||
PINCTRL_PIN(108, "PLGPIO108"), \
|
||||
PINCTRL_PIN(109, "PLGPIO109"), \
|
||||
PINCTRL_PIN(110, "PLGPIO110"), \
|
||||
PINCTRL_PIN(111, "PLGPIO111"), \
|
||||
PINCTRL_PIN(112, "PLGPIO112"), \
|
||||
PINCTRL_PIN(113, "PLGPIO113"), \
|
||||
PINCTRL_PIN(114, "PLGPIO114"), \
|
||||
PINCTRL_PIN(115, "PLGPIO115"), \
|
||||
PINCTRL_PIN(116, "PLGPIO116"), \
|
||||
PINCTRL_PIN(117, "PLGPIO117"), \
|
||||
PINCTRL_PIN(118, "PLGPIO118"), \
|
||||
PINCTRL_PIN(119, "PLGPIO119"), \
|
||||
PINCTRL_PIN(120, "PLGPIO120"), \
|
||||
PINCTRL_PIN(121, "PLGPIO121"), \
|
||||
PINCTRL_PIN(122, "PLGPIO122"), \
|
||||
PINCTRL_PIN(123, "PLGPIO123"), \
|
||||
PINCTRL_PIN(124, "PLGPIO124"), \
|
||||
PINCTRL_PIN(125, "PLGPIO125"), \
|
||||
PINCTRL_PIN(126, "PLGPIO126"), \
|
||||
PINCTRL_PIN(127, "PLGPIO127"), \
|
||||
PINCTRL_PIN(128, "PLGPIO128"), \
|
||||
PINCTRL_PIN(129, "PLGPIO129"), \
|
||||
PINCTRL_PIN(130, "PLGPIO130"), \
|
||||
PINCTRL_PIN(131, "PLGPIO131"), \
|
||||
PINCTRL_PIN(132, "PLGPIO132"), \
|
||||
PINCTRL_PIN(133, "PLGPIO133"), \
|
||||
PINCTRL_PIN(134, "PLGPIO134"), \
|
||||
PINCTRL_PIN(135, "PLGPIO135"), \
|
||||
PINCTRL_PIN(136, "PLGPIO136"), \
|
||||
PINCTRL_PIN(137, "PLGPIO137"), \
|
||||
PINCTRL_PIN(138, "PLGPIO138"), \
|
||||
PINCTRL_PIN(139, "PLGPIO139"), \
|
||||
PINCTRL_PIN(140, "PLGPIO140"), \
|
||||
PINCTRL_PIN(141, "PLGPIO141"), \
|
||||
PINCTRL_PIN(142, "PLGPIO142"), \
|
||||
PINCTRL_PIN(143, "PLGPIO143"), \
|
||||
PINCTRL_PIN(144, "PLGPIO144"), \
|
||||
PINCTRL_PIN(145, "PLGPIO145"), \
|
||||
PINCTRL_PIN(146, "PLGPIO146"), \
|
||||
PINCTRL_PIN(147, "PLGPIO147"), \
|
||||
PINCTRL_PIN(148, "PLGPIO148"), \
|
||||
PINCTRL_PIN(149, "PLGPIO149"), \
|
||||
PINCTRL_PIN(150, "PLGPIO150"), \
|
||||
PINCTRL_PIN(151, "PLGPIO151"), \
|
||||
PINCTRL_PIN(152, "PLGPIO152"), \
|
||||
PINCTRL_PIN(153, "PLGPIO153"), \
|
||||
PINCTRL_PIN(154, "PLGPIO154"), \
|
||||
PINCTRL_PIN(155, "PLGPIO155"), \
|
||||
PINCTRL_PIN(156, "PLGPIO156"), \
|
||||
PINCTRL_PIN(157, "PLGPIO157"), \
|
||||
PINCTRL_PIN(158, "PLGPIO158"), \
|
||||
PINCTRL_PIN(159, "PLGPIO159"), \
|
||||
PINCTRL_PIN(160, "PLGPIO160"), \
|
||||
PINCTRL_PIN(161, "PLGPIO161"), \
|
||||
PINCTRL_PIN(162, "PLGPIO162"), \
|
||||
PINCTRL_PIN(163, "PLGPIO163"), \
|
||||
PINCTRL_PIN(164, "PLGPIO164"), \
|
||||
PINCTRL_PIN(165, "PLGPIO165"), \
|
||||
PINCTRL_PIN(166, "PLGPIO166"), \
|
||||
PINCTRL_PIN(167, "PLGPIO167"), \
|
||||
PINCTRL_PIN(168, "PLGPIO168"), \
|
||||
PINCTRL_PIN(169, "PLGPIO169"), \
|
||||
PINCTRL_PIN(170, "PLGPIO170"), \
|
||||
PINCTRL_PIN(171, "PLGPIO171"), \
|
||||
PINCTRL_PIN(172, "PLGPIO172"), \
|
||||
PINCTRL_PIN(173, "PLGPIO173"), \
|
||||
PINCTRL_PIN(174, "PLGPIO174"), \
|
||||
PINCTRL_PIN(175, "PLGPIO175"), \
|
||||
PINCTRL_PIN(176, "PLGPIO176"), \
|
||||
PINCTRL_PIN(177, "PLGPIO177"), \
|
||||
PINCTRL_PIN(178, "PLGPIO178"), \
|
||||
PINCTRL_PIN(179, "PLGPIO179"), \
|
||||
PINCTRL_PIN(180, "PLGPIO180"), \
|
||||
PINCTRL_PIN(181, "PLGPIO181"), \
|
||||
PINCTRL_PIN(182, "PLGPIO182"), \
|
||||
PINCTRL_PIN(183, "PLGPIO183"), \
|
||||
PINCTRL_PIN(184, "PLGPIO184"), \
|
||||
PINCTRL_PIN(185, "PLGPIO185"), \
|
||||
PINCTRL_PIN(186, "PLGPIO186"), \
|
||||
PINCTRL_PIN(187, "PLGPIO187"), \
|
||||
PINCTRL_PIN(188, "PLGPIO188"), \
|
||||
PINCTRL_PIN(189, "PLGPIO189"), \
|
||||
PINCTRL_PIN(190, "PLGPIO190"), \
|
||||
PINCTRL_PIN(191, "PLGPIO191"), \
|
||||
PINCTRL_PIN(192, "PLGPIO192"), \
|
||||
PINCTRL_PIN(193, "PLGPIO193"), \
|
||||
PINCTRL_PIN(194, "PLGPIO194"), \
|
||||
PINCTRL_PIN(195, "PLGPIO195"), \
|
||||
PINCTRL_PIN(196, "PLGPIO196"), \
|
||||
PINCTRL_PIN(197, "PLGPIO197"), \
|
||||
PINCTRL_PIN(198, "PLGPIO198"), \
|
||||
PINCTRL_PIN(199, "PLGPIO199"), \
|
||||
PINCTRL_PIN(200, "PLGPIO200"), \
|
||||
PINCTRL_PIN(201, "PLGPIO201"), \
|
||||
PINCTRL_PIN(202, "PLGPIO202"), \
|
||||
PINCTRL_PIN(203, "PLGPIO203"), \
|
||||
PINCTRL_PIN(204, "PLGPIO204"), \
|
||||
PINCTRL_PIN(205, "PLGPIO205"), \
|
||||
PINCTRL_PIN(206, "PLGPIO206"), \
|
||||
PINCTRL_PIN(207, "PLGPIO207"), \
|
||||
PINCTRL_PIN(208, "PLGPIO208"), \
|
||||
PINCTRL_PIN(209, "PLGPIO209"), \
|
||||
PINCTRL_PIN(210, "PLGPIO210"), \
|
||||
PINCTRL_PIN(211, "PLGPIO211"), \
|
||||
PINCTRL_PIN(212, "PLGPIO212"), \
|
||||
PINCTRL_PIN(213, "PLGPIO213"), \
|
||||
PINCTRL_PIN(214, "PLGPIO214"), \
|
||||
PINCTRL_PIN(215, "PLGPIO215"), \
|
||||
PINCTRL_PIN(216, "PLGPIO216"), \
|
||||
PINCTRL_PIN(217, "PLGPIO217"), \
|
||||
PINCTRL_PIN(218, "PLGPIO218"), \
|
||||
PINCTRL_PIN(219, "PLGPIO219"), \
|
||||
PINCTRL_PIN(220, "PLGPIO220"), \
|
||||
PINCTRL_PIN(221, "PLGPIO221"), \
|
||||
PINCTRL_PIN(222, "PLGPIO222"), \
|
||||
PINCTRL_PIN(223, "PLGPIO223"), \
|
||||
PINCTRL_PIN(224, "PLGPIO224"), \
|
||||
PINCTRL_PIN(225, "PLGPIO225"), \
|
||||
PINCTRL_PIN(226, "PLGPIO226"), \
|
||||
PINCTRL_PIN(227, "PLGPIO227"), \
|
||||
PINCTRL_PIN(228, "PLGPIO228"), \
|
||||
PINCTRL_PIN(229, "PLGPIO229"), \
|
||||
PINCTRL_PIN(230, "PLGPIO230"), \
|
||||
PINCTRL_PIN(231, "PLGPIO231"), \
|
||||
PINCTRL_PIN(232, "PLGPIO232"), \
|
||||
PINCTRL_PIN(233, "PLGPIO233"), \
|
||||
PINCTRL_PIN(234, "PLGPIO234"), \
|
||||
PINCTRL_PIN(235, "PLGPIO235"), \
|
||||
PINCTRL_PIN(236, "PLGPIO236"), \
|
||||
PINCTRL_PIN(237, "PLGPIO237"), \
|
||||
PINCTRL_PIN(238, "PLGPIO238"), \
|
||||
PINCTRL_PIN(239, "PLGPIO239"), \
|
||||
PINCTRL_PIN(240, "PLGPIO240"), \
|
||||
PINCTRL_PIN(241, "PLGPIO241"), \
|
||||
PINCTRL_PIN(242, "PLGPIO242"), \
|
||||
PINCTRL_PIN(243, "PLGPIO243"), \
|
||||
PINCTRL_PIN(244, "PLGPIO244"), \
|
||||
PINCTRL_PIN(245, "PLGPIO245")
|
||||
|
||||
#endif /* __PINMUX_SPEAR_H__ */
|
2737
drivers/pinctrl/spear/pinctrl-spear1310.c
Normal file
2737
drivers/pinctrl/spear/pinctrl-spear1310.c
Normal file
File diff suppressed because it is too large
Load diff
2053
drivers/pinctrl/spear/pinctrl-spear1340.c
Normal file
2053
drivers/pinctrl/spear/pinctrl-spear1340.c
Normal file
File diff suppressed because it is too large
Load diff
710
drivers/pinctrl/spear/pinctrl-spear300.c
Normal file
710
drivers/pinctrl/spear/pinctrl-spear300.c
Normal file
|
@ -0,0 +1,710 @@
|
|||
/*
|
||||
* Driver for the ST Microelectronics SPEAr300 pinmux
|
||||
*
|
||||
* Copyright (C) 2012 ST Microelectronics
|
||||
* Viresh Kumar <viresh.linux@gmail.com>
|
||||
*
|
||||
* This file is licensed under the terms of the GNU General Public
|
||||
* License version 2. This program is licensed "as is" without any
|
||||
* warranty of any kind, whether express or implied.
|
||||
*/
|
||||
|
||||
#include <linux/err.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/of_device.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include "pinctrl-spear3xx.h"
|
||||
|
||||
#define DRIVER_NAME "spear300-pinmux"
|
||||
|
||||
/* addresses */
|
||||
#define PMX_CONFIG_REG 0x00
|
||||
#define MODE_CONFIG_REG 0x04
|
||||
|
||||
/* modes */
|
||||
#define NAND_MODE (1 << 0)
|
||||
#define NOR_MODE (1 << 1)
|
||||
#define PHOTO_FRAME_MODE (1 << 2)
|
||||
#define LEND_IP_PHONE_MODE (1 << 3)
|
||||
#define HEND_IP_PHONE_MODE (1 << 4)
|
||||
#define LEND_WIFI_PHONE_MODE (1 << 5)
|
||||
#define HEND_WIFI_PHONE_MODE (1 << 6)
|
||||
#define ATA_PABX_WI2S_MODE (1 << 7)
|
||||
#define ATA_PABX_I2S_MODE (1 << 8)
|
||||
#define CAML_LCDW_MODE (1 << 9)
|
||||
#define CAMU_LCD_MODE (1 << 10)
|
||||
#define CAMU_WLCD_MODE (1 << 11)
|
||||
#define CAML_LCD_MODE (1 << 12)
|
||||
|
||||
static struct spear_pmx_mode pmx_mode_nand = {
|
||||
.name = "nand",
|
||||
.mode = NAND_MODE,
|
||||
.reg = MODE_CONFIG_REG,
|
||||
.mask = 0x0000000F,
|
||||
.val = 0x00,
|
||||
};
|
||||
|
||||
static struct spear_pmx_mode pmx_mode_nor = {
|
||||
.name = "nor",
|
||||
.mode = NOR_MODE,
|
||||
.reg = MODE_CONFIG_REG,
|
||||
.mask = 0x0000000F,
|
||||
.val = 0x01,
|
||||
};
|
||||
|
||||
static struct spear_pmx_mode pmx_mode_photo_frame = {
|
||||
.name = "photo frame mode",
|
||||
.mode = PHOTO_FRAME_MODE,
|
||||
.reg = MODE_CONFIG_REG,
|
||||
.mask = 0x0000000F,
|
||||
.val = 0x02,
|
||||
};
|
||||
|
||||
static struct spear_pmx_mode pmx_mode_lend_ip_phone = {
|
||||
.name = "lend ip phone mode",
|
||||
.mode = LEND_IP_PHONE_MODE,
|
||||
.reg = MODE_CONFIG_REG,
|
||||
.mask = 0x0000000F,
|
||||
.val = 0x03,
|
||||
};
|
||||
|
||||
static struct spear_pmx_mode pmx_mode_hend_ip_phone = {
|
||||
.name = "hend ip phone mode",
|
||||
.mode = HEND_IP_PHONE_MODE,
|
||||
.reg = MODE_CONFIG_REG,
|
||||
.mask = 0x0000000F,
|
||||
.val = 0x04,
|
||||
};
|
||||
|
||||
static struct spear_pmx_mode pmx_mode_lend_wifi_phone = {
|
||||
.name = "lend wifi phone mode",
|
||||
.mode = LEND_WIFI_PHONE_MODE,
|
||||
.reg = MODE_CONFIG_REG,
|
||||
.mask = 0x0000000F,
|
||||
.val = 0x05,
|
||||
};
|
||||
|
||||
static struct spear_pmx_mode pmx_mode_hend_wifi_phone = {
|
||||
.name = "hend wifi phone mode",
|
||||
.mode = HEND_WIFI_PHONE_MODE,
|
||||
.reg = MODE_CONFIG_REG,
|
||||
.mask = 0x0000000F,
|
||||
.val = 0x06,
|
||||
};
|
||||
|
||||
static struct spear_pmx_mode pmx_mode_ata_pabx_wi2s = {
|
||||
.name = "ata pabx wi2s mode",
|
||||
.mode = ATA_PABX_WI2S_MODE,
|
||||
.reg = MODE_CONFIG_REG,
|
||||
.mask = 0x0000000F,
|
||||
.val = 0x07,
|
||||
};
|
||||
|
||||
static struct spear_pmx_mode pmx_mode_ata_pabx_i2s = {
|
||||
.name = "ata pabx i2s mode",
|
||||
.mode = ATA_PABX_I2S_MODE,
|
||||
.reg = MODE_CONFIG_REG,
|
||||
.mask = 0x0000000F,
|
||||
.val = 0x08,
|
||||
};
|
||||
|
||||
static struct spear_pmx_mode pmx_mode_caml_lcdw = {
|
||||
.name = "caml lcdw mode",
|
||||
.mode = CAML_LCDW_MODE,
|
||||
.reg = MODE_CONFIG_REG,
|
||||
.mask = 0x0000000F,
|
||||
.val = 0x0C,
|
||||
};
|
||||
|
||||
static struct spear_pmx_mode pmx_mode_camu_lcd = {
|
||||
.name = "camu lcd mode",
|
||||
.mode = CAMU_LCD_MODE,
|
||||
.reg = MODE_CONFIG_REG,
|
||||
.mask = 0x0000000F,
|
||||
.val = 0x0D,
|
||||
};
|
||||
|
||||
static struct spear_pmx_mode pmx_mode_camu_wlcd = {
|
||||
.name = "camu wlcd mode",
|
||||
.mode = CAMU_WLCD_MODE,
|
||||
.reg = MODE_CONFIG_REG,
|
||||
.mask = 0x0000000F,
|
||||
.val = 0xE,
|
||||
};
|
||||
|
||||
static struct spear_pmx_mode pmx_mode_caml_lcd = {
|
||||
.name = "caml lcd mode",
|
||||
.mode = CAML_LCD_MODE,
|
||||
.reg = MODE_CONFIG_REG,
|
||||
.mask = 0x0000000F,
|
||||
.val = 0x0F,
|
||||
};
|
||||
|
||||
static struct spear_pmx_mode *spear300_pmx_modes[] = {
|
||||
&pmx_mode_nand,
|
||||
&pmx_mode_nor,
|
||||
&pmx_mode_photo_frame,
|
||||
&pmx_mode_lend_ip_phone,
|
||||
&pmx_mode_hend_ip_phone,
|
||||
&pmx_mode_lend_wifi_phone,
|
||||
&pmx_mode_hend_wifi_phone,
|
||||
&pmx_mode_ata_pabx_wi2s,
|
||||
&pmx_mode_ata_pabx_i2s,
|
||||
&pmx_mode_caml_lcdw,
|
||||
&pmx_mode_camu_lcd,
|
||||
&pmx_mode_camu_wlcd,
|
||||
&pmx_mode_caml_lcd,
|
||||
};
|
||||
|
||||
/* fsmc_2chips_pins */
|
||||
static const unsigned fsmc_2chips_pins[] = { 1, 97 };
|
||||
static struct spear_muxreg fsmc_2chips_muxreg[] = {
|
||||
{
|
||||
.reg = PMX_CONFIG_REG,
|
||||
.mask = PMX_FIRDA_MASK,
|
||||
.val = 0,
|
||||
},
|
||||
};
|
||||
|
||||
static struct spear_modemux fsmc_2chips_modemux[] = {
|
||||
{
|
||||
.modes = NAND_MODE | NOR_MODE | PHOTO_FRAME_MODE |
|
||||
ATA_PABX_WI2S_MODE | ATA_PABX_I2S_MODE,
|
||||
.muxregs = fsmc_2chips_muxreg,
|
||||
.nmuxregs = ARRAY_SIZE(fsmc_2chips_muxreg),
|
||||
},
|
||||
};
|
||||
|
||||
static struct spear_pingroup fsmc_2chips_pingroup = {
|
||||
.name = "fsmc_2chips_grp",
|
||||
.pins = fsmc_2chips_pins,
|
||||
.npins = ARRAY_SIZE(fsmc_2chips_pins),
|
||||
.modemuxs = fsmc_2chips_modemux,
|
||||
.nmodemuxs = ARRAY_SIZE(fsmc_2chips_modemux),
|
||||
};
|
||||
|
||||
/* fsmc_4chips_pins */
|
||||
static const unsigned fsmc_4chips_pins[] = { 1, 2, 3, 97 };
|
||||
static struct spear_muxreg fsmc_4chips_muxreg[] = {
|
||||
{
|
||||
.reg = PMX_CONFIG_REG,
|
||||
.mask = PMX_FIRDA_MASK | PMX_UART0_MASK,
|
||||
.val = 0,
|
||||
},
|
||||
};
|
||||
|
||||
static struct spear_modemux fsmc_4chips_modemux[] = {
|
||||
{
|
||||
.modes = NAND_MODE | NOR_MODE | PHOTO_FRAME_MODE |
|
||||
ATA_PABX_WI2S_MODE | ATA_PABX_I2S_MODE,
|
||||
.muxregs = fsmc_4chips_muxreg,
|
||||
.nmuxregs = ARRAY_SIZE(fsmc_4chips_muxreg),
|
||||
},
|
||||
};
|
||||
|
||||
static struct spear_pingroup fsmc_4chips_pingroup = {
|
||||
.name = "fsmc_4chips_grp",
|
||||
.pins = fsmc_4chips_pins,
|
||||
.npins = ARRAY_SIZE(fsmc_4chips_pins),
|
||||
.modemuxs = fsmc_4chips_modemux,
|
||||
.nmodemuxs = ARRAY_SIZE(fsmc_4chips_modemux),
|
||||
};
|
||||
|
||||
static const char *const fsmc_grps[] = { "fsmc_2chips_grp", "fsmc_4chips_grp"
|
||||
};
|
||||
static struct spear_function fsmc_function = {
|
||||
.name = "fsmc",
|
||||
.groups = fsmc_grps,
|
||||
.ngroups = ARRAY_SIZE(fsmc_grps),
|
||||
};
|
||||
|
||||
/* clcd_lcdmode_pins */
|
||||
static const unsigned clcd_lcdmode_pins[] = { 49, 50 };
|
||||
static struct spear_muxreg clcd_lcdmode_muxreg[] = {
|
||||
{
|
||||
.reg = PMX_CONFIG_REG,
|
||||
.mask = PMX_TIMER_0_1_MASK | PMX_TIMER_2_3_MASK,
|
||||
.val = 0,
|
||||
},
|
||||
};
|
||||
|
||||
static struct spear_modemux clcd_lcdmode_modemux[] = {
|
||||
{
|
||||
.modes = HEND_IP_PHONE_MODE | HEND_WIFI_PHONE_MODE |
|
||||
CAMU_LCD_MODE | CAML_LCD_MODE,
|
||||
.muxregs = clcd_lcdmode_muxreg,
|
||||
.nmuxregs = ARRAY_SIZE(clcd_lcdmode_muxreg),
|
||||
},
|
||||
};
|
||||
|
||||
static struct spear_pingroup clcd_lcdmode_pingroup = {
|
||||
.name = "clcd_lcdmode_grp",
|
||||
.pins = clcd_lcdmode_pins,
|
||||
.npins = ARRAY_SIZE(clcd_lcdmode_pins),
|
||||
.modemuxs = clcd_lcdmode_modemux,
|
||||
.nmodemuxs = ARRAY_SIZE(clcd_lcdmode_modemux),
|
||||
};
|
||||
|
||||
/* clcd_pfmode_pins */
|
||||
static const unsigned clcd_pfmode_pins[] = { 47, 48, 49, 50 };
|
||||
static struct spear_muxreg clcd_pfmode_muxreg[] = {
|
||||
{
|
||||
.reg = PMX_CONFIG_REG,
|
||||
.mask = PMX_TIMER_2_3_MASK,
|
||||
.val = 0,
|
||||
},
|
||||
};
|
||||
|
||||
static struct spear_modemux clcd_pfmode_modemux[] = {
|
||||
{
|
||||
.modes = PHOTO_FRAME_MODE,
|
||||
.muxregs = clcd_pfmode_muxreg,
|
||||
.nmuxregs = ARRAY_SIZE(clcd_pfmode_muxreg),
|
||||
},
|
||||
};
|
||||
|
||||
static struct spear_pingroup clcd_pfmode_pingroup = {
|
||||
.name = "clcd_pfmode_grp",
|
||||
.pins = clcd_pfmode_pins,
|
||||
.npins = ARRAY_SIZE(clcd_pfmode_pins),
|
||||
.modemuxs = clcd_pfmode_modemux,
|
||||
.nmodemuxs = ARRAY_SIZE(clcd_pfmode_modemux),
|
||||
};
|
||||
|
||||
static const char *const clcd_grps[] = { "clcd_lcdmode_grp", "clcd_pfmode_grp"
|
||||
};
|
||||
static struct spear_function clcd_function = {
|
||||
.name = "clcd",
|
||||
.groups = clcd_grps,
|
||||
.ngroups = ARRAY_SIZE(clcd_grps),
|
||||
};
|
||||
|
||||
/* tdm_pins */
|
||||
static const unsigned tdm_pins[] = { 34, 35, 36, 37, 38 };
|
||||
static struct spear_muxreg tdm_muxreg[] = {
|
||||
{
|
||||
.reg = PMX_CONFIG_REG,
|
||||
.mask = PMX_UART0_MODEM_MASK | PMX_SSP_CS_MASK,
|
||||
.val = 0,
|
||||
},
|
||||
};
|
||||
|
||||
static struct spear_modemux tdm_modemux[] = {
|
||||
{
|
||||
.modes = PHOTO_FRAME_MODE | LEND_IP_PHONE_MODE |
|
||||
HEND_IP_PHONE_MODE | LEND_WIFI_PHONE_MODE
|
||||
| HEND_WIFI_PHONE_MODE | ATA_PABX_WI2S_MODE
|
||||
| ATA_PABX_I2S_MODE | CAML_LCDW_MODE | CAMU_LCD_MODE
|
||||
| CAMU_WLCD_MODE | CAML_LCD_MODE,
|
||||
.muxregs = tdm_muxreg,
|
||||
.nmuxregs = ARRAY_SIZE(tdm_muxreg),
|
||||
},
|
||||
};
|
||||
|
||||
static struct spear_pingroup tdm_pingroup = {
|
||||
.name = "tdm_grp",
|
||||
.pins = tdm_pins,
|
||||
.npins = ARRAY_SIZE(tdm_pins),
|
||||
.modemuxs = tdm_modemux,
|
||||
.nmodemuxs = ARRAY_SIZE(tdm_modemux),
|
||||
};
|
||||
|
||||
static const char *const tdm_grps[] = { "tdm_grp" };
|
||||
static struct spear_function tdm_function = {
|
||||
.name = "tdm",
|
||||
.groups = tdm_grps,
|
||||
.ngroups = ARRAY_SIZE(tdm_grps),
|
||||
};
|
||||
|
||||
/* i2c_clk_pins */
|
||||
static const unsigned i2c_clk_pins[] = { 45, 46, 47, 48 };
|
||||
static struct spear_muxreg i2c_clk_muxreg[] = {
|
||||
{
|
||||
.reg = PMX_CONFIG_REG,
|
||||
.mask = PMX_TIMER_0_1_MASK | PMX_TIMER_2_3_MASK,
|
||||
.val = 0,
|
||||
},
|
||||
};
|
||||
|
||||
static struct spear_modemux i2c_clk_modemux[] = {
|
||||
{
|
||||
.modes = LEND_IP_PHONE_MODE | HEND_IP_PHONE_MODE |
|
||||
LEND_WIFI_PHONE_MODE | HEND_WIFI_PHONE_MODE |
|
||||
ATA_PABX_WI2S_MODE | ATA_PABX_I2S_MODE | CAML_LCDW_MODE
|
||||
| CAML_LCD_MODE,
|
||||
.muxregs = i2c_clk_muxreg,
|
||||
.nmuxregs = ARRAY_SIZE(i2c_clk_muxreg),
|
||||
},
|
||||
};
|
||||
|
||||
static struct spear_pingroup i2c_clk_pingroup = {
|
||||
.name = "i2c_clk_grp_grp",
|
||||
.pins = i2c_clk_pins,
|
||||
.npins = ARRAY_SIZE(i2c_clk_pins),
|
||||
.modemuxs = i2c_clk_modemux,
|
||||
.nmodemuxs = ARRAY_SIZE(i2c_clk_modemux),
|
||||
};
|
||||
|
||||
static const char *const i2c_grps[] = { "i2c_clk_grp" };
|
||||
static struct spear_function i2c_function = {
|
||||
.name = "i2c1",
|
||||
.groups = i2c_grps,
|
||||
.ngroups = ARRAY_SIZE(i2c_grps),
|
||||
};
|
||||
|
||||
/* caml_pins */
|
||||
static const unsigned caml_pins[] = { 12, 13, 14, 15, 16, 17, 18, 19, 20, 21 };
|
||||
static struct spear_muxreg caml_muxreg[] = {
|
||||
{
|
||||
.reg = PMX_CONFIG_REG,
|
||||
.mask = PMX_MII_MASK,
|
||||
.val = 0,
|
||||
},
|
||||
};
|
||||
|
||||
static struct spear_modemux caml_modemux[] = {
|
||||
{
|
||||
.modes = CAML_LCDW_MODE | CAML_LCD_MODE,
|
||||
.muxregs = caml_muxreg,
|
||||
.nmuxregs = ARRAY_SIZE(caml_muxreg),
|
||||
},
|
||||
};
|
||||
|
||||
static struct spear_pingroup caml_pingroup = {
|
||||
.name = "caml_grp",
|
||||
.pins = caml_pins,
|
||||
.npins = ARRAY_SIZE(caml_pins),
|
||||
.modemuxs = caml_modemux,
|
||||
.nmodemuxs = ARRAY_SIZE(caml_modemux),
|
||||
};
|
||||
|
||||
/* camu_pins */
|
||||
static const unsigned camu_pins[] = { 16, 17, 18, 19, 20, 21, 45, 46, 47, 48 };
|
||||
static struct spear_muxreg camu_muxreg[] = {
|
||||
{
|
||||
.reg = PMX_CONFIG_REG,
|
||||
.mask = PMX_TIMER_0_1_MASK | PMX_TIMER_2_3_MASK | PMX_MII_MASK,
|
||||
.val = 0,
|
||||
},
|
||||
};
|
||||
|
||||
static struct spear_modemux camu_modemux[] = {
|
||||
{
|
||||
.modes = CAMU_LCD_MODE | CAMU_WLCD_MODE,
|
||||
.muxregs = camu_muxreg,
|
||||
.nmuxregs = ARRAY_SIZE(camu_muxreg),
|
||||
},
|
||||
};
|
||||
|
||||
static struct spear_pingroup camu_pingroup = {
|
||||
.name = "camu_grp",
|
||||
.pins = camu_pins,
|
||||
.npins = ARRAY_SIZE(camu_pins),
|
||||
.modemuxs = camu_modemux,
|
||||
.nmodemuxs = ARRAY_SIZE(camu_modemux),
|
||||
};
|
||||
|
||||
static const char *const cam_grps[] = { "caml_grp", "camu_grp" };
|
||||
static struct spear_function cam_function = {
|
||||
.name = "cam",
|
||||
.groups = cam_grps,
|
||||
.ngroups = ARRAY_SIZE(cam_grps),
|
||||
};
|
||||
|
||||
/* dac_pins */
|
||||
static const unsigned dac_pins[] = { 43, 44 };
|
||||
static struct spear_muxreg dac_muxreg[] = {
|
||||
{
|
||||
.reg = PMX_CONFIG_REG,
|
||||
.mask = PMX_TIMER_0_1_MASK,
|
||||
.val = 0,
|
||||
},
|
||||
};
|
||||
|
||||
static struct spear_modemux dac_modemux[] = {
|
||||
{
|
||||
.modes = ATA_PABX_I2S_MODE | CAML_LCDW_MODE | CAMU_LCD_MODE
|
||||
| CAMU_WLCD_MODE | CAML_LCD_MODE,
|
||||
.muxregs = dac_muxreg,
|
||||
.nmuxregs = ARRAY_SIZE(dac_muxreg),
|
||||
},
|
||||
};
|
||||
|
||||
static struct spear_pingroup dac_pingroup = {
|
||||
.name = "dac_grp",
|
||||
.pins = dac_pins,
|
||||
.npins = ARRAY_SIZE(dac_pins),
|
||||
.modemuxs = dac_modemux,
|
||||
.nmodemuxs = ARRAY_SIZE(dac_modemux),
|
||||
};
|
||||
|
||||
static const char *const dac_grps[] = { "dac_grp" };
|
||||
static struct spear_function dac_function = {
|
||||
.name = "dac",
|
||||
.groups = dac_grps,
|
||||
.ngroups = ARRAY_SIZE(dac_grps),
|
||||
};
|
||||
|
||||
/* i2s_pins */
|
||||
static const unsigned i2s_pins[] = { 39, 40, 41, 42 };
|
||||
static struct spear_muxreg i2s_muxreg[] = {
|
||||
{
|
||||
.reg = PMX_CONFIG_REG,
|
||||
.mask = PMX_UART0_MODEM_MASK,
|
||||
.val = 0,
|
||||
},
|
||||
};
|
||||
|
||||
static struct spear_modemux i2s_modemux[] = {
|
||||
{
|
||||
.modes = LEND_IP_PHONE_MODE | HEND_IP_PHONE_MODE
|
||||
| LEND_WIFI_PHONE_MODE | HEND_WIFI_PHONE_MODE |
|
||||
ATA_PABX_I2S_MODE | CAML_LCDW_MODE | CAMU_LCD_MODE
|
||||
| CAMU_WLCD_MODE | CAML_LCD_MODE,
|
||||
.muxregs = i2s_muxreg,
|
||||
.nmuxregs = ARRAY_SIZE(i2s_muxreg),
|
||||
},
|
||||
};
|
||||
|
||||
static struct spear_pingroup i2s_pingroup = {
|
||||
.name = "i2s_grp",
|
||||
.pins = i2s_pins,
|
||||
.npins = ARRAY_SIZE(i2s_pins),
|
||||
.modemuxs = i2s_modemux,
|
||||
.nmodemuxs = ARRAY_SIZE(i2s_modemux),
|
||||
};
|
||||
|
||||
static const char *const i2s_grps[] = { "i2s_grp" };
|
||||
static struct spear_function i2s_function = {
|
||||
.name = "i2s",
|
||||
.groups = i2s_grps,
|
||||
.ngroups = ARRAY_SIZE(i2s_grps),
|
||||
};
|
||||
|
||||
/* sdhci_4bit_pins */
|
||||
static const unsigned sdhci_4bit_pins[] = { 28, 29, 30, 31, 32, 33 };
|
||||
static struct spear_muxreg sdhci_4bit_muxreg[] = {
|
||||
{
|
||||
.reg = PMX_CONFIG_REG,
|
||||
.mask = PMX_GPIO_PIN0_MASK | PMX_GPIO_PIN1_MASK |
|
||||
PMX_GPIO_PIN2_MASK | PMX_GPIO_PIN3_MASK |
|
||||
PMX_GPIO_PIN4_MASK | PMX_GPIO_PIN5_MASK,
|
||||
.val = 0,
|
||||
},
|
||||
};
|
||||
|
||||
static struct spear_modemux sdhci_4bit_modemux[] = {
|
||||
{
|
||||
.modes = PHOTO_FRAME_MODE | LEND_IP_PHONE_MODE |
|
||||
HEND_IP_PHONE_MODE | LEND_WIFI_PHONE_MODE |
|
||||
HEND_WIFI_PHONE_MODE | CAML_LCDW_MODE | CAMU_LCD_MODE |
|
||||
CAMU_WLCD_MODE | CAML_LCD_MODE | ATA_PABX_WI2S_MODE,
|
||||
.muxregs = sdhci_4bit_muxreg,
|
||||
.nmuxregs = ARRAY_SIZE(sdhci_4bit_muxreg),
|
||||
},
|
||||
};
|
||||
|
||||
static struct spear_pingroup sdhci_4bit_pingroup = {
|
||||
.name = "sdhci_4bit_grp",
|
||||
.pins = sdhci_4bit_pins,
|
||||
.npins = ARRAY_SIZE(sdhci_4bit_pins),
|
||||
.modemuxs = sdhci_4bit_modemux,
|
||||
.nmodemuxs = ARRAY_SIZE(sdhci_4bit_modemux),
|
||||
};
|
||||
|
||||
/* sdhci_8bit_pins */
|
||||
static const unsigned sdhci_8bit_pins[] = { 24, 25, 26, 27, 28, 29, 30, 31, 32,
|
||||
33 };
|
||||
static struct spear_muxreg sdhci_8bit_muxreg[] = {
|
||||
{
|
||||
.reg = PMX_CONFIG_REG,
|
||||
.mask = PMX_GPIO_PIN0_MASK | PMX_GPIO_PIN1_MASK |
|
||||
PMX_GPIO_PIN2_MASK | PMX_GPIO_PIN3_MASK |
|
||||
PMX_GPIO_PIN4_MASK | PMX_GPIO_PIN5_MASK | PMX_MII_MASK,
|
||||
.val = 0,
|
||||
},
|
||||
};
|
||||
|
||||
static struct spear_modemux sdhci_8bit_modemux[] = {
|
||||
{
|
||||
.modes = PHOTO_FRAME_MODE | LEND_IP_PHONE_MODE |
|
||||
HEND_IP_PHONE_MODE | LEND_WIFI_PHONE_MODE |
|
||||
HEND_WIFI_PHONE_MODE | CAML_LCDW_MODE | CAMU_LCD_MODE |
|
||||
CAMU_WLCD_MODE | CAML_LCD_MODE,
|
||||
.muxregs = sdhci_8bit_muxreg,
|
||||
.nmuxregs = ARRAY_SIZE(sdhci_8bit_muxreg),
|
||||
},
|
||||
};
|
||||
|
||||
static struct spear_pingroup sdhci_8bit_pingroup = {
|
||||
.name = "sdhci_8bit_grp",
|
||||
.pins = sdhci_8bit_pins,
|
||||
.npins = ARRAY_SIZE(sdhci_8bit_pins),
|
||||
.modemuxs = sdhci_8bit_modemux,
|
||||
.nmodemuxs = ARRAY_SIZE(sdhci_8bit_modemux),
|
||||
};
|
||||
|
||||
static const char *const sdhci_grps[] = { "sdhci_4bit_grp", "sdhci_8bit_grp" };
|
||||
static struct spear_function sdhci_function = {
|
||||
.name = "sdhci",
|
||||
.groups = sdhci_grps,
|
||||
.ngroups = ARRAY_SIZE(sdhci_grps),
|
||||
};
|
||||
|
||||
/* gpio1_0_to_3_pins */
|
||||
static const unsigned gpio1_0_to_3_pins[] = { 39, 40, 41, 42 };
|
||||
static struct spear_muxreg gpio1_0_to_3_muxreg[] = {
|
||||
{
|
||||
.reg = PMX_CONFIG_REG,
|
||||
.mask = PMX_UART0_MODEM_MASK,
|
||||
.val = 0,
|
||||
},
|
||||
};
|
||||
|
||||
static struct spear_modemux gpio1_0_to_3_modemux[] = {
|
||||
{
|
||||
.modes = PHOTO_FRAME_MODE,
|
||||
.muxregs = gpio1_0_to_3_muxreg,
|
||||
.nmuxregs = ARRAY_SIZE(gpio1_0_to_3_muxreg),
|
||||
},
|
||||
};
|
||||
|
||||
static struct spear_pingroup gpio1_0_to_3_pingroup = {
|
||||
.name = "gpio1_0_to_3_grp",
|
||||
.pins = gpio1_0_to_3_pins,
|
||||
.npins = ARRAY_SIZE(gpio1_0_to_3_pins),
|
||||
.modemuxs = gpio1_0_to_3_modemux,
|
||||
.nmodemuxs = ARRAY_SIZE(gpio1_0_to_3_modemux),
|
||||
};
|
||||
|
||||
/* gpio1_4_to_7_pins */
|
||||
static const unsigned gpio1_4_to_7_pins[] = { 43, 44, 45, 46 };
|
||||
|
||||
static struct spear_muxreg gpio1_4_to_7_muxreg[] = {
|
||||
{
|
||||
.reg = PMX_CONFIG_REG,
|
||||
.mask = PMX_TIMER_0_1_MASK | PMX_TIMER_2_3_MASK,
|
||||
.val = 0,
|
||||
},
|
||||
};
|
||||
|
||||
static struct spear_modemux gpio1_4_to_7_modemux[] = {
|
||||
{
|
||||
.modes = PHOTO_FRAME_MODE,
|
||||
.muxregs = gpio1_4_to_7_muxreg,
|
||||
.nmuxregs = ARRAY_SIZE(gpio1_4_to_7_muxreg),
|
||||
},
|
||||
};
|
||||
|
||||
static struct spear_pingroup gpio1_4_to_7_pingroup = {
|
||||
.name = "gpio1_4_to_7_grp",
|
||||
.pins = gpio1_4_to_7_pins,
|
||||
.npins = ARRAY_SIZE(gpio1_4_to_7_pins),
|
||||
.modemuxs = gpio1_4_to_7_modemux,
|
||||
.nmodemuxs = ARRAY_SIZE(gpio1_4_to_7_modemux),
|
||||
};
|
||||
|
||||
static const char *const gpio1_grps[] = { "gpio1_0_to_3_grp", "gpio1_4_to_7_grp"
|
||||
};
|
||||
static struct spear_function gpio1_function = {
|
||||
.name = "gpio1",
|
||||
.groups = gpio1_grps,
|
||||
.ngroups = ARRAY_SIZE(gpio1_grps),
|
||||
};
|
||||
|
||||
/* pingroups */
|
||||
static struct spear_pingroup *spear300_pingroups[] = {
|
||||
SPEAR3XX_COMMON_PINGROUPS,
|
||||
&fsmc_2chips_pingroup,
|
||||
&fsmc_4chips_pingroup,
|
||||
&clcd_lcdmode_pingroup,
|
||||
&clcd_pfmode_pingroup,
|
||||
&tdm_pingroup,
|
||||
&i2c_clk_pingroup,
|
||||
&caml_pingroup,
|
||||
&camu_pingroup,
|
||||
&dac_pingroup,
|
||||
&i2s_pingroup,
|
||||
&sdhci_4bit_pingroup,
|
||||
&sdhci_8bit_pingroup,
|
||||
&gpio1_0_to_3_pingroup,
|
||||
&gpio1_4_to_7_pingroup,
|
||||
};
|
||||
|
||||
/* functions */
|
||||
static struct spear_function *spear300_functions[] = {
|
||||
SPEAR3XX_COMMON_FUNCTIONS,
|
||||
&fsmc_function,
|
||||
&clcd_function,
|
||||
&tdm_function,
|
||||
&i2c_function,
|
||||
&cam_function,
|
||||
&dac_function,
|
||||
&i2s_function,
|
||||
&sdhci_function,
|
||||
&gpio1_function,
|
||||
};
|
||||
|
||||
static const struct of_device_id spear300_pinctrl_of_match[] = {
|
||||
{
|
||||
.compatible = "st,spear300-pinmux",
|
||||
},
|
||||
{},
|
||||
};
|
||||
|
||||
static int spear300_pinctrl_probe(struct platform_device *pdev)
|
||||
{
|
||||
int ret;
|
||||
|
||||
spear3xx_machdata.groups = spear300_pingroups;
|
||||
spear3xx_machdata.ngroups = ARRAY_SIZE(spear300_pingroups);
|
||||
spear3xx_machdata.functions = spear300_functions;
|
||||
spear3xx_machdata.nfunctions = ARRAY_SIZE(spear300_functions);
|
||||
spear3xx_machdata.gpio_pingroups = NULL;
|
||||
spear3xx_machdata.ngpio_pingroups = 0;
|
||||
|
||||
spear3xx_machdata.modes_supported = true;
|
||||
spear3xx_machdata.pmx_modes = spear300_pmx_modes;
|
||||
spear3xx_machdata.npmx_modes = ARRAY_SIZE(spear300_pmx_modes);
|
||||
|
||||
pmx_init_addr(&spear3xx_machdata, PMX_CONFIG_REG);
|
||||
|
||||
ret = spear_pinctrl_probe(pdev, &spear3xx_machdata);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int spear300_pinctrl_remove(struct platform_device *pdev)
|
||||
{
|
||||
return spear_pinctrl_remove(pdev);
|
||||
}
|
||||
|
||||
static struct platform_driver spear300_pinctrl_driver = {
|
||||
.driver = {
|
||||
.name = DRIVER_NAME,
|
||||
.owner = THIS_MODULE,
|
||||
.of_match_table = spear300_pinctrl_of_match,
|
||||
},
|
||||
.probe = spear300_pinctrl_probe,
|
||||
.remove = spear300_pinctrl_remove,
|
||||
};
|
||||
|
||||
static int __init spear300_pinctrl_init(void)
|
||||
{
|
||||
return platform_driver_register(&spear300_pinctrl_driver);
|
||||
}
|
||||
arch_initcall(spear300_pinctrl_init);
|
||||
|
||||
static void __exit spear300_pinctrl_exit(void)
|
||||
{
|
||||
platform_driver_unregister(&spear300_pinctrl_driver);
|
||||
}
|
||||
module_exit(spear300_pinctrl_exit);
|
||||
|
||||
MODULE_AUTHOR("Viresh Kumar <viresh.linux@gmail.com>");
|
||||
MODULE_DESCRIPTION("ST Microelectronics SPEAr300 pinctrl driver");
|
||||
MODULE_LICENSE("GPL v2");
|
||||
MODULE_DEVICE_TABLE(of, spear300_pinctrl_of_match);
|
433
drivers/pinctrl/spear/pinctrl-spear310.c
Normal file
433
drivers/pinctrl/spear/pinctrl-spear310.c
Normal file
|
@ -0,0 +1,433 @@
|
|||
/*
|
||||
* Driver for the ST Microelectronics SPEAr310 pinmux
|
||||
*
|
||||
* Copyright (C) 2012 ST Microelectronics
|
||||
* Viresh Kumar <viresh.linux@gmail.com>
|
||||
*
|
||||
* This file is licensed under the terms of the GNU General Public
|
||||
* License version 2. This program is licensed "as is" without any
|
||||
* warranty of any kind, whether express or implied.
|
||||
*/
|
||||
|
||||
#include <linux/err.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/of_device.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include "pinctrl-spear3xx.h"
|
||||
|
||||
#define DRIVER_NAME "spear310-pinmux"
|
||||
|
||||
/* addresses */
|
||||
#define PMX_CONFIG_REG 0x08
|
||||
|
||||
/* emi_cs_0_to_5_pins */
|
||||
static const unsigned emi_cs_0_to_5_pins[] = { 45, 46, 47, 48, 49, 50 };
|
||||
static struct spear_muxreg emi_cs_0_to_5_muxreg[] = {
|
||||
{
|
||||
.reg = PMX_CONFIG_REG,
|
||||
.mask = PMX_TIMER_0_1_MASK | PMX_TIMER_2_3_MASK,
|
||||
.val = 0,
|
||||
},
|
||||
};
|
||||
|
||||
static struct spear_modemux emi_cs_0_to_5_modemux[] = {
|
||||
{
|
||||
.muxregs = emi_cs_0_to_5_muxreg,
|
||||
.nmuxregs = ARRAY_SIZE(emi_cs_0_to_5_muxreg),
|
||||
},
|
||||
};
|
||||
|
||||
static struct spear_pingroup emi_cs_0_to_5_pingroup = {
|
||||
.name = "emi_cs_0_to_5_grp",
|
||||
.pins = emi_cs_0_to_5_pins,
|
||||
.npins = ARRAY_SIZE(emi_cs_0_to_5_pins),
|
||||
.modemuxs = emi_cs_0_to_5_modemux,
|
||||
.nmodemuxs = ARRAY_SIZE(emi_cs_0_to_5_modemux),
|
||||
};
|
||||
|
||||
static const char *const emi_cs_0_to_5_grps[] = { "emi_cs_0_to_5_grp" };
|
||||
static struct spear_function emi_cs_0_to_5_function = {
|
||||
.name = "emi",
|
||||
.groups = emi_cs_0_to_5_grps,
|
||||
.ngroups = ARRAY_SIZE(emi_cs_0_to_5_grps),
|
||||
};
|
||||
|
||||
/* uart1_pins */
|
||||
static const unsigned uart1_pins[] = { 0, 1 };
|
||||
static struct spear_muxreg uart1_muxreg[] = {
|
||||
{
|
||||
.reg = PMX_CONFIG_REG,
|
||||
.mask = PMX_FIRDA_MASK,
|
||||
.val = 0,
|
||||
},
|
||||
};
|
||||
|
||||
static struct spear_modemux uart1_modemux[] = {
|
||||
{
|
||||
.muxregs = uart1_muxreg,
|
||||
.nmuxregs = ARRAY_SIZE(uart1_muxreg),
|
||||
},
|
||||
};
|
||||
|
||||
static struct spear_pingroup uart1_pingroup = {
|
||||
.name = "uart1_grp",
|
||||
.pins = uart1_pins,
|
||||
.npins = ARRAY_SIZE(uart1_pins),
|
||||
.modemuxs = uart1_modemux,
|
||||
.nmodemuxs = ARRAY_SIZE(uart1_modemux),
|
||||
};
|
||||
|
||||
static const char *const uart1_grps[] = { "uart1_grp" };
|
||||
static struct spear_function uart1_function = {
|
||||
.name = "uart1",
|
||||
.groups = uart1_grps,
|
||||
.ngroups = ARRAY_SIZE(uart1_grps),
|
||||
};
|
||||
|
||||
/* uart2_pins */
|
||||
static const unsigned uart2_pins[] = { 43, 44 };
|
||||
static struct spear_muxreg uart2_muxreg[] = {
|
||||
{
|
||||
.reg = PMX_CONFIG_REG,
|
||||
.mask = PMX_TIMER_0_1_MASK,
|
||||
.val = 0,
|
||||
},
|
||||
};
|
||||
|
||||
static struct spear_modemux uart2_modemux[] = {
|
||||
{
|
||||
.muxregs = uart2_muxreg,
|
||||
.nmuxregs = ARRAY_SIZE(uart2_muxreg),
|
||||
},
|
||||
};
|
||||
|
||||
static struct spear_pingroup uart2_pingroup = {
|
||||
.name = "uart2_grp",
|
||||
.pins = uart2_pins,
|
||||
.npins = ARRAY_SIZE(uart2_pins),
|
||||
.modemuxs = uart2_modemux,
|
||||
.nmodemuxs = ARRAY_SIZE(uart2_modemux),
|
||||
};
|
||||
|
||||
static const char *const uart2_grps[] = { "uart2_grp" };
|
||||
static struct spear_function uart2_function = {
|
||||
.name = "uart2",
|
||||
.groups = uart2_grps,
|
||||
.ngroups = ARRAY_SIZE(uart2_grps),
|
||||
};
|
||||
|
||||
/* uart3_pins */
|
||||
static const unsigned uart3_pins[] = { 37, 38 };
|
||||
static struct spear_muxreg uart3_muxreg[] = {
|
||||
{
|
||||
.reg = PMX_CONFIG_REG,
|
||||
.mask = PMX_UART0_MODEM_MASK,
|
||||
.val = 0,
|
||||
},
|
||||
};
|
||||
|
||||
static struct spear_modemux uart3_modemux[] = {
|
||||
{
|
||||
.muxregs = uart3_muxreg,
|
||||
.nmuxregs = ARRAY_SIZE(uart3_muxreg),
|
||||
},
|
||||
};
|
||||
|
||||
static struct spear_pingroup uart3_pingroup = {
|
||||
.name = "uart3_grp",
|
||||
.pins = uart3_pins,
|
||||
.npins = ARRAY_SIZE(uart3_pins),
|
||||
.modemuxs = uart3_modemux,
|
||||
.nmodemuxs = ARRAY_SIZE(uart3_modemux),
|
||||
};
|
||||
|
||||
static const char *const uart3_grps[] = { "uart3_grp" };
|
||||
static struct spear_function uart3_function = {
|
||||
.name = "uart3",
|
||||
.groups = uart3_grps,
|
||||
.ngroups = ARRAY_SIZE(uart3_grps),
|
||||
};
|
||||
|
||||
/* uart4_pins */
|
||||
static const unsigned uart4_pins[] = { 39, 40 };
|
||||
static struct spear_muxreg uart4_muxreg[] = {
|
||||
{
|
||||
.reg = PMX_CONFIG_REG,
|
||||
.mask = PMX_UART0_MODEM_MASK,
|
||||
.val = 0,
|
||||
},
|
||||
};
|
||||
|
||||
static struct spear_modemux uart4_modemux[] = {
|
||||
{
|
||||
.muxregs = uart4_muxreg,
|
||||
.nmuxregs = ARRAY_SIZE(uart4_muxreg),
|
||||
},
|
||||
};
|
||||
|
||||
static struct spear_pingroup uart4_pingroup = {
|
||||
.name = "uart4_grp",
|
||||
.pins = uart4_pins,
|
||||
.npins = ARRAY_SIZE(uart4_pins),
|
||||
.modemuxs = uart4_modemux,
|
||||
.nmodemuxs = ARRAY_SIZE(uart4_modemux),
|
||||
};
|
||||
|
||||
static const char *const uart4_grps[] = { "uart4_grp" };
|
||||
static struct spear_function uart4_function = {
|
||||
.name = "uart4",
|
||||
.groups = uart4_grps,
|
||||
.ngroups = ARRAY_SIZE(uart4_grps),
|
||||
};
|
||||
|
||||
/* uart5_pins */
|
||||
static const unsigned uart5_pins[] = { 41, 42 };
|
||||
static struct spear_muxreg uart5_muxreg[] = {
|
||||
{
|
||||
.reg = PMX_CONFIG_REG,
|
||||
.mask = PMX_UART0_MODEM_MASK,
|
||||
.val = 0,
|
||||
},
|
||||
};
|
||||
|
||||
static struct spear_modemux uart5_modemux[] = {
|
||||
{
|
||||
.muxregs = uart5_muxreg,
|
||||
.nmuxregs = ARRAY_SIZE(uart5_muxreg),
|
||||
},
|
||||
};
|
||||
|
||||
static struct spear_pingroup uart5_pingroup = {
|
||||
.name = "uart5_grp",
|
||||
.pins = uart5_pins,
|
||||
.npins = ARRAY_SIZE(uart5_pins),
|
||||
.modemuxs = uart5_modemux,
|
||||
.nmodemuxs = ARRAY_SIZE(uart5_modemux),
|
||||
};
|
||||
|
||||
static const char *const uart5_grps[] = { "uart5_grp" };
|
||||
static struct spear_function uart5_function = {
|
||||
.name = "uart5",
|
||||
.groups = uart5_grps,
|
||||
.ngroups = ARRAY_SIZE(uart5_grps),
|
||||
};
|
||||
|
||||
/* fsmc_pins */
|
||||
static const unsigned fsmc_pins[] = { 34, 35, 36 };
|
||||
static struct spear_muxreg fsmc_muxreg[] = {
|
||||
{
|
||||
.reg = PMX_CONFIG_REG,
|
||||
.mask = PMX_SSP_CS_MASK,
|
||||
.val = 0,
|
||||
},
|
||||
};
|
||||
|
||||
static struct spear_modemux fsmc_modemux[] = {
|
||||
{
|
||||
.muxregs = fsmc_muxreg,
|
||||
.nmuxregs = ARRAY_SIZE(fsmc_muxreg),
|
||||
},
|
||||
};
|
||||
|
||||
static struct spear_pingroup fsmc_pingroup = {
|
||||
.name = "fsmc_grp",
|
||||
.pins = fsmc_pins,
|
||||
.npins = ARRAY_SIZE(fsmc_pins),
|
||||
.modemuxs = fsmc_modemux,
|
||||
.nmodemuxs = ARRAY_SIZE(fsmc_modemux),
|
||||
};
|
||||
|
||||
static const char *const fsmc_grps[] = { "fsmc_grp" };
|
||||
static struct spear_function fsmc_function = {
|
||||
.name = "fsmc",
|
||||
.groups = fsmc_grps,
|
||||
.ngroups = ARRAY_SIZE(fsmc_grps),
|
||||
};
|
||||
|
||||
/* rs485_0_pins */
|
||||
static const unsigned rs485_0_pins[] = { 19, 20, 21, 22, 23 };
|
||||
static struct spear_muxreg rs485_0_muxreg[] = {
|
||||
{
|
||||
.reg = PMX_CONFIG_REG,
|
||||
.mask = PMX_MII_MASK,
|
||||
.val = 0,
|
||||
},
|
||||
};
|
||||
|
||||
static struct spear_modemux rs485_0_modemux[] = {
|
||||
{
|
||||
.muxregs = rs485_0_muxreg,
|
||||
.nmuxregs = ARRAY_SIZE(rs485_0_muxreg),
|
||||
},
|
||||
};
|
||||
|
||||
static struct spear_pingroup rs485_0_pingroup = {
|
||||
.name = "rs485_0_grp",
|
||||
.pins = rs485_0_pins,
|
||||
.npins = ARRAY_SIZE(rs485_0_pins),
|
||||
.modemuxs = rs485_0_modemux,
|
||||
.nmodemuxs = ARRAY_SIZE(rs485_0_modemux),
|
||||
};
|
||||
|
||||
static const char *const rs485_0_grps[] = { "rs485_0" };
|
||||
static struct spear_function rs485_0_function = {
|
||||
.name = "rs485_0",
|
||||
.groups = rs485_0_grps,
|
||||
.ngroups = ARRAY_SIZE(rs485_0_grps),
|
||||
};
|
||||
|
||||
/* rs485_1_pins */
|
||||
static const unsigned rs485_1_pins[] = { 14, 15, 16, 17, 18 };
|
||||
static struct spear_muxreg rs485_1_muxreg[] = {
|
||||
{
|
||||
.reg = PMX_CONFIG_REG,
|
||||
.mask = PMX_MII_MASK,
|
||||
.val = 0,
|
||||
},
|
||||
};
|
||||
|
||||
static struct spear_modemux rs485_1_modemux[] = {
|
||||
{
|
||||
.muxregs = rs485_1_muxreg,
|
||||
.nmuxregs = ARRAY_SIZE(rs485_1_muxreg),
|
||||
},
|
||||
};
|
||||
|
||||
static struct spear_pingroup rs485_1_pingroup = {
|
||||
.name = "rs485_1_grp",
|
||||
.pins = rs485_1_pins,
|
||||
.npins = ARRAY_SIZE(rs485_1_pins),
|
||||
.modemuxs = rs485_1_modemux,
|
||||
.nmodemuxs = ARRAY_SIZE(rs485_1_modemux),
|
||||
};
|
||||
|
||||
static const char *const rs485_1_grps[] = { "rs485_1" };
|
||||
static struct spear_function rs485_1_function = {
|
||||
.name = "rs485_1",
|
||||
.groups = rs485_1_grps,
|
||||
.ngroups = ARRAY_SIZE(rs485_1_grps),
|
||||
};
|
||||
|
||||
/* tdm_pins */
|
||||
static const unsigned tdm_pins[] = { 10, 11, 12, 13 };
|
||||
static struct spear_muxreg tdm_muxreg[] = {
|
||||
{
|
||||
.reg = PMX_CONFIG_REG,
|
||||
.mask = PMX_MII_MASK,
|
||||
.val = 0,
|
||||
},
|
||||
};
|
||||
|
||||
static struct spear_modemux tdm_modemux[] = {
|
||||
{
|
||||
.muxregs = tdm_muxreg,
|
||||
.nmuxregs = ARRAY_SIZE(tdm_muxreg),
|
||||
},
|
||||
};
|
||||
|
||||
static struct spear_pingroup tdm_pingroup = {
|
||||
.name = "tdm_grp",
|
||||
.pins = tdm_pins,
|
||||
.npins = ARRAY_SIZE(tdm_pins),
|
||||
.modemuxs = tdm_modemux,
|
||||
.nmodemuxs = ARRAY_SIZE(tdm_modemux),
|
||||
};
|
||||
|
||||
static const char *const tdm_grps[] = { "tdm_grp" };
|
||||
static struct spear_function tdm_function = {
|
||||
.name = "tdm",
|
||||
.groups = tdm_grps,
|
||||
.ngroups = ARRAY_SIZE(tdm_grps),
|
||||
};
|
||||
|
||||
/* pingroups */
|
||||
static struct spear_pingroup *spear310_pingroups[] = {
|
||||
SPEAR3XX_COMMON_PINGROUPS,
|
||||
&emi_cs_0_to_5_pingroup,
|
||||
&uart1_pingroup,
|
||||
&uart2_pingroup,
|
||||
&uart3_pingroup,
|
||||
&uart4_pingroup,
|
||||
&uart5_pingroup,
|
||||
&fsmc_pingroup,
|
||||
&rs485_0_pingroup,
|
||||
&rs485_1_pingroup,
|
||||
&tdm_pingroup,
|
||||
};
|
||||
|
||||
/* functions */
|
||||
static struct spear_function *spear310_functions[] = {
|
||||
SPEAR3XX_COMMON_FUNCTIONS,
|
||||
&emi_cs_0_to_5_function,
|
||||
&uart1_function,
|
||||
&uart2_function,
|
||||
&uart3_function,
|
||||
&uart4_function,
|
||||
&uart5_function,
|
||||
&fsmc_function,
|
||||
&rs485_0_function,
|
||||
&rs485_1_function,
|
||||
&tdm_function,
|
||||
};
|
||||
|
||||
static const struct of_device_id spear310_pinctrl_of_match[] = {
|
||||
{
|
||||
.compatible = "st,spear310-pinmux",
|
||||
},
|
||||
{},
|
||||
};
|
||||
|
||||
static int spear310_pinctrl_probe(struct platform_device *pdev)
|
||||
{
|
||||
int ret;
|
||||
|
||||
spear3xx_machdata.groups = spear310_pingroups;
|
||||
spear3xx_machdata.ngroups = ARRAY_SIZE(spear310_pingroups);
|
||||
spear3xx_machdata.functions = spear310_functions;
|
||||
spear3xx_machdata.nfunctions = ARRAY_SIZE(spear310_functions);
|
||||
|
||||
pmx_init_addr(&spear3xx_machdata, PMX_CONFIG_REG);
|
||||
pmx_init_gpio_pingroup_addr(spear3xx_machdata.gpio_pingroups,
|
||||
spear3xx_machdata.ngpio_pingroups, PMX_CONFIG_REG);
|
||||
|
||||
spear3xx_machdata.modes_supported = false;
|
||||
|
||||
ret = spear_pinctrl_probe(pdev, &spear3xx_machdata);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int spear310_pinctrl_remove(struct platform_device *pdev)
|
||||
{
|
||||
return spear_pinctrl_remove(pdev);
|
||||
}
|
||||
|
||||
static struct platform_driver spear310_pinctrl_driver = {
|
||||
.driver = {
|
||||
.name = DRIVER_NAME,
|
||||
.owner = THIS_MODULE,
|
||||
.of_match_table = spear310_pinctrl_of_match,
|
||||
},
|
||||
.probe = spear310_pinctrl_probe,
|
||||
.remove = spear310_pinctrl_remove,
|
||||
};
|
||||
|
||||
static int __init spear310_pinctrl_init(void)
|
||||
{
|
||||
return platform_driver_register(&spear310_pinctrl_driver);
|
||||
}
|
||||
arch_initcall(spear310_pinctrl_init);
|
||||
|
||||
static void __exit spear310_pinctrl_exit(void)
|
||||
{
|
||||
platform_driver_unregister(&spear310_pinctrl_driver);
|
||||
}
|
||||
module_exit(spear310_pinctrl_exit);
|
||||
|
||||
MODULE_AUTHOR("Viresh Kumar <viresh.linux@gmail.com>");
|
||||
MODULE_DESCRIPTION("ST Microelectronics SPEAr310 pinctrl driver");
|
||||
MODULE_LICENSE("GPL v2");
|
||||
MODULE_DEVICE_TABLE(of, spear310_pinctrl_of_match);
|
3474
drivers/pinctrl/spear/pinctrl-spear320.c
Normal file
3474
drivers/pinctrl/spear/pinctrl-spear320.c
Normal file
File diff suppressed because it is too large
Load diff
524
drivers/pinctrl/spear/pinctrl-spear3xx.c
Normal file
524
drivers/pinctrl/spear/pinctrl-spear3xx.c
Normal file
|
@ -0,0 +1,524 @@
|
|||
/*
|
||||
* Driver for the ST Microelectronics SPEAr3xx pinmux
|
||||
*
|
||||
* Copyright (C) 2012 ST Microelectronics
|
||||
* Viresh Kumar <viresh.linux@gmail.com>
|
||||
*
|
||||
* This file is licensed under the terms of the GNU General Public
|
||||
* License version 2. This program is licensed "as is" without any
|
||||
* warranty of any kind, whether express or implied.
|
||||
*/
|
||||
|
||||
#include <linux/pinctrl/pinctrl.h>
|
||||
|
||||
#include "pinctrl-spear3xx.h"
|
||||
|
||||
/* pins */
|
||||
static const struct pinctrl_pin_desc spear3xx_pins[] = {
|
||||
SPEAR_PIN_0_TO_101,
|
||||
};
|
||||
|
||||
/* firda_pins */
|
||||
static const unsigned firda_pins[] = { 0, 1 };
|
||||
static struct spear_muxreg firda_muxreg[] = {
|
||||
{
|
||||
.reg = -1,
|
||||
.mask = PMX_FIRDA_MASK,
|
||||
.val = PMX_FIRDA_MASK,
|
||||
},
|
||||
};
|
||||
|
||||
static struct spear_modemux firda_modemux[] = {
|
||||
{
|
||||
.modes = ~0,
|
||||
.muxregs = firda_muxreg,
|
||||
.nmuxregs = ARRAY_SIZE(firda_muxreg),
|
||||
},
|
||||
};
|
||||
|
||||
struct spear_pingroup spear3xx_firda_pingroup = {
|
||||
.name = "firda_grp",
|
||||
.pins = firda_pins,
|
||||
.npins = ARRAY_SIZE(firda_pins),
|
||||
.modemuxs = firda_modemux,
|
||||
.nmodemuxs = ARRAY_SIZE(firda_modemux),
|
||||
};
|
||||
|
||||
static const char *const firda_grps[] = { "firda_grp" };
|
||||
struct spear_function spear3xx_firda_function = {
|
||||
.name = "firda",
|
||||
.groups = firda_grps,
|
||||
.ngroups = ARRAY_SIZE(firda_grps),
|
||||
};
|
||||
|
||||
/* i2c_pins */
|
||||
static const unsigned i2c_pins[] = { 4, 5 };
|
||||
static struct spear_muxreg i2c_muxreg[] = {
|
||||
{
|
||||
.reg = -1,
|
||||
.mask = PMX_I2C_MASK,
|
||||
.val = PMX_I2C_MASK,
|
||||
},
|
||||
};
|
||||
|
||||
static struct spear_modemux i2c_modemux[] = {
|
||||
{
|
||||
.modes = ~0,
|
||||
.muxregs = i2c_muxreg,
|
||||
.nmuxregs = ARRAY_SIZE(i2c_muxreg),
|
||||
},
|
||||
};
|
||||
|
||||
struct spear_pingroup spear3xx_i2c_pingroup = {
|
||||
.name = "i2c0_grp",
|
||||
.pins = i2c_pins,
|
||||
.npins = ARRAY_SIZE(i2c_pins),
|
||||
.modemuxs = i2c_modemux,
|
||||
.nmodemuxs = ARRAY_SIZE(i2c_modemux),
|
||||
};
|
||||
|
||||
static const char *const i2c_grps[] = { "i2c0_grp" };
|
||||
struct spear_function spear3xx_i2c_function = {
|
||||
.name = "i2c0",
|
||||
.groups = i2c_grps,
|
||||
.ngroups = ARRAY_SIZE(i2c_grps),
|
||||
};
|
||||
|
||||
/* ssp_cs_pins */
|
||||
static const unsigned ssp_cs_pins[] = { 34, 35, 36 };
|
||||
static struct spear_muxreg ssp_cs_muxreg[] = {
|
||||
{
|
||||
.reg = -1,
|
||||
.mask = PMX_SSP_CS_MASK,
|
||||
.val = PMX_SSP_CS_MASK,
|
||||
},
|
||||
};
|
||||
|
||||
static struct spear_modemux ssp_cs_modemux[] = {
|
||||
{
|
||||
.modes = ~0,
|
||||
.muxregs = ssp_cs_muxreg,
|
||||
.nmuxregs = ARRAY_SIZE(ssp_cs_muxreg),
|
||||
},
|
||||
};
|
||||
|
||||
struct spear_pingroup spear3xx_ssp_cs_pingroup = {
|
||||
.name = "ssp_cs_grp",
|
||||
.pins = ssp_cs_pins,
|
||||
.npins = ARRAY_SIZE(ssp_cs_pins),
|
||||
.modemuxs = ssp_cs_modemux,
|
||||
.nmodemuxs = ARRAY_SIZE(ssp_cs_modemux),
|
||||
};
|
||||
|
||||
static const char *const ssp_cs_grps[] = { "ssp_cs_grp" };
|
||||
struct spear_function spear3xx_ssp_cs_function = {
|
||||
.name = "ssp_cs",
|
||||
.groups = ssp_cs_grps,
|
||||
.ngroups = ARRAY_SIZE(ssp_cs_grps),
|
||||
};
|
||||
|
||||
/* ssp_pins */
|
||||
static const unsigned ssp_pins[] = { 6, 7, 8, 9 };
|
||||
static struct spear_muxreg ssp_muxreg[] = {
|
||||
{
|
||||
.reg = -1,
|
||||
.mask = PMX_SSP_MASK,
|
||||
.val = PMX_SSP_MASK,
|
||||
},
|
||||
};
|
||||
|
||||
static struct spear_modemux ssp_modemux[] = {
|
||||
{
|
||||
.modes = ~0,
|
||||
.muxregs = ssp_muxreg,
|
||||
.nmuxregs = ARRAY_SIZE(ssp_muxreg),
|
||||
},
|
||||
};
|
||||
|
||||
struct spear_pingroup spear3xx_ssp_pingroup = {
|
||||
.name = "ssp0_grp",
|
||||
.pins = ssp_pins,
|
||||
.npins = ARRAY_SIZE(ssp_pins),
|
||||
.modemuxs = ssp_modemux,
|
||||
.nmodemuxs = ARRAY_SIZE(ssp_modemux),
|
||||
};
|
||||
|
||||
static const char *const ssp_grps[] = { "ssp0_grp" };
|
||||
struct spear_function spear3xx_ssp_function = {
|
||||
.name = "ssp0",
|
||||
.groups = ssp_grps,
|
||||
.ngroups = ARRAY_SIZE(ssp_grps),
|
||||
};
|
||||
|
||||
/* mii_pins */
|
||||
static const unsigned mii_pins[] = { 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20,
|
||||
21, 22, 23, 24, 25, 26, 27 };
|
||||
static struct spear_muxreg mii_muxreg[] = {
|
||||
{
|
||||
.reg = -1,
|
||||
.mask = PMX_MII_MASK,
|
||||
.val = PMX_MII_MASK,
|
||||
},
|
||||
};
|
||||
|
||||
static struct spear_modemux mii_modemux[] = {
|
||||
{
|
||||
.modes = ~0,
|
||||
.muxregs = mii_muxreg,
|
||||
.nmuxregs = ARRAY_SIZE(mii_muxreg),
|
||||
},
|
||||
};
|
||||
|
||||
struct spear_pingroup spear3xx_mii_pingroup = {
|
||||
.name = "mii0_grp",
|
||||
.pins = mii_pins,
|
||||
.npins = ARRAY_SIZE(mii_pins),
|
||||
.modemuxs = mii_modemux,
|
||||
.nmodemuxs = ARRAY_SIZE(mii_modemux),
|
||||
};
|
||||
|
||||
static const char *const mii_grps[] = { "mii0_grp" };
|
||||
struct spear_function spear3xx_mii_function = {
|
||||
.name = "mii0",
|
||||
.groups = mii_grps,
|
||||
.ngroups = ARRAY_SIZE(mii_grps),
|
||||
};
|
||||
|
||||
/* gpio0_pin0_pins */
|
||||
static const unsigned gpio0_pin0_pins[] = { 28 };
|
||||
static struct spear_muxreg gpio0_pin0_muxreg[] = {
|
||||
{
|
||||
.reg = -1,
|
||||
.mask = PMX_GPIO_PIN0_MASK,
|
||||
.val = PMX_GPIO_PIN0_MASK,
|
||||
},
|
||||
};
|
||||
|
||||
static struct spear_modemux gpio0_pin0_modemux[] = {
|
||||
{
|
||||
.modes = ~0,
|
||||
.muxregs = gpio0_pin0_muxreg,
|
||||
.nmuxregs = ARRAY_SIZE(gpio0_pin0_muxreg),
|
||||
},
|
||||
};
|
||||
|
||||
struct spear_pingroup spear3xx_gpio0_pin0_pingroup = {
|
||||
.name = "gpio0_pin0_grp",
|
||||
.pins = gpio0_pin0_pins,
|
||||
.npins = ARRAY_SIZE(gpio0_pin0_pins),
|
||||
.modemuxs = gpio0_pin0_modemux,
|
||||
.nmodemuxs = ARRAY_SIZE(gpio0_pin0_modemux),
|
||||
};
|
||||
|
||||
/* gpio0_pin1_pins */
|
||||
static const unsigned gpio0_pin1_pins[] = { 29 };
|
||||
static struct spear_muxreg gpio0_pin1_muxreg[] = {
|
||||
{
|
||||
.reg = -1,
|
||||
.mask = PMX_GPIO_PIN1_MASK,
|
||||
.val = PMX_GPIO_PIN1_MASK,
|
||||
},
|
||||
};
|
||||
|
||||
static struct spear_modemux gpio0_pin1_modemux[] = {
|
||||
{
|
||||
.modes = ~0,
|
||||
.muxregs = gpio0_pin1_muxreg,
|
||||
.nmuxregs = ARRAY_SIZE(gpio0_pin1_muxreg),
|
||||
},
|
||||
};
|
||||
|
||||
struct spear_pingroup spear3xx_gpio0_pin1_pingroup = {
|
||||
.name = "gpio0_pin1_grp",
|
||||
.pins = gpio0_pin1_pins,
|
||||
.npins = ARRAY_SIZE(gpio0_pin1_pins),
|
||||
.modemuxs = gpio0_pin1_modemux,
|
||||
.nmodemuxs = ARRAY_SIZE(gpio0_pin1_modemux),
|
||||
};
|
||||
|
||||
/* gpio0_pin2_pins */
|
||||
static const unsigned gpio0_pin2_pins[] = { 30 };
|
||||
static struct spear_muxreg gpio0_pin2_muxreg[] = {
|
||||
{
|
||||
.reg = -1,
|
||||
.mask = PMX_GPIO_PIN2_MASK,
|
||||
.val = PMX_GPIO_PIN2_MASK,
|
||||
},
|
||||
};
|
||||
|
||||
static struct spear_modemux gpio0_pin2_modemux[] = {
|
||||
{
|
||||
.modes = ~0,
|
||||
.muxregs = gpio0_pin2_muxreg,
|
||||
.nmuxregs = ARRAY_SIZE(gpio0_pin2_muxreg),
|
||||
},
|
||||
};
|
||||
|
||||
struct spear_pingroup spear3xx_gpio0_pin2_pingroup = {
|
||||
.name = "gpio0_pin2_grp",
|
||||
.pins = gpio0_pin2_pins,
|
||||
.npins = ARRAY_SIZE(gpio0_pin2_pins),
|
||||
.modemuxs = gpio0_pin2_modemux,
|
||||
.nmodemuxs = ARRAY_SIZE(gpio0_pin2_modemux),
|
||||
};
|
||||
|
||||
/* gpio0_pin3_pins */
|
||||
static const unsigned gpio0_pin3_pins[] = { 31 };
|
||||
static struct spear_muxreg gpio0_pin3_muxreg[] = {
|
||||
{
|
||||
.reg = -1,
|
||||
.mask = PMX_GPIO_PIN3_MASK,
|
||||
.val = PMX_GPIO_PIN3_MASK,
|
||||
},
|
||||
};
|
||||
|
||||
static struct spear_modemux gpio0_pin3_modemux[] = {
|
||||
{
|
||||
.modes = ~0,
|
||||
.muxregs = gpio0_pin3_muxreg,
|
||||
.nmuxregs = ARRAY_SIZE(gpio0_pin3_muxreg),
|
||||
},
|
||||
};
|
||||
|
||||
struct spear_pingroup spear3xx_gpio0_pin3_pingroup = {
|
||||
.name = "gpio0_pin3_grp",
|
||||
.pins = gpio0_pin3_pins,
|
||||
.npins = ARRAY_SIZE(gpio0_pin3_pins),
|
||||
.modemuxs = gpio0_pin3_modemux,
|
||||
.nmodemuxs = ARRAY_SIZE(gpio0_pin3_modemux),
|
||||
};
|
||||
|
||||
/* gpio0_pin4_pins */
|
||||
static const unsigned gpio0_pin4_pins[] = { 32 };
|
||||
static struct spear_muxreg gpio0_pin4_muxreg[] = {
|
||||
{
|
||||
.reg = -1,
|
||||
.mask = PMX_GPIO_PIN4_MASK,
|
||||
.val = PMX_GPIO_PIN4_MASK,
|
||||
},
|
||||
};
|
||||
|
||||
static struct spear_modemux gpio0_pin4_modemux[] = {
|
||||
{
|
||||
.modes = ~0,
|
||||
.muxregs = gpio0_pin4_muxreg,
|
||||
.nmuxregs = ARRAY_SIZE(gpio0_pin4_muxreg),
|
||||
},
|
||||
};
|
||||
|
||||
struct spear_pingroup spear3xx_gpio0_pin4_pingroup = {
|
||||
.name = "gpio0_pin4_grp",
|
||||
.pins = gpio0_pin4_pins,
|
||||
.npins = ARRAY_SIZE(gpio0_pin4_pins),
|
||||
.modemuxs = gpio0_pin4_modemux,
|
||||
.nmodemuxs = ARRAY_SIZE(gpio0_pin4_modemux),
|
||||
};
|
||||
|
||||
/* gpio0_pin5_pins */
|
||||
static const unsigned gpio0_pin5_pins[] = { 33 };
|
||||
static struct spear_muxreg gpio0_pin5_muxreg[] = {
|
||||
{
|
||||
.reg = -1,
|
||||
.mask = PMX_GPIO_PIN5_MASK,
|
||||
.val = PMX_GPIO_PIN5_MASK,
|
||||
},
|
||||
};
|
||||
|
||||
static struct spear_modemux gpio0_pin5_modemux[] = {
|
||||
{
|
||||
.modes = ~0,
|
||||
.muxregs = gpio0_pin5_muxreg,
|
||||
.nmuxregs = ARRAY_SIZE(gpio0_pin5_muxreg),
|
||||
},
|
||||
};
|
||||
|
||||
struct spear_pingroup spear3xx_gpio0_pin5_pingroup = {
|
||||
.name = "gpio0_pin5_grp",
|
||||
.pins = gpio0_pin5_pins,
|
||||
.npins = ARRAY_SIZE(gpio0_pin5_pins),
|
||||
.modemuxs = gpio0_pin5_modemux,
|
||||
.nmodemuxs = ARRAY_SIZE(gpio0_pin5_modemux),
|
||||
};
|
||||
|
||||
static const char *const gpio0_grps[] = { "gpio0_pin0_grp", "gpio0_pin1_grp",
|
||||
"gpio0_pin2_grp", "gpio0_pin3_grp", "gpio0_pin4_grp", "gpio0_pin5_grp",
|
||||
};
|
||||
struct spear_function spear3xx_gpio0_function = {
|
||||
.name = "gpio0",
|
||||
.groups = gpio0_grps,
|
||||
.ngroups = ARRAY_SIZE(gpio0_grps),
|
||||
};
|
||||
|
||||
/* uart0_ext_pins */
|
||||
static const unsigned uart0_ext_pins[] = { 37, 38, 39, 40, 41, 42 };
|
||||
static struct spear_muxreg uart0_ext_muxreg[] = {
|
||||
{
|
||||
.reg = -1,
|
||||
.mask = PMX_UART0_MODEM_MASK,
|
||||
.val = PMX_UART0_MODEM_MASK,
|
||||
},
|
||||
};
|
||||
|
||||
static struct spear_modemux uart0_ext_modemux[] = {
|
||||
{
|
||||
.modes = ~0,
|
||||
.muxregs = uart0_ext_muxreg,
|
||||
.nmuxregs = ARRAY_SIZE(uart0_ext_muxreg),
|
||||
},
|
||||
};
|
||||
|
||||
struct spear_pingroup spear3xx_uart0_ext_pingroup = {
|
||||
.name = "uart0_ext_grp",
|
||||
.pins = uart0_ext_pins,
|
||||
.npins = ARRAY_SIZE(uart0_ext_pins),
|
||||
.modemuxs = uart0_ext_modemux,
|
||||
.nmodemuxs = ARRAY_SIZE(uart0_ext_modemux),
|
||||
};
|
||||
|
||||
static const char *const uart0_ext_grps[] = { "uart0_ext_grp" };
|
||||
struct spear_function spear3xx_uart0_ext_function = {
|
||||
.name = "uart0_ext",
|
||||
.groups = uart0_ext_grps,
|
||||
.ngroups = ARRAY_SIZE(uart0_ext_grps),
|
||||
};
|
||||
|
||||
/* uart0_pins */
|
||||
static const unsigned uart0_pins[] = { 2, 3 };
|
||||
static struct spear_muxreg uart0_muxreg[] = {
|
||||
{
|
||||
.reg = -1,
|
||||
.mask = PMX_UART0_MASK,
|
||||
.val = PMX_UART0_MASK,
|
||||
},
|
||||
};
|
||||
|
||||
static struct spear_modemux uart0_modemux[] = {
|
||||
{
|
||||
.modes = ~0,
|
||||
.muxregs = uart0_muxreg,
|
||||
.nmuxregs = ARRAY_SIZE(uart0_muxreg),
|
||||
},
|
||||
};
|
||||
|
||||
struct spear_pingroup spear3xx_uart0_pingroup = {
|
||||
.name = "uart0_grp",
|
||||
.pins = uart0_pins,
|
||||
.npins = ARRAY_SIZE(uart0_pins),
|
||||
.modemuxs = uart0_modemux,
|
||||
.nmodemuxs = ARRAY_SIZE(uart0_modemux),
|
||||
};
|
||||
|
||||
static const char *const uart0_grps[] = { "uart0_grp" };
|
||||
struct spear_function spear3xx_uart0_function = {
|
||||
.name = "uart0",
|
||||
.groups = uart0_grps,
|
||||
.ngroups = ARRAY_SIZE(uart0_grps),
|
||||
};
|
||||
|
||||
/* timer_0_1_pins */
|
||||
static const unsigned timer_0_1_pins[] = { 43, 44, 47, 48 };
|
||||
static struct spear_muxreg timer_0_1_muxreg[] = {
|
||||
{
|
||||
.reg = -1,
|
||||
.mask = PMX_TIMER_0_1_MASK,
|
||||
.val = PMX_TIMER_0_1_MASK,
|
||||
},
|
||||
};
|
||||
|
||||
static struct spear_modemux timer_0_1_modemux[] = {
|
||||
{
|
||||
.modes = ~0,
|
||||
.muxregs = timer_0_1_muxreg,
|
||||
.nmuxregs = ARRAY_SIZE(timer_0_1_muxreg),
|
||||
},
|
||||
};
|
||||
|
||||
struct spear_pingroup spear3xx_timer_0_1_pingroup = {
|
||||
.name = "timer_0_1_grp",
|
||||
.pins = timer_0_1_pins,
|
||||
.npins = ARRAY_SIZE(timer_0_1_pins),
|
||||
.modemuxs = timer_0_1_modemux,
|
||||
.nmodemuxs = ARRAY_SIZE(timer_0_1_modemux),
|
||||
};
|
||||
|
||||
static const char *const timer_0_1_grps[] = { "timer_0_1_grp" };
|
||||
struct spear_function spear3xx_timer_0_1_function = {
|
||||
.name = "timer_0_1",
|
||||
.groups = timer_0_1_grps,
|
||||
.ngroups = ARRAY_SIZE(timer_0_1_grps),
|
||||
};
|
||||
|
||||
/* timer_2_3_pins */
|
||||
static const unsigned timer_2_3_pins[] = { 45, 46, 49, 50 };
|
||||
static struct spear_muxreg timer_2_3_muxreg[] = {
|
||||
{
|
||||
.reg = -1,
|
||||
.mask = PMX_TIMER_2_3_MASK,
|
||||
.val = PMX_TIMER_2_3_MASK,
|
||||
},
|
||||
};
|
||||
|
||||
static struct spear_modemux timer_2_3_modemux[] = {
|
||||
{
|
||||
.modes = ~0,
|
||||
.muxregs = timer_2_3_muxreg,
|
||||
.nmuxregs = ARRAY_SIZE(timer_2_3_muxreg),
|
||||
},
|
||||
};
|
||||
|
||||
struct spear_pingroup spear3xx_timer_2_3_pingroup = {
|
||||
.name = "timer_2_3_grp",
|
||||
.pins = timer_2_3_pins,
|
||||
.npins = ARRAY_SIZE(timer_2_3_pins),
|
||||
.modemuxs = timer_2_3_modemux,
|
||||
.nmodemuxs = ARRAY_SIZE(timer_2_3_modemux),
|
||||
};
|
||||
|
||||
static const char *const timer_2_3_grps[] = { "timer_2_3_grp" };
|
||||
struct spear_function spear3xx_timer_2_3_function = {
|
||||
.name = "timer_2_3",
|
||||
.groups = timer_2_3_grps,
|
||||
.ngroups = ARRAY_SIZE(timer_2_3_grps),
|
||||
};
|
||||
|
||||
/* Define muxreg arrays */
|
||||
DEFINE_MUXREG(firda_pins, 0, PMX_FIRDA_MASK, 0);
|
||||
DEFINE_MUXREG(i2c_pins, 0, PMX_I2C_MASK, 0);
|
||||
DEFINE_MUXREG(ssp_cs_pins, 0, PMX_SSP_CS_MASK, 0);
|
||||
DEFINE_MUXREG(ssp_pins, 0, PMX_SSP_MASK, 0);
|
||||
DEFINE_MUXREG(mii_pins, 0, PMX_MII_MASK, 0);
|
||||
DEFINE_MUXREG(gpio0_pin0_pins, 0, PMX_GPIO_PIN0_MASK, 0);
|
||||
DEFINE_MUXREG(gpio0_pin1_pins, 0, PMX_GPIO_PIN1_MASK, 0);
|
||||
DEFINE_MUXREG(gpio0_pin2_pins, 0, PMX_GPIO_PIN2_MASK, 0);
|
||||
DEFINE_MUXREG(gpio0_pin3_pins, 0, PMX_GPIO_PIN3_MASK, 0);
|
||||
DEFINE_MUXREG(gpio0_pin4_pins, 0, PMX_GPIO_PIN4_MASK, 0);
|
||||
DEFINE_MUXREG(gpio0_pin5_pins, 0, PMX_GPIO_PIN5_MASK, 0);
|
||||
DEFINE_MUXREG(uart0_ext_pins, 0, PMX_UART0_MODEM_MASK, 0);
|
||||
DEFINE_MUXREG(uart0_pins, 0, PMX_UART0_MASK, 0);
|
||||
DEFINE_MUXREG(timer_0_1_pins, 0, PMX_TIMER_0_1_MASK, 0);
|
||||
DEFINE_MUXREG(timer_2_3_pins, 0, PMX_TIMER_2_3_MASK, 0);
|
||||
|
||||
static struct spear_gpio_pingroup spear3xx_gpio_pingroup[] = {
|
||||
GPIO_PINGROUP(firda_pins),
|
||||
GPIO_PINGROUP(i2c_pins),
|
||||
GPIO_PINGROUP(ssp_cs_pins),
|
||||
GPIO_PINGROUP(ssp_pins),
|
||||
GPIO_PINGROUP(mii_pins),
|
||||
GPIO_PINGROUP(gpio0_pin0_pins),
|
||||
GPIO_PINGROUP(gpio0_pin1_pins),
|
||||
GPIO_PINGROUP(gpio0_pin2_pins),
|
||||
GPIO_PINGROUP(gpio0_pin3_pins),
|
||||
GPIO_PINGROUP(gpio0_pin4_pins),
|
||||
GPIO_PINGROUP(gpio0_pin5_pins),
|
||||
GPIO_PINGROUP(uart0_ext_pins),
|
||||
GPIO_PINGROUP(uart0_pins),
|
||||
GPIO_PINGROUP(timer_0_1_pins),
|
||||
GPIO_PINGROUP(timer_2_3_pins),
|
||||
};
|
||||
|
||||
struct spear_pinctrl_machdata spear3xx_machdata = {
|
||||
.pins = spear3xx_pins,
|
||||
.npins = ARRAY_SIZE(spear3xx_pins),
|
||||
.gpio_pingroups = spear3xx_gpio_pingroup,
|
||||
.ngpio_pingroups = ARRAY_SIZE(spear3xx_gpio_pingroup),
|
||||
};
|
93
drivers/pinctrl/spear/pinctrl-spear3xx.h
Normal file
93
drivers/pinctrl/spear/pinctrl-spear3xx.h
Normal file
|
@ -0,0 +1,93 @@
|
|||
/*
|
||||
* Header file for the ST Microelectronics SPEAr3xx pinmux
|
||||
*
|
||||
* Copyright (C) 2012 ST Microelectronics
|
||||
* Viresh Kumar <viresh.linux@gmail.com>
|
||||
*
|
||||
* This file is licensed under the terms of the GNU General Public
|
||||
* License version 2. This program is licensed "as is" without any
|
||||
* warranty of any kind, whether express or implied.
|
||||
*/
|
||||
|
||||
#ifndef __PINMUX_SPEAR3XX_H__
|
||||
#define __PINMUX_SPEAR3XX_H__
|
||||
|
||||
#include "pinctrl-spear.h"
|
||||
|
||||
/* pad mux declarations */
|
||||
#define PMX_PWM_MASK (1 << 16)
|
||||
#define PMX_FIRDA_MASK (1 << 14)
|
||||
#define PMX_I2C_MASK (1 << 13)
|
||||
#define PMX_SSP_CS_MASK (1 << 12)
|
||||
#define PMX_SSP_MASK (1 << 11)
|
||||
#define PMX_MII_MASK (1 << 10)
|
||||
#define PMX_GPIO_PIN0_MASK (1 << 9)
|
||||
#define PMX_GPIO_PIN1_MASK (1 << 8)
|
||||
#define PMX_GPIO_PIN2_MASK (1 << 7)
|
||||
#define PMX_GPIO_PIN3_MASK (1 << 6)
|
||||
#define PMX_GPIO_PIN4_MASK (1 << 5)
|
||||
#define PMX_GPIO_PIN5_MASK (1 << 4)
|
||||
#define PMX_UART0_MODEM_MASK (1 << 3)
|
||||
#define PMX_UART0_MASK (1 << 2)
|
||||
#define PMX_TIMER_2_3_MASK (1 << 1)
|
||||
#define PMX_TIMER_0_1_MASK (1 << 0)
|
||||
|
||||
extern struct spear_pingroup spear3xx_firda_pingroup;
|
||||
extern struct spear_pingroup spear3xx_gpio0_pin0_pingroup;
|
||||
extern struct spear_pingroup spear3xx_gpio0_pin1_pingroup;
|
||||
extern struct spear_pingroup spear3xx_gpio0_pin2_pingroup;
|
||||
extern struct spear_pingroup spear3xx_gpio0_pin3_pingroup;
|
||||
extern struct spear_pingroup spear3xx_gpio0_pin4_pingroup;
|
||||
extern struct spear_pingroup spear3xx_gpio0_pin5_pingroup;
|
||||
extern struct spear_pingroup spear3xx_i2c_pingroup;
|
||||
extern struct spear_pingroup spear3xx_mii_pingroup;
|
||||
extern struct spear_pingroup spear3xx_ssp_cs_pingroup;
|
||||
extern struct spear_pingroup spear3xx_ssp_pingroup;
|
||||
extern struct spear_pingroup spear3xx_timer_0_1_pingroup;
|
||||
extern struct spear_pingroup spear3xx_timer_2_3_pingroup;
|
||||
extern struct spear_pingroup spear3xx_uart0_ext_pingroup;
|
||||
extern struct spear_pingroup spear3xx_uart0_pingroup;
|
||||
|
||||
#define SPEAR3XX_COMMON_PINGROUPS \
|
||||
&spear3xx_firda_pingroup, \
|
||||
&spear3xx_gpio0_pin0_pingroup, \
|
||||
&spear3xx_gpio0_pin1_pingroup, \
|
||||
&spear3xx_gpio0_pin2_pingroup, \
|
||||
&spear3xx_gpio0_pin3_pingroup, \
|
||||
&spear3xx_gpio0_pin4_pingroup, \
|
||||
&spear3xx_gpio0_pin5_pingroup, \
|
||||
&spear3xx_i2c_pingroup, \
|
||||
&spear3xx_mii_pingroup, \
|
||||
&spear3xx_ssp_cs_pingroup, \
|
||||
&spear3xx_ssp_pingroup, \
|
||||
&spear3xx_timer_0_1_pingroup, \
|
||||
&spear3xx_timer_2_3_pingroup, \
|
||||
&spear3xx_uart0_ext_pingroup, \
|
||||
&spear3xx_uart0_pingroup
|
||||
|
||||
extern struct spear_function spear3xx_firda_function;
|
||||
extern struct spear_function spear3xx_gpio0_function;
|
||||
extern struct spear_function spear3xx_i2c_function;
|
||||
extern struct spear_function spear3xx_mii_function;
|
||||
extern struct spear_function spear3xx_ssp_cs_function;
|
||||
extern struct spear_function spear3xx_ssp_function;
|
||||
extern struct spear_function spear3xx_timer_0_1_function;
|
||||
extern struct spear_function spear3xx_timer_2_3_function;
|
||||
extern struct spear_function spear3xx_uart0_ext_function;
|
||||
extern struct spear_function spear3xx_uart0_function;
|
||||
|
||||
#define SPEAR3XX_COMMON_FUNCTIONS \
|
||||
&spear3xx_firda_function, \
|
||||
&spear3xx_gpio0_function, \
|
||||
&spear3xx_i2c_function, \
|
||||
&spear3xx_mii_function, \
|
||||
&spear3xx_ssp_cs_function, \
|
||||
&spear3xx_ssp_function, \
|
||||
&spear3xx_timer_0_1_function, \
|
||||
&spear3xx_timer_2_3_function, \
|
||||
&spear3xx_uart0_ext_function, \
|
||||
&spear3xx_uart0_function
|
||||
|
||||
extern struct spear_pinctrl_machdata spear3xx_machdata;
|
||||
|
||||
#endif /* __PINMUX_SPEAR3XX_H__ */
|
Loading…
Add table
Add a link
Reference in a new issue