Commit 22595e28 authored by Viresh Kumar's avatar Viresh Kumar

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

This merges dependency branch pinctrl/devel for SPEAr DT updates.
parents 9489e9dc 4ddb1c29
...@@ -75,4 +75,40 @@ Example of two SOC GPIO banks defined as gpio-controller nodes: ...@@ -75,4 +75,40 @@ Example of two SOC GPIO banks defined as gpio-controller nodes:
gpio-controller; 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.
...@@ -439,6 +439,48 @@ slower clock delays the rising edge of SCK, and the I2C master adjusts its ...@@ -439,6 +439,48 @@ slower clock delays the rising edge of SCK, and the I2C master adjusts its
signaling rate accordingly. 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? What do these conventions omit?
=============================== ===============================
One of the biggest things these conventions omit is pin multiplexing, since One of the biggest things these conventions omit is pin multiplexing, since
......
...@@ -364,6 +364,9 @@ will get an pin number into its handled number range. Further it is also passed ...@@ -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 the range ID value, so that the pin controller knows which range it should
deal with. 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 PINMUX interfaces
================= =================
...@@ -1193,4 +1196,6 @@ foo_switch() ...@@ -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.
...@@ -181,6 +181,10 @@ gpio1: gpio@e0680000 { ...@@ -181,6 +181,10 @@ gpio1: gpio@e0680000 {
status = "okay"; status = "okay";
}; };
gpio@d8400000 {
status = "okay";
};
i2c0: i2c@e0280000 { i2c0: i2c@e0280000 {
status = "okay"; status = "okay";
}; };
......
...@@ -70,6 +70,12 @@ gmac4: eth@5c700000 { ...@@ -70,6 +70,12 @@ gmac4: eth@5c700000 {
status = "disabled"; status = "disabled";
}; };
pinmux: pinmux@e0700000 {
compatible = "st,spear1310-pinmux";
reg = <0xe0700000 0x1000>;
#gpio-range-cells = <2>;
};
spi1: spi@5d400000 { spi1: spi@5d400000 {
compatible = "arm,pl022", "arm,primecell"; compatible = "arm,pl022", "arm,primecell";
reg = <0x5d400000 0x1000>; reg = <0x5d400000 0x1000>;
...@@ -179,6 +185,27 @@ serial@5cc00000 { ...@@ -179,6 +185,27 @@ serial@5cc00000 {
thermal@e07008c4 { thermal@e07008c4 {
st,thermal-flags = <0x7000>; 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>;
};
}; };
}; };
}; };
...@@ -193,6 +193,10 @@ gpio1: gpio@e0680000 { ...@@ -193,6 +193,10 @@ gpio1: gpio@e0680000 {
status = "okay"; status = "okay";
}; };
gpio@e2800000 {
status = "okay";
};
i2c0: i2c@e0280000 { i2c0: i2c@e0280000 {
status = "okay"; status = "okay";
}; };
......
...@@ -24,6 +24,12 @@ ahci@b1000000 { ...@@ -24,6 +24,12 @@ ahci@b1000000 {
status = "disabled"; status = "disabled";
}; };
pinmux: pinmux@e0700000 {
compatible = "st,spear1340-pinmux";
reg = <0xe0700000 0x1000>;
#gpio-range-cells = <2>;
};
spi1: spi@5d400000 { spi1: spi@5d400000 {
compatible = "arm,pl022", "arm,primecell"; compatible = "arm,pl022", "arm,primecell";
reg = <0x5d400000 0x1000>; reg = <0x5d400000 0x1000>;
...@@ -51,6 +57,26 @@ serial@b4100000 { ...@@ -51,6 +57,26 @@ serial@b4100000 {
thermal@e07008c4 { thermal@e07008c4 {
st,thermal-flags = <0x2a00>; 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>;
};
}; };
}; };
}; };
...@@ -22,9 +22,10 @@ ahb { ...@@ -22,9 +22,10 @@ ahb {
0xb0000000 0xb0000000 0x10000000 0xb0000000 0xb0000000 0x10000000
0xd0000000 0xd0000000 0x30000000>; 0xd0000000 0xd0000000 0x30000000>;
pinmux@b4000000 { pinmux: pinmux@b4000000 {
compatible = "st,spear310-pinmux"; compatible = "st,spear310-pinmux";
reg = <0xb4000000 0x1000>; reg = <0xb4000000 0x1000>;
#gpio-range-cells = <2>;
}; };
fsmc: flash@44000000 { fsmc: flash@44000000 {
...@@ -75,6 +76,25 @@ serial@b2200000 { ...@@ -75,6 +76,25 @@ serial@b2200000 {
reg = <0xb2200000 0x1000>; reg = <0xb2200000 0x1000>;
status = "disabled"; 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>;
};
}; };
}; };
}; };
...@@ -164,6 +164,10 @@ gpio0: gpio@fc980000 { ...@@ -164,6 +164,10 @@ gpio0: gpio@fc980000 {
status = "okay"; status = "okay";
}; };
gpio@b3000000 {
status = "okay";
};
i2c0: i2c@d0180000 { i2c0: i2c@d0180000 {
status = "okay"; status = "okay";
}; };
......
...@@ -21,9 +21,10 @@ ahb { ...@@ -21,9 +21,10 @@ ahb {
ranges = <0x40000000 0x40000000 0x80000000 ranges = <0x40000000 0x40000000 0x80000000
0xd0000000 0xd0000000 0x30000000>; 0xd0000000 0xd0000000 0x30000000>;
pinmux@b3000000 { pinmux: pinmux@b3000000 {
compatible = "st,spear320-pinmux"; compatible = "st,spear320-pinmux";
reg = <0xb3000000 0x1000>; reg = <0xb3000000 0x1000>;
#gpio-range-cells = <2>;
}; };
clcd@90000000 { clcd@90000000 {
...@@ -90,6 +91,26 @@ serial@a4000000 { ...@@ -90,6 +91,26 @@ serial@a4000000 {
reg = <0xa4000000 0x1000>; reg = <0xa4000000 0x1000>;
status = "disabled"; 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>;
};
}; };
}; };
}; };
...@@ -1445,7 +1445,6 @@ static struct platform_device pinctrl_device = { ...@@ -1445,7 +1445,6 @@ static struct platform_device pinctrl_device = {
static struct u300_gpio_platform u300_gpio_plat = { static struct u300_gpio_platform u300_gpio_plat = {
.ports = 7, .ports = 7,
.gpio_base = 0, .gpio_base = 0,
.gpio_irq_base = IRQ_U300_GPIO_BASE,
.pinctrl_device = &pinctrl_device, .pinctrl_device = &pinctrl_device,
}; };
...@@ -1804,7 +1803,7 @@ MACHINE_START(U300, "Ericsson AB U335 S335/B335 Prototype Board") ...@@ -1804,7 +1803,7 @@ MACHINE_START(U300, "Ericsson AB U335 S335/B335 Prototype Board")
/* Maintainer: Linus Walleij <linus.walleij@stericsson.com> */ /* Maintainer: Linus Walleij <linus.walleij@stericsson.com> */
.atag_offset = 0x100, .atag_offset = 0x100,
.map_io = u300_map_io, .map_io = u300_map_io,
.nr_irqs = NR_IRQS_U300, .nr_irqs = 0,
.init_irq = u300_init_irq, .init_irq = u300_init_irq,
.handle_irq = vic_handle_irq, .handle_irq = vic_handle_irq,
.timer = &u300_timer, .timer = &u300_timer,
......
...@@ -12,79 +12,69 @@ ...@@ -12,79 +12,69 @@
#ifndef __MACH_IRQS_H #ifndef __MACH_IRQS_H
#define __MACH_IRQS_H #define __MACH_IRQS_H
#define IRQ_U300_INTCON0_START 1 #define IRQ_U300_INTCON0_START 32
#define IRQ_U300_INTCON1_START 33 #define IRQ_U300_INTCON1_START 64
/* These are on INTCON0 - 30 lines */ /* These are on INTCON0 - 30 lines */
#define IRQ_U300_IRQ0_EXT 1 #define IRQ_U300_IRQ0_EXT 32
#define IRQ_U300_IRQ1_EXT 2 #define IRQ_U300_IRQ1_EXT 33
#define IRQ_U300_DMA 3 #define IRQ_U300_DMA 34
#define IRQ_U300_VIDEO_ENC_0 4 #define IRQ_U300_VIDEO_ENC_0 35
#define IRQ_U300_VIDEO_ENC_1 5 #define IRQ_U300_VIDEO_ENC_1 36
#define IRQ_U300_AAIF_RX 6 #define IRQ_U300_AAIF_RX 37
#define IRQ_U300_AAIF_TX 7 #define IRQ_U300_AAIF_TX 38
#define IRQ_U300_AAIF_VGPIO 8 #define IRQ_U300_AAIF_VGPIO 39
#define IRQ_U300_AAIF_WAKEUP 9 #define IRQ_U300_AAIF_WAKEUP 40
#define IRQ_U300_PCM_I2S0_FRAME 10 #define IRQ_U300_PCM_I2S0_FRAME 41
#define IRQ_U300_PCM_I2S0_FIFO 11 #define IRQ_U300_PCM_I2S0_FIFO 42
#define IRQ_U300_PCM_I2S1_FRAME 12 #define IRQ_U300_PCM_I2S1_FRAME 43
#define IRQ_U300_PCM_I2S1_FIFO 13 #define IRQ_U300_PCM_I2S1_FIFO 44
#define IRQ_U300_XGAM_GAMCON 14 #define IRQ_U300_XGAM_GAMCON 45
#define IRQ_U300_XGAM_CDI 15 #define IRQ_U300_XGAM_CDI 46
#define IRQ_U300_XGAM_CDICON 16 #define IRQ_U300_XGAM_CDICON 47
#define IRQ_U300_XGAM_PDI 18 #define IRQ_U300_XGAM_PDI 49
#define IRQ_U300_XGAM_PDICON 19 #define IRQ_U300_XGAM_PDICON 50
#define IRQ_U300_XGAM_GAMEACC 20 #define IRQ_U300_XGAM_GAMEACC 51
#define IRQ_U300_XGAM_MCIDCT 21 #define IRQ_U300_XGAM_MCIDCT 52
#define IRQ_U300_APEX 22 #define IRQ_U300_APEX 53
#define IRQ_U300_UART0 23 #define IRQ_U300_UART0 54
#define IRQ_U300_SPI 24 #define IRQ_U300_SPI 55
#define IRQ_U300_TIMER_APP_OS 25 #define IRQ_U300_TIMER_APP_OS 56
#define IRQ_U300_TIMER_APP_DD 26 #define IRQ_U300_TIMER_APP_DD 57
#define IRQ_U300_TIMER_APP_GP1 27 #define IRQ_U300_TIMER_APP_GP1 58
#define IRQ_U300_TIMER_APP_GP2 28 #define IRQ_U300_TIMER_APP_GP2 59
#define IRQ_U300_TIMER_OS 29 #define IRQ_U300_TIMER_OS 60
#define IRQ_U300_TIMER_MS 30 #define IRQ_U300_TIMER_MS 61
#define IRQ_U300_KEYPAD_KEYBF 31 #define IRQ_U300_KEYPAD_KEYBF 62
#define IRQ_U300_KEYPAD_KEYBR 32 #define IRQ_U300_KEYPAD_KEYBR 63
/* These are on INTCON1 - 32 lines */ /* These are on INTCON1 - 32 lines */
#define IRQ_U300_GPIO_PORT0 33 #define IRQ_U300_GPIO_PORT0 64
#define IRQ_U300_GPIO_PORT1 34 #define IRQ_U300_GPIO_PORT1 65
#define IRQ_U300_GPIO_PORT2 35 #define IRQ_U300_GPIO_PORT2 66
/* These are for DB3150, DB3200 and DB3350 */ /* These are for DB3150, DB3200 and DB3350 */
#define IRQ_U300_WDOG 36 #define IRQ_U300_WDOG 67
#define IRQ_U300_EVHIST 37 #define IRQ_U300_EVHIST 68
#define IRQ_U300_MSPRO 38 #define IRQ_U300_MSPRO 69
#define IRQ_U300_MMCSD_MCIINTR0 39 #define IRQ_U300_MMCSD_MCIINTR0 70
#define IRQ_U300_MMCSD_MCIINTR1 40 #define IRQ_U300_MMCSD_MCIINTR1 71
#define IRQ_U300_I2C0 41 #define IRQ_U300_I2C0 72
#define IRQ_U300_I2C1 42 #define IRQ_U300_I2C1 73
#define IRQ_U300_RTC 43 #define IRQ_U300_RTC 74
#define IRQ_U300_NFIF 44 #define IRQ_U300_NFIF 75
#define IRQ_U300_NFIF2 45 #define IRQ_U300_NFIF2 76
/* The DB3350-specific interrupt lines */ /* The DB3350-specific interrupt lines */
#define IRQ_U300_ISP_F0 46 #define IRQ_U300_ISP_F0 77
#define IRQ_U300_ISP_F1 47 #define IRQ_U300_ISP_F1 78
#define IRQ_U300_ISP_F2 48 #define IRQ_U300_ISP_F2 79
#define IRQ_U300_ISP_F3 49 #define IRQ_U300_ISP_F3 80
#define IRQ_U300_ISP_F4 50 #define IRQ_U300_ISP_F4 81
#define IRQ_U300_GPIO_PORT3 51 #define IRQ_U300_GPIO_PORT3 82
#define IRQ_U300_SYSCON_PLL_LOCK 52 #define IRQ_U300_SYSCON_PLL_LOCK 83
#define IRQ_U300_UART1 53 #define IRQ_U300_UART1 84
#define IRQ_U300_GPIO_PORT4 54 #define IRQ_U300_GPIO_PORT4 85
#define IRQ_U300_GPIO_PORT5 55 #define IRQ_U300_GPIO_PORT5 86
#define IRQ_U300_GPIO_PORT6 56 #define IRQ_U300_GPIO_PORT6 87
#define U300_VIC_IRQS_END 57 #define U300_VIC_IRQS_END 88
/* 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)
#endif #endif
...@@ -19,6 +19,7 @@ ...@@ -19,6 +19,7 @@
#include <linux/of.h> #include <linux/of.h>
#include <linux/of_address.h> #include <linux/of_address.h>
#include <linux/of_gpio.h> #include <linux/of_gpio.h>
#include <linux/pinctrl/pinctrl.h>
#include <linux/slab.h> #include <linux/slab.h>
/* Private data structure for of_gpiochip_find_and_xlate */ /* Private data structure for of_gpiochip_find_and_xlate */
...@@ -216,6 +217,42 @@ int of_mm_gpiochip_add(struct device_node *np, ...@@ -216,6 +217,42 @@ int of_mm_gpiochip_add(struct device_node *np,
} }
EXPORT_SYMBOL(of_mm_gpiochip_add); 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) void of_gpiochip_add(struct gpio_chip *chip)
{ {
if ((!chip->of_node) && (chip->dev)) if ((!chip->of_node) && (chip->dev))
...@@ -229,11 +266,14 @@ void of_gpiochip_add(struct gpio_chip *chip) ...@@ -229,11 +266,14 @@ void of_gpiochip_add(struct gpio_chip *chip)
chip->of_xlate = of_gpio_simple_xlate; chip->of_xlate = of_gpio_simple_xlate;
} }
of_gpiochip_add_pin_range(chip);
of_node_get(chip->of_node); of_node_get(chip->of_node);
} }
void of_gpiochip_remove(struct gpio_chip *chip) void of_gpiochip_remove(struct gpio_chip *chip)
{ {
gpiochip_remove_pin_ranges(chip);
if (chip->of_node) if (chip->of_node)
of_node_put(chip->of_node); of_node_put(chip->of_node);
} }
...@@ -1083,6 +1083,10 @@ int gpiochip_add(struct gpio_chip *chip) ...@@ -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); of_gpiochip_add(chip);
unlock: unlock:
...@@ -1123,6 +1127,7 @@ int gpiochip_remove(struct gpio_chip *chip) ...@@ -1123,6 +1127,7 @@ int gpiochip_remove(struct gpio_chip *chip)
spin_lock_irqsave(&gpio_lock, flags); spin_lock_irqsave(&gpio_lock, flags);
gpiochip_remove_pin_ranges(chip);
of_gpiochip_remove(chip); of_gpiochip_remove(chip);
for (id = chip->base; id < chip->base + chip->ngpio; id++) { for (id = chip->base; id < chip->base + chip->ngpio; id++) {
...@@ -1180,6 +1185,47 @@ struct gpio_chip *gpiochip_find(void *data, ...@@ -1180,6 +1185,47 @@ struct gpio_chip *gpiochip_find(void *data,
} }
EXPORT_SYMBOL_GPL(gpiochip_find); 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 /* These "optional" allocation calls help prevent drivers from stomping
* on each other, and help provide better diagnostics in debugfs. * on each other, and help provide better diagnostics in debugfs.
* They're called even less than the "set direction" calls. * They're called even less than the "set direction" calls.
......
...@@ -143,8 +143,8 @@ config PINCTRL_SINGLE ...@@ -143,8 +143,8 @@ config PINCTRL_SINGLE
This selects the device tree based generic pinctrl driver. This selects the device tree based generic pinctrl driver.
config PINCTRL_SIRF config PINCTRL_SIRF
bool "CSR SiRFprimaII pin controller driver" bool "CSR SiRFprimaII/SiRFmarco pin controller driver"
depends on ARCH_PRIMA2 depends on ARCH_SIRF
select PINMUX select PINMUX
config PINCTRL_TEGRA config PINCTRL_TEGRA
...@@ -188,27 +188,7 @@ config PINCTRL_EXYNOS4 ...@@ -188,27 +188,7 @@ config PINCTRL_EXYNOS4
depends on OF && GPIOLIB depends on OF && GPIOLIB
select PINCTRL_SAMSUNG select PINCTRL_SAMSUNG
config PINCTRL_MVEBU source "drivers/pinctrl/mvebu/Kconfig"
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/spear/Kconfig" source "drivers/pinctrl/spear/Kconfig"
......
...@@ -36,12 +36,8 @@ obj-$(CONFIG_PINCTRL_U300) += pinctrl-u300.o ...@@ -36,12 +36,8 @@ obj-$(CONFIG_PINCTRL_U300) += pinctrl-u300.o
obj-$(CONFIG_PINCTRL_COH901) += pinctrl-coh901.o obj-$(CONFIG_PINCTRL_COH901) += pinctrl-coh901.o
obj-$(CONFIG_PINCTRL_SAMSUNG) += pinctrl-samsung.o obj-$(CONFIG_PINCTRL_SAMSUNG) += pinctrl-samsung.o
obj-$(CONFIG_PINCTRL_EXYNOS4) += pinctrl-exynos.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_XWAY) += pinctrl-xway.o
obj-$(CONFIG_PINCTRL_LANTIQ) += pinctrl-lantiq.o obj-$(CONFIG_PINCTRL_LANTIQ) += pinctrl-lantiq.o
obj-$(CONFIG_PLAT_ORION) += mvebu/
obj-$(CONFIG_PLAT_SPEAR) += spear/ obj-$(CONFIG_PLAT_SPEAR) += spear/
...@@ -345,6 +345,33 @@ void pinctrl_add_gpio_ranges(struct pinctrl_dev *pctldev, ...@@ -345,6 +345,33 @@ void pinctrl_add_gpio_ranges(struct pinctrl_dev *pctldev,
} }
EXPORT_SYMBOL_GPL(pinctrl_add_gpio_ranges); 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 * pinctrl_get_group_selector() - returns the group selector for a group
* @pctldev: the pin controller handling the group * @pctldev: the pin controller handling the group
...@@ -563,6 +590,8 @@ static int add_setting(struct pinctrl *p, struct pinctrl_map const *map) ...@@ -563,6 +590,8 @@ static int add_setting(struct pinctrl *p, struct pinctrl_map const *map)
return -EPROBE_DEFER; return -EPROBE_DEFER;
} }
setting->dev_name = map->dev_name;
switch (map->type) { switch (map->type) {
case PIN_MAP_TYPE_MUX_GROUP: case PIN_MAP_TYPE_MUX_GROUP:
ret = pinmux_map_to_setting(map, setting); ret = pinmux_map_to_setting(map, setting);
......
...@@ -105,12 +105,14 @@ struct pinctrl_setting_configs { ...@@ -105,12 +105,14 @@ struct pinctrl_setting_configs {
* @type: the type of setting * @type: the type of setting
* @pctldev: pin control device handling to be programmed. Not used for * @pctldev: pin control device handling to be programmed. Not used for
* PIN_MAP_TYPE_DUMMY_STATE. * PIN_MAP_TYPE_DUMMY_STATE.
* @dev_name: the name of the device using this state
* @data: Data specific to the setting type * @data: Data specific to the setting type
*/ */
struct pinctrl_setting { struct pinctrl_setting {
struct list_head node; struct list_head node;
enum pinctrl_map_type type; enum pinctrl_map_type type;
struct pinctrl_dev *pctldev; struct pinctrl_dev *pctldev;
const char *dev_name;
union { union {
struct pinctrl_setting_mux mux; struct pinctrl_setting_mux mux;
struct pinctrl_setting_configs configs; struct pinctrl_setting_configs configs;
......
...@@ -106,6 +106,17 @@ static struct pinctrl_dev *find_pinctrl_by_of_node(struct device_node *np) ...@@ -106,6 +106,17 @@ static struct pinctrl_dev *find_pinctrl_by_of_node(struct device_node *np)
return NULL; 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, static int dt_to_map_one_config(struct pinctrl *p, const char *statename,
struct device_node *np_config) struct device_node *np_config)
{ {
......
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
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
...@@ -24,7 +24,6 @@ ...@@ -24,7 +24,6 @@
#include <linux/pinctrl/pinctrl.h> #include <linux/pinctrl/pinctrl.h>
#include <linux/pinctrl/pinmux.h> #include <linux/pinctrl/pinmux.h>
#include "core.h"
#include "pinctrl-mvebu.h" #include "pinctrl-mvebu.h"
#define MPPS_PER_REG 8 #define MPPS_PER_REG 8
......
...@@ -13,6 +13,7 @@ ...@@ -13,6 +13,7 @@
#include <linux/delay.h> #include <linux/delay.h>
#include <linux/errno.h> #include <linux/errno.h>
#include <linux/io.h> #include <linux/io.h>
#include <linux/irqdomain.h>
#include <linux/clk.h> #include <linux/clk.h>
#include <linux/err.h> #include <linux/err.h>
#include <linux/platform_device.h> #include <linux/platform_device.h>
...@@ -64,10 +65,8 @@ struct u300_gpio { ...@@ -64,10 +65,8 @@ struct u300_gpio {
struct gpio_chip chip; struct gpio_chip chip;
struct list_head port_list; struct list_head port_list;
struct clk *clk; struct clk *clk;
struct resource *memres;
void __iomem *base; void __iomem *base;
struct device *dev; struct device *dev;
int irq_base;
u32 stride; u32 stride;
/* Register offsets */ /* Register offsets */
u32 pcr; u32 pcr;
...@@ -83,6 +82,7 @@ struct u300_gpio_port { ...@@ -83,6 +82,7 @@ struct u300_gpio_port {
struct list_head node; struct list_head node;
struct u300_gpio *gpio; struct u300_gpio *gpio;
char name[8]; char name[8];
struct irq_domain *domain;
int irq; int irq;
int number; int number;
u8 toggle_edge_mode; u8 toggle_edge_mode;
...@@ -314,10 +314,30 @@ static int u300_gpio_direction_output(struct gpio_chip *chip, unsigned offset, ...@@ -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) static int u300_gpio_to_irq(struct gpio_chip *chip, unsigned offset)
{ {
struct u300_gpio *gpio = to_u300_gpio(chip); 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, list_for_each(p, &gpio->port_list) {
retirq); 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; return retirq;
} }
...@@ -467,7 +487,7 @@ static int u300_gpio_irq_type(struct irq_data *d, unsigned trigger) ...@@ -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_port *port = irq_data_get_irq_chip_data(d);
struct u300_gpio *gpio = port->gpio; struct u300_gpio *gpio = port->gpio;
int offset = d->irq - gpio->irq_base; int offset = (port->number << 3) + d->hwirq;
u32 val; u32 val;
if ((trigger & IRQF_TRIGGER_RISING) && if ((trigger & IRQF_TRIGGER_RISING) &&
...@@ -503,10 +523,12 @@ static void u300_gpio_irq_enable(struct irq_data *d) ...@@ -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_port *port = irq_data_get_irq_chip_data(d);
struct u300_gpio *gpio = port->gpio; struct u300_gpio *gpio = port->gpio;
int offset = d->irq - gpio->irq_base; int offset = (port->number << 3) + d->hwirq;
u32 val; u32 val;
unsigned long flags; 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); local_irq_save(flags);
val = readl(U300_PIN_REG(offset, ien)); val = readl(U300_PIN_REG(offset, ien));
writel(val | U300_PIN_BIT(offset), 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) ...@@ -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_port *port = irq_data_get_irq_chip_data(d);
struct u300_gpio *gpio = port->gpio; struct u300_gpio *gpio = port->gpio;
int offset = d->irq - gpio->irq_base; int offset = (port->number << 3) + d->hwirq;
u32 val; u32 val;
unsigned long flags; unsigned long flags;
...@@ -555,8 +577,7 @@ static void u300_gpio_irq_handler(unsigned irq, struct irq_desc *desc) ...@@ -555,8 +577,7 @@ static void u300_gpio_irq_handler(unsigned irq, struct irq_desc *desc)
int irqoffset; int irqoffset;
for_each_set_bit(irqoffset, &val, U300_GPIO_PINS_PER_PORT) { for_each_set_bit(irqoffset, &val, U300_GPIO_PINS_PER_PORT) {
int pin_irq = gpio->irq_base + (port->number << 3) int pin_irq = irq_find_mapping(port->domain, irqoffset);
+ irqoffset;
int offset = pinoffset + irqoffset; int offset = pinoffset + irqoffset;
dev_dbg(gpio->dev, "GPIO IRQ %d on pin %d\n", 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) ...@@ -631,6 +652,8 @@ static inline void u300_gpio_free_ports(struct u300_gpio *gpio)
list_for_each_safe(p, n, &gpio->port_list) { list_for_each_safe(p, n, &gpio->port_list) {
port = list_entry(p, struct u300_gpio_port, node); port = list_entry(p, struct u300_gpio_port, node);
list_del(&port->node); list_del(&port->node);
if (port->domain)
irq_domain_remove(port->domain);
kfree(port); kfree(port);
} }
} }
...@@ -639,56 +662,46 @@ static int __init u300_gpio_probe(struct platform_device *pdev) ...@@ -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_platform *plat = dev_get_platdata(&pdev->dev);
struct u300_gpio *gpio; struct u300_gpio *gpio;
struct resource *memres;
int err = 0; int err = 0;
int portno; int portno;
u32 val; u32 val;
u32 ifr; u32 ifr;
int i; int i;
gpio = kzalloc(sizeof(struct u300_gpio), GFP_KERNEL); gpio = devm_kzalloc(&pdev->dev, sizeof(struct u300_gpio), GFP_KERNEL);
if (gpio == NULL) { if (gpio == NULL)
dev_err(&pdev->dev, "failed to allocate memory\n");
return -ENOMEM; return -ENOMEM;
}
gpio->chip = u300_gpio_chip; gpio->chip = u300_gpio_chip;
gpio->chip.ngpio = plat->ports * U300_GPIO_PINS_PER_PORT; gpio->chip.ngpio = plat->ports * U300_GPIO_PINS_PER_PORT;
gpio->irq_base = plat->gpio_irq_base;
gpio->chip.dev = &pdev->dev; gpio->chip.dev = &pdev->dev;
gpio->chip.base = plat->gpio_base; gpio->chip.base = plat->gpio_base;
gpio->dev = &pdev->dev; gpio->dev = &pdev->dev;
/* Get GPIO clock */ memres = platform_get_resource(pdev, IORESOURCE_MEM, 0);
gpio->clk = clk_get(gpio->dev, NULL); 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)) { if (IS_ERR(gpio->clk)) {
err = PTR_ERR(gpio->clk); err = PTR_ERR(gpio->clk);
dev_err(gpio->dev, "could not get GPIO clock\n"); dev_err(gpio->dev, "could not get GPIO clock\n");
goto err_no_clk; return err;
} }
err = clk_prepare_enable(gpio->clk); err = clk_prepare_enable(gpio->clk);
if (err) { if (err) {
dev_err(gpio->dev, "could not enable GPIO clock\n"); dev_err(gpio->dev, "could not enable GPIO clock\n");
goto err_no_clk_enable; return err;
}
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;
} }
dev_info(gpio->dev, dev_info(gpio->dev,
...@@ -732,18 +745,26 @@ static int __init u300_gpio_probe(struct platform_device *pdev) ...@@ -732,18 +745,26 @@ static int __init u300_gpio_probe(struct platform_device *pdev)
port->irq = platform_get_irq_byname(pdev, port->irq = platform_get_irq_byname(pdev,
port->name); 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->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_chained_handler(port->irq, u300_gpio_irq_handler);
irq_set_handler_data(port->irq, port); irq_set_handler_data(port->irq, port);
/* For each GPIO pin set the unique IRQ handler */ /* For each GPIO pin set the unique IRQ handler */
for (i = 0; i < U300_GPIO_PINS_PER_PORT; i++) { 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", dev_dbg(gpio->dev, "GPIO%d on port %s gets IRQ %d\n",
irqno, port->name); gpio->chip.base + (port->number << 3) + i,
port->name, irqno);
irq_set_chip_and_handler(irqno, &u300_gpio_irqchip, irq_set_chip_and_handler(irqno, &u300_gpio_irqchip,
handle_simple_irq); handle_simple_irq);
set_irq_flags(irqno, IRQF_VALID); set_irq_flags(irqno, IRQF_VALID);
...@@ -776,18 +797,10 @@ static int __init u300_gpio_probe(struct platform_device *pdev) ...@@ -776,18 +797,10 @@ static int __init u300_gpio_probe(struct platform_device *pdev)
err_no_pinctrl: err_no_pinctrl:
err = gpiochip_remove(&gpio->chip); err = gpiochip_remove(&gpio->chip);
err_no_chip: err_no_chip:
err_no_domain:
err_no_port: err_no_port:
u300_gpio_free_ports(gpio); 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); 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); dev_info(&pdev->dev, "module ERROR:%d\n", err);
return err; return err;
} }
...@@ -806,13 +819,8 @@ static int __exit u300_gpio_remove(struct platform_device *pdev) ...@@ -806,13 +819,8 @@ static int __exit u300_gpio_remove(struct platform_device *pdev)
return err; return err;
} }
u300_gpio_free_ports(gpio); u300_gpio_free_ports(gpio);
iounmap(gpio->base);
release_mem_region(gpio->memres->start,
resource_size(gpio->memres));
clk_disable_unprepare(gpio->clk); clk_disable_unprepare(gpio->clk);
clk_put(gpio->clk);
platform_set_drvdata(pdev, NULL); platform_set_drvdata(pdev, NULL);
kfree(gpio);
return 0; return 0;
} }
......
...@@ -36,6 +36,7 @@ ...@@ -36,6 +36,7 @@
/* list of external wakeup controllers supported */ /* list of external wakeup controllers supported */
static const struct of_device_id exynos_wkup_irq_ids[] = { static const struct of_device_id exynos_wkup_irq_ids[] = {
{ .compatible = "samsung,exynos4210-wakeup-eint", }, { .compatible = "samsung,exynos4210-wakeup-eint", },
{ }
}; };
static void exynos_gpio_irq_unmask(struct irq_data *irqd) static void exynos_gpio_irq_unmask(struct irq_data *irqd)
......
...@@ -33,9 +33,9 @@ ...@@ -33,9 +33,9 @@
#define SIRFSOC_RSC_PIN_MUX 0x4 #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_CTRL(g, i) ((g)*0x100 + (i)*4)
#define SIRFSOC_GPIO_DSP_EN0 (0x80) #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_INT_STATUS(g) ((g)*0x100 + 0x8C)
#define SIRFSOC_GPIO_CTL_INTR_LOW_MASK 0x1 #define SIRFSOC_GPIO_CTL_INTR_LOW_MASK 0x1
...@@ -60,6 +60,7 @@ struct sirfsoc_gpio_bank { ...@@ -60,6 +60,7 @@ struct sirfsoc_gpio_bank {
int id; int id;
int parent_irq; int parent_irq;
spinlock_t lock; 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]; static struct sirfsoc_gpio_bank sgpio_bank[SIRFSOC_GPIO_NO_OF_BANKS];
...@@ -191,6 +192,7 @@ struct sirfsoc_pmx { ...@@ -191,6 +192,7 @@ struct sirfsoc_pmx {
struct pinctrl_dev *pmx; struct pinctrl_dev *pmx;
void __iomem *gpio_virtbase; void __iomem *gpio_virtbase;
void __iomem *rsc_virtbase; void __iomem *rsc_virtbase;
bool is_marco;
}; };
/* SIRFSOC_GPIO_PAD_EN set */ /* SIRFSOC_GPIO_PAD_EN set */
...@@ -1088,12 +1090,21 @@ static void sirfsoc_pinmux_endisable(struct sirfsoc_pmx *spmx, unsigned selector ...@@ -1088,12 +1090,21 @@ static void sirfsoc_pinmux_endisable(struct sirfsoc_pmx *spmx, unsigned selector
for (i = 0; i < mux->muxmask_counts; i++) { for (i = 0; i < mux->muxmask_counts; i++) {
u32 muxval; u32 muxval;
if (!spmx->is_marco) {
muxval = readl(spmx->gpio_virtbase + SIRFSOC_GPIO_PAD_EN(mask[i].group)); muxval = readl(spmx->gpio_virtbase + SIRFSOC_GPIO_PAD_EN(mask[i].group));
if (enable) if (enable)
muxval = muxval & ~mask[i].mask; muxval = muxval & ~mask[i].mask;
else else
muxval = muxval | mask[i].mask; muxval = muxval | mask[i].mask;
writel(muxval, spmx->gpio_virtbase + SIRFSOC_GPIO_PAD_EN(mask[i].group)); 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) { if (mux->funcmask && enable) {
...@@ -1158,9 +1169,14 @@ static int sirfsoc_pinmux_request_gpio(struct pinctrl_dev *pmxdev, ...@@ -1158,9 +1169,14 @@ static int sirfsoc_pinmux_request_gpio(struct pinctrl_dev *pmxdev,
spmx = pinctrl_dev_get_drvdata(pmxdev); spmx = pinctrl_dev_get_drvdata(pmxdev);
if (!spmx->is_marco) {
muxval = readl(spmx->gpio_virtbase + SIRFSOC_GPIO_PAD_EN(group)); muxval = readl(spmx->gpio_virtbase + SIRFSOC_GPIO_PAD_EN(group));
muxval = muxval | (1 << (offset - range->pin_base)); muxval = muxval | (1 << (offset - range->pin_base));
writel(muxval, spmx->gpio_virtbase + SIRFSOC_GPIO_PAD_EN(group)); 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; return 0;
} }
...@@ -1218,6 +1234,7 @@ static void __iomem *sirfsoc_rsc_of_iomap(void) ...@@ -1218,6 +1234,7 @@ static void __iomem *sirfsoc_rsc_of_iomap(void)
{ {
const struct of_device_id rsc_ids[] = { const struct of_device_id rsc_ids[] = {
{ .compatible = "sirf,prima2-rsc" }, { .compatible = "sirf,prima2-rsc" },
{ .compatible = "sirf,marco-rsc" },
{} {}
}; };
struct device_node *np; struct device_node *np;
...@@ -1259,6 +1276,9 @@ static int __devinit sirfsoc_pinmux_probe(struct platform_device *pdev) ...@@ -1259,6 +1276,9 @@ static int __devinit sirfsoc_pinmux_probe(struct platform_device *pdev)
goto out_no_rsc_remap; 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 */ /* Now register the pin controller and all pins it handles */
spmx->pmx = pinctrl_register(&sirfsoc_pinmux_desc, &pdev->dev, spmx); spmx->pmx = pinctrl_register(&sirfsoc_pinmux_desc, &pdev->dev, spmx);
if (!spmx->pmx) { if (!spmx->pmx) {
...@@ -1287,6 +1307,7 @@ static int __devinit sirfsoc_pinmux_probe(struct platform_device *pdev) ...@@ -1287,6 +1307,7 @@ static int __devinit sirfsoc_pinmux_probe(struct platform_device *pdev)
static const struct of_device_id pinmux_ids[] __devinitconst = { static const struct of_device_id pinmux_ids[] __devinitconst = {
{ .compatible = "sirf,prima2-pinctrl" }, { .compatible = "sirf,prima2-pinctrl" },
{ .compatible = "sirf,marco-pinctrl" },
{} {}
}; };
...@@ -1621,7 +1642,7 @@ static void sirfsoc_gpio_set_value(struct gpio_chip *chip, unsigned offset, ...@@ -1621,7 +1642,7 @@ static void sirfsoc_gpio_set_value(struct gpio_chip *chip, unsigned offset,
spin_unlock_irqrestore(&bank->lock, flags); spin_unlock_irqrestore(&bank->lock, flags);
} }
int sirfsoc_gpio_irq_map(struct irq_domain *d, unsigned int irq, static int sirfsoc_gpio_irq_map(struct irq_domain *d, unsigned int irq,
irq_hw_number_t hwirq) irq_hw_number_t hwirq)
{ {
struct sirfsoc_gpio_bank *bank = d->host_data; struct sirfsoc_gpio_bank *bank = d->host_data;
...@@ -1648,6 +1669,7 @@ static int __devinit sirfsoc_gpio_probe(struct device_node *np) ...@@ -1648,6 +1669,7 @@ static int __devinit sirfsoc_gpio_probe(struct device_node *np)
struct sirfsoc_gpio_bank *bank; struct sirfsoc_gpio_bank *bank;
void *regs; void *regs;
struct platform_device *pdev; struct platform_device *pdev;
bool is_marco = false;
pdev = of_find_device_by_node(np); pdev = of_find_device_by_node(np);
if (!pdev) if (!pdev)
...@@ -1657,6 +1679,9 @@ static int __devinit sirfsoc_gpio_probe(struct device_node *np) ...@@ -1657,6 +1679,9 @@ static int __devinit sirfsoc_gpio_probe(struct device_node *np)
if (!regs) if (!regs)
return -ENOMEM; return -ENOMEM;
if (of_device_is_compatible(np, "sirf,marco-pinctrl"))
is_marco = 1;
for (i = 0; i < SIRFSOC_GPIO_NO_OF_BANKS; i++) { for (i = 0; i < SIRFSOC_GPIO_NO_OF_BANKS; i++) {
bank = &sgpio_bank[i]; bank = &sgpio_bank[i];
spin_lock_init(&bank->lock); spin_lock_init(&bank->lock);
...@@ -1673,6 +1698,7 @@ static int __devinit sirfsoc_gpio_probe(struct device_node *np) ...@@ -1673,6 +1698,7 @@ static int __devinit sirfsoc_gpio_probe(struct device_node *np)
bank->chip.gc.of_node = np; bank->chip.gc.of_node = np;
bank->chip.regs = regs; bank->chip.regs = regs;
bank->id = i; bank->id = i;
bank->is_marco = is_marco;
bank->parent_irq = platform_get_irq(pdev, i); bank->parent_irq = platform_get_irq(pdev, i);
if (bank->parent_irq < 0) { if (bank->parent_irq < 0) {
err = bank->parent_irq; err = bank->parent_irq;
......
...@@ -663,8 +663,6 @@ static const struct pinctrl_pin_desc u300_pads[] = { ...@@ -663,8 +663,6 @@ static const struct pinctrl_pin_desc u300_pads[] = {
struct u300_pmx { struct u300_pmx {
struct device *dev; struct device *dev;
struct pinctrl_dev *pctl; struct pinctrl_dev *pctl;
u32 phybase;
u32 physize;
void __iomem *virtbase; void __iomem *virtbase;
}; };
...@@ -1054,8 +1052,7 @@ static struct pinctrl_gpio_range *u300_match_gpio_range(unsigned pin) ...@@ -1054,8 +1052,7 @@ static struct pinctrl_gpio_range *u300_match_gpio_range(unsigned pin)
return NULL; return NULL;
} }
int u300_pin_config_get(struct pinctrl_dev *pctldev, static int u300_pin_config_get(struct pinctrl_dev *pctldev, unsigned pin,
unsigned pin,
unsigned long *config) unsigned long *config)
{ {
struct pinctrl_gpio_range *range = u300_match_gpio_range(pin); struct pinctrl_gpio_range *range = u300_match_gpio_range(pin);
...@@ -1069,8 +1066,7 @@ int u300_pin_config_get(struct pinctrl_dev *pctldev, ...@@ -1069,8 +1066,7 @@ int u300_pin_config_get(struct pinctrl_dev *pctldev,
config); config);
} }
int u300_pin_config_set(struct pinctrl_dev *pctldev, static int u300_pin_config_set(struct pinctrl_dev *pctldev, unsigned pin,
unsigned pin,
unsigned long config) unsigned long config)
{ {
struct pinctrl_gpio_range *range = u300_match_gpio_range(pin); struct pinctrl_gpio_range *range = u300_match_gpio_range(pin);
...@@ -1110,7 +1106,6 @@ static int __devinit u300_pmx_probe(struct platform_device *pdev) ...@@ -1110,7 +1106,6 @@ static int __devinit u300_pmx_probe(struct platform_device *pdev)
struct u300_pmx *upmx; struct u300_pmx *upmx;
struct resource *res; struct resource *res;
struct gpio_chip *gpio_chip = dev_get_platdata(&pdev->dev); struct gpio_chip *gpio_chip = dev_get_platdata(&pdev->dev);
int ret;
int i; int i;
/* Create state holders etc for this driver */ /* Create state holders etc for this driver */
...@@ -1123,26 +1118,15 @@ static int __devinit u300_pmx_probe(struct platform_device *pdev) ...@@ -1123,26 +1118,15 @@ static int __devinit u300_pmx_probe(struct platform_device *pdev)
res = platform_get_resource(pdev, IORESOURCE_MEM, 0); res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
if (!res) if (!res)
return -ENOENT; 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); upmx->virtbase = devm_request_and_ioremap(&pdev->dev, res);
if (!upmx->virtbase) { if (!upmx->virtbase)
ret = -ENOMEM; return -ENOMEM;
goto out_no_remap;
}
upmx->pctl = pinctrl_register(&u300_pmx_desc, &pdev->dev, upmx); upmx->pctl = pinctrl_register(&u300_pmx_desc, &pdev->dev, upmx);
if (!upmx->pctl) { if (!upmx->pctl) {
dev_err(&pdev->dev, "could not register U300 pinmux driver\n"); dev_err(&pdev->dev, "could not register U300 pinmux driver\n");
ret = -EINVAL; return -EINVAL;
goto out_no_pmx;
} }
/* We will handle a range of GPIO pins */ /* We will handle a range of GPIO pins */
...@@ -1156,14 +1140,6 @@ static int __devinit u300_pmx_probe(struct platform_device *pdev) ...@@ -1156,14 +1140,6 @@ static int __devinit u300_pmx_probe(struct platform_device *pdev)
dev_info(&pdev->dev, "initialized U300 pin control driver\n"); dev_info(&pdev->dev, "initialized U300 pin control driver\n");
return 0; 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) static int __devexit u300_pmx_remove(struct platform_device *pdev)
...@@ -1171,8 +1147,6 @@ 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); struct u300_pmx *upmx = platform_get_drvdata(pdev);
pinctrl_unregister(upmx->pctl); pinctrl_unregister(upmx->pctl);
iounmap(upmx->virtbase);
release_mem_region(upmx->phybase, upmx->physize);
platform_set_drvdata(pdev, NULL); platform_set_drvdata(pdev, NULL);
return 0; return 0;
......
...@@ -314,14 +314,11 @@ int pinmux_map_to_setting(struct pinctrl_map const *map, ...@@ -314,14 +314,11 @@ int pinmux_map_to_setting(struct pinctrl_map const *map,
{ {
struct pinctrl_dev *pctldev = setting->pctldev; struct pinctrl_dev *pctldev = setting->pctldev;
const struct pinmux_ops *pmxops = pctldev->desc->pmxops; const struct pinmux_ops *pmxops = pctldev->desc->pmxops;
const struct pinctrl_ops *pctlops = pctldev->desc->pctlops;
char const * const *groups; char const * const *groups;
unsigned num_groups; unsigned num_groups;
int ret; int ret;
const char *group; const char *group;
int i; int i;
const unsigned *pins;
unsigned num_pins;
if (!pmxops) { if (!pmxops) {
dev_err(pctldev->dev, "does not support mux function\n"); dev_err(pctldev->dev, "does not support mux function\n");
...@@ -376,53 +373,12 @@ int pinmux_map_to_setting(struct pinctrl_map const *map, ...@@ -376,53 +373,12 @@ int pinmux_map_to_setting(struct pinctrl_map const *map,
} }
setting->data.mux.group = ret; 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; return 0;
} }
void pinmux_free_setting(struct pinctrl_setting const *setting) void pinmux_free_setting(struct pinctrl_setting const *setting)
{ {
struct pinctrl_dev *pctldev = setting->pctldev; /* This function is currently unused */
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);
} }
int pinmux_enable_setting(struct pinctrl_setting const *setting) int pinmux_enable_setting(struct pinctrl_setting const *setting)
...@@ -446,6 +402,22 @@ 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; 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++) { for (i = 0; i < num_pins; i++) {
desc = pin_desc_get(pctldev, pins[i]); desc = pin_desc_get(pctldev, pins[i]);
if (desc == NULL) { if (desc == NULL) {
...@@ -482,6 +454,7 @@ void pinmux_disable_setting(struct pinctrl_setting const *setting) ...@@ -482,6 +454,7 @@ void pinmux_disable_setting(struct pinctrl_setting const *setting)
num_pins = 0; num_pins = 0;
} }
/* Flag the descs that no setting is active */
for (i = 0; i < num_pins; i++) { for (i = 0; i < num_pins; i++) {
desc = pin_desc_get(pctldev, pins[i]); desc = pin_desc_get(pctldev, pins[i]);
if (desc == NULL) { if (desc == NULL) {
...@@ -493,6 +466,10 @@ void pinmux_disable_setting(struct pinctrl_setting const *setting) ...@@ -493,6 +466,10 @@ void pinmux_disable_setting(struct pinctrl_setting const *setting)
desc->mux_setting = NULL; desc->mux_setting = NULL;
} }
/* And release the pins */
for (i = 0; i < num_pins; i++)
pin_free(pctldev, pins[i], NULL);
if (ops->disable) if (ops->disable)
ops->disable(pctldev, setting->data.mux.func, setting->data.mux.group); ops->disable(pctldev, setting->data.mux.func, setting->data.mux.group);
} }
......
...@@ -25,20 +25,31 @@ config PINCTRL_SPEAR310 ...@@ -25,20 +25,31 @@ config PINCTRL_SPEAR310
bool "ST Microelectronics SPEAr310 SoC pin controller driver" bool "ST Microelectronics SPEAr310 SoC pin controller driver"
depends on MACH_SPEAR310 depends on MACH_SPEAR310
select PINCTRL_SPEAR3XX select PINCTRL_SPEAR3XX
select PINCTRL_SPEAR_PLGPIO
config PINCTRL_SPEAR320 config PINCTRL_SPEAR320
bool "ST Microelectronics SPEAr320 SoC pin controller driver" bool "ST Microelectronics SPEAr320 SoC pin controller driver"
depends on MACH_SPEAR320 depends on MACH_SPEAR320
select PINCTRL_SPEAR3XX select PINCTRL_SPEAR3XX
select PINCTRL_SPEAR_PLGPIO
config PINCTRL_SPEAR1310 config PINCTRL_SPEAR1310
bool "ST Microelectronics SPEAr1310 SoC pin controller driver" bool "ST Microelectronics SPEAr1310 SoC pin controller driver"
depends on MACH_SPEAR1310 depends on MACH_SPEAR1310
select PINCTRL_SPEAR select PINCTRL_SPEAR
select PINCTRL_SPEAR_PLGPIO
config PINCTRL_SPEAR1340 config PINCTRL_SPEAR1340
bool "ST Microelectronics SPEAr1340 SoC pin controller driver" bool "ST Microelectronics SPEAr1340 SoC pin controller driver"
depends on MACH_SPEAR1340 depends on MACH_SPEAR1340
select PINCTRL_SPEAR 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 endif
# SPEAr pinmux support # SPEAr pinmux support
obj-$(CONFIG_PINCTRL_SPEAR_PLGPIO) += pinctrl-plgpio.o
obj-$(CONFIG_PINCTRL_SPEAR) += pinctrl-spear.o obj-$(CONFIG_PINCTRL_SPEAR) += pinctrl-spear.o
obj-$(CONFIG_PINCTRL_SPEAR3XX) += pinctrl-spear3xx.o obj-$(CONFIG_PINCTRL_SPEAR3XX) += pinctrl-spear3xx.o
obj-$(CONFIG_PINCTRL_SPEAR300) += pinctrl-spear300.o obj-$(CONFIG_PINCTRL_SPEAR300) += pinctrl-spear300.o
......
This diff is collapsed.
...@@ -18,6 +18,7 @@ ...@@ -18,6 +18,7 @@
#include <linux/module.h> #include <linux/module.h>
#include <linux/of.h> #include <linux/of.h>
#include <linux/of_address.h> #include <linux/of_address.h>
#include <linux/of_gpio.h>
#include <linux/pinctrl/machine.h> #include <linux/pinctrl/machine.h>
#include <linux/pinctrl/pinctrl.h> #include <linux/pinctrl/pinctrl.h>
#include <linux/pinctrl/pinmux.h> #include <linux/pinctrl/pinmux.h>
...@@ -38,6 +39,28 @@ static inline void pmx_writel(struct spear_pmx *pmx, u32 val, u32 reg) ...@@ -38,6 +39,28 @@ static inline void pmx_writel(struct spear_pmx *pmx, u32 val, u32 reg)
writel_relaxed(val, pmx->vbase + 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) static int set_mode(struct spear_pmx *pmx, int mode)
{ {
struct spear_pmx_mode *pmx_mode = NULL; struct spear_pmx_mode *pmx_mode = NULL;
...@@ -70,6 +93,17 @@ static int set_mode(struct spear_pmx *pmx, int mode) ...@@ -70,6 +93,17 @@ static int set_mode(struct spear_pmx *pmx, int mode)
return 0; 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) void __devinit pmx_init_addr(struct spear_pinctrl_machdata *machdata, u16 reg)
{ {
struct spear_pingroup *pgroup; struct spear_pingroup *pgroup;
...@@ -216,9 +250,7 @@ static int spear_pinctrl_endisable(struct pinctrl_dev *pctldev, ...@@ -216,9 +250,7 @@ static int spear_pinctrl_endisable(struct pinctrl_dev *pctldev,
struct spear_pmx *pmx = pinctrl_dev_get_drvdata(pctldev); struct spear_pmx *pmx = pinctrl_dev_get_drvdata(pctldev);
const struct spear_pingroup *pgroup; const struct spear_pingroup *pgroup;
const struct spear_modemux *modemux; const struct spear_modemux *modemux;
struct spear_muxreg *muxreg; int i;
u32 val, temp;
int i, j;
bool found = false; bool found = false;
pgroup = pmx->machdata->groups[group]; pgroup = pmx->machdata->groups[group];
...@@ -233,20 +265,8 @@ static int spear_pinctrl_endisable(struct pinctrl_dev *pctldev, ...@@ -233,20 +265,8 @@ static int spear_pinctrl_endisable(struct pinctrl_dev *pctldev,
} }
found = true; found = true;
for (j = 0; j < modemux->nmuxregs; j++) { muxregs_endisable(pmx, modemux->muxregs, modemux->nmuxregs,
muxreg = &modemux->muxregs[j]; enable);
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);
}
} }
if (!found) { if (!found) {
...@@ -270,12 +290,65 @@ static void spear_pinctrl_disable(struct pinctrl_dev *pctldev, ...@@ -270,12 +290,65 @@ static void spear_pinctrl_disable(struct pinctrl_dev *pctldev,
spear_pinctrl_endisable(pctldev, function, group, false); 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 = { static struct pinmux_ops spear_pinmux_ops = {
.get_functions_count = spear_pinctrl_get_funcs_count, .get_functions_count = spear_pinctrl_get_funcs_count,
.get_function_name = spear_pinctrl_get_func_name, .get_function_name = spear_pinctrl_get_func_name,
.get_function_groups = spear_pinctrl_get_func_groups, .get_function_groups = spear_pinctrl_get_func_groups,
.enable = spear_pinctrl_enable, .enable = spear_pinctrl_enable,
.disable = spear_pinctrl_disable, .disable = spear_pinctrl_disable,
.gpio_request_enable = gpio_request_enable,
.gpio_disable_free = gpio_disable_free,
}; };
static struct pinctrl_desc spear_pinctrl_desc = { static struct pinctrl_desc spear_pinctrl_desc = {
......
...@@ -12,6 +12,7 @@ ...@@ -12,6 +12,7 @@
#ifndef __PINMUX_SPEAR_H__ #ifndef __PINMUX_SPEAR_H__
#define __PINMUX_SPEAR_H__ #define __PINMUX_SPEAR_H__
#include <linux/gpio.h>
#include <linux/pinctrl/pinctrl.h> #include <linux/pinctrl/pinctrl.h>
#include <linux/types.h> #include <linux/types.h>
...@@ -46,6 +47,44 @@ struct spear_muxreg { ...@@ -46,6 +47,44 @@ struct spear_muxreg {
u32 val; 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 * struct spear_modemux - SPEAr mode mux configuration
* @modes: mode ids supported by this group of muxregs * @modes: mode ids supported by this group of muxregs
...@@ -100,6 +139,8 @@ struct spear_function { ...@@ -100,6 +139,8 @@ struct spear_function {
* @nfunctions: The numbmer of entries in @functions. * @nfunctions: The numbmer of entries in @functions.
* @groups: An array describing all pin groups the pin SoC supports. * @groups: An array describing all pin groups the pin SoC supports.
* @ngroups: The numbmer of entries in @groups. * @ngroups: The numbmer of entries in @groups.
* @gpio_pingroups: gpio pingroups
* @ngpio_pingroups: gpio pingroups count
* *
* @modes_supported: Does SoC support modes * @modes_supported: Does SoC support modes
* @mode: mode configured from probe * @mode: mode configured from probe
...@@ -113,6 +154,8 @@ struct spear_pinctrl_machdata { ...@@ -113,6 +154,8 @@ struct spear_pinctrl_machdata {
unsigned nfunctions; unsigned nfunctions;
struct spear_pingroup **groups; struct spear_pingroup **groups;
unsigned ngroups; unsigned ngroups;
struct spear_gpio_pingroup *gpio_pingroups;
unsigned ngpio_pingroups;
bool modes_supported; bool modes_supported;
u16 mode; u16 mode;
...@@ -136,6 +179,9 @@ struct spear_pmx { ...@@ -136,6 +179,9 @@ struct spear_pmx {
/* exported routines */ /* exported routines */
void __devinit pmx_init_addr(struct spear_pinctrl_machdata *machdata, u16 reg); 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, int __devinit spear_pinctrl_probe(struct platform_device *pdev,
struct spear_pinctrl_machdata *machdata); struct spear_pinctrl_machdata *machdata);
int __devexit spear_pinctrl_remove(struct platform_device *pdev); int __devexit spear_pinctrl_remove(struct platform_device *pdev);
......
This diff is collapsed.
...@@ -661,6 +661,8 @@ static int __devinit spear300_pinctrl_probe(struct platform_device *pdev) ...@@ -661,6 +661,8 @@ static int __devinit spear300_pinctrl_probe(struct platform_device *pdev)
spear3xx_machdata.ngroups = ARRAY_SIZE(spear300_pingroups); spear3xx_machdata.ngroups = ARRAY_SIZE(spear300_pingroups);
spear3xx_machdata.functions = spear300_functions; spear3xx_machdata.functions = spear300_functions;
spear3xx_machdata.nfunctions = ARRAY_SIZE(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.modes_supported = true;
spear3xx_machdata.pmx_modes = spear300_pmx_modes; spear3xx_machdata.pmx_modes = spear300_pmx_modes;
......
...@@ -388,6 +388,8 @@ static int __devinit spear310_pinctrl_probe(struct platform_device *pdev) ...@@ -388,6 +388,8 @@ static int __devinit spear310_pinctrl_probe(struct platform_device *pdev)
spear3xx_machdata.nfunctions = ARRAY_SIZE(spear310_functions); spear3xx_machdata.nfunctions = ARRAY_SIZE(spear310_functions);
pmx_init_addr(&spear3xx_machdata, PMX_CONFIG_REG); 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; spear3xx_machdata.modes_supported = false;
......
...@@ -3431,6 +3431,8 @@ static int __devinit spear320_pinctrl_probe(struct platform_device *pdev) ...@@ -3431,6 +3431,8 @@ static int __devinit spear320_pinctrl_probe(struct platform_device *pdev)
spear3xx_machdata.npmx_modes = ARRAY_SIZE(spear320_pmx_modes); spear3xx_machdata.npmx_modes = ARRAY_SIZE(spear320_pmx_modes);
pmx_init_addr(&spear3xx_machdata, PMX_CONFIG_REG); 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); ret = spear_pinctrl_probe(pdev, &spear3xx_machdata);
if (ret) if (ret)
......
...@@ -481,7 +481,44 @@ struct spear_function spear3xx_timer_2_3_function = { ...@@ -481,7 +481,44 @@ struct spear_function spear3xx_timer_2_3_function = {
.ngroups = ARRAY_SIZE(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 = { struct spear_pinctrl_machdata spear3xx_machdata = {
.pins = spear3xx_pins, .pins = spear3xx_pins,
.npins = ARRAY_SIZE(spear3xx_pins), .npins = ARRAY_SIZE(spear3xx_pins),
.gpio_pingroups = spear3xx_gpio_pingroup,
.ngpio_pingroups = ARRAY_SIZE(spear3xx_gpio_pingroup),
}; };
...@@ -5,6 +5,7 @@ ...@@ -5,6 +5,7 @@
#include <linux/types.h> #include <linux/types.h>
#include <linux/errno.h> #include <linux/errno.h>
#include <linux/of.h> #include <linux/of.h>
#include <linux/pinctrl/pinctrl.h>
#ifdef CONFIG_GPIOLIB #ifdef CONFIG_GPIOLIB
...@@ -134,6 +135,15 @@ struct gpio_chip { ...@@ -134,6 +135,15 @@ struct gpio_chip {
int (*of_xlate)(struct gpio_chip *gc, int (*of_xlate)(struct gpio_chip *gc,
const struct of_phandle_args *gpiospec, u32 *flags); const struct of_phandle_args *gpiospec, u32 *flags);
#endif #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, extern const char *gpiochip_is_requested(struct gpio_chip *chip,
...@@ -257,4 +267,39 @@ static inline void gpio_unexport(unsigned gpio) ...@@ -257,4 +267,39 @@ static inline void gpio_unexport(unsigned gpio)
} }
#endif /* CONFIG_GPIO_SYSFS */ #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 */ #endif /* _ASM_GENERIC_GPIO_H */
...@@ -72,9 +72,9 @@ static inline int irq_to_gpio(unsigned int irq) ...@@ -72,9 +72,9 @@ static inline int irq_to_gpio(unsigned int irq)
return -EINVAL; return -EINVAL;
} }
#endif #endif /* ! CONFIG_ARCH_HAVE_CUSTOM_GPIO_H */
#else #else /* ! CONFIG_GENERIC_GPIO */
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/types.h> #include <linux/types.h>
...@@ -231,6 +231,20 @@ static inline int irq_to_gpio(unsigned irq) ...@@ -231,6 +231,20 @@ static inline int irq_to_gpio(unsigned irq)
return -EINVAL; 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 */ #endif /* __LINUX_GPIO_H */
...@@ -134,6 +134,22 @@ extern void pinctrl_add_gpio_range(struct pinctrl_dev *pctldev, ...@@ -134,6 +134,22 @@ extern void pinctrl_add_gpio_range(struct pinctrl_dev *pctldev,
extern void pinctrl_add_gpio_ranges(struct pinctrl_dev *pctldev, extern void pinctrl_add_gpio_ranges(struct pinctrl_dev *pctldev,
struct pinctrl_gpio_range *ranges, struct pinctrl_gpio_range *ranges,
unsigned nranges); 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 const char *pinctrl_dev_get_name(struct pinctrl_dev *pctldev);
extern void *pinctrl_dev_get_drvdata(struct pinctrl_dev *pctldev); extern void *pinctrl_dev_get_drvdata(struct pinctrl_dev *pctldev);
#else #else
......
...@@ -13,13 +13,11 @@ ...@@ -13,13 +13,11 @@
* struct u300_gpio_platform - U300 GPIO platform data * struct u300_gpio_platform - U300 GPIO platform data
* @ports: number of GPIO block ports * @ports: number of GPIO block ports
* @gpio_base: first GPIO number for this block (use a free range) * @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 * @pinctrl_device: pin control device to spawn as child
*/ */
struct u300_gpio_platform { struct u300_gpio_platform {
u8 ports; u8 ports;
int gpio_base; int gpio_base;
int gpio_irq_base;
struct platform_device *pinctrl_device; struct platform_device *pinctrl_device;
}; };
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment