dect
/
linux-2.6
Archived
13
0
Fork 0

Merge commit 'pinctrl/devel 4ddb1c2' into spear-for-3.8

This merges dependency branch pinctrl/devel for SPEAr DT updates.
This commit is contained in:
Viresh Kumar 2012-11-26 15:44:02 +05:30
commit 22595e2815
46 changed files with 1826 additions and 273 deletions

View File

@ -75,4 +75,40 @@ Example of two SOC GPIO banks defined as gpio-controller nodes:
gpio-controller;
};
2.1) gpio-controller and pinctrl subsystem
------------------------------------------
gpio-controller on a SOC might be tightly coupled with the pinctrl
subsystem, in the sense that the pins can be used by other functions
together with optional gpio feature.
While the pin allocation is totally managed by the pin ctrl subsystem,
gpio (under gpiolib) is still maintained by gpio drivers. It may happen
that different pin ranges in a SoC is managed by different gpio drivers.
This makes it logical to let gpio drivers announce their pin ranges to
the pin ctrl subsystem and call 'pinctrl_request_gpio' in order to
request the corresponding pin before any gpio usage.
For this, the gpio controller can use a pinctrl phandle and pins to
announce the pinrange to the pin ctrl subsystem. For example,
qe_pio_e: gpio-controller@1460 {
#gpio-cells = <2>;
compatible = "fsl,qe-pario-bank-e", "fsl,qe-pario-bank";
reg = <0x1460 0x18>;
gpio-controller;
gpio-ranges = <&pinctrl1 20 10>, <&pinctrl2 50 20>;
}
where,
&pinctrl1 and &pinctrl2 is the phandle to the pinctrl DT node.
Next values specify the base pin and number of pins for the range
handled by 'qe_pio_e' gpio. In the given example from base pin 20 to
pin 29 under pinctrl1 and pin 50 to pin 69 under pinctrl2 is handled
by this gpio controller.
The pinctrl node must have "#gpio-range-cells" property to show number of
arguments to pass with phandle from gpio controllers node.

View File

@ -439,6 +439,48 @@ slower clock delays the rising edge of SCK, and the I2C master adjusts its
signaling rate accordingly.
GPIO controllers and the pinctrl subsystem
------------------------------------------
A GPIO controller on a SOC might be tightly coupled with the pinctrl
subsystem, in the sense that the pins can be used by other functions
together with an optional gpio feature. We have already covered the
case where e.g. a GPIO controller need to reserve a pin or set the
direction of a pin by calling any of:
pinctrl_request_gpio()
pinctrl_free_gpio()
pinctrl_gpio_direction_input()
pinctrl_gpio_direction_output()
But how does the pin control subsystem cross-correlate the GPIO
numbers (which are a global business) to a certain pin on a certain
pin controller?
This is done by registering "ranges" of pins, which are essentially
cross-reference tables. These are described in
Documentation/pinctrl.txt
While the pin allocation is totally managed by the pinctrl subsystem,
gpio (under gpiolib) is still maintained by gpio drivers. It may happen
that different pin ranges in a SoC is managed by different gpio drivers.
This makes it logical to let gpio drivers announce their pin ranges to
the pin ctrl subsystem before it will call 'pinctrl_request_gpio' in order
to request the corresponding pin to be prepared by the pinctrl subsystem
before any gpio usage.
For this, the gpio controller can register its pin range with pinctrl
subsystem. There are two ways of doing it currently: with or without DT.
For with DT support refer to Documentation/devicetree/bindings/gpio/gpio.txt.
For non-DT support, user can call gpiochip_add_pin_range() with appropriate
parameters to register a range of gpio pins with a pinctrl driver. For this
exact name string of pinctrl device has to be passed as one of the
argument to this routine.
What do these conventions omit?
===============================
One of the biggest things these conventions omit is pin multiplexing, since

View File

@ -364,6 +364,9 @@ will get an pin number into its handled number range. Further it is also passed
the range ID value, so that the pin controller knows which range it should
deal with.
Calling pinctrl_add_gpio_range from pinctrl driver is DEPRECATED. Please see
section 2.1 of Documentation/devicetree/bindings/gpio/gpio.txt on how to bind
pinctrl and gpio drivers.
PINMUX interfaces
=================
@ -1193,4 +1196,6 @@ foo_switch()
...
}
The above has to be done from process context.
The above has to be done from process context. The reservation of the pins
will be done when the state is activated, so in effect one specific pin
can be used by different functions at different times on a running system.

View File

@ -181,6 +181,10 @@
status = "okay";
};
gpio@d8400000 {
status = "okay";
};
i2c0: i2c@e0280000 {
status = "okay";
};

View File

@ -70,6 +70,12 @@
status = "disabled";
};
pinmux: pinmux@e0700000 {
compatible = "st,spear1310-pinmux";
reg = <0xe0700000 0x1000>;
#gpio-range-cells = <2>;
};
spi1: spi@5d400000 {
compatible = "arm,pl022", "arm,primecell";
reg = <0x5d400000 0x1000>;
@ -179,6 +185,27 @@
thermal@e07008c4 {
st,thermal-flags = <0x7000>;
};
gpiopinctrl: gpio@d8400000 {
compatible = "st,spear-plgpio";
reg = <0xd8400000 0x1000>;
interrupts = <0 100 0x4>;
#interrupt-cells = <1>;
interrupt-controller;
gpio-controller;
#gpio-cells = <2>;
gpio-ranges = <&pinmux 0 246>;
status = "disabled";
st-plgpio,ngpio = <246>;
st-plgpio,enb-reg = <0xd0>;
st-plgpio,wdata-reg = <0x90>;
st-plgpio,dir-reg = <0xb0>;
st-plgpio,ie-reg = <0x30>;
st-plgpio,rdata-reg = <0x70>;
st-plgpio,mis-reg = <0x10>;
st-plgpio,eit-reg = <0x50>;
};
};
};
};

View File

@ -193,6 +193,10 @@
status = "okay";
};
gpio@e2800000 {
status = "okay";
};
i2c0: i2c@e0280000 {
status = "okay";
};

View File

@ -24,6 +24,12 @@
status = "disabled";
};
pinmux: pinmux@e0700000 {
compatible = "st,spear1340-pinmux";
reg = <0xe0700000 0x1000>;
#gpio-range-cells = <2>;
};
spi1: spi@5d400000 {
compatible = "arm,pl022", "arm,primecell";
reg = <0x5d400000 0x1000>;
@ -51,6 +57,26 @@
thermal@e07008c4 {
st,thermal-flags = <0x2a00>;
};
gpiopinctrl: gpio@e2800000 {
compatible = "st,spear-plgpio";
reg = <0xe2800000 0x1000>;
interrupts = <0 107 0x4>;
#interrupt-cells = <1>;
interrupt-controller;
gpio-controller;
#gpio-cells = <2>;
gpio-ranges = <&pinmux 0 252>;
status = "disabled";
st-plgpio,ngpio = <250>;
st-plgpio,wdata-reg = <0x40>;
st-plgpio,dir-reg = <0x00>;
st-plgpio,ie-reg = <0x80>;
st-plgpio,rdata-reg = <0x20>;
st-plgpio,mis-reg = <0xa0>;
st-plgpio,eit-reg = <0x60>;
};
};
};
};

View File

@ -22,9 +22,10 @@
0xb0000000 0xb0000000 0x10000000
0xd0000000 0xd0000000 0x30000000>;
pinmux@b4000000 {
pinmux: pinmux@b4000000 {
compatible = "st,spear310-pinmux";
reg = <0xb4000000 0x1000>;
#gpio-range-cells = <2>;
};
fsmc: flash@44000000 {
@ -75,6 +76,25 @@
reg = <0xb2200000 0x1000>;
status = "disabled";
};
gpiopinctrl: gpio@b4000000 {
compatible = "st,spear-plgpio";
reg = <0xb4000000 0x1000>;
#interrupt-cells = <1>;
interrupt-controller;
gpio-controller;
#gpio-cells = <2>;
gpio-ranges = <&pinmux 0 102>;
status = "disabled";
st-plgpio,ngpio = <102>;
st-plgpio,enb-reg = <0x10>;
st-plgpio,wdata-reg = <0x20>;
st-plgpio,dir-reg = <0x30>;
st-plgpio,ie-reg = <0x50>;
st-plgpio,rdata-reg = <0x40>;
st-plgpio,mis-reg = <0x60>;
};
};
};
};

View File

@ -164,6 +164,10 @@
status = "okay";
};
gpio@b3000000 {
status = "okay";
};
i2c0: i2c@d0180000 {
status = "okay";
};

View File

@ -21,9 +21,10 @@
ranges = <0x40000000 0x40000000 0x80000000
0xd0000000 0xd0000000 0x30000000>;
pinmux@b3000000 {
pinmux: pinmux@b3000000 {
compatible = "st,spear320-pinmux";
reg = <0xb3000000 0x1000>;
#gpio-range-cells = <2>;
};
clcd@90000000 {
@ -90,6 +91,26 @@
reg = <0xa4000000 0x1000>;
status = "disabled";
};
gpiopinctrl: gpio@b3000000 {
compatible = "st,spear-plgpio";
reg = <0xb3000000 0x1000>;
#interrupt-cells = <1>;
interrupt-controller;
gpio-controller;
#gpio-cells = <2>;
gpio-ranges = <&pinmux 0 102>;
status = "disabled";
st-plgpio,ngpio = <102>;
st-plgpio,enb-reg = <0x24>;
st-plgpio,wdata-reg = <0x34>;
st-plgpio,dir-reg = <0x44>;
st-plgpio,ie-reg = <0x64>;
st-plgpio,rdata-reg = <0x54>;
st-plgpio,mis-reg = <0x84>;
st-plgpio,eit-reg = <0x94>;
};
};
};
};

View File

@ -1445,7 +1445,6 @@ static struct platform_device pinctrl_device = {
static struct u300_gpio_platform u300_gpio_plat = {
.ports = 7,
.gpio_base = 0,
.gpio_irq_base = IRQ_U300_GPIO_BASE,
.pinctrl_device = &pinctrl_device,
};
@ -1804,7 +1803,7 @@ MACHINE_START(U300, "Ericsson AB U335 S335/B335 Prototype Board")
/* Maintainer: Linus Walleij <linus.walleij@stericsson.com> */
.atag_offset = 0x100,
.map_io = u300_map_io,
.nr_irqs = NR_IRQS_U300,
.nr_irqs = 0,
.init_irq = u300_init_irq,
.handle_irq = vic_handle_irq,
.timer = &u300_timer,

View File

@ -12,79 +12,69 @@
#ifndef __MACH_IRQS_H
#define __MACH_IRQS_H
#define IRQ_U300_INTCON0_START 1
#define IRQ_U300_INTCON1_START 33
#define IRQ_U300_INTCON0_START 32
#define IRQ_U300_INTCON1_START 64
/* These are on INTCON0 - 30 lines */
#define IRQ_U300_IRQ0_EXT 1
#define IRQ_U300_IRQ1_EXT 2
#define IRQ_U300_DMA 3
#define IRQ_U300_VIDEO_ENC_0 4
#define IRQ_U300_VIDEO_ENC_1 5
#define IRQ_U300_AAIF_RX 6
#define IRQ_U300_AAIF_TX 7
#define IRQ_U300_AAIF_VGPIO 8
#define IRQ_U300_AAIF_WAKEUP 9
#define IRQ_U300_PCM_I2S0_FRAME 10
#define IRQ_U300_PCM_I2S0_FIFO 11
#define IRQ_U300_PCM_I2S1_FRAME 12
#define IRQ_U300_PCM_I2S1_FIFO 13
#define IRQ_U300_XGAM_GAMCON 14
#define IRQ_U300_XGAM_CDI 15
#define IRQ_U300_XGAM_CDICON 16
#define IRQ_U300_XGAM_PDI 18
#define IRQ_U300_XGAM_PDICON 19
#define IRQ_U300_XGAM_GAMEACC 20
#define IRQ_U300_XGAM_MCIDCT 21
#define IRQ_U300_APEX 22
#define IRQ_U300_UART0 23
#define IRQ_U300_SPI 24
#define IRQ_U300_TIMER_APP_OS 25
#define IRQ_U300_TIMER_APP_DD 26
#define IRQ_U300_TIMER_APP_GP1 27
#define IRQ_U300_TIMER_APP_GP2 28
#define IRQ_U300_TIMER_OS 29
#define IRQ_U300_TIMER_MS 30
#define IRQ_U300_KEYPAD_KEYBF 31
#define IRQ_U300_KEYPAD_KEYBR 32
#define IRQ_U300_IRQ0_EXT 32
#define IRQ_U300_IRQ1_EXT 33
#define IRQ_U300_DMA 34
#define IRQ_U300_VIDEO_ENC_0 35
#define IRQ_U300_VIDEO_ENC_1 36
#define IRQ_U300_AAIF_RX 37
#define IRQ_U300_AAIF_TX 38
#define IRQ_U300_AAIF_VGPIO 39
#define IRQ_U300_AAIF_WAKEUP 40
#define IRQ_U300_PCM_I2S0_FRAME 41
#define IRQ_U300_PCM_I2S0_FIFO 42
#define IRQ_U300_PCM_I2S1_FRAME 43
#define IRQ_U300_PCM_I2S1_FIFO 44
#define IRQ_U300_XGAM_GAMCON 45
#define IRQ_U300_XGAM_CDI 46
#define IRQ_U300_XGAM_CDICON 47
#define IRQ_U300_XGAM_PDI 49
#define IRQ_U300_XGAM_PDICON 50
#define IRQ_U300_XGAM_GAMEACC 51
#define IRQ_U300_XGAM_MCIDCT 52
#define IRQ_U300_APEX 53
#define IRQ_U300_UART0 54
#define IRQ_U300_SPI 55
#define IRQ_U300_TIMER_APP_OS 56
#define IRQ_U300_TIMER_APP_DD 57
#define IRQ_U300_TIMER_APP_GP1 58
#define IRQ_U300_TIMER_APP_GP2 59
#define IRQ_U300_TIMER_OS 60
#define IRQ_U300_TIMER_MS 61
#define IRQ_U300_KEYPAD_KEYBF 62
#define IRQ_U300_KEYPAD_KEYBR 63
/* These are on INTCON1 - 32 lines */
#define IRQ_U300_GPIO_PORT0 33
#define IRQ_U300_GPIO_PORT1 34
#define IRQ_U300_GPIO_PORT2 35
#define IRQ_U300_GPIO_PORT0 64
#define IRQ_U300_GPIO_PORT1 65
#define IRQ_U300_GPIO_PORT2 66
/* These are for DB3150, DB3200 and DB3350 */
#define IRQ_U300_WDOG 36
#define IRQ_U300_EVHIST 37
#define IRQ_U300_MSPRO 38
#define IRQ_U300_MMCSD_MCIINTR0 39
#define IRQ_U300_MMCSD_MCIINTR1 40
#define IRQ_U300_I2C0 41
#define IRQ_U300_I2C1 42
#define IRQ_U300_RTC 43
#define IRQ_U300_NFIF 44
#define IRQ_U300_NFIF2 45
#define IRQ_U300_WDOG 67
#define IRQ_U300_EVHIST 68
#define IRQ_U300_MSPRO 69
#define IRQ_U300_MMCSD_MCIINTR0 70
#define IRQ_U300_MMCSD_MCIINTR1 71
#define IRQ_U300_I2C0 72
#define IRQ_U300_I2C1 73
#define IRQ_U300_RTC 74
#define IRQ_U300_NFIF 75
#define IRQ_U300_NFIF2 76
/* The DB3350-specific interrupt lines */
#define IRQ_U300_ISP_F0 46
#define IRQ_U300_ISP_F1 47
#define IRQ_U300_ISP_F2 48
#define IRQ_U300_ISP_F3 49
#define IRQ_U300_ISP_F4 50
#define IRQ_U300_GPIO_PORT3 51
#define IRQ_U300_SYSCON_PLL_LOCK 52
#define IRQ_U300_UART1 53
#define IRQ_U300_GPIO_PORT4 54
#define IRQ_U300_GPIO_PORT5 55
#define IRQ_U300_GPIO_PORT6 56
#define U300_VIC_IRQS_END 57
/* Maximum 8*7 GPIO lines */
#ifdef CONFIG_PINCTRL_COH901
#define IRQ_U300_GPIO_BASE (U300_VIC_IRQS_END)
#define IRQ_U300_GPIO_END (IRQ_U300_GPIO_BASE + 56)
#else
#define IRQ_U300_GPIO_END (U300_VIC_IRQS_END)
#endif
#define NR_IRQS_U300 (IRQ_U300_GPIO_END - IRQ_U300_INTCON0_START)
#define IRQ_U300_ISP_F0 77
#define IRQ_U300_ISP_F1 78
#define IRQ_U300_ISP_F2 79
#define IRQ_U300_ISP_F3 80
#define IRQ_U300_ISP_F4 81
#define IRQ_U300_GPIO_PORT3 82
#define IRQ_U300_SYSCON_PLL_LOCK 83
#define IRQ_U300_UART1 84
#define IRQ_U300_GPIO_PORT4 85
#define IRQ_U300_GPIO_PORT5 86
#define IRQ_U300_GPIO_PORT6 87
#define U300_VIC_IRQS_END 88
#endif

View File

@ -19,6 +19,7 @@
#include <linux/of.h>
#include <linux/of_address.h>
#include <linux/of_gpio.h>
#include <linux/pinctrl/pinctrl.h>
#include <linux/slab.h>
/* Private data structure for of_gpiochip_find_and_xlate */
@ -216,6 +217,42 @@ err0:
}
EXPORT_SYMBOL(of_mm_gpiochip_add);
#ifdef CONFIG_PINCTRL
static void of_gpiochip_add_pin_range(struct gpio_chip *chip)
{
struct device_node *np = chip->of_node;
struct of_phandle_args pinspec;
struct pinctrl_dev *pctldev;
int index = 0, ret;
if (!np)
return;
do {
ret = of_parse_phandle_with_args(np, "gpio-ranges",
"#gpio-range-cells", index, &pinspec);
if (ret)
break;
pctldev = of_pinctrl_get(pinspec.np);
if (!pctldev)
break;
ret = gpiochip_add_pin_range(chip,
pinctrl_dev_get_name(pctldev),
pinspec.args[0],
pinspec.args[1]);
if (ret)
break;
} while (index++);
}
#else
static void of_gpiochip_add_pin_range(struct gpio_chip *chip) {}
#endif
void of_gpiochip_add(struct gpio_chip *chip)
{
if ((!chip->of_node) && (chip->dev))
@ -229,11 +266,14 @@ void of_gpiochip_add(struct gpio_chip *chip)
chip->of_xlate = of_gpio_simple_xlate;
}
of_gpiochip_add_pin_range(chip);
of_node_get(chip->of_node);
}
void of_gpiochip_remove(struct gpio_chip *chip)
{
gpiochip_remove_pin_ranges(chip);
if (chip->of_node)
of_node_put(chip->of_node);
}

View File

@ -1083,6 +1083,10 @@ int gpiochip_add(struct gpio_chip *chip)
}
}
#ifdef CONFIG_PINCTRL
INIT_LIST_HEAD(&chip->pin_ranges);
#endif
of_gpiochip_add(chip);
unlock:
@ -1123,6 +1127,7 @@ int gpiochip_remove(struct gpio_chip *chip)
spin_lock_irqsave(&gpio_lock, flags);
gpiochip_remove_pin_ranges(chip);
of_gpiochip_remove(chip);
for (id = chip->base; id < chip->base + chip->ngpio; id++) {
@ -1180,6 +1185,47 @@ struct gpio_chip *gpiochip_find(void *data,
}
EXPORT_SYMBOL_GPL(gpiochip_find);
#ifdef CONFIG_PINCTRL
int gpiochip_add_pin_range(struct gpio_chip *chip, const char *pinctl_name,
unsigned int pin_base, unsigned int npins)
{
struct gpio_pin_range *pin_range;
pin_range = devm_kzalloc(chip->dev, sizeof(*pin_range), GFP_KERNEL);
if (!pin_range) {
pr_err("%s: GPIO chip: failed to allocate pin ranges\n",
chip->label);
return -ENOMEM;
}
pin_range->range.name = chip->label;
pin_range->range.base = chip->base;
pin_range->range.pin_base = pin_base;
pin_range->range.npins = npins;
pin_range->pctldev = find_pinctrl_and_add_gpio_range(pinctl_name,
&pin_range->range);
list_add_tail(&pin_range->node, &chip->pin_ranges);
return 0;
}
EXPORT_SYMBOL_GPL(gpiochip_add_pin_range);
void gpiochip_remove_pin_ranges(struct gpio_chip *chip)
{
struct gpio_pin_range *pin_range, *tmp;
list_for_each_entry_safe(pin_range, tmp, &chip->pin_ranges, node) {
list_del(&pin_range->node);
pinctrl_remove_gpio_range(pin_range->pctldev,
&pin_range->range);
}
}
EXPORT_SYMBOL_GPL(gpiochip_remove_pin_ranges);
#endif /* CONFIG_PINCTRL */
/* These "optional" allocation calls help prevent drivers from stomping
* on each other, and help provide better diagnostics in debugfs.
* They're called even less than the "set direction" calls.

View File

@ -143,8 +143,8 @@ config PINCTRL_SINGLE
This selects the device tree based generic pinctrl driver.
config PINCTRL_SIRF
bool "CSR SiRFprimaII pin controller driver"
depends on ARCH_PRIMA2
bool "CSR SiRFprimaII/SiRFmarco pin controller driver"
depends on ARCH_SIRF
select PINMUX
config PINCTRL_TEGRA
@ -188,27 +188,7 @@ config PINCTRL_EXYNOS4
depends on OF && GPIOLIB
select PINCTRL_SAMSUNG
config PINCTRL_MVEBU
bool
depends on ARCH_MVEBU
select PINMUX
select PINCONF
config PINCTRL_DOVE
bool
select PINCTRL_MVEBU
config PINCTRL_KIRKWOOD
bool
select PINCTRL_MVEBU
config PINCTRL_ARMADA_370
bool
select PINCTRL_MVEBU
config PINCTRL_ARMADA_XP
bool
select PINCTRL_MVEBU
source "drivers/pinctrl/mvebu/Kconfig"
source "drivers/pinctrl/spear/Kconfig"

View File

@ -36,12 +36,8 @@ obj-$(CONFIG_PINCTRL_U300) += pinctrl-u300.o
obj-$(CONFIG_PINCTRL_COH901) += pinctrl-coh901.o
obj-$(CONFIG_PINCTRL_SAMSUNG) += pinctrl-samsung.o
obj-$(CONFIG_PINCTRL_EXYNOS4) += pinctrl-exynos.o
obj-$(CONFIG_PINCTRL_MVEBU) += pinctrl-mvebu.o
obj-$(CONFIG_PINCTRL_DOVE) += pinctrl-dove.o
obj-$(CONFIG_PINCTRL_KIRKWOOD) += pinctrl-kirkwood.o
obj-$(CONFIG_PINCTRL_ARMADA_370) += pinctrl-armada-370.o
obj-$(CONFIG_PINCTRL_ARMADA_XP) += pinctrl-armada-xp.o
obj-$(CONFIG_PINCTRL_XWAY) += pinctrl-xway.o
obj-$(CONFIG_PINCTRL_LANTIQ) += pinctrl-lantiq.o
obj-$(CONFIG_PLAT_ORION) += mvebu/
obj-$(CONFIG_PLAT_SPEAR) += spear/

View File

@ -345,6 +345,33 @@ void pinctrl_add_gpio_ranges(struct pinctrl_dev *pctldev,
}
EXPORT_SYMBOL_GPL(pinctrl_add_gpio_ranges);
struct pinctrl_dev *find_pinctrl_and_add_gpio_range(const char *devname,
struct pinctrl_gpio_range *range)
{
struct pinctrl_dev *pctldev = get_pinctrl_dev_from_devname(devname);
if (!pctldev)
return NULL;
pinctrl_add_gpio_range(pctldev, range);
return pctldev;
}
EXPORT_SYMBOL_GPL(find_pinctrl_and_add_gpio_range);
/**
* pinctrl_remove_gpio_range() - remove a range of GPIOs fro a pin controller
* @pctldev: pin controller device to remove the range from
* @range: the GPIO range to remove
*/
void pinctrl_remove_gpio_range(struct pinctrl_dev *pctldev,
struct pinctrl_gpio_range *range)
{
mutex_lock(&pinctrl_mutex);
list_del(&range->node);
mutex_unlock(&pinctrl_mutex);
}
EXPORT_SYMBOL_GPL(pinctrl_remove_gpio_range);
/**
* pinctrl_get_group_selector() - returns the group selector for a group
* @pctldev: the pin controller handling the group
@ -563,6 +590,8 @@ static int add_setting(struct pinctrl *p, struct pinctrl_map const *map)
return -EPROBE_DEFER;
}
setting->dev_name = map->dev_name;
switch (map->type) {
case PIN_MAP_TYPE_MUX_GROUP:
ret = pinmux_map_to_setting(map, setting);

View File

@ -105,12 +105,14 @@ struct pinctrl_setting_configs {
* @type: the type of setting
* @pctldev: pin control device handling to be programmed. Not used for
* PIN_MAP_TYPE_DUMMY_STATE.
* @dev_name: the name of the device using this state
* @data: Data specific to the setting type
*/
struct pinctrl_setting {
struct list_head node;
enum pinctrl_map_type type;
struct pinctrl_dev *pctldev;
const char *dev_name;
union {
struct pinctrl_setting_mux mux;
struct pinctrl_setting_configs configs;

View File

@ -106,6 +106,17 @@ static struct pinctrl_dev *find_pinctrl_by_of_node(struct device_node *np)
return NULL;
}
struct pinctrl_dev *of_pinctrl_get(struct device_node *np)
{
struct pinctrl_dev *pctldev;
pctldev = find_pinctrl_by_of_node(np);
if (!pctldev)
return NULL;
return pctldev;
}
static int dt_to_map_one_config(struct pinctrl *p, const char *statename,
struct device_node *np_config)
{

View File

@ -0,0 +1,24 @@
if PLAT_ORION
config PINCTRL_MVEBU
bool
select PINMUX
select PINCONF
config PINCTRL_DOVE
bool
select PINCTRL_MVEBU
config PINCTRL_KIRKWOOD
bool
select PINCTRL_MVEBU
config PINCTRL_ARMADA_370
bool
select PINCTRL_MVEBU
config PINCTRL_ARMADA_XP
bool
select PINCTRL_MVEBU
endif

View File

@ -0,0 +1,5 @@
obj-$(CONFIG_PINCTRL_MVEBU) += pinctrl-mvebu.o
obj-$(CONFIG_PINCTRL_DOVE) += pinctrl-dove.o
obj-$(CONFIG_PINCTRL_KIRKWOOD) += pinctrl-kirkwood.o
obj-$(CONFIG_PINCTRL_ARMADA_370) += pinctrl-armada-370.o
obj-$(CONFIG_PINCTRL_ARMADA_XP) += pinctrl-armada-xp.o

View File

@ -24,7 +24,6 @@
#include <linux/pinctrl/pinctrl.h>
#include <linux/pinctrl/pinmux.h>
#include "core.h"
#include "pinctrl-mvebu.h"
#define MPPS_PER_REG 8

View File

@ -13,6 +13,7 @@
#include <linux/delay.h>
#include <linux/errno.h>
#include <linux/io.h>
#include <linux/irqdomain.h>
#include <linux/clk.h>
#include <linux/err.h>
#include <linux/platform_device.h>
@ -64,10 +65,8 @@ struct u300_gpio {
struct gpio_chip chip;
struct list_head port_list;
struct clk *clk;
struct resource *memres;
void __iomem *base;
struct device *dev;
int irq_base;
u32 stride;
/* Register offsets */
u32 pcr;
@ -83,6 +82,7 @@ struct u300_gpio_port {
struct list_head node;
struct u300_gpio *gpio;
char name[8];
struct irq_domain *domain;
int irq;
int number;
u8 toggle_edge_mode;
@ -314,10 +314,30 @@ static int u300_gpio_direction_output(struct gpio_chip *chip, unsigned offset,
static int u300_gpio_to_irq(struct gpio_chip *chip, unsigned offset)
{
struct u300_gpio *gpio = to_u300_gpio(chip);
int retirq = gpio->irq_base + offset;
int portno = offset >> 3;
struct u300_gpio_port *port = NULL;
struct list_head *p;
int retirq;
dev_dbg(gpio->dev, "request IRQ for GPIO %d, return %d\n", offset,
retirq);
list_for_each(p, &gpio->port_list) {
port = list_entry(p, struct u300_gpio_port, node);
if (port->number == portno)
break;
}
if (port == NULL) {
dev_err(gpio->dev, "could not locate port for GPIO %d IRQ\n",
offset);
return -EINVAL;
}
/*
* The local hwirqs on the port are the lower three bits, there
* are exactly 8 IRQs per port since they are 8-bit
*/
retirq = irq_find_mapping(port->domain, (offset & 0x7));
dev_dbg(gpio->dev, "request IRQ for GPIO %d, return %d from port %d\n",
offset, retirq, port->number);
return retirq;
}
@ -467,7 +487,7 @@ static int u300_gpio_irq_type(struct irq_data *d, unsigned trigger)
{
struct u300_gpio_port *port = irq_data_get_irq_chip_data(d);
struct u300_gpio *gpio = port->gpio;
int offset = d->irq - gpio->irq_base;
int offset = (port->number << 3) + d->hwirq;
u32 val;
if ((trigger & IRQF_TRIGGER_RISING) &&
@ -503,10 +523,12 @@ static void u300_gpio_irq_enable(struct irq_data *d)
{
struct u300_gpio_port *port = irq_data_get_irq_chip_data(d);
struct u300_gpio *gpio = port->gpio;
int offset = d->irq - gpio->irq_base;
int offset = (port->number << 3) + d->hwirq;
u32 val;
unsigned long flags;
dev_dbg(gpio->dev, "enable IRQ for hwirq %lu on port %s, offset %d\n",
d->hwirq, port->name, offset);
local_irq_save(flags);
val = readl(U300_PIN_REG(offset, ien));
writel(val | U300_PIN_BIT(offset), U300_PIN_REG(offset, ien));
@ -517,7 +539,7 @@ static void u300_gpio_irq_disable(struct irq_data *d)
{
struct u300_gpio_port *port = irq_data_get_irq_chip_data(d);
struct u300_gpio *gpio = port->gpio;
int offset = d->irq - gpio->irq_base;
int offset = (port->number << 3) + d->hwirq;
u32 val;
unsigned long flags;
@ -555,8 +577,7 @@ static void u300_gpio_irq_handler(unsigned irq, struct irq_desc *desc)
int irqoffset;
for_each_set_bit(irqoffset, &val, U300_GPIO_PINS_PER_PORT) {
int pin_irq = gpio->irq_base + (port->number << 3)
+ irqoffset;
int pin_irq = irq_find_mapping(port->domain, irqoffset);
int offset = pinoffset + irqoffset;
dev_dbg(gpio->dev, "GPIO IRQ %d on pin %d\n",
@ -631,6 +652,8 @@ static inline void u300_gpio_free_ports(struct u300_gpio *gpio)
list_for_each_safe(p, n, &gpio->port_list) {
port = list_entry(p, struct u300_gpio_port, node);
list_del(&port->node);
if (port->domain)
irq_domain_remove(port->domain);
kfree(port);
}
}
@ -639,56 +662,46 @@ static int __init u300_gpio_probe(struct platform_device *pdev)
{
struct u300_gpio_platform *plat = dev_get_platdata(&pdev->dev);
struct u300_gpio *gpio;
struct resource *memres;
int err = 0;
int portno;
u32 val;
u32 ifr;
int i;
gpio = kzalloc(sizeof(struct u300_gpio), GFP_KERNEL);
if (gpio == NULL) {
dev_err(&pdev->dev, "failed to allocate memory\n");
gpio = devm_kzalloc(&pdev->dev, sizeof(struct u300_gpio), GFP_KERNEL);
if (gpio == NULL)
return -ENOMEM;
}
gpio->chip = u300_gpio_chip;
gpio->chip.ngpio = plat->ports * U300_GPIO_PINS_PER_PORT;
gpio->irq_base = plat->gpio_irq_base;
gpio->chip.dev = &pdev->dev;
gpio->chip.base = plat->gpio_base;
gpio->dev = &pdev->dev;
/* Get GPIO clock */
gpio->clk = clk_get(gpio->dev, NULL);
memres = platform_get_resource(pdev, IORESOURCE_MEM, 0);
if (!memres) {
dev_err(gpio->dev, "could not get GPIO memory resource\n");
return -ENODEV;
}
gpio->base = devm_request_and_ioremap(&pdev->dev, memres);
if (!gpio->base) {
dev_err(gpio->dev, "could not get remap memory\n");
return -ENOMEM;
}
gpio->clk = devm_clk_get(gpio->dev, NULL);
if (IS_ERR(gpio->clk)) {
err = PTR_ERR(gpio->clk);
dev_err(gpio->dev, "could not get GPIO clock\n");
goto err_no_clk;
return err;
}
err = clk_prepare_enable(gpio->clk);
if (err) {
dev_err(gpio->dev, "could not enable GPIO clock\n");
goto err_no_clk_enable;
}
gpio->memres = platform_get_resource(pdev, IORESOURCE_MEM, 0);
if (!gpio->memres) {
dev_err(gpio->dev, "could not get GPIO memory resource\n");
err = -ENODEV;
goto err_no_resource;
}
if (!request_mem_region(gpio->memres->start,
resource_size(gpio->memres),
"GPIO Controller")) {
err = -ENODEV;
goto err_no_ioregion;
}
gpio->base = ioremap(gpio->memres->start, resource_size(gpio->memres));
if (!gpio->base) {
err = -ENOMEM;
goto err_no_ioremap;
return err;
}
dev_info(gpio->dev,
@ -732,18 +745,26 @@ static int __init u300_gpio_probe(struct platform_device *pdev)
port->irq = platform_get_irq_byname(pdev,
port->name);
dev_dbg(gpio->dev, "register IRQ %d for %s\n", port->irq,
dev_dbg(gpio->dev, "register IRQ %d for port %s\n", port->irq,
port->name);
port->domain = irq_domain_add_linear(pdev->dev.of_node,
U300_GPIO_PINS_PER_PORT,
&irq_domain_simple_ops,
port);
if (!port->domain)
goto err_no_domain;
irq_set_chained_handler(port->irq, u300_gpio_irq_handler);
irq_set_handler_data(port->irq, port);
/* For each GPIO pin set the unique IRQ handler */
for (i = 0; i < U300_GPIO_PINS_PER_PORT; i++) {
int irqno = gpio->irq_base + (portno << 3) + i;
int irqno = irq_create_mapping(port->domain, i);
dev_dbg(gpio->dev, "handler for IRQ %d on %s\n",
irqno, port->name);
dev_dbg(gpio->dev, "GPIO%d on port %s gets IRQ %d\n",
gpio->chip.base + (port->number << 3) + i,
port->name, irqno);
irq_set_chip_and_handler(irqno, &u300_gpio_irqchip,
handle_simple_irq);
set_irq_flags(irqno, IRQF_VALID);
@ -776,18 +797,10 @@ static int __init u300_gpio_probe(struct platform_device *pdev)
err_no_pinctrl:
err = gpiochip_remove(&gpio->chip);
err_no_chip:
err_no_domain:
err_no_port:
u300_gpio_free_ports(gpio);
iounmap(gpio->base);
err_no_ioremap:
release_mem_region(gpio->memres->start, resource_size(gpio->memres));
err_no_ioregion:
err_no_resource:
clk_disable_unprepare(gpio->clk);
err_no_clk_enable:
clk_put(gpio->clk);
err_no_clk:
kfree(gpio);
dev_info(&pdev->dev, "module ERROR:%d\n", err);
return err;
}
@ -806,13 +819,8 @@ static int __exit u300_gpio_remove(struct platform_device *pdev)
return err;
}
u300_gpio_free_ports(gpio);
iounmap(gpio->base);
release_mem_region(gpio->memres->start,
resource_size(gpio->memres));
clk_disable_unprepare(gpio->clk);
clk_put(gpio->clk);
platform_set_drvdata(pdev, NULL);
kfree(gpio);
return 0;
}

View File

@ -36,6 +36,7 @@
/* list of external wakeup controllers supported */
static const struct of_device_id exynos_wkup_irq_ids[] = {
{ .compatible = "samsung,exynos4210-wakeup-eint", },
{ }
};
static void exynos_gpio_irq_unmask(struct irq_data *irqd)

View File

@ -32,10 +32,10 @@
#define SIRFSOC_NUM_PADS 622
#define SIRFSOC_RSC_PIN_MUX 0x4
#define SIRFSOC_GPIO_PAD_EN(g) ((g)*0x100 + 0x84)
#define SIRFSOC_GPIO_PAD_EN(g) ((g)*0x100 + 0x84)
#define SIRFSOC_GPIO_PAD_EN_CLR(g) ((g)*0x100 + 0x90)
#define SIRFSOC_GPIO_CTRL(g, i) ((g)*0x100 + (i)*4)
#define SIRFSOC_GPIO_DSP_EN0 (0x80)
#define SIRFSOC_GPIO_PAD_EN(g) ((g)*0x100 + 0x84)
#define SIRFSOC_GPIO_INT_STATUS(g) ((g)*0x100 + 0x8C)
#define SIRFSOC_GPIO_CTL_INTR_LOW_MASK 0x1
@ -60,6 +60,7 @@ struct sirfsoc_gpio_bank {
int id;
int parent_irq;
spinlock_t lock;
bool is_marco; /* for marco, some registers are different with prima2 */
};
static struct sirfsoc_gpio_bank sgpio_bank[SIRFSOC_GPIO_NO_OF_BANKS];
@ -191,6 +192,7 @@ struct sirfsoc_pmx {
struct pinctrl_dev *pmx;
void __iomem *gpio_virtbase;
void __iomem *rsc_virtbase;
bool is_marco;
};
/* SIRFSOC_GPIO_PAD_EN set */
@ -1088,12 +1090,21 @@ static void sirfsoc_pinmux_endisable(struct sirfsoc_pmx *spmx, unsigned selector
for (i = 0; i < mux->muxmask_counts; i++) {
u32 muxval;
muxval = readl(spmx->gpio_virtbase + SIRFSOC_GPIO_PAD_EN(mask[i].group));
if (enable)
muxval = muxval & ~mask[i].mask;
else
muxval = muxval | mask[i].mask;
writel(muxval, spmx->gpio_virtbase + SIRFSOC_GPIO_PAD_EN(mask[i].group));
if (!spmx->is_marco) {
muxval = readl(spmx->gpio_virtbase + SIRFSOC_GPIO_PAD_EN(mask[i].group));
if (enable)
muxval = muxval & ~mask[i].mask;
else
muxval = muxval | mask[i].mask;
writel(muxval, spmx->gpio_virtbase + SIRFSOC_GPIO_PAD_EN(mask[i].group));
} else {
if (enable)
writel(mask[i].mask, spmx->gpio_virtbase +
SIRFSOC_GPIO_PAD_EN_CLR(mask[i].group));
else
writel(mask[i].mask, spmx->gpio_virtbase +
SIRFSOC_GPIO_PAD_EN(mask[i].group));
}
}
if (mux->funcmask && enable) {
@ -1158,9 +1169,14 @@ static int sirfsoc_pinmux_request_gpio(struct pinctrl_dev *pmxdev,
spmx = pinctrl_dev_get_drvdata(pmxdev);
muxval = readl(spmx->gpio_virtbase + SIRFSOC_GPIO_PAD_EN(group));
muxval = muxval | (1 << (offset - range->pin_base));
writel(muxval, spmx->gpio_virtbase + SIRFSOC_GPIO_PAD_EN(group));
if (!spmx->is_marco) {
muxval = readl(spmx->gpio_virtbase + SIRFSOC_GPIO_PAD_EN(group));
muxval = muxval | (1 << (offset - range->pin_base));
writel(muxval, spmx->gpio_virtbase + SIRFSOC_GPIO_PAD_EN(group));
} else {
writel(1 << (offset - range->pin_base), spmx->gpio_virtbase +
SIRFSOC_GPIO_PAD_EN(group));
}
return 0;
}
@ -1218,6 +1234,7 @@ static void __iomem *sirfsoc_rsc_of_iomap(void)
{
const struct of_device_id rsc_ids[] = {
{ .compatible = "sirf,prima2-rsc" },
{ .compatible = "sirf,marco-rsc" },
{}
};
struct device_node *np;
@ -1259,6 +1276,9 @@ static int __devinit sirfsoc_pinmux_probe(struct platform_device *pdev)
goto out_no_rsc_remap;
}
if (of_device_is_compatible(np, "sirf,marco-pinctrl"))
spmx->is_marco = 1;
/* Now register the pin controller and all pins it handles */
spmx->pmx = pinctrl_register(&sirfsoc_pinmux_desc, &pdev->dev, spmx);
if (!spmx->pmx) {
@ -1287,6 +1307,7 @@ out_no_gpio_remap:
static const struct of_device_id pinmux_ids[] __devinitconst = {
{ .compatible = "sirf,prima2-pinctrl" },
{ .compatible = "sirf,marco-pinctrl" },
{}
};
@ -1621,8 +1642,8 @@ static void sirfsoc_gpio_set_value(struct gpio_chip *chip, unsigned offset,
spin_unlock_irqrestore(&bank->lock, flags);
}
int sirfsoc_gpio_irq_map(struct irq_domain *d, unsigned int irq,
irq_hw_number_t hwirq)
static int sirfsoc_gpio_irq_map(struct irq_domain *d, unsigned int irq,
irq_hw_number_t hwirq)
{
struct sirfsoc_gpio_bank *bank = d->host_data;
@ -1648,6 +1669,7 @@ static int __devinit sirfsoc_gpio_probe(struct device_node *np)
struct sirfsoc_gpio_bank *bank;
void *regs;
struct platform_device *pdev;
bool is_marco = false;
pdev = of_find_device_by_node(np);
if (!pdev)
@ -1657,6 +1679,9 @@ static int __devinit sirfsoc_gpio_probe(struct device_node *np)
if (!regs)
return -ENOMEM;
if (of_device_is_compatible(np, "sirf,marco-pinctrl"))
is_marco = 1;
for (i = 0; i < SIRFSOC_GPIO_NO_OF_BANKS; i++) {
bank = &sgpio_bank[i];
spin_lock_init(&bank->lock);
@ -1673,6 +1698,7 @@ static int __devinit sirfsoc_gpio_probe(struct device_node *np)
bank->chip.gc.of_node = np;
bank->chip.regs = regs;
bank->id = i;
bank->is_marco = is_marco;
bank->parent_irq = platform_get_irq(pdev, i);
if (bank->parent_irq < 0) {
err = bank->parent_irq;

View File

@ -663,8 +663,6 @@ static const struct pinctrl_pin_desc u300_pads[] = {
struct u300_pmx {
struct device *dev;
struct pinctrl_dev *pctl;
u32 phybase;
u32 physize;
void __iomem *virtbase;
};
@ -1054,9 +1052,8 @@ static struct pinctrl_gpio_range *u300_match_gpio_range(unsigned pin)
return NULL;
}
int u300_pin_config_get(struct pinctrl_dev *pctldev,
unsigned pin,
unsigned long *config)
static int u300_pin_config_get(struct pinctrl_dev *pctldev, unsigned pin,
unsigned long *config)
{
struct pinctrl_gpio_range *range = u300_match_gpio_range(pin);
@ -1069,9 +1066,8 @@ int u300_pin_config_get(struct pinctrl_dev *pctldev,
config);
}
int u300_pin_config_set(struct pinctrl_dev *pctldev,
unsigned pin,
unsigned long config)
static int u300_pin_config_set(struct pinctrl_dev *pctldev, unsigned pin,
unsigned long config)
{
struct pinctrl_gpio_range *range = u300_match_gpio_range(pin);
int ret;
@ -1110,7 +1106,6 @@ static int __devinit u300_pmx_probe(struct platform_device *pdev)
struct u300_pmx *upmx;
struct resource *res;
struct gpio_chip *gpio_chip = dev_get_platdata(&pdev->dev);
int ret;
int i;
/* Create state holders etc for this driver */
@ -1123,26 +1118,15 @@ static int __devinit u300_pmx_probe(struct platform_device *pdev)
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
if (!res)
return -ENOENT;
upmx->phybase = res->start;
upmx->physize = resource_size(res);
if (request_mem_region(upmx->phybase, upmx->physize,
DRIVER_NAME) == NULL) {
ret = -ENOMEM;
goto out_no_memregion;
}
upmx->virtbase = ioremap(upmx->phybase, upmx->physize);
if (!upmx->virtbase) {
ret = -ENOMEM;
goto out_no_remap;
}
upmx->virtbase = devm_request_and_ioremap(&pdev->dev, res);
if (!upmx->virtbase)
return -ENOMEM;
upmx->pctl = pinctrl_register(&u300_pmx_desc, &pdev->dev, upmx);
if (!upmx->pctl) {
dev_err(&pdev->dev, "could not register U300 pinmux driver\n");
ret = -EINVAL;
goto out_no_pmx;
return -EINVAL;
}
/* We will handle a range of GPIO pins */
@ -1156,14 +1140,6 @@ static int __devinit u300_pmx_probe(struct platform_device *pdev)
dev_info(&pdev->dev, "initialized U300 pin control driver\n");
return 0;
out_no_pmx:
iounmap(upmx->virtbase);
out_no_remap:
platform_set_drvdata(pdev, NULL);
out_no_memregion:
release_mem_region(upmx->phybase, upmx->physize);
return ret;
}
static int __devexit u300_pmx_remove(struct platform_device *pdev)
@ -1171,8 +1147,6 @@ static int __devexit u300_pmx_remove(struct platform_device *pdev)
struct u300_pmx *upmx = platform_get_drvdata(pdev);
pinctrl_unregister(upmx->pctl);
iounmap(upmx->virtbase);
release_mem_region(upmx->phybase, upmx->physize);
platform_set_drvdata(pdev, NULL);
return 0;

View File

@ -314,14 +314,11 @@ int pinmux_map_to_setting(struct pinctrl_map const *map,
{
struct pinctrl_dev *pctldev = setting->pctldev;
const struct pinmux_ops *pmxops = pctldev->desc->pmxops;
const struct pinctrl_ops *pctlops = pctldev->desc->pctlops;
char const * const *groups;
unsigned num_groups;
int ret;
const char *group;
int i;
const unsigned *pins;
unsigned num_pins;
if (!pmxops) {
dev_err(pctldev->dev, "does not support mux function\n");
@ -376,53 +373,12 @@ int pinmux_map_to_setting(struct pinctrl_map const *map,
}
setting->data.mux.group = ret;
ret = pctlops->get_group_pins(pctldev, setting->data.mux.group, &pins,
&num_pins);
if (ret) {
dev_err(pctldev->dev,
"could not get pins for device %s group selector %d\n",
pinctrl_dev_get_name(pctldev), setting->data.mux.group);
return -ENODEV;
}
/* Try to allocate all pins in this group, one by one */
for (i = 0; i < num_pins; i++) {
ret = pin_request(pctldev, pins[i], map->dev_name, NULL);
if (ret) {
dev_err(pctldev->dev,
"could not request pin %d on device %s\n",
pins[i], pinctrl_dev_get_name(pctldev));
/* On error release all taken pins */
i--; /* this pin just failed */
for (; i >= 0; i--)
pin_free(pctldev, pins[i], NULL);
return -ENODEV;
}
}
return 0;
}
void pinmux_free_setting(struct pinctrl_setting const *setting)
{
struct pinctrl_dev *pctldev = setting->pctldev;
const struct pinctrl_ops *pctlops = pctldev->desc->pctlops;
const unsigned *pins;
unsigned num_pins;
int ret;
int i;
ret = pctlops->get_group_pins(pctldev, setting->data.mux.group,
&pins, &num_pins);
if (ret) {
dev_err(pctldev->dev,
"could not get pins for device %s group selector %d\n",
pinctrl_dev_get_name(pctldev), setting->data.mux.group);
return;
}
for (i = 0; i < num_pins; i++)
pin_free(pctldev, pins[i], NULL);
/* This function is currently unused */
}
int pinmux_enable_setting(struct pinctrl_setting const *setting)
@ -446,6 +402,22 @@ int pinmux_enable_setting(struct pinctrl_setting const *setting)
num_pins = 0;
}
/* Try to allocate all pins in this group, one by one */
for (i = 0; i < num_pins; i++) {
ret = pin_request(pctldev, pins[i], setting->dev_name, NULL);
if (ret) {
dev_err(pctldev->dev,
"could not request pin %d on device %s\n",
pins[i], pinctrl_dev_get_name(pctldev));
/* On error release all taken pins */
i--; /* this pin just failed */
for (; i >= 0; i--)
pin_free(pctldev, pins[i], NULL);
return -ENODEV;
}
}
/* Now that we have acquired the pins, encode the mux setting */
for (i = 0; i < num_pins; i++) {
desc = pin_desc_get(pctldev, pins[i]);
if (desc == NULL) {
@ -482,6 +454,7 @@ void pinmux_disable_setting(struct pinctrl_setting const *setting)
num_pins = 0;
}
/* Flag the descs that no setting is active */
for (i = 0; i < num_pins; i++) {
desc = pin_desc_get(pctldev, pins[i]);
if (desc == NULL) {
@ -493,6 +466,10 @@ void pinmux_disable_setting(struct pinctrl_setting const *setting)
desc->mux_setting = NULL;
}
/* And release the pins */
for (i = 0; i < num_pins; i++)
pin_free(pctldev, pins[i], NULL);
if (ops->disable)
ops->disable(pctldev, setting->data.mux.func, setting->data.mux.group);
}

View File

@ -25,20 +25,31 @@ 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
help
Say yes here to support PLGPIO controller on ST Microelectronics SPEAr
SoCs.
endif

View File

@ -1,5 +1,6 @@
# 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

View File

@ -0,0 +1,746 @@
/*
* 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.h>
#include <linux/io.h>
#include <linux/irq.h>
#include <linux/irqdomain.h>
#include <linux/module.h>
#include <linux/pinctrl/consumer.h>
#include <linux/platform_device.h>
#include <linux/pm.h>
#include <linux/spinlock.h>
#include <asm/mach/irq.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
* irq_base: irq number of plgpio0
* 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;
unsigned irq_base;
struct irq_domain *irq_domain;
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
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_prepare_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:
clk_disable_unprepare(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_unprepare(plgpio->clk);
pinctrl_free_gpio(gpio);
}
static int plgpio_to_irq(struct gpio_chip *chip, unsigned offset)
{
struct plgpio *plgpio = container_of(chip, struct plgpio, chip);
if (plgpio->irq_base < 0)
return -EINVAL;
return irq_find_mapping(plgpio->irq_domain, offset);
}
/* PLGPIO IRQ */
static void plgpio_irq_disable(struct irq_data *d)
{
struct plgpio *plgpio = irq_data_get_irq_chip_data(d);
int offset = d->irq - plgpio->irq_base;
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 plgpio *plgpio = irq_data_get_irq_chip_data(d);
int offset = d->irq - plgpio->irq_base;
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 plgpio *plgpio = irq_data_get_irq_chip_data(d);
int offset = d->irq - plgpio->irq_base;
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 plgpio *plgpio = irq_get_handler_data(irq);
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(plgpio_to_irq(&plgpio->chip, 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;
}
int spear310_o2p(int offset)
{
if (offset <= 3)
return 101 - offset;
else if (offset <= 31)
return offset - 4;
else
return offset + 2;
}
static int __devinit 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 __devinit plgpio_probe(struct platform_device *pdev)
{
struct device_node *np = pdev->dev.of_node;
struct plgpio *plgpio;
struct resource *res;
int ret, irq, i;
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
if (!res) {
dev_err(&pdev->dev, "invalid IORESOURCE_MEM\n");
return -EBUSY;
}
plgpio = devm_kzalloc(&pdev->dev, sizeof(*plgpio), GFP_KERNEL);
if (!plgpio) {
dev_err(&pdev->dev, "memory allocation fail\n");
return -ENOMEM;
}
plgpio->base = devm_request_and_ioremap(&pdev->dev, res);
if (!plgpio->base) {
dev_err(&pdev->dev, "request and ioremap fail\n");
return -ENOMEM;
}
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
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->irq_base = -1;
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.to_irq = plgpio_to_irq;
plgpio->chip.label = dev_name(&pdev->dev);
plgpio->chip.dev = &pdev->dev;
plgpio->chip.owner = THIS_MODULE;
ret = gpiochip_add(&plgpio->chip);
if (ret) {
dev_err(&pdev->dev, "unable to add gpio chip\n");
return ret;
}
irq = platform_get_irq(pdev, 0);
if (irq < 0) {
dev_info(&pdev->dev, "irqs not supported\n");
return 0;
}
plgpio->irq_base = irq_alloc_descs(-1, 0, plgpio->chip.ngpio, 0);
if (IS_ERR_VALUE(plgpio->irq_base)) {
/* we would not support irq for gpio */
dev_warn(&pdev->dev, "couldn't allocate irq base\n");
return 0;
}
plgpio->irq_domain = irq_domain_add_legacy(np, plgpio->chip.ngpio,
plgpio->irq_base, 0, &irq_domain_simple_ops, NULL);
if (WARN_ON(!plgpio->irq_domain)) {
dev_err(&pdev->dev, "irq domain init failed\n");
irq_free_descs(plgpio->irq_base, plgpio->chip.ngpio);
ret = -ENXIO;
goto remove_gpiochip;
}
irq_set_chained_handler(irq, plgpio_irq_handler);
for (i = 0; i < plgpio->chip.ngpio; i++) {
irq_set_chip_and_handler(i + plgpio->irq_base, &plgpio_irqchip,
handle_simple_irq);
set_irq_flags(i + plgpio->irq_base, IRQF_VALID);
irq_set_chip_data(i + plgpio->irq_base, plgpio);
}
irq_set_handler_data(irq, plgpio);
dev_info(&pdev->dev, "PLGPIO registered with IRQs\n");
return 0;
remove_gpiochip:
dev_info(&pdev->dev, "Remove gpiochip\n");
if (gpiochip_remove(&plgpio->chip))
dev_err(&pdev->dev, "unable to remove gpiochip\n");
return ret;
}
#ifdef CONFIG_PM
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 = of_match_ptr(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");

View File

@ -18,6 +18,7 @@
#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>
@ -38,6 +39,28 @@ static inline void pmx_writel(struct spear_pmx *pmx, u32 val, u32 reg)
writel_relaxed(val, pmx->vbase + reg);
}
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;
@ -70,6 +93,17 @@ static int set_mode(struct spear_pmx *pmx, int mode)
return 0;
}
void __devinit
pmx_init_gpio_pingroup_addr(struct spear_gpio_pingroup *gpio_pingroup,
unsigned count, u16 reg)
{
int i = 0, j = 0;
for (; i < count; i++)
for (; j < gpio_pingroup[i].nmuxregs; j++)
gpio_pingroup[i].muxregs[j].reg = reg;
}
void __devinit pmx_init_addr(struct spear_pinctrl_machdata *machdata, u16 reg)
{
struct spear_pingroup *pgroup;
@ -216,9 +250,7 @@ static int spear_pinctrl_endisable(struct pinctrl_dev *pctldev,
struct spear_pmx *pmx = pinctrl_dev_get_drvdata(pctldev);
const struct spear_pingroup *pgroup;
const struct spear_modemux *modemux;
struct spear_muxreg *muxreg;
u32 val, temp;
int i, j;
int i;
bool found = false;
pgroup = pmx->machdata->groups[group];
@ -233,20 +265,8 @@ static int spear_pinctrl_endisable(struct pinctrl_dev *pctldev,
}
found = true;
for (j = 0; j < modemux->nmuxregs; j++) {
muxreg = &modemux->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);
}
muxregs_endisable(pmx, modemux->muxregs, modemux->nmuxregs,
enable);
}
if (!found) {
@ -270,12 +290,65 @@ static void spear_pinctrl_disable(struct pinctrl_dev *pctldev,
spear_pinctrl_endisable(pctldev, function, group, false);
}
/* 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 = 0, j;
if (!pmx->machdata->gpio_pingroups)
return NULL;
for (; 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 ERR_PTR(-EINVAL);
}
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_gpio_pingroup *gpio_pingroup;
gpio_pingroup = get_gpio_pingroup(pmx, offset);
if (IS_ERR(gpio_pingroup))
return PTR_ERR(gpio_pingroup);
if (gpio_pingroup)
muxregs_endisable(pmx, gpio_pingroup->muxregs,
gpio_pingroup->nmuxregs, 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 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,
.enable = spear_pinctrl_enable,
.disable = spear_pinctrl_disable,
.gpio_request_enable = gpio_request_enable,
.gpio_disable_free = gpio_disable_free,
};
static struct pinctrl_desc spear_pinctrl_desc = {

View File

@ -12,6 +12,7 @@
#ifndef __PINMUX_SPEAR_H__
#define __PINMUX_SPEAR_H__
#include <linux/gpio.h>
#include <linux/pinctrl/pinctrl.h>
#include <linux/types.h>
@ -46,6 +47,44 @@ struct spear_muxreg {
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
@ -100,6 +139,8 @@ struct spear_function {
* @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
@ -113,6 +154,8 @@ struct spear_pinctrl_machdata {
unsigned nfunctions;
struct spear_pingroup **groups;
unsigned ngroups;
struct spear_gpio_pingroup *gpio_pingroups;
unsigned ngpio_pingroups;
bool modes_supported;
u16 mode;
@ -136,6 +179,9 @@ struct spear_pmx {
/* exported routines */
void __devinit pmx_init_addr(struct spear_pinctrl_machdata *machdata, u16 reg);
void __devinit
pmx_init_gpio_pingroup_addr(struct spear_gpio_pingroup *gpio_pingroup,
unsigned count, u16 reg);
int __devinit spear_pinctrl_probe(struct platform_device *pdev,
struct spear_pinctrl_machdata *machdata);
int __devexit spear_pinctrl_remove(struct platform_device *pdev);

View File

@ -2418,6 +2418,268 @@ static struct spear_function *spear1310_functions[] = {
&gpt64_function,
};
static const unsigned pin18[] = { 18, };
static const unsigned pin19[] = { 19, };
static const unsigned pin20[] = { 20, };
static const unsigned pin21[] = { 21, };
static const unsigned pin22[] = { 22, };
static const unsigned pin23[] = { 23, };
static const unsigned pin54[] = { 54, };
static const unsigned pin55[] = { 55, };
static const unsigned pin56[] = { 56, };
static const unsigned pin57[] = { 57, };
static const unsigned pin58[] = { 58, };
static const unsigned pin59[] = { 59, };
static const unsigned pin60[] = { 60, };
static const unsigned pin61[] = { 61, };
static const unsigned pin62[] = { 62, };
static const unsigned pin63[] = { 63, };
static const unsigned pin143[] = { 143, };
static const unsigned pin144[] = { 144, };
static const unsigned pin145[] = { 145, };
static const unsigned pin146[] = { 146, };
static const unsigned pin147[] = { 147, };
static const unsigned pin148[] = { 148, };
static const unsigned pin149[] = { 149, };
static const unsigned pin150[] = { 150, };
static const unsigned pin151[] = { 151, };
static const unsigned pin152[] = { 152, };
static const unsigned pin205[] = { 205, };
static const unsigned pin206[] = { 206, };
static const unsigned pin211[] = { 211, };
static const unsigned pin212[] = { 212, };
static const unsigned pin213[] = { 213, };
static const unsigned pin214[] = { 214, };
static const unsigned pin215[] = { 215, };
static const unsigned pin216[] = { 216, };
static const unsigned pin217[] = { 217, };
static const unsigned pin218[] = { 218, };
static const unsigned pin219[] = { 219, };
static const unsigned pin220[] = { 220, };
static const unsigned pin221[] = { 221, };
static const unsigned pin222[] = { 222, };
static const unsigned pin223[] = { 223, };
static const unsigned pin224[] = { 224, };
static const unsigned pin225[] = { 225, };
static const unsigned pin226[] = { 226, };
static const unsigned pin227[] = { 227, };
static const unsigned pin228[] = { 228, };
static const unsigned pin229[] = { 229, };
static const unsigned pin230[] = { 230, };
static const unsigned pin231[] = { 231, };
static const unsigned pin232[] = { 232, };
static const unsigned pin233[] = { 233, };
static const unsigned pin234[] = { 234, };
static const unsigned pin235[] = { 235, };
static const unsigned pin236[] = { 236, };
static const unsigned pin237[] = { 237, };
static const unsigned pin238[] = { 238, };
static const unsigned pin239[] = { 239, };
static const unsigned pin240[] = { 240, };
static const unsigned pin241[] = { 241, };
static const unsigned pin242[] = { 242, };
static const unsigned pin243[] = { 243, };
static const unsigned pin244[] = { 244, };
static const unsigned pin245[] = { 245, };
static const unsigned pin_grp0[] = { 173, 174, };
static const unsigned pin_grp1[] = { 175, 185, 188, 197, 198, };
static const unsigned pin_grp2[] = { 176, 177, 178, 179, 184, 186, 187, 189,
190, 191, 192, };
static const unsigned pin_grp3[] = { 180, 181, 182, 183, 193, 194, 195, 196, };
static const unsigned pin_grp4[] = { 199, 200, };
static const unsigned pin_grp5[] = { 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74,
75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, };
static const unsigned pin_grp6[] = { 86, 87, 88, 89, 90, 91, 92, 93, };
static const unsigned pin_grp7[] = { 98, 99, };
static const unsigned pin_grp8[] = { 158, 159, 160, 161, 162, 163, 164, 165,
166, 167, 168, 169, 170, 171, 172, };
/* Define muxreg arrays */
DEFINE_2_MUXREG(i2c0_pins, PAD_FUNCTION_EN_0, PAD_DIRECTION_SEL_0, PMX_I2C0_MASK, 0, 1);
DEFINE_2_MUXREG(ssp0_pins, PAD_FUNCTION_EN_0, PAD_DIRECTION_SEL_0, PMX_SSP0_MASK, 0, 1);
DEFINE_2_MUXREG(ssp0_cs0_pins, PAD_FUNCTION_EN_2, PAD_DIRECTION_SEL_2, PMX_SSP0_CS0_MASK, 0, 1);
DEFINE_2_MUXREG(ssp0_cs1_2_pins, PAD_FUNCTION_EN_2, PAD_DIRECTION_SEL_2, PMX_SSP0_CS1_2_MASK, 0, 1);
DEFINE_2_MUXREG(i2s0_pins, PAD_FUNCTION_EN_0, PAD_DIRECTION_SEL_0, PMX_I2S0_MASK, 0, 1);
DEFINE_2_MUXREG(i2s1_pins, PAD_FUNCTION_EN_1, PAD_DIRECTION_SEL_1, PMX_I2S1_MASK, 0, 1);
DEFINE_2_MUXREG(clcd_pins, PAD_FUNCTION_EN_0, PAD_DIRECTION_SEL_0, PMX_CLCD1_MASK, 0, 1);
DEFINE_2_MUXREG(clcd_high_res_pins, PAD_FUNCTION_EN_1, PAD_DIRECTION_SEL_1, PMX_CLCD2_MASK, 0, 1);
DEFINE_2_MUXREG(pin18, PAD_FUNCTION_EN_0, PAD_DIRECTION_SEL_0, PMX_EGPIO15_MASK, 0, 1);
DEFINE_2_MUXREG(pin19, PAD_FUNCTION_EN_0, PAD_DIRECTION_SEL_0, PMX_EGPIO14_MASK, 0, 1);
DEFINE_2_MUXREG(pin20, PAD_FUNCTION_EN_0, PAD_DIRECTION_SEL_0, PMX_EGPIO13_MASK, 0, 1);
DEFINE_2_MUXREG(pin21, PAD_FUNCTION_EN_0, PAD_DIRECTION_SEL_0, PMX_EGPIO12_MASK, 0, 1);
DEFINE_2_MUXREG(pin22, PAD_FUNCTION_EN_0, PAD_DIRECTION_SEL_0, PMX_EGPIO11_MASK, 0, 1);
DEFINE_2_MUXREG(pin23, PAD_FUNCTION_EN_0, PAD_DIRECTION_SEL_0, PMX_EGPIO10_MASK, 0, 1);
DEFINE_2_MUXREG(pin143, PAD_FUNCTION_EN_0, PAD_DIRECTION_SEL_0, PMX_EGPIO00_MASK, 0, 1);
DEFINE_2_MUXREG(pin144, PAD_FUNCTION_EN_0, PAD_DIRECTION_SEL_0, PMX_EGPIO01_MASK, 0, 1);
DEFINE_2_MUXREG(pin145, PAD_FUNCTION_EN_0, PAD_DIRECTION_SEL_0, PMX_EGPIO02_MASK, 0, 1);
DEFINE_2_MUXREG(pin146, PAD_FUNCTION_EN_0, PAD_DIRECTION_SEL_0, PMX_EGPIO03_MASK, 0, 1);
DEFINE_2_MUXREG(pin147, PAD_FUNCTION_EN_0, PAD_DIRECTION_SEL_0, PMX_EGPIO04_MASK, 0, 1);
DEFINE_2_MUXREG(pin148, PAD_FUNCTION_EN_0, PAD_DIRECTION_SEL_0, PMX_EGPIO05_MASK, 0, 1);
DEFINE_2_MUXREG(pin149, PAD_FUNCTION_EN_0, PAD_DIRECTION_SEL_0, PMX_EGPIO06_MASK, 0, 1);
DEFINE_2_MUXREG(pin150, PAD_FUNCTION_EN_0, PAD_DIRECTION_SEL_0, PMX_EGPIO07_MASK, 0, 1);
DEFINE_2_MUXREG(pin151, PAD_FUNCTION_EN_0, PAD_DIRECTION_SEL_0, PMX_EGPIO08_MASK, 0, 1);
DEFINE_2_MUXREG(pin152, PAD_FUNCTION_EN_0, PAD_DIRECTION_SEL_0, PMX_EGPIO09_MASK, 0, 1);
DEFINE_2_MUXREG(smi_2_chips_pins, PAD_FUNCTION_EN_0, PAD_DIRECTION_SEL_0, PMX_SMI_MASK, 0, 1);
DEFINE_2_MUXREG(pin54, PAD_FUNCTION_EN_1, PAD_DIRECTION_SEL_1, PMX_SMINCS3_MASK, 0, 1);
DEFINE_2_MUXREG(pin55, PAD_FUNCTION_EN_1, PAD_DIRECTION_SEL_1, PMX_SMINCS2_MASK, 0, 1);
DEFINE_2_MUXREG(pin56, PAD_FUNCTION_EN_1, PAD_DIRECTION_SEL_1, PMX_NFRSTPWDWN3_MASK, 0, 1);
DEFINE_2_MUXREG(pin57, PAD_FUNCTION_EN_0, PAD_DIRECTION_SEL_0, PMX_NFRSTPWDWN2_MASK, 0, 1);
DEFINE_2_MUXREG(pin58, PAD_FUNCTION_EN_0, PAD_DIRECTION_SEL_0, PMX_NFRSTPWDWN1_MASK, 0, 1);
DEFINE_2_MUXREG(pin59, PAD_FUNCTION_EN_0, PAD_DIRECTION_SEL_0, PMX_NFRSTPWDWN0_MASK, 0, 1);
DEFINE_2_MUXREG(pin60, PAD_FUNCTION_EN_0, PAD_DIRECTION_SEL_0, PMX_NFWPRT3_MASK, 0, 1);
DEFINE_2_MUXREG(pin61, PAD_FUNCTION_EN_0, PAD_DIRECTION_SEL_0, PMX_NFCE3_MASK, 0, 1);
DEFINE_2_MUXREG(pin62, PAD_FUNCTION_EN_0, PAD_DIRECTION_SEL_0, PMX_NFAD25_MASK, 0, 1);
DEFINE_2_MUXREG(pin63, PAD_FUNCTION_EN_0, PAD_DIRECTION_SEL_0, PMX_NFAD24_MASK, 0, 1);
DEFINE_2_MUXREG(pin_grp0, PAD_FUNCTION_EN_0, PAD_DIRECTION_SEL_0, PMX_GMIICLK_MASK, 0, 1);
DEFINE_2_MUXREG(pin_grp1, PAD_FUNCTION_EN_0, PAD_DIRECTION_SEL_0, PMX_GMIICOL_CRS_XFERER_MIITXCLK_MASK, 0, 1);
DEFINE_2_MUXREG(pin_grp2, PAD_FUNCTION_EN_0, PAD_DIRECTION_SEL_0, PMX_RXCLK_RDV_TXEN_D03_MASK, 0, 1);
DEFINE_2_MUXREG(pin_grp3, PAD_FUNCTION_EN_0, PAD_DIRECTION_SEL_0, PMX_GMIID47_MASK, 0, 1);
DEFINE_2_MUXREG(pin_grp4, PAD_FUNCTION_EN_0, PAD_DIRECTION_SEL_0, PMX_MDC_MDIO_MASK, 0, 1);
DEFINE_2_MUXREG(pin_grp5, PAD_FUNCTION_EN_0, PAD_DIRECTION_SEL_0, PMX_NFAD23_MASK, 0, 1);
DEFINE_2_MUXREG(pin_grp6, PAD_FUNCTION_EN_0, PAD_DIRECTION_SEL_0, PMX_MCI_DATA8_15_MASK, 0, 1);
DEFINE_2_MUXREG(pin_grp7, PAD_FUNCTION_EN_1, PAD_DIRECTION_SEL_1, PMX_NFCE2_MASK, 0, 1);
DEFINE_2_MUXREG(pin_grp8, PAD_FUNCTION_EN_1, PAD_DIRECTION_SEL_1, PMX_NAND8_MASK, 0, 1);
DEFINE_2_MUXREG(nand_16bit_pins, PAD_FUNCTION_EN_1, PAD_DIRECTION_SEL_1, PMX_NAND16BIT_1_MASK, 0, 1);
DEFINE_2_MUXREG(pin205, PAD_FUNCTION_EN_1, PAD_DIRECTION_SEL_1, PMX_KBD_COL1_MASK | PMX_NFCE1_MASK, 0, 1);
DEFINE_2_MUXREG(pin206, PAD_FUNCTION_EN_1, PAD_DIRECTION_SEL_1, PMX_KBD_COL0_MASK | PMX_NFCE2_MASK, 0, 1);
DEFINE_2_MUXREG(pin211, PAD_FUNCTION_EN_1, PAD_DIRECTION_SEL_1, PMX_KBD_ROW1_MASK | PMX_NFWPRT1_MASK, 0, 1);
DEFINE_2_MUXREG(pin212, PAD_FUNCTION_EN_1, PAD_DIRECTION_SEL_1, PMX_KBD_ROW0_MASK | PMX_NFWPRT2_MASK, 0, 1);
DEFINE_2_MUXREG(pin213, PAD_FUNCTION_EN_1, PAD_DIRECTION_SEL_1, PMX_MCIDATA0_MASK, 0, 1);
DEFINE_2_MUXREG(pin214, PAD_FUNCTION_EN_1, PAD_DIRECTION_SEL_1, PMX_MCIDATA1_MASK, 0, 1);
DEFINE_2_MUXREG(pin215, PAD_FUNCTION_EN_1, PAD_DIRECTION_SEL_1, PMX_MCIDATA2_MASK, 0, 1);
DEFINE_2_MUXREG(pin216, PAD_FUNCTION_EN_1, PAD_DIRECTION_SEL_1, PMX_MCIDATA3_MASK, 0, 1);
DEFINE_2_MUXREG(pin217, PAD_FUNCTION_EN_1, PAD_DIRECTION_SEL_1, PMX_MCIDATA4_MASK, 0, 1);
DEFINE_2_MUXREG(pin218, PAD_FUNCTION_EN_2, PAD_DIRECTION_SEL_2, PMX_MCIDATA5_MASK, 0, 1);
DEFINE_2_MUXREG(pin219, PAD_FUNCTION_EN_2, PAD_DIRECTION_SEL_2, PMX_MCIDATA6_MASK, 0, 1);
DEFINE_2_MUXREG(pin220, PAD_FUNCTION_EN_2, PAD_DIRECTION_SEL_2, PMX_MCIDATA7_MASK, 0, 1);
DEFINE_2_MUXREG(pin221, PAD_FUNCTION_EN_2, PAD_DIRECTION_SEL_2, PMX_MCIDATA1SD_MASK, 0, 1);
DEFINE_2_MUXREG(pin222, PAD_FUNCTION_EN_2, PAD_DIRECTION_SEL_2, PMX_MCIDATA2SD_MASK, 0, 1);
DEFINE_2_MUXREG(pin223, PAD_FUNCTION_EN_2, PAD_DIRECTION_SEL_2, PMX_MCIDATA3SD_MASK, 0, 1);
DEFINE_2_MUXREG(pin224, PAD_FUNCTION_EN_2, PAD_DIRECTION_SEL_2, PMX_MCIADDR0ALE_MASK, 0, 1);
DEFINE_2_MUXREG(pin225, PAD_FUNCTION_EN_2, PAD_DIRECTION_SEL_2, PMX_MCIADDR1CLECLK_MASK, 0, 1);
DEFINE_2_MUXREG(pin226, PAD_FUNCTION_EN_2, PAD_DIRECTION_SEL_2, PMX_MCIADDR2_MASK, 0, 1);
DEFINE_2_MUXREG(pin227, PAD_FUNCTION_EN_2, PAD_DIRECTION_SEL_2, PMX_MCICECF_MASK, 0, 1);
DEFINE_2_MUXREG(pin228, PAD_FUNCTION_EN_2, PAD_DIRECTION_SEL_2, PMX_MCICEXD_MASK, 0, 1);
DEFINE_2_MUXREG(pin229, PAD_FUNCTION_EN_2, PAD_DIRECTION_SEL_2, PMX_MCICESDMMC_MASK, 0, 1);
DEFINE_2_MUXREG(pin230, PAD_FUNCTION_EN_2, PAD_DIRECTION_SEL_2, PMX_MCICDCF1_MASK, 0, 1);
DEFINE_2_MUXREG(pin231, PAD_FUNCTION_EN_2, PAD_DIRECTION_SEL_2, PMX_MCICDCF2_MASK, 0, 1);
DEFINE_2_MUXREG(pin232, PAD_FUNCTION_EN_2, PAD_DIRECTION_SEL_2, PMX_MCICDXD_MASK, 0, 1);
DEFINE_2_MUXREG(pin233, PAD_FUNCTION_EN_2, PAD_DIRECTION_SEL_2, PMX_MCICDSDMMC_MASK, 0, 1);
DEFINE_2_MUXREG(pin234, PAD_FUNCTION_EN_2, PAD_DIRECTION_SEL_2, PMX_MCIDATADIR_MASK, 0, 1);
DEFINE_2_MUXREG(pin235, PAD_FUNCTION_EN_2, PAD_DIRECTION_SEL_2, PMX_MCIDMARQWP_MASK, 0, 1);
DEFINE_2_MUXREG(pin236, PAD_FUNCTION_EN_2, PAD_DIRECTION_SEL_2, PMX_MCIIORDRE_MASK, 0, 1);
DEFINE_2_MUXREG(pin237, PAD_FUNCTION_EN_2, PAD_DIRECTION_SEL_2, PMX_MCIIOWRWE_MASK, 0, 1);
DEFINE_2_MUXREG(pin238, PAD_FUNCTION_EN_2, PAD_DIRECTION_SEL_2, PMX_MCIRESETCF_MASK, 0, 1);
DEFINE_2_MUXREG(pin239, PAD_FUNCTION_EN_2, PAD_DIRECTION_SEL_2, PMX_MCICS0CE_MASK, 0, 1);
DEFINE_2_MUXREG(pin240, PAD_FUNCTION_EN_2, PAD_DIRECTION_SEL_2, PMX_MCICFINTR_MASK, 0, 1);
DEFINE_2_MUXREG(pin241, PAD_FUNCTION_EN_2, PAD_DIRECTION_SEL_2, PMX_MCIIORDY_MASK, 0, 1);
DEFINE_2_MUXREG(pin242, PAD_FUNCTION_EN_2, PAD_DIRECTION_SEL_2, PMX_MCICS1_MASK, 0, 1);
DEFINE_2_MUXREG(pin243, PAD_FUNCTION_EN_2, PAD_DIRECTION_SEL_2, PMX_MCIDMAACK_MASK, 0, 1);
DEFINE_2_MUXREG(pin244, PAD_FUNCTION_EN_2, PAD_DIRECTION_SEL_2, PMX_MCISDCMD_MASK, 0, 1);
DEFINE_2_MUXREG(pin245, PAD_FUNCTION_EN_2, PAD_DIRECTION_SEL_2, PMX_MCILEDS_MASK, 0, 1);
DEFINE_2_MUXREG(keyboard_rowcol6_8_pins, PAD_FUNCTION_EN_1, PAD_DIRECTION_SEL_1, PMX_KBD_ROWCOL68_MASK, 0, 1);
DEFINE_2_MUXREG(uart0_pins, PAD_FUNCTION_EN_0, PAD_DIRECTION_SEL_0, PMX_UART0_MASK, 0, 1);
DEFINE_2_MUXREG(uart0_modem_pins, PAD_FUNCTION_EN_1, PAD_DIRECTION_SEL_1, PMX_UART0_MODEM_MASK, 0, 1);
DEFINE_2_MUXREG(gpt0_tmr0_pins, PAD_FUNCTION_EN_1, PAD_DIRECTION_SEL_1, PMX_GPT0_TMR0_MASK, 0, 1);
DEFINE_2_MUXREG(gpt0_tmr1_pins, PAD_FUNCTION_EN_1, PAD_DIRECTION_SEL_1, PMX_GPT0_TMR1_MASK, 0, 1);
DEFINE_2_MUXREG(gpt1_tmr0_pins, PAD_FUNCTION_EN_1, PAD_DIRECTION_SEL_1, PMX_GPT1_TMR0_MASK, 0, 1);
DEFINE_2_MUXREG(gpt1_tmr1_pins, PAD_FUNCTION_EN_1, PAD_DIRECTION_SEL_1, PMX_GPT1_TMR1_MASK, 0, 1);
DEFINE_2_MUXREG(touch_xy_pins, PAD_FUNCTION_EN_1, PAD_DIRECTION_SEL_1, PMX_TOUCH_XY_MASK, 0, 1);
static struct spear_gpio_pingroup spear1310_gpio_pingroup[] = {
GPIO_PINGROUP(i2c0_pins),
GPIO_PINGROUP(ssp0_pins),
GPIO_PINGROUP(ssp0_cs0_pins),
GPIO_PINGROUP(ssp0_cs1_2_pins),
GPIO_PINGROUP(i2s0_pins),
GPIO_PINGROUP(i2s1_pins),
GPIO_PINGROUP(clcd_pins),
GPIO_PINGROUP(clcd_high_res_pins),
GPIO_PINGROUP(pin18),
GPIO_PINGROUP(pin19),
GPIO_PINGROUP(pin20),
GPIO_PINGROUP(pin21),
GPIO_PINGROUP(pin22),
GPIO_PINGROUP(pin23),
GPIO_PINGROUP(pin143),
GPIO_PINGROUP(pin144),
GPIO_PINGROUP(pin145),
GPIO_PINGROUP(pin146),
GPIO_PINGROUP(pin147),
GPIO_PINGROUP(pin148),
GPIO_PINGROUP(pin149),
GPIO_PINGROUP(pin150),
GPIO_PINGROUP(pin151),
GPIO_PINGROUP(pin152),
GPIO_PINGROUP(smi_2_chips_pins),
GPIO_PINGROUP(pin54),
GPIO_PINGROUP(pin55),
GPIO_PINGROUP(pin56),
GPIO_PINGROUP(pin57),
GPIO_PINGROUP(pin58),
GPIO_PINGROUP(pin59),
GPIO_PINGROUP(pin60),
GPIO_PINGROUP(pin61),
GPIO_PINGROUP(pin62),
GPIO_PINGROUP(pin63),
GPIO_PINGROUP(pin_grp0),
GPIO_PINGROUP(pin_grp1),
GPIO_PINGROUP(pin_grp2),
GPIO_PINGROUP(pin_grp3),
GPIO_PINGROUP(pin_grp4),
GPIO_PINGROUP(pin_grp5),
GPIO_PINGROUP(pin_grp6),
GPIO_PINGROUP(pin_grp7),
GPIO_PINGROUP(pin_grp8),
GPIO_PINGROUP(nand_16bit_pins),
GPIO_PINGROUP(pin205),
GPIO_PINGROUP(pin206),
GPIO_PINGROUP(pin211),
GPIO_PINGROUP(pin212),
GPIO_PINGROUP(pin213),
GPIO_PINGROUP(pin214),
GPIO_PINGROUP(pin215),
GPIO_PINGROUP(pin216),
GPIO_PINGROUP(pin217),
GPIO_PINGROUP(pin218),
GPIO_PINGROUP(pin219),
GPIO_PINGROUP(pin220),
GPIO_PINGROUP(pin221),
GPIO_PINGROUP(pin222),
GPIO_PINGROUP(pin223),
GPIO_PINGROUP(pin224),
GPIO_PINGROUP(pin225),
GPIO_PINGROUP(pin226),
GPIO_PINGROUP(pin227),
GPIO_PINGROUP(pin228),
GPIO_PINGROUP(pin229),
GPIO_PINGROUP(pin230),
GPIO_PINGROUP(pin231),
GPIO_PINGROUP(pin232),
GPIO_PINGROUP(pin233),
GPIO_PINGROUP(pin234),
GPIO_PINGROUP(pin235),
GPIO_PINGROUP(pin236),
GPIO_PINGROUP(pin237),
GPIO_PINGROUP(pin238),
GPIO_PINGROUP(pin239),
GPIO_PINGROUP(pin240),
GPIO_PINGROUP(pin241),
GPIO_PINGROUP(pin242),
GPIO_PINGROUP(pin243),
GPIO_PINGROUP(pin244),
GPIO_PINGROUP(pin245),
GPIO_PINGROUP(keyboard_rowcol6_8_pins),
GPIO_PINGROUP(uart0_pins),
GPIO_PINGROUP(uart0_modem_pins),
GPIO_PINGROUP(gpt0_tmr0_pins),
GPIO_PINGROUP(gpt0_tmr1_pins),
GPIO_PINGROUP(gpt1_tmr0_pins),
GPIO_PINGROUP(gpt1_tmr1_pins),
GPIO_PINGROUP(touch_xy_pins),
};
static struct spear_pinctrl_machdata spear1310_machdata = {
.pins = spear1310_pins,
.npins = ARRAY_SIZE(spear1310_pins),
@ -2425,6 +2687,8 @@ static struct spear_pinctrl_machdata spear1310_machdata = {
.ngroups = ARRAY_SIZE(spear1310_pingroups),
.functions = spear1310_functions,
.nfunctions = ARRAY_SIZE(spear1310_functions),
.gpio_pingroups = spear1310_gpio_pingroup,
.ngpio_pingroups = ARRAY_SIZE(spear1310_gpio_pingroup),
.modes_supported = false,
};

View File

@ -661,6 +661,8 @@ static int __devinit spear300_pinctrl_probe(struct platform_device *pdev)
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;

View File

@ -388,6 +388,8 @@ static int __devinit spear310_pinctrl_probe(struct platform_device *pdev)
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;

View File

@ -3431,6 +3431,8 @@ static int __devinit spear320_pinctrl_probe(struct platform_device *pdev)
spear3xx_machdata.npmx_modes = ARRAY_SIZE(spear320_pmx_modes);
pmx_init_addr(&spear3xx_machdata, PMX_CONFIG_REG);
pmx_init_gpio_pingroup_addr(spear3xx_machdata.gpio_pingroups,
spear3xx_machdata.ngpio_pingroups, PMX_CONFIG_REG);
ret = spear_pinctrl_probe(pdev, &spear3xx_machdata);
if (ret)

View File

@ -481,7 +481,44 @@ struct spear_function spear3xx_timer_2_3_function = {
.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),
};

View File

@ -5,6 +5,7 @@
#include <linux/types.h>
#include <linux/errno.h>
#include <linux/of.h>
#include <linux/pinctrl/pinctrl.h>
#ifdef CONFIG_GPIOLIB
@ -134,6 +135,15 @@ struct gpio_chip {
int (*of_xlate)(struct gpio_chip *gc,
const struct of_phandle_args *gpiospec, u32 *flags);
#endif
#ifdef CONFIG_PINCTRL
/*
* If CONFIG_PINCTRL is enabled, then gpio controllers can optionally
* describe the actual pin range which they serve in an SoC. This
* information would be used by pinctrl subsystem to configure
* corresponding pins for gpio usage.
*/
struct list_head pin_ranges;
#endif
};
extern const char *gpiochip_is_requested(struct gpio_chip *chip,
@ -257,4 +267,39 @@ static inline void gpio_unexport(unsigned gpio)
}
#endif /* CONFIG_GPIO_SYSFS */
#ifdef CONFIG_PINCTRL
/**
* struct gpio_pin_range - pin range controlled by a gpio chip
* @head: list for maintaining set of pin ranges, used internally
* @pctldev: pinctrl device which handles corresponding pins
* @range: actual range of pins controlled by a gpio controller
*/
struct gpio_pin_range {
struct list_head node;
struct pinctrl_dev *pctldev;
struct pinctrl_gpio_range range;
};
int gpiochip_add_pin_range(struct gpio_chip *chip, const char *pinctl_name,
unsigned int pin_base, unsigned int npins);
void gpiochip_remove_pin_ranges(struct gpio_chip *chip);
#else
static inline int
gpiochip_add_pin_range(struct gpio_chip *chip, const char *pinctl_name,
unsigned int pin_base, unsigned int npins)
{
return 0;
}
static inline void
gpiochip_remove_pin_ranges(struct gpio_chip *chip)
{
}
#endif /* CONFIG_PINCTRL */
#endif /* _ASM_GENERIC_GPIO_H */

View File

@ -72,9 +72,9 @@ static inline int irq_to_gpio(unsigned int irq)
return -EINVAL;
}
#endif
#endif /* ! CONFIG_ARCH_HAVE_CUSTOM_GPIO_H */
#else
#else /* ! CONFIG_GENERIC_GPIO */
#include <linux/kernel.h>
#include <linux/types.h>
@ -231,6 +231,20 @@ static inline int irq_to_gpio(unsigned irq)
return -EINVAL;
}
#endif
static inline int
gpiochip_add_pin_range(struct gpio_chip *chip, const char *pinctl_name,
unsigned int pin_base, unsigned int npins)
{
WARN_ON(1);
return -EINVAL;
}
static inline void
gpiochip_remove_pin_ranges(struct gpio_chip *chip)
{
WARN_ON(1);
}
#endif /* ! CONFIG_GENERIC_GPIO */
#endif /* __LINUX_GPIO_H */

View File

@ -134,6 +134,22 @@ extern void pinctrl_add_gpio_range(struct pinctrl_dev *pctldev,
extern void pinctrl_add_gpio_ranges(struct pinctrl_dev *pctldev,
struct pinctrl_gpio_range *ranges,
unsigned nranges);
extern void pinctrl_remove_gpio_range(struct pinctrl_dev *pctldev,
struct pinctrl_gpio_range *range);
extern struct pinctrl_dev *find_pinctrl_and_add_gpio_range(const char *devname,
struct pinctrl_gpio_range *range);
#ifdef CONFIG_OF
extern struct pinctrl_dev *of_pinctrl_get(struct device_node *np);
#else
static inline
struct pinctrl_dev *of_pinctrl_get(struct device_node *np)
{
return NULL;
}
#endif /* CONFIG_OF */
extern const char *pinctrl_dev_get_name(struct pinctrl_dev *pctldev);
extern void *pinctrl_dev_get_drvdata(struct pinctrl_dev *pctldev);
#else

View File

@ -13,13 +13,11 @@
* struct u300_gpio_platform - U300 GPIO platform data
* @ports: number of GPIO block ports
* @gpio_base: first GPIO number for this block (use a free range)
* @gpio_irq_base: first GPIO IRQ number for this block (use a free range)
* @pinctrl_device: pin control device to spawn as child
*/
struct u300_gpio_platform {
u8 ports;
int gpio_base;
int gpio_irq_base;
struct platform_device *pinctrl_device;
};