Merge branch 'spear-for-3.8' of git://git.linaro.org/people/vireshk/linux into next/dt2
From Viresh Kumar <viresh.kumar@linaro.org>: These are DT updates for SPEAr SoCs. There aren't any fixes that we want to get into 3.7-rc* and we are happy with 3.8. Some of the dtbs which use gpiopinctrl have dependency on Linus's pinctrl tree, where an earlier update for adding gpiopinctrl node is present. * 'spear-for-3.8' of git://git.linaro.org/people/vireshk/linux: ARM: SPEAr3xx: Shirq: Move shirq controller out of plat/ ARM: SPEAr320: DT: Add SPEAr 320 HMI board support ARM: SPEAr3xx: DT: add shirq node for interrupt multiplexor ARM: SPEAr3xx: shirq: simplify and move the shared irq multiplexor to DT ARM: SPEAr1310: Fix AUXDATA for compact flash controller ARM: SPEAr13xx: Remove fields not required for ssp controller ARM: SPEAr1310: Move 1310 specific misc register into machine specific files ARM: SPEAr: DT: Update device nodes ARM: SPEAr: DT: add uart state to fix warning ARM: SPEAr: DT: Modify DT bindings for STMMAC ARM: SPEAr: DT: Fix existing DT support ARM: SPEAr: DT: Update partition info for MTD devices ARM: SPEAr: DT: Update pinctrl list ARM: SPEAr13xx: DT: Add spics gpio controller nodes Signed-off-by: Arnd Bergmann <arnd@arndb.de>
This commit is contained in:
commit
eabc5fa51c
|
@ -0,0 +1,48 @@
|
|||
* SPEAr Shared IRQ layer (shirq)
|
||||
|
||||
SPEAr3xx architecture includes shared/multiplexed irqs for certain set
|
||||
of devices. The multiplexor provides a single interrupt to parent
|
||||
interrupt controller (VIC) on behalf of a group of devices.
|
||||
|
||||
There can be multiple groups available on SPEAr3xx variants but not
|
||||
exceeding 4. The number of devices in a group can differ, further they
|
||||
may share same set of status/mask registers spanning across different
|
||||
bit masks. Also in some cases the group may not have enable or other
|
||||
registers. This makes software little complex.
|
||||
|
||||
A single node in the device tree is used to describe the shared
|
||||
interrupt multiplexor (one node for all groups). A group in the
|
||||
interrupt controller shares config/control registers with other groups.
|
||||
For example, a 32-bit interrupt enable/disable config register can
|
||||
accommodate upto 4 interrupt groups.
|
||||
|
||||
Required properties:
|
||||
- compatible: should be, either of
|
||||
- "st,spear300-shirq"
|
||||
- "st,spear310-shirq"
|
||||
- "st,spear320-shirq"
|
||||
- interrupt-controller: Identifies the node as an interrupt controller.
|
||||
- #interrupt-cells: should be <1> which basically contains the offset
|
||||
(starting from 0) of interrupts for all the groups.
|
||||
- reg: Base address and size of shirq registers.
|
||||
- interrupts: The list of interrupts generated by the groups which are
|
||||
then connected to a parent interrupt controller. Each group is
|
||||
associated with one of the interrupts, hence number of interrupts (to
|
||||
parent) is equal to number of groups. The format of the interrupt
|
||||
specifier depends in the interrupt parent controller.
|
||||
|
||||
Optional properties:
|
||||
- interrupt-parent: pHandle of the parent interrupt controller, if not
|
||||
inherited from the parent node.
|
||||
|
||||
Example:
|
||||
|
||||
The following is an example from the SPEAr320 SoC dtsi file.
|
||||
|
||||
shirq: interrupt-controller@0xb3000000 {
|
||||
compatible = "st,spear320-shirq";
|
||||
reg = <0xb3000000 0x1000>;
|
||||
interrupts = <28 29 30 1>;
|
||||
#interrupt-cells = <1>;
|
||||
interrupt-controller;
|
||||
};
|
|
@ -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.
|
||||
|
|
|
@ -0,0 +1,50 @@
|
|||
=== ST Microelectronics SPEAr SPI CS Driver ===
|
||||
|
||||
SPEAr platform provides a provision to control chipselects of ARM PL022 Prime
|
||||
Cell spi controller through its system registers, which otherwise remains under
|
||||
PL022 control. If chipselect remain under PL022 control then they would be
|
||||
released as soon as transfer is over and TxFIFO becomes empty. This is not
|
||||
desired by some of the device protocols above spi which expect (multiple)
|
||||
transfers without releasing their chipselects.
|
||||
|
||||
Chipselects can be controlled by software by turning them as GPIOs. SPEAr
|
||||
provides another interface through system registers through which software can
|
||||
directly control each PL022 chipselect. Hence, it is natural for SPEAr to export
|
||||
the control of this interface as gpio.
|
||||
|
||||
Required properties:
|
||||
|
||||
* compatible: should be defined as "st,spear-spics-gpio"
|
||||
* reg: mentioning address range of spics controller
|
||||
* st-spics,peripcfg-reg: peripheral configuration register offset
|
||||
* st-spics,sw-enable-bit: bit offset to enable sw control
|
||||
* st-spics,cs-value-bit: bit offset to drive chipselect low or high
|
||||
* st-spics,cs-enable-mask: chip select number bit mask
|
||||
* st-spics,cs-enable-shift: chip select number program offset
|
||||
* gpio-controller: Marks the device node as gpio controller
|
||||
* #gpio-cells: should be 1 and will mention chip select number
|
||||
|
||||
All the above bit offsets are within peripcfg register.
|
||||
|
||||
Example:
|
||||
-------
|
||||
spics: spics@e0700000{
|
||||
compatible = "st,spear-spics-gpio";
|
||||
reg = <0xe0700000 0x1000>;
|
||||
st-spics,peripcfg-reg = <0x3b0>;
|
||||
st-spics,sw-enable-bit = <12>;
|
||||
st-spics,cs-value-bit = <11>;
|
||||
st-spics,cs-enable-mask = <3>;
|
||||
st-spics,cs-enable-shift = <8>;
|
||||
gpio-controller;
|
||||
#gpio-cells = <2>;
|
||||
};
|
||||
|
||||
|
||||
spi0: spi@e0100000 {
|
||||
status = "okay";
|
||||
num-cs = <3>;
|
||||
cs-gpios = <&gpio1 7 0>, <&spics 0>,
|
||||
<&spics 1>;
|
||||
...
|
||||
}
|
|
@ -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
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -364,6 +364,7 @@ config ARCH_CNS3XXX
|
|||
|
||||
config ARCH_CLPS711X
|
||||
bool "Cirrus Logic CLPS711x/EP721x/EP731x-based"
|
||||
select ARCH_REQUIRE_GPIOLIB
|
||||
select ARCH_USES_GETTIMEOFFSET
|
||||
select CLKDEV_LOOKUP
|
||||
select COMMON_CLK
|
||||
|
|
|
@ -82,7 +82,8 @@ dtb-$(CONFIG_ARCH_SPEAR13XX) += spear1310-evb.dtb \
|
|||
spear1340-evb.dtb
|
||||
dtb-$(CONFIG_ARCH_SPEAR3XX)+= spear300-evb.dtb \
|
||||
spear310-evb.dtb \
|
||||
spear320-evb.dtb
|
||||
spear320-evb.dtb \
|
||||
spear320-hmi.dtb
|
||||
dtb-$(CONFIG_ARCH_SPEAR6XX)+= spear600-evb.dtb
|
||||
dtb-$(CONFIG_ARCH_TEGRA) += tegra20-harmony.dtb \
|
||||
tegra20-medcom-wide.dtb \
|
||||
|
|
|
@ -30,10 +30,14 @@
|
|||
pinctrl-0 = <&state_default>;
|
||||
|
||||
state_default: pinmux {
|
||||
i2c0-pmx {
|
||||
i2c0 {
|
||||
st,pins = "i2c0_grp";
|
||||
st,function = "i2c0";
|
||||
};
|
||||
i2s0 {
|
||||
st,pins = "i2s0_grp";
|
||||
st,function = "i2s0";
|
||||
};
|
||||
i2s1 {
|
||||
st,pins = "i2s1_grp";
|
||||
st,function = "i2s1";
|
||||
|
@ -42,6 +46,10 @@
|
|||
st,pins = "arm_gpio_grp";
|
||||
st,function = "arm_gpio";
|
||||
};
|
||||
clcd {
|
||||
st,pins = "clcd_grp" , "clcd_high_res";
|
||||
st,function = "clcd";
|
||||
};
|
||||
eth {
|
||||
st,pins = "gmii_grp";
|
||||
st,function = "gmii";
|
||||
|
@ -74,11 +82,6 @@
|
|||
st,pins = "i2c_1_2_grp";
|
||||
st,function = "i2c_1_2";
|
||||
};
|
||||
pci {
|
||||
st,pins = "pcie0_grp","pcie1_grp",
|
||||
"pcie2_grp";
|
||||
st,function = "pci";
|
||||
};
|
||||
smii {
|
||||
st,pins = "smii_0_1_2_grp";
|
||||
st,function = "smii_0_1_2";
|
||||
|
@ -88,6 +91,14 @@
|
|||
"nand_16bit_grp";
|
||||
st,function = "nand";
|
||||
};
|
||||
sata {
|
||||
st,pins = "sata0_grp";
|
||||
st,function = "sata";
|
||||
};
|
||||
pcie {
|
||||
st,pins = "pcie1_grp", "pcie2_grp";
|
||||
st,function = "pci_express";
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
|
@ -109,9 +120,49 @@
|
|||
|
||||
fsmc: flash@b0000000 {
|
||||
status = "okay";
|
||||
|
||||
partition@0 {
|
||||
label = "xloader";
|
||||
reg = <0x0 0x80000>;
|
||||
};
|
||||
partition@80000 {
|
||||
label = "u-boot";
|
||||
reg = <0x80000 0x140000>;
|
||||
};
|
||||
partition@1C0000 {
|
||||
label = "environment";
|
||||
reg = <0x1C0000 0x40000>;
|
||||
};
|
||||
partition@200000 {
|
||||
label = "dtb";
|
||||
reg = <0x200000 0x40000>;
|
||||
};
|
||||
partition@240000 {
|
||||
label = "linux";
|
||||
reg = <0x240000 0xC00000>;
|
||||
};
|
||||
partition@E40000 {
|
||||
label = "rootfs";
|
||||
reg = <0xE40000 0x0>;
|
||||
};
|
||||
};
|
||||
|
||||
gpio_keys {
|
||||
compatible = "gpio-keys";
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
button@1 {
|
||||
label = "wakeup";
|
||||
linux,code = <0x100>;
|
||||
gpios = <&gpio0 7 0x4>;
|
||||
debounce-interval = <20>;
|
||||
gpio-key,wakeup = <1>;
|
||||
};
|
||||
};
|
||||
|
||||
gmac0: eth@e2000000 {
|
||||
phy-mode = "gmii";
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
|
@ -135,23 +186,27 @@
|
|||
};
|
||||
partition@10000 {
|
||||
label = "u-boot";
|
||||
reg = <0x10000 0x40000>;
|
||||
reg = <0x10000 0x50000>;
|
||||
};
|
||||
partition@50000 {
|
||||
partition@60000 {
|
||||
label = "environment";
|
||||
reg = <0x60000 0x10000>;
|
||||
};
|
||||
partition@70000 {
|
||||
label = "dtb";
|
||||
reg = <0x70000 0x10000>;
|
||||
};
|
||||
partition@80000 {
|
||||
label = "linux";
|
||||
reg = <0x50000 0x2c0000>;
|
||||
reg = <0x80000 0x310000>;
|
||||
};
|
||||
partition@310000 {
|
||||
partition@390000 {
|
||||
label = "rootfs";
|
||||
reg = <0x310000 0x4f0000>;
|
||||
reg = <0x390000 0x0>;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
spi0: spi@e0100000 {
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
ehci@e4800000 {
|
||||
status = "okay";
|
||||
};
|
||||
|
@ -181,11 +236,11 @@
|
|||
status = "okay";
|
||||
};
|
||||
|
||||
i2c0: i2c@e0280000 {
|
||||
gpio@d8400000 {
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
i2c1: i2c@5cd00000 {
|
||||
i2c0: i2c@e0280000 {
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
|
@ -273,6 +328,7 @@
|
|||
0x08080052 >;
|
||||
autorepeat;
|
||||
st,mode = <0>;
|
||||
suspended_rate = <2000000>;
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
|
@ -282,6 +338,81 @@
|
|||
|
||||
serial@e0000000 {
|
||||
status = "okay";
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <>;
|
||||
};
|
||||
|
||||
spi0: spi@e0100000 {
|
||||
status = "okay";
|
||||
num-cs = <3>;
|
||||
cs-gpios = <&gpio1 7 0>, <&spics 0>, <&spics 1>;
|
||||
|
||||
stmpe610@0 {
|
||||
compatible = "st,stmpe610";
|
||||
reg = <0>;
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
spi-max-frequency = <1000000>;
|
||||
spi-cpha;
|
||||
pl022,hierarchy = <0>;
|
||||
pl022,interface = <0>;
|
||||
pl022,slave-tx-disable;
|
||||
pl022,com-mode = <0>;
|
||||
pl022,rx-level-trig = <0>;
|
||||
pl022,tx-level-trig = <0>;
|
||||
pl022,ctrl-len = <0x7>;
|
||||
pl022,wait-state = <0>;
|
||||
pl022,duplex = <0>;
|
||||
interrupts = <6 0x4>;
|
||||
interrupt-parent = <&gpio1>;
|
||||
irq-trigger = <0x2>;
|
||||
|
||||
stmpe_touchscreen {
|
||||
compatible = "st,stmpe-ts";
|
||||
ts,sample-time = <4>;
|
||||
ts,mod-12b = <1>;
|
||||
ts,ref-sel = <0>;
|
||||
ts,adc-freq = <1>;
|
||||
ts,ave-ctrl = <1>;
|
||||
ts,touch-det-delay = <2>;
|
||||
ts,settling = <2>;
|
||||
ts,fraction-z = <7>;
|
||||
ts,i-drive = <1>;
|
||||
};
|
||||
};
|
||||
|
||||
m25p80@1 {
|
||||
compatible = "st,m25p80";
|
||||
reg = <1>;
|
||||
spi-max-frequency = <12000000>;
|
||||
spi-cpol;
|
||||
spi-cpha;
|
||||
pl022,hierarchy = <0>;
|
||||
pl022,interface = <0>;
|
||||
pl022,slave-tx-disable;
|
||||
pl022,com-mode = <0x2>;
|
||||
pl022,rx-level-trig = <0>;
|
||||
pl022,tx-level-trig = <0>;
|
||||
pl022,ctrl-len = <0x11>;
|
||||
pl022,wait-state = <0>;
|
||||
pl022,duplex = <0>;
|
||||
};
|
||||
|
||||
spidev@2 {
|
||||
compatible = "spidev";
|
||||
reg = <2>;
|
||||
spi-max-frequency = <25000000>;
|
||||
spi-cpha;
|
||||
pl022,hierarchy = <0>;
|
||||
pl022,interface = <0>;
|
||||
pl022,slave-tx-disable;
|
||||
pl022,com-mode = <0x2>;
|
||||
pl022,rx-level-trig = <0>;
|
||||
pl022,tx-level-trig = <0>;
|
||||
pl022,ctrl-len = <0x11>;
|
||||
pl022,wait-state = <0>;
|
||||
pl022,duplex = <0>;
|
||||
};
|
||||
};
|
||||
|
||||
wdt@ec800620 {
|
||||
|
|
|
@ -17,6 +17,18 @@
|
|||
compatible = "st,spear1310";
|
||||
|
||||
ahb {
|
||||
spics: spics@e0700000{
|
||||
compatible = "st,spear-spics-gpio";
|
||||
reg = <0xe0700000 0x1000>;
|
||||
st-spics,peripcfg-reg = <0x3b0>;
|
||||
st-spics,sw-enable-bit = <12>;
|
||||
st-spics,cs-value-bit = <11>;
|
||||
st-spics,cs-enable-mask = <3>;
|
||||
st-spics,cs-enable-shift = <8>;
|
||||
gpio-controller;
|
||||
#gpio-cells = <2>;
|
||||
};
|
||||
|
||||
ahci@b1000000 {
|
||||
compatible = "snps,spear-ahci";
|
||||
reg = <0xb1000000 0x10000>;
|
||||
|
@ -43,6 +55,7 @@
|
|||
reg = <0x5c400000 0x8000>;
|
||||
interrupts = <0 95 0x4>;
|
||||
interrupt-names = "macirq";
|
||||
phy-mode = "mii";
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
|
@ -51,6 +64,7 @@
|
|||
reg = <0x5c500000 0x8000>;
|
||||
interrupts = <0 96 0x4>;
|
||||
interrupt-names = "macirq";
|
||||
phy-mode = "mii";
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
|
@ -59,6 +73,7 @@
|
|||
reg = <0x5c600000 0x8000>;
|
||||
interrupts = <0 97 0x4>;
|
||||
interrupt-names = "macirq";
|
||||
phy-mode = "rmii";
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
|
@ -67,14 +82,14 @@
|
|||
reg = <0x5c700000 0x8000>;
|
||||
interrupts = <0 98 0x4>;
|
||||
interrupt-names = "macirq";
|
||||
phy-mode = "rgmii";
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
spi1: spi@5d400000 {
|
||||
compatible = "arm,pl022", "arm,primecell";
|
||||
reg = <0x5d400000 0x1000>;
|
||||
interrupts = <0 99 0x4>;
|
||||
status = "disabled";
|
||||
pinmux: pinmux@e0700000 {
|
||||
compatible = "st,spear1310-pinmux";
|
||||
reg = <0xe0700000 0x1000>;
|
||||
#gpio-range-cells = <2>;
|
||||
};
|
||||
|
||||
apb {
|
||||
|
@ -141,6 +156,15 @@
|
|||
status = "disabled";
|
||||
};
|
||||
|
||||
spi1: spi@5d400000 {
|
||||
compatible = "arm,pl022", "arm,primecell";
|
||||
reg = <0x5d400000 0x1000>;
|
||||
interrupts = <0 99 0x4>;
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
serial@5c800000 {
|
||||
compatible = "arm,pl011", "arm,primecell";
|
||||
reg = <0x5c800000 0x1000>;
|
||||
|
@ -179,6 +203,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>;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
|
|
@ -38,20 +38,15 @@
|
|||
st,pins = "fsmc_8bit_grp";
|
||||
st,function = "fsmc";
|
||||
};
|
||||
kbd {
|
||||
st,pins = "keyboard_row_col_grp",
|
||||
"keyboard_col5_grp";
|
||||
st,function = "keyboard";
|
||||
};
|
||||
uart0 {
|
||||
st,pins = "uart0_grp", "uart0_enh_grp";
|
||||
st,pins = "uart0_grp";
|
||||
st,function = "uart0";
|
||||
};
|
||||
i2c0-pmx {
|
||||
i2c0 {
|
||||
st,pins = "i2c0_grp";
|
||||
st,function = "i2c0";
|
||||
};
|
||||
i2c1-pmx {
|
||||
i2c1 {
|
||||
st,pins = "i2c1_grp";
|
||||
st,function = "i2c1";
|
||||
};
|
||||
|
@ -64,14 +59,9 @@
|
|||
st,function = "spdif_out";
|
||||
};
|
||||
ssp0 {
|
||||
st,pins = "ssp0_grp", "ssp0_cs1_grp",
|
||||
"ssp0_cs3_grp";
|
||||
st,pins = "ssp0_grp", "ssp0_cs1_grp", "ssp0_cs2_grp", "ssp0_cs3_grp";
|
||||
st,function = "ssp0";
|
||||
};
|
||||
pwm {
|
||||
st,pins = "pwm2_grp", "pwm3_grp";
|
||||
st,function = "pwm";
|
||||
};
|
||||
smi-pmx {
|
||||
st,pins = "smi_grp";
|
||||
st,function = "smi";
|
||||
|
@ -84,6 +74,18 @@
|
|||
st,pins = "gmii_grp", "rgmii_grp";
|
||||
st,function = "gmac";
|
||||
};
|
||||
cam0 {
|
||||
st,pins = "cam0_grp";
|
||||
st,function = "cam0";
|
||||
};
|
||||
cam1 {
|
||||
st,pins = "cam1_grp";
|
||||
st,function = "cam1";
|
||||
};
|
||||
cam2 {
|
||||
st,pins = "cam2_grp";
|
||||
st,function = "cam2";
|
||||
};
|
||||
cam3 {
|
||||
st,pins = "cam3_grp";
|
||||
st,function = "cam3";
|
||||
|
@ -108,9 +110,18 @@
|
|||
st,pins = "sata_grp";
|
||||
st,function = "sata";
|
||||
};
|
||||
pcie {
|
||||
st,pins = "pcie_grp";
|
||||
st,function = "pcie";
|
||||
};
|
||||
|
||||
};
|
||||
};
|
||||
|
||||
ahci@b1000000 {
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
dma@ea800000 {
|
||||
status = "okay";
|
||||
};
|
||||
|
@ -121,9 +132,35 @@
|
|||
|
||||
fsmc: flash@b0000000 {
|
||||
status = "okay";
|
||||
|
||||
partition@0 {
|
||||
label = "xloader";
|
||||
reg = <0x0 0x200000>;
|
||||
};
|
||||
partition@200000 {
|
||||
label = "u-boot";
|
||||
reg = <0x200000 0x200000>;
|
||||
};
|
||||
partition@400000 {
|
||||
label = "environment";
|
||||
reg = <0x400000 0x100000>;
|
||||
};
|
||||
partition@500000 {
|
||||
label = "dtb";
|
||||
reg = <0x500000 0x100000>;
|
||||
};
|
||||
partition@600000 {
|
||||
label = "linux";
|
||||
reg = <0x600000 0xC00000>;
|
||||
};
|
||||
partition@1200000 {
|
||||
label = "rootfs";
|
||||
reg = <0x1200000 0x0>;
|
||||
};
|
||||
};
|
||||
|
||||
gmac0: eth@e2000000 {
|
||||
phy-mode = "rgmii";
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
|
@ -147,31 +184,62 @@
|
|||
};
|
||||
partition@10000 {
|
||||
label = "u-boot";
|
||||
reg = <0x10000 0x40000>;
|
||||
reg = <0x10000 0x50000>;
|
||||
};
|
||||
partition@50000 {
|
||||
partition@60000 {
|
||||
label = "environment";
|
||||
reg = <0x60000 0x10000>;
|
||||
};
|
||||
partition@70000 {
|
||||
label = "dtb";
|
||||
reg = <0x70000 0x10000>;
|
||||
};
|
||||
partition@80000 {
|
||||
label = "linux";
|
||||
reg = <0x50000 0x2c0000>;
|
||||
reg = <0x80000 0x310000>;
|
||||
};
|
||||
partition@310000 {
|
||||
partition@390000 {
|
||||
label = "rootfs";
|
||||
reg = <0x310000 0x4f0000>;
|
||||
reg = <0x390000 0x0>;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
spi0: spi@e0100000 {
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
ehci@e4800000 {
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
gpio_keys {
|
||||
compatible = "gpio-keys";
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
button@1 {
|
||||
label = "wakeup";
|
||||
linux,code = <0x100>;
|
||||
gpios = <&gpio1 1 0x4>;
|
||||
debounce-interval = <20>;
|
||||
gpio-key,wakeup = <1>;
|
||||
};
|
||||
};
|
||||
|
||||
ehci@e5800000 {
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
i2s0: i2s-play@b2400000 {
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
i2s1: i2s-rec@b2000000 {
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
incodec: dir-hifi {
|
||||
compatible = "dummy,dir-hifi";
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
ohci@e4000000 {
|
||||
status = "okay";
|
||||
};
|
||||
|
@ -180,11 +248,43 @@
|
|||
status = "okay";
|
||||
};
|
||||
|
||||
outcodec: dit-hifi {
|
||||
compatible = "dummy,dit-hifi";
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
sound {
|
||||
compatible = "spear,spear-evb";
|
||||
audio-controllers = <&spdif0 &spdif1 &i2s0 &i2s1>;
|
||||
audio-codecs = <&incodec &outcodec &sta529 &sta529>;
|
||||
codec_dai_name = "dir-hifi", "dit-hifi", "sta529-audio", "sta529-audio";
|
||||
stream_name = "spdif-cap", "spdif-play", "i2s-play", "i2s-cap";
|
||||
dai_name = "spdifin-pcm", "spdifout-pcm", "i2s0-pcm", "i2s1-pcm";
|
||||
nr_controllers = <4>;
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
spdif0: spdif-in@d0100000 {
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
spdif1: spdif-out@d0000000 {
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
apb {
|
||||
adc@e0080000 {
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
i2s-play@b2400000 {
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
i2s-rec@b2000000 {
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
gpio0: gpio@e0600000 {
|
||||
status = "okay";
|
||||
};
|
||||
|
@ -193,12 +293,42 @@
|
|||
status = "okay";
|
||||
};
|
||||
|
||||
gpio@e2800000 {
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
i2c0: i2c@e0280000 {
|
||||
status = "okay";
|
||||
|
||||
sta529: sta529@1a {
|
||||
compatible = "st,sta529";
|
||||
reg = <0x1a>;
|
||||
};
|
||||
};
|
||||
|
||||
i2c1: i2c@b4000000 {
|
||||
status = "okay";
|
||||
|
||||
eeprom0@56 {
|
||||
compatible = "st,eeprom";
|
||||
reg = <0x56>;
|
||||
};
|
||||
|
||||
stmpe801@41 {
|
||||
compatible = "st,stmpe801";
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
reg = <0x41>;
|
||||
interrupts = <4 0x4>;
|
||||
interrupt-parent = <&gpio0>;
|
||||
irq-trigger = <0x2>;
|
||||
|
||||
stmpegpio: stmpe_gpio {
|
||||
compatible = "st,stmpe-gpio";
|
||||
gpio-controller;
|
||||
#gpio-cells = <2>;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
kbd@e0300000 {
|
||||
|
@ -285,6 +415,7 @@
|
|||
0x08080052 >;
|
||||
autorepeat;
|
||||
st,mode = <0>;
|
||||
suspended_rate = <2000000>;
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
|
@ -294,10 +425,92 @@
|
|||
|
||||
serial@e0000000 {
|
||||
status = "okay";
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <>;
|
||||
};
|
||||
|
||||
serial@b4100000 {
|
||||
status = "okay";
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <>;
|
||||
};
|
||||
|
||||
spi0: spi@e0100000 {
|
||||
status = "okay";
|
||||
num-cs = <3>;
|
||||
cs-gpios = <&gpiopinctrl 80 0>, <&gpiopinctrl 24 0>,
|
||||
<&gpiopinctrl 85 0>;
|
||||
|
||||
m25p80@0 {
|
||||
compatible = "m25p80";
|
||||
reg = <0>;
|
||||
spi-max-frequency = <12000000>;
|
||||
spi-cpol;
|
||||
spi-cpha;
|
||||
pl022,hierarchy = <0>;
|
||||
pl022,interface = <0>;
|
||||
pl022,slave-tx-disable;
|
||||
pl022,com-mode = <0x2>;
|
||||
pl022,rx-level-trig = <0>;
|
||||
pl022,tx-level-trig = <0>;
|
||||
pl022,ctrl-len = <0x11>;
|
||||
pl022,wait-state = <0>;
|
||||
pl022,duplex = <0>;
|
||||
};
|
||||
|
||||
stmpe610@1 {
|
||||
compatible = "st,stmpe610";
|
||||
spi-max-frequency = <1000000>;
|
||||
spi-cpha;
|
||||
reg = <1>;
|
||||
pl022,hierarchy = <0>;
|
||||
pl022,interface = <0>;
|
||||
pl022,slave-tx-disable;
|
||||
pl022,com-mode = <0>;
|
||||
pl022,rx-level-trig = <0>;
|
||||
pl022,tx-level-trig = <0>;
|
||||
pl022,ctrl-len = <0x7>;
|
||||
pl022,wait-state = <0>;
|
||||
pl022,duplex = <0>;
|
||||
interrupts = <100 0>;
|
||||
interrupt-parent = <&gpiopinctrl>;
|
||||
irq-trigger = <0x2>;
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
stmpe_touchscreen {
|
||||
compatible = "st,stmpe-ts";
|
||||
ts,sample-time = <4>;
|
||||
ts,mod-12b = <1>;
|
||||
ts,ref-sel = <0>;
|
||||
ts,adc-freq = <1>;
|
||||
ts,ave-ctrl = <1>;
|
||||
ts,touch-det-delay = <2>;
|
||||
ts,settling = <2>;
|
||||
ts,fraction-z = <7>;
|
||||
ts,i-drive = <1>;
|
||||
};
|
||||
};
|
||||
|
||||
spidev@2 {
|
||||
compatible = "spidev";
|
||||
reg = <2>;
|
||||
spi-max-frequency = <25000000>;
|
||||
spi-cpha;
|
||||
pl022,hierarchy = <0>;
|
||||
pl022,interface = <0>;
|
||||
pl022,slave-tx-disable;
|
||||
pl022,com-mode = <0x2>;
|
||||
pl022,rx-level-trig = <0>;
|
||||
pl022,tx-level-trig = <0>;
|
||||
pl022,ctrl-len = <0x11>;
|
||||
pl022,wait-state = <0>;
|
||||
pl022,duplex = <0>;
|
||||
};
|
||||
};
|
||||
|
||||
timer@ec800600 {
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
wdt@ec800620 {
|
||||
|
|
|
@ -17,6 +17,20 @@
|
|||
compatible = "st,spear1340";
|
||||
|
||||
ahb {
|
||||
|
||||
spics: spics@e0700000{
|
||||
compatible = "st,spear-spics-gpio";
|
||||
reg = <0xe0700000 0x1000>;
|
||||
st-spics,peripcfg-reg = <0x42c>;
|
||||
st-spics,sw-enable-bit = <21>;
|
||||
st-spics,cs-value-bit = <20>;
|
||||
st-spics,cs-enable-mask = <3>;
|
||||
st-spics,cs-enable-shift = <18>;
|
||||
gpio-controller;
|
||||
#gpio-cells = <2>;
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
ahci@b1000000 {
|
||||
compatible = "snps,spear-ahci";
|
||||
reg = <0xb1000000 0x10000>;
|
||||
|
@ -24,9 +38,61 @@
|
|||
status = "disabled";
|
||||
};
|
||||
|
||||
i2s-play@b2400000 {
|
||||
compatible = "snps,designware-i2s";
|
||||
reg = <0xb2400000 0x10000>;
|
||||
interrupt-names = "play_irq";
|
||||
interrupts = <0 98 0x4
|
||||
0 99 0x4>;
|
||||
play;
|
||||
channel = <8>;
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
i2s-rec@b2000000 {
|
||||
compatible = "snps,designware-i2s";
|
||||
reg = <0xb2000000 0x10000>;
|
||||
interrupt-names = "record_irq";
|
||||
interrupts = <0 100 0x4
|
||||
0 101 0x4>;
|
||||
record;
|
||||
channel = <8>;
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
pinmux: pinmux@e0700000 {
|
||||
compatible = "st,spear1340-pinmux";
|
||||
reg = <0xe0700000 0x1000>;
|
||||
#gpio-range-cells = <2>;
|
||||
};
|
||||
|
||||
pwm: pwm@e0180000 {
|
||||
compatible ="st,spear13xx-pwm";
|
||||
reg = <0xe0180000 0x1000>;
|
||||
#pwm-cells = <2>;
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
spdif-in@d0100000 {
|
||||
compatible = "st,spdif-in";
|
||||
reg = < 0xd0100000 0x20000
|
||||
0xd0110000 0x10000 >;
|
||||
interrupts = <0 84 0x4>;
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
spdif-out@d0000000 {
|
||||
compatible = "st,spdif-out";
|
||||
reg = <0xd0000000 0x20000>;
|
||||
interrupts = <0 85 0x4>;
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
spi1: spi@5d400000 {
|
||||
compatible = "arm,pl022", "arm,primecell";
|
||||
reg = <0x5d400000 0x1000>;
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
interrupts = <0 99 0x4>;
|
||||
status = "disabled";
|
||||
};
|
||||
|
@ -38,6 +104,7 @@
|
|||
compatible = "snps,designware-i2c";
|
||||
reg = <0xb4000000 0x1000>;
|
||||
interrupts = <0 104 0x4>;
|
||||
write-16bit;
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
|
@ -51,6 +118,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>;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
|
|
@ -64,12 +64,26 @@
|
|||
bootargs = "console=ttyAMA0,115200";
|
||||
};
|
||||
|
||||
cpufreq {
|
||||
compatible = "st,cpufreq-spear";
|
||||
cpufreq_tbl = < 166000
|
||||
200000
|
||||
250000
|
||||
300000
|
||||
400000
|
||||
500000
|
||||
600000 >;
|
||||
status = "disable";
|
||||
};
|
||||
|
||||
ahb {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <1>;
|
||||
compatible = "simple-bus";
|
||||
ranges = <0x50000000 0x50000000 0x10000000
|
||||
0xb0000000 0xb0000000 0x10000000
|
||||
0xd0000000 0xd0000000 0x02000000
|
||||
0xd8000000 0xd8000000 0x01000000
|
||||
0xe0000000 0xe0000000 0x10000000>;
|
||||
|
||||
sdhci@b3000000 {
|
||||
|
@ -81,7 +95,7 @@
|
|||
|
||||
cf@b2800000 {
|
||||
compatible = "arasan,cf-spear1340";
|
||||
reg = <0xb2800000 0x100>;
|
||||
reg = <0xb2800000 0x1000>;
|
||||
interrupts = <0 29 0x4>;
|
||||
status = "disabled";
|
||||
};
|
||||
|
@ -113,6 +127,7 @@
|
|||
0 23 0x4>;
|
||||
st,ale-off = <0x20000>;
|
||||
st,cle-off = <0x10000>;
|
||||
st,mode = <2>;
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
|
@ -125,6 +140,13 @@
|
|||
status = "disabled";
|
||||
};
|
||||
|
||||
pcm {
|
||||
compatible = "st,pcm-audio";
|
||||
#address-cells = <0>;
|
||||
#size-cells = <0>;
|
||||
status = "disable";
|
||||
};
|
||||
|
||||
smi: flash@ea000000 {
|
||||
compatible = "st,spear600-smi";
|
||||
#address-cells = <1>;
|
||||
|
@ -134,17 +156,11 @@
|
|||
status = "disabled";
|
||||
};
|
||||
|
||||
spi0: spi@e0100000 {
|
||||
compatible = "arm,pl022", "arm,primecell";
|
||||
reg = <0xe0100000 0x1000>;
|
||||
interrupts = <0 31 0x4>;
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
ehci@e4800000 {
|
||||
compatible = "st,spear600-ehci", "usb-ehci";
|
||||
reg = <0xe4800000 0x1000>;
|
||||
interrupts = <0 64 0x4>;
|
||||
usbh0_id = <0>;
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
|
@ -152,6 +168,7 @@
|
|||
compatible = "st,spear600-ehci", "usb-ehci";
|
||||
reg = <0xe5800000 0x1000>;
|
||||
interrupts = <0 66 0x4>;
|
||||
usbh1_id = <1>;
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
|
@ -159,6 +176,7 @@
|
|||
compatible = "st,spear600-ohci", "usb-ohci";
|
||||
reg = <0xe4000000 0x1000>;
|
||||
interrupts = <0 65 0x4>;
|
||||
usbh0_id = <0>;
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
|
@ -166,6 +184,7 @@
|
|||
compatible = "st,spear600-ohci", "usb-ohci";
|
||||
reg = <0xe5000000 0x1000>;
|
||||
interrupts = <0 67 0x4>;
|
||||
usbh1_id = <1>;
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
|
@ -175,6 +194,8 @@
|
|||
compatible = "simple-bus";
|
||||
ranges = <0x50000000 0x50000000 0x10000000
|
||||
0xb0000000 0xb0000000 0x10000000
|
||||
0xd0000000 0xd0000000 0x02000000
|
||||
0xd8000000 0xd8000000 0x01000000
|
||||
0xe0000000 0xe0000000 0x10000000>;
|
||||
|
||||
gpio0: gpio@e0600000 {
|
||||
|
@ -215,8 +236,35 @@
|
|||
status = "disabled";
|
||||
};
|
||||
|
||||
i2s@e0180000 {
|
||||
compatible = "st,designware-i2s";
|
||||
reg = <0xe0180000 0x1000>;
|
||||
interrupt-names = "play_irq", "record_irq";
|
||||
interrupts = <0 10 0x4
|
||||
0 11 0x4 >;
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
i2s@e0200000 {
|
||||
compatible = "st,designware-i2s";
|
||||
reg = <0xe0200000 0x1000>;
|
||||
interrupt-names = "play_irq", "record_irq";
|
||||
interrupts = <0 26 0x4
|
||||
0 53 0x4>;
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
spi0: spi@e0100000 {
|
||||
compatible = "arm,pl022", "arm,primecell";
|
||||
reg = <0xe0100000 0x1000>;
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
interrupts = <0 31 0x4>;
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
rtc@e0580000 {
|
||||
compatible = "st,spear-rtc";
|
||||
compatible = "st,spear600-rtc";
|
||||
reg = <0xe0580000 0x1000>;
|
||||
interrupts = <0 36 0x4>;
|
||||
status = "disabled";
|
||||
|
@ -232,7 +280,7 @@
|
|||
adc@e0080000 {
|
||||
compatible = "st,spear600-adc";
|
||||
reg = <0xe0080000 0x1000>;
|
||||
interrupts = <0 44 0x4>;
|
||||
interrupts = <0 12 0x4>;
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
|
@ -245,7 +293,8 @@
|
|||
timer@ec800600 {
|
||||
compatible = "arm,cortex-a9-twd-timer";
|
||||
reg = <0xec800600 0x20>;
|
||||
interrupts = <1 13 0x301>;
|
||||
interrupts = <1 13 0x4>;
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
wdt@ec800620 {
|
||||
|
@ -257,6 +306,7 @@
|
|||
thermal@e07008c4 {
|
||||
compatible = "st,thermal-spear1340";
|
||||
reg = <0xe07008c4 0x4>;
|
||||
thermal_flags = <0x7000>;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
|
|
@ -100,15 +100,23 @@
|
|||
};
|
||||
partition@10000 {
|
||||
label = "u-boot";
|
||||
reg = <0x10000 0x40000>;
|
||||
reg = <0x10000 0x50000>;
|
||||
};
|
||||
partition@50000 {
|
||||
partition@60000 {
|
||||
label = "environment";
|
||||
reg = <0x60000 0x10000>;
|
||||
};
|
||||
partition@70000 {
|
||||
label = "dtb";
|
||||
reg = <0x70000 0x10000>;
|
||||
};
|
||||
partition@80000 {
|
||||
label = "linux";
|
||||
reg = <0x50000 0x2c0000>;
|
||||
reg = <0x80000 0x310000>;
|
||||
};
|
||||
partition@310000 {
|
||||
partition@390000 {
|
||||
label = "rootfs";
|
||||
reg = <0x310000 0x4f0000>;
|
||||
reg = <0x390000 0x0>;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
@ -235,6 +243,8 @@
|
|||
|
||||
serial@d0000000 {
|
||||
status = "okay";
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <>;
|
||||
};
|
||||
|
||||
wdt@fc880000 {
|
||||
|
|
|
@ -27,7 +27,7 @@
|
|||
};
|
||||
|
||||
clcd@60000000 {
|
||||
compatible = "arm,clcd-pl110", "arm,primecell";
|
||||
compatible = "arm,pl110", "arm,primecell";
|
||||
reg = <0x60000000 0x1000>;
|
||||
interrupts = <30>;
|
||||
status = "disabled";
|
||||
|
@ -52,6 +52,14 @@
|
|||
status = "disabled";
|
||||
};
|
||||
|
||||
shirq: interrupt-controller@0x50000000 {
|
||||
compatible = "st,spear300-shirq";
|
||||
reg = <0x50000000 0x1000>;
|
||||
interrupts = <28>;
|
||||
#interrupt-cells = <1>;
|
||||
interrupt-controller;
|
||||
};
|
||||
|
||||
apb {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <1>;
|
||||
|
@ -64,12 +72,16 @@
|
|||
compatible = "arm,pl061", "arm,primecell";
|
||||
gpio-controller;
|
||||
reg = <0xa9000000 0x1000>;
|
||||
interrupts = <8>;
|
||||
interrupt-parent = <&shirq>;
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
kbd@a0000000 {
|
||||
compatible = "st,spear300-kbd";
|
||||
reg = <0xa0000000 0x1000>;
|
||||
interrupts = <7>;
|
||||
interrupt-parent = <&shirq>;
|
||||
status = "disabled";
|
||||
};
|
||||
};
|
||||
|
|
|
@ -114,15 +114,23 @@
|
|||
};
|
||||
partition@10000 {
|
||||
label = "u-boot";
|
||||
reg = <0x10000 0x40000>;
|
||||
reg = <0x10000 0x50000>;
|
||||
};
|
||||
partition@50000 {
|
||||
partition@60000 {
|
||||
label = "environment";
|
||||
reg = <0x60000 0x10000>;
|
||||
};
|
||||
partition@70000 {
|
||||
label = "dtb";
|
||||
reg = <0x70000 0x10000>;
|
||||
};
|
||||
partition@80000 {
|
||||
label = "linux";
|
||||
reg = <0x50000 0x2c0000>;
|
||||
reg = <0x80000 0x310000>;
|
||||
};
|
||||
partition@310000 {
|
||||
partition@390000 {
|
||||
label = "rootfs";
|
||||
reg = <0x310000 0x4f0000>;
|
||||
reg = <0x390000 0x0>;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
@ -158,26 +166,38 @@
|
|||
|
||||
serial@d0000000 {
|
||||
status = "okay";
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <>;
|
||||
};
|
||||
|
||||
serial@b2000000 {
|
||||
status = "okay";
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <>;
|
||||
};
|
||||
|
||||
serial@b2080000 {
|
||||
status = "okay";
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <>;
|
||||
};
|
||||
|
||||
serial@b2100000 {
|
||||
status = "okay";
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <>;
|
||||
};
|
||||
|
||||
serial@b2180000 {
|
||||
status = "okay";
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <>;
|
||||
};
|
||||
|
||||
serial@b2200000 {
|
||||
status = "okay";
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <>;
|
||||
};
|
||||
|
||||
wdt@fc880000 {
|
||||
|
|
|
@ -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 {
|
||||
|
@ -39,6 +40,14 @@
|
|||
status = "disabled";
|
||||
};
|
||||
|
||||
shirq: interrupt-controller@0xb4000000 {
|
||||
compatible = "st,spear310-shirq";
|
||||
reg = <0xb4000000 0x1000>;
|
||||
interrupts = <28 29 30 1>;
|
||||
#interrupt-cells = <1>;
|
||||
interrupt-controller;
|
||||
};
|
||||
|
||||
apb {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <1>;
|
||||
|
@ -49,32 +58,61 @@
|
|||
serial@b2000000 {
|
||||
compatible = "arm,pl011", "arm,primecell";
|
||||
reg = <0xb2000000 0x1000>;
|
||||
interrupts = <8>;
|
||||
interrupt-parent = <&shirq>;
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
serial@b2080000 {
|
||||
compatible = "arm,pl011", "arm,primecell";
|
||||
reg = <0xb2080000 0x1000>;
|
||||
interrupts = <9>;
|
||||
interrupt-parent = <&shirq>;
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
serial@b2100000 {
|
||||
compatible = "arm,pl011", "arm,primecell";
|
||||
reg = <0xb2100000 0x1000>;
|
||||
interrupts = <10>;
|
||||
interrupt-parent = <&shirq>;
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
serial@b2180000 {
|
||||
compatible = "arm,pl011", "arm,primecell";
|
||||
reg = <0xb2180000 0x1000>;
|
||||
interrupts = <11>;
|
||||
interrupt-parent = <&shirq>;
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
serial@b2200000 {
|
||||
compatible = "arm,pl011", "arm,primecell";
|
||||
reg = <0xb2200000 0x1000>;
|
||||
interrupts = <12>;
|
||||
interrupt-parent = <&shirq>;
|
||||
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>;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
|
|
@ -76,20 +76,12 @@
|
|||
st,function = "mii2";
|
||||
};
|
||||
pwm0_1 {
|
||||
st,pins = "pwm0_1_pin_14_15_grp";
|
||||
st,pins = "pwm0_1_pin_37_38_grp";
|
||||
st,function = "pwm0_1";
|
||||
};
|
||||
pwm2 {
|
||||
st,pins = "pwm2_pin_13_grp";
|
||||
st,function = "pwm2";
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
clcd@90000000 {
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
dma@fc400000 {
|
||||
status = "okay";
|
||||
};
|
||||
|
@ -103,6 +95,7 @@
|
|||
};
|
||||
|
||||
sdhci@70000000 {
|
||||
power-gpio = <&gpiopinctrl 61 1>;
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
|
@ -122,15 +115,23 @@
|
|||
};
|
||||
partition@10000 {
|
||||
label = "u-boot";
|
||||
reg = <0x10000 0x40000>;
|
||||
reg = <0x10000 0x50000>;
|
||||
};
|
||||
partition@50000 {
|
||||
partition@60000 {
|
||||
label = "environment";
|
||||
reg = <0x60000 0x10000>;
|
||||
};
|
||||
partition@70000 {
|
||||
label = "dtb";
|
||||
reg = <0x70000 0x10000>;
|
||||
};
|
||||
partition@80000 {
|
||||
label = "linux";
|
||||
reg = <0x50000 0x2c0000>;
|
||||
reg = <0x80000 0x310000>;
|
||||
};
|
||||
partition@310000 {
|
||||
partition@390000 {
|
||||
label = "rootfs";
|
||||
reg = <0x310000 0x4f0000>;
|
||||
reg = <0x390000 0x0>;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
@ -164,6 +165,10 @@
|
|||
status = "okay";
|
||||
};
|
||||
|
||||
gpio@b3000000 {
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
i2c0: i2c@d0180000 {
|
||||
status = "okay";
|
||||
};
|
||||
|
@ -178,14 +183,20 @@
|
|||
|
||||
serial@d0000000 {
|
||||
status = "okay";
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <>;
|
||||
};
|
||||
|
||||
serial@a3000000 {
|
||||
status = "okay";
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <>;
|
||||
};
|
||||
|
||||
serial@a4000000 {
|
||||
status = "okay";
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <>;
|
||||
};
|
||||
|
||||
wdt@fc880000 {
|
||||
|
|
|
@ -0,0 +1,305 @@
|
|||
/*
|
||||
* DTS file for SPEAr320 Evaluation Baord
|
||||
*
|
||||
* Copyright 2012 Shiraz Hashim <shiraz.hashim@st.com>
|
||||
*
|
||||
* The code contained herein is licensed under the GNU General Public
|
||||
* License. You may obtain a copy of the GNU General Public License
|
||||
* Version 2 or later at the following locations:
|
||||
*
|
||||
* http://www.opensource.org/licenses/gpl-license.html
|
||||
* http://www.gnu.org/copyleft/gpl.html
|
||||
*/
|
||||
|
||||
/dts-v1/;
|
||||
/include/ "spear320.dtsi"
|
||||
|
||||
/ {
|
||||
model = "ST SPEAr320 HMI Board";
|
||||
compatible = "st,spear320-hmi", "st,spear320";
|
||||
#address-cells = <1>;
|
||||
#size-cells = <1>;
|
||||
|
||||
memory {
|
||||
reg = <0 0x40000000>;
|
||||
};
|
||||
|
||||
ahb {
|
||||
pinmux@b3000000 {
|
||||
st,pinmux-mode = <4>;
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <&state_default>;
|
||||
|
||||
state_default: pinmux {
|
||||
i2c0 {
|
||||
st,pins = "i2c0_grp";
|
||||
st,function = "i2c0";
|
||||
};
|
||||
ssp0 {
|
||||
st,pins = "ssp0_grp";
|
||||
st,function = "ssp0";
|
||||
};
|
||||
uart0 {
|
||||
st,pins = "uart0_grp";
|
||||
st,function = "uart0";
|
||||
};
|
||||
clcd {
|
||||
st,pins = "clcd_grp";
|
||||
st,function = "clcd";
|
||||
};
|
||||
fsmc {
|
||||
st,pins = "fsmc_8bit_grp";
|
||||
st,function = "fsmc";
|
||||
};
|
||||
sdhci {
|
||||
st,pins = "sdhci_cd_12_grp";
|
||||
st,function = "sdhci";
|
||||
};
|
||||
i2s {
|
||||
st,pins = "i2s_grp";
|
||||
st,function = "i2s";
|
||||
};
|
||||
uart1 {
|
||||
st,pins = "uart1_grp";
|
||||
st,function = "uart1";
|
||||
};
|
||||
uart2 {
|
||||
st,pins = "uart2_grp";
|
||||
st,function = "uart2";
|
||||
};
|
||||
can0 {
|
||||
st,pins = "can0_grp";
|
||||
st,function = "can0";
|
||||
};
|
||||
can1 {
|
||||
st,pins = "can1_grp";
|
||||
st,function = "can1";
|
||||
};
|
||||
mii0_1 {
|
||||
st,pins = "rmii0_1_grp";
|
||||
st,function = "mii0_1";
|
||||
};
|
||||
pwm0_1 {
|
||||
st,pins = "pwm0_1_pin_37_38_grp";
|
||||
st,function = "pwm0_1";
|
||||
};
|
||||
pwm2 {
|
||||
st,pins = "pwm2_pin_34_grp";
|
||||
st,function = "pwm2";
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
clcd@90000000 {
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
dma@fc400000 {
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
ehci@e1800000 {
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
fsmc: flash@4c000000 {
|
||||
status = "okay";
|
||||
|
||||
partition@0 {
|
||||
label = "xloader";
|
||||
reg = <0x0 0x80000>;
|
||||
};
|
||||
partition@80000 {
|
||||
label = "u-boot";
|
||||
reg = <0x80000 0x140000>;
|
||||
};
|
||||
partition@1C0000 {
|
||||
label = "environment";
|
||||
reg = <0x1C0000 0x40000>;
|
||||
};
|
||||
partition@200000 {
|
||||
label = "dtb";
|
||||
reg = <0x200000 0x40000>;
|
||||
};
|
||||
partition@240000 {
|
||||
label = "linux";
|
||||
reg = <0x240000 0xC00000>;
|
||||
};
|
||||
partition@E40000 {
|
||||
label = "rootfs";
|
||||
reg = <0xE40000 0x0>;
|
||||
};
|
||||
};
|
||||
|
||||
gpio_keys {
|
||||
compatible = "gpio-keys";
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
button@1 {
|
||||
label = "user button 1";
|
||||
linux,code = <0x100>;
|
||||
gpios = <&stmpegpio 3 0x4>;
|
||||
debounce-interval = <20>;
|
||||
gpio-key,wakeup = <1>;
|
||||
};
|
||||
|
||||
button@2 {
|
||||
label = "user button 2";
|
||||
linux,code = <0x200>;
|
||||
gpios = <&stmpegpio 2 0x4>;
|
||||
debounce-interval = <20>;
|
||||
gpio-key,wakeup = <1>;
|
||||
};
|
||||
};
|
||||
|
||||
ohci@e1900000 {
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
ohci@e2100000 {
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
pwm: pwm@a8000000 {
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
sdhci@70000000 {
|
||||
power-gpio = <&gpiopinctrl 50 1>;
|
||||
power_always_enb;
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
smi: flash@fc000000 {
|
||||
status = "okay";
|
||||
clock-rate=<50000000>;
|
||||
|
||||
flash@f8000000 {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <1>;
|
||||
reg = <0xf8000000 0x800000>;
|
||||
st,smi-fast-mode;
|
||||
|
||||
partition@0 {
|
||||
label = "xloader";
|
||||
reg = <0x0 0x10000>;
|
||||
};
|
||||
partition@10000 {
|
||||
label = "u-boot";
|
||||
reg = <0x10000 0x50000>;
|
||||
};
|
||||
partition@60000 {
|
||||
label = "environment";
|
||||
reg = <0x60000 0x10000>;
|
||||
};
|
||||
partition@70000 {
|
||||
label = "dtb";
|
||||
reg = <0x70000 0x10000>;
|
||||
};
|
||||
partition@80000 {
|
||||
label = "linux";
|
||||
reg = <0x80000 0x310000>;
|
||||
};
|
||||
partition@390000 {
|
||||
label = "rootfs";
|
||||
reg = <0x390000 0x0>;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
spi0: spi@d0100000 {
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
spi1: spi@a5000000 {
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
spi2: spi@a6000000 {
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
usbd@e1100000 {
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
apb {
|
||||
gpio0: gpio@fc980000 {
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
gpio@b3000000 {
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
i2c0: i2c@d0180000 {
|
||||
status = "okay";
|
||||
|
||||
stmpe811@41 {
|
||||
compatible = "st,stmpe811";
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
reg = <0x41>;
|
||||
irq-over-gpio;
|
||||
irq-gpios = <&gpiopinctrl 29 0x4>;
|
||||
id = <0>;
|
||||
blocks = <0x5>;
|
||||
irq-trigger = <0x1>;
|
||||
|
||||
stmpegpio: stmpe-gpio {
|
||||
compatible = "stmpe,gpio";
|
||||
reg = <0>;
|
||||
gpio-controller;
|
||||
#gpio-cells = <2>;
|
||||
gpio,norequest-mask = <0xF3>;
|
||||
};
|
||||
|
||||
stmpe610-ts {
|
||||
compatible = "stmpe,ts";
|
||||
reg = <0>;
|
||||
ts,sample-time = <4>;
|
||||
ts,mod-12b = <1>;
|
||||
ts,ref-sel = <0>;
|
||||
ts,adc-freq = <1>;
|
||||
ts,ave-ctrl = <1>;
|
||||
ts,touch-det-delay = <3>;
|
||||
ts,settling = <4>;
|
||||
ts,fraction-z = <7>;
|
||||
ts,i-drive = <1>;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
i2c1: i2c@a7000000 {
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
rtc@fc900000 {
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
serial@d0000000 {
|
||||
status = "okay";
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <>;
|
||||
};
|
||||
|
||||
serial@a3000000 {
|
||||
status = "okay";
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <>;
|
||||
};
|
||||
|
||||
serial@a4000000 {
|
||||
status = "okay";
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <>;
|
||||
};
|
||||
|
||||
wdt@fc880000 {
|
||||
status = "okay";
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
|
@ -21,15 +21,17 @@
|
|||
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 {
|
||||
compatible = "arm,clcd-pl110", "arm,primecell";
|
||||
compatible = "arm,pl110", "arm,primecell";
|
||||
reg = <0x90000000 0x1000>;
|
||||
interrupts = <33>;
|
||||
interrupts = <8>;
|
||||
interrupt-parent = <&shirq>;
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
|
@ -48,27 +50,51 @@
|
|||
sdhci@70000000 {
|
||||
compatible = "st,sdhci-spear";
|
||||
reg = <0x70000000 0x100>;
|
||||
interrupts = <29>;
|
||||
interrupts = <10>;
|
||||
interrupt-parent = <&shirq>;
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
shirq: interrupt-controller@0xb3000000 {
|
||||
compatible = "st,spear320-shirq";
|
||||
reg = <0xb3000000 0x1000>;
|
||||
interrupts = <30 28 29 1>;
|
||||
#interrupt-cells = <1>;
|
||||
interrupt-controller;
|
||||
};
|
||||
|
||||
spi1: spi@a5000000 {
|
||||
compatible = "arm,pl022", "arm,primecell";
|
||||
reg = <0xa5000000 0x1000>;
|
||||
interrupts = <15>;
|
||||
interrupt-parent = <&shirq>;
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
spi2: spi@a6000000 {
|
||||
compatible = "arm,pl022", "arm,primecell";
|
||||
reg = <0xa6000000 0x1000>;
|
||||
interrupts = <16>;
|
||||
interrupt-parent = <&shirq>;
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
pwm: pwm@a8000000 {
|
||||
compatible ="st,spear-pwm";
|
||||
reg = <0xa8000000 0x1000>;
|
||||
#pwm-cells = <2>;
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
apb {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <1>;
|
||||
compatible = "simple-bus";
|
||||
ranges = <0xa0000000 0xa0000000 0x10000000
|
||||
ranges = <0xa0000000 0xa0000000 0x20000000
|
||||
0xd0000000 0xd0000000 0x30000000>;
|
||||
|
||||
i2c1: i2c@a7000000 {
|
||||
|
@ -76,20 +102,46 @@
|
|||
#size-cells = <0>;
|
||||
compatible = "snps,designware-i2c";
|
||||
reg = <0xa7000000 0x1000>;
|
||||
interrupts = <21>;
|
||||
interrupt-parent = <&shirq>;
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
serial@a3000000 {
|
||||
compatible = "arm,pl011", "arm,primecell";
|
||||
reg = <0xa3000000 0x1000>;
|
||||
interrupts = <13>;
|
||||
interrupt-parent = <&shirq>;
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
serial@a4000000 {
|
||||
compatible = "arm,pl011", "arm,primecell";
|
||||
reg = <0xa4000000 0x1000>;
|
||||
interrupts = <14>;
|
||||
interrupt-parent = <&shirq>;
|
||||
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>;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
|
|
@ -53,6 +53,7 @@
|
|||
reg = <0xe0800000 0x8000>;
|
||||
interrupts = <23 22>;
|
||||
interrupt-names = "macirq", "eth_wake_irq";
|
||||
phy-mode = "mii";
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
|
@ -69,6 +70,8 @@
|
|||
compatible = "arm,pl022", "arm,primecell";
|
||||
reg = <0xd0100000 0x1000>;
|
||||
interrupts = <20>;
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
|
@ -120,7 +123,7 @@
|
|||
};
|
||||
|
||||
rtc@fc900000 {
|
||||
compatible = "st,spear-rtc";
|
||||
compatible = "st,spear600-rtc";
|
||||
reg = <0xfc900000 0x1000>;
|
||||
interrupts = <10>;
|
||||
status = "disabled";
|
||||
|
|
|
@ -24,15 +24,35 @@
|
|||
};
|
||||
|
||||
ahb {
|
||||
clcd@fc200000 {
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
dma@fc400000 {
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
ehci@e1800000 {
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
ehci@e2000000 {
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
gmac: ethernet@e0800000 {
|
||||
phy-mode = "gmii";
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
ohci@e1900000 {
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
ohci@e2100000 {
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
smi: flash@fc000000 {
|
||||
status = "okay";
|
||||
clock-rate=<50000000>;
|
||||
|
@ -49,15 +69,23 @@
|
|||
};
|
||||
partition@10000 {
|
||||
label = "u-boot";
|
||||
reg = <0x10000 0x40000>;
|
||||
reg = <0x10000 0x50000>;
|
||||
};
|
||||
partition@50000 {
|
||||
partition@60000 {
|
||||
label = "environment";
|
||||
reg = <0x60000 0x10000>;
|
||||
};
|
||||
partition@70000 {
|
||||
label = "dtb";
|
||||
reg = <0x70000 0x10000>;
|
||||
};
|
||||
partition@80000 {
|
||||
label = "linux";
|
||||
reg = <0x50000 0x2c0000>;
|
||||
reg = <0x80000 0x310000>;
|
||||
};
|
||||
partition@310000 {
|
||||
partition@390000 {
|
||||
label = "rootfs";
|
||||
reg = <0x310000 0x4f0000>;
|
||||
reg = <0x390000 0x0>;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
@ -65,10 +93,18 @@
|
|||
apb {
|
||||
serial@d0000000 {
|
||||
status = "okay";
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <>;
|
||||
};
|
||||
|
||||
serial@d0080000 {
|
||||
status = "okay";
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <>;
|
||||
};
|
||||
|
||||
rtc@fc900000 {
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
i2c@d0200000 {
|
||||
|
|
|
@ -45,6 +45,14 @@
|
|||
#interrupt-cells = <1>;
|
||||
};
|
||||
|
||||
clcd@fc200000 {
|
||||
compatible = "arm,pl110", "arm,primecell";
|
||||
reg = <0xfc200000 0x1000>;
|
||||
interrupt-parent = <&vic1>;
|
||||
interrupts = <12>;
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
dma@fc400000 {
|
||||
compatible = "arm,pl080", "arm,primecell";
|
||||
reg = <0xfc400000 0x1000>;
|
||||
|
@ -59,6 +67,7 @@
|
|||
interrupt-parent = <&vic1>;
|
||||
interrupts = <24 23>;
|
||||
interrupt-names = "macirq", "eth_wake_irq";
|
||||
phy-mode = "gmii";
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
|
@ -178,6 +187,13 @@
|
|||
status = "disabled";
|
||||
};
|
||||
|
||||
rtc@fc900000 {
|
||||
compatible = "st,spear600-rtc";
|
||||
reg = <0xfc900000 0x1000>;
|
||||
interrupts = <10>;
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
timer@f0000000 {
|
||||
compatible = "st,spear-timer";
|
||||
reg = <0xf0000000 0x400>;
|
||||
|
|
|
@ -47,14 +47,6 @@
|
|||
#define DMAC1_BASE UL(0xEB000000)
|
||||
#define MCIF_CF_BASE UL(0xB2800000)
|
||||
|
||||
/* Devices present in SPEAr1310 */
|
||||
#ifdef CONFIG_MACH_SPEAR1310
|
||||
#define SPEAR1310_RAS_GRP1_BASE UL(0xD8000000)
|
||||
#define VA_SPEAR1310_RAS_GRP1_BASE UL(0xFA000000)
|
||||
#define SPEAR1310_RAS_BASE UL(0xD8400000)
|
||||
#define VA_SPEAR1310_RAS_BASE IOMEM(UL(0xFA400000))
|
||||
#endif /* CONFIG_MACH_SPEAR1310 */
|
||||
|
||||
/* Debug uart for linux, will be used for debug and uncompress messages */
|
||||
#define SPEAR_DBG_UART_BASE UART_BASE
|
||||
#define VA_SPEAR_DBG_UART_BASE VA_UART_BASE
|
||||
|
|
|
@ -15,6 +15,7 @@
|
|||
|
||||
#include <linux/amba/pl022.h>
|
||||
#include <linux/of_platform.h>
|
||||
#include <linux/pata_arasan_cf_data.h>
|
||||
#include <asm/hardware/gic.h>
|
||||
#include <asm/mach/arch.h>
|
||||
#include <asm/mach/map.h>
|
||||
|
@ -27,16 +28,25 @@
|
|||
#define SPEAR1310_SATA1_BASE UL(0xB1800000)
|
||||
#define SPEAR1310_SATA2_BASE UL(0xB4000000)
|
||||
|
||||
#define SPEAR1310_RAS_GRP1_BASE UL(0xD8000000)
|
||||
#define VA_SPEAR1310_RAS_GRP1_BASE UL(0xFA000000)
|
||||
#define SPEAR1310_RAS_BASE UL(0xD8400000)
|
||||
#define VA_SPEAR1310_RAS_BASE IOMEM(UL(0xFA400000))
|
||||
|
||||
static struct arasan_cf_pdata cf_pdata = {
|
||||
.cf_if_clk = CF_IF_CLK_166M,
|
||||
.quirk = CF_BROKEN_UDMA,
|
||||
.dma_priv = &cf_dma_priv,
|
||||
};
|
||||
|
||||
/* ssp device registration */
|
||||
static struct pl022_ssp_controller ssp1_plat_data = {
|
||||
.bus_id = 0,
|
||||
.enable_dma = 0,
|
||||
.num_chipselect = 3,
|
||||
};
|
||||
|
||||
/* Add SPEAr1310 auxdata to pass platform data */
|
||||
static struct of_dev_auxdata spear1310_auxdata_lookup[] __initdata = {
|
||||
OF_DEV_AUXDATA("arasan,cf-spear1340", MCIF_CF_BASE, NULL, &cf_dma_priv),
|
||||
OF_DEV_AUXDATA("arasan,cf-spear1340", MCIF_CF_BASE, NULL, &cf_pdata),
|
||||
OF_DEV_AUXDATA("snps,dma-spear1340", DMAC0_BASE, NULL, &dmac_plat_data),
|
||||
OF_DEV_AUXDATA("snps,dma-spear1340", DMAC1_BASE, NULL, &dmac_plat_data),
|
||||
OF_DEV_AUXDATA("arm,pl022", SSP_BASE, NULL, &pl022_plat_data),
|
||||
|
|
|
@ -57,12 +57,10 @@ static struct dw_dma_slave ssp_dma_param[] = {
|
|||
};
|
||||
|
||||
struct pl022_ssp_controller pl022_plat_data = {
|
||||
.bus_id = 0,
|
||||
.enable_dma = 1,
|
||||
.dma_filter = dw_dma_filter,
|
||||
.dma_rx_param = &ssp_dma_param[1],
|
||||
.dma_tx_param = &ssp_dma_param[0],
|
||||
.num_chipselect = 3,
|
||||
};
|
||||
|
||||
/* CF device registration */
|
||||
|
|
|
@ -14,14 +14,6 @@
|
|||
#ifndef __MACH_IRQS_H
|
||||
#define __MACH_IRQS_H
|
||||
|
||||
/* FIXME: probe all these from DT */
|
||||
#define SPEAR3XX_IRQ_INTRCOMM_RAS_ARM 1
|
||||
#define SPEAR3XX_IRQ_GEN_RAS_1 28
|
||||
#define SPEAR3XX_IRQ_GEN_RAS_2 29
|
||||
#define SPEAR3XX_IRQ_GEN_RAS_3 30
|
||||
#define SPEAR3XX_IRQ_VIC_END 32
|
||||
#define SPEAR3XX_VIRQ_START SPEAR3XX_IRQ_VIC_END
|
||||
|
||||
#define NR_IRQS 160
|
||||
#define NR_IRQS 256
|
||||
|
||||
#endif /* __MACH_IRQS_H */
|
||||
|
|
|
@ -17,102 +17,9 @@
|
|||
#include <linux/of_platform.h>
|
||||
#include <asm/hardware/vic.h>
|
||||
#include <asm/mach/arch.h>
|
||||
#include <plat/shirq.h>
|
||||
#include <mach/generic.h>
|
||||
#include <mach/spear.h>
|
||||
|
||||
/* Base address of various IPs */
|
||||
#define SPEAR300_TELECOM_BASE UL(0x50000000)
|
||||
|
||||
/* Interrupt registers offsets and masks */
|
||||
#define SPEAR300_INT_ENB_MASK_REG 0x54
|
||||
#define SPEAR300_INT_STS_MASK_REG 0x58
|
||||
#define SPEAR300_IT_PERS_S_IRQ_MASK (1 << 0)
|
||||
#define SPEAR300_IT_CHANGE_S_IRQ_MASK (1 << 1)
|
||||
#define SPEAR300_I2S_IRQ_MASK (1 << 2)
|
||||
#define SPEAR300_TDM_IRQ_MASK (1 << 3)
|
||||
#define SPEAR300_CAMERA_L_IRQ_MASK (1 << 4)
|
||||
#define SPEAR300_CAMERA_F_IRQ_MASK (1 << 5)
|
||||
#define SPEAR300_CAMERA_V_IRQ_MASK (1 << 6)
|
||||
#define SPEAR300_KEYBOARD_IRQ_MASK (1 << 7)
|
||||
#define SPEAR300_GPIO1_IRQ_MASK (1 << 8)
|
||||
|
||||
#define SPEAR300_SHIRQ_RAS1_MASK 0x1FF
|
||||
|
||||
#define SPEAR300_SOC_CONFIG_BASE UL(0x99000000)
|
||||
|
||||
|
||||
/* SPEAr300 Virtual irq definitions */
|
||||
/* IRQs sharing IRQ_GEN_RAS_1 */
|
||||
#define SPEAR300_VIRQ_IT_PERS_S (SPEAR3XX_VIRQ_START + 0)
|
||||
#define SPEAR300_VIRQ_IT_CHANGE_S (SPEAR3XX_VIRQ_START + 1)
|
||||
#define SPEAR300_VIRQ_I2S (SPEAR3XX_VIRQ_START + 2)
|
||||
#define SPEAR300_VIRQ_TDM (SPEAR3XX_VIRQ_START + 3)
|
||||
#define SPEAR300_VIRQ_CAMERA_L (SPEAR3XX_VIRQ_START + 4)
|
||||
#define SPEAR300_VIRQ_CAMERA_F (SPEAR3XX_VIRQ_START + 5)
|
||||
#define SPEAR300_VIRQ_CAMERA_V (SPEAR3XX_VIRQ_START + 6)
|
||||
#define SPEAR300_VIRQ_KEYBOARD (SPEAR3XX_VIRQ_START + 7)
|
||||
#define SPEAR300_VIRQ_GPIO1 (SPEAR3XX_VIRQ_START + 8)
|
||||
|
||||
/* IRQs sharing IRQ_GEN_RAS_3 */
|
||||
#define SPEAR300_IRQ_CLCD SPEAR3XX_IRQ_GEN_RAS_3
|
||||
|
||||
/* IRQs sharing IRQ_INTRCOMM_RAS_ARM */
|
||||
#define SPEAR300_IRQ_SDHCI SPEAR3XX_IRQ_INTRCOMM_RAS_ARM
|
||||
|
||||
/* spear3xx shared irq */
|
||||
static struct shirq_dev_config shirq_ras1_config[] = {
|
||||
{
|
||||
.virq = SPEAR300_VIRQ_IT_PERS_S,
|
||||
.enb_mask = SPEAR300_IT_PERS_S_IRQ_MASK,
|
||||
.status_mask = SPEAR300_IT_PERS_S_IRQ_MASK,
|
||||
}, {
|
||||
.virq = SPEAR300_VIRQ_IT_CHANGE_S,
|
||||
.enb_mask = SPEAR300_IT_CHANGE_S_IRQ_MASK,
|
||||
.status_mask = SPEAR300_IT_CHANGE_S_IRQ_MASK,
|
||||
}, {
|
||||
.virq = SPEAR300_VIRQ_I2S,
|
||||
.enb_mask = SPEAR300_I2S_IRQ_MASK,
|
||||
.status_mask = SPEAR300_I2S_IRQ_MASK,
|
||||
}, {
|
||||
.virq = SPEAR300_VIRQ_TDM,
|
||||
.enb_mask = SPEAR300_TDM_IRQ_MASK,
|
||||
.status_mask = SPEAR300_TDM_IRQ_MASK,
|
||||
}, {
|
||||
.virq = SPEAR300_VIRQ_CAMERA_L,
|
||||
.enb_mask = SPEAR300_CAMERA_L_IRQ_MASK,
|
||||
.status_mask = SPEAR300_CAMERA_L_IRQ_MASK,
|
||||
}, {
|
||||
.virq = SPEAR300_VIRQ_CAMERA_F,
|
||||
.enb_mask = SPEAR300_CAMERA_F_IRQ_MASK,
|
||||
.status_mask = SPEAR300_CAMERA_F_IRQ_MASK,
|
||||
}, {
|
||||
.virq = SPEAR300_VIRQ_CAMERA_V,
|
||||
.enb_mask = SPEAR300_CAMERA_V_IRQ_MASK,
|
||||
.status_mask = SPEAR300_CAMERA_V_IRQ_MASK,
|
||||
}, {
|
||||
.virq = SPEAR300_VIRQ_KEYBOARD,
|
||||
.enb_mask = SPEAR300_KEYBOARD_IRQ_MASK,
|
||||
.status_mask = SPEAR300_KEYBOARD_IRQ_MASK,
|
||||
}, {
|
||||
.virq = SPEAR300_VIRQ_GPIO1,
|
||||
.enb_mask = SPEAR300_GPIO1_IRQ_MASK,
|
||||
.status_mask = SPEAR300_GPIO1_IRQ_MASK,
|
||||
},
|
||||
};
|
||||
|
||||
static struct spear_shirq shirq_ras1 = {
|
||||
.irq = SPEAR3XX_IRQ_GEN_RAS_1,
|
||||
.dev_config = shirq_ras1_config,
|
||||
.dev_count = ARRAY_SIZE(shirq_ras1_config),
|
||||
.regs = {
|
||||
.enb_reg = SPEAR300_INT_ENB_MASK_REG,
|
||||
.status_reg = SPEAR300_INT_STS_MASK_REG,
|
||||
.status_reg_mask = SPEAR300_SHIRQ_RAS1_MASK,
|
||||
.clear_reg = -1,
|
||||
},
|
||||
};
|
||||
|
||||
/* DMAC platform data's slave info */
|
||||
struct pl08x_channel_data spear300_dma_info[] = {
|
||||
{
|
||||
|
@ -285,21 +192,11 @@ static struct of_dev_auxdata spear300_auxdata_lookup[] __initdata = {
|
|||
|
||||
static void __init spear300_dt_init(void)
|
||||
{
|
||||
int ret;
|
||||
|
||||
pl080_plat_data.slave_channels = spear300_dma_info;
|
||||
pl080_plat_data.num_slave_channels = ARRAY_SIZE(spear300_dma_info);
|
||||
|
||||
of_platform_populate(NULL, of_default_bus_match_table,
|
||||
spear300_auxdata_lookup, NULL);
|
||||
|
||||
/* shared irq registration */
|
||||
shirq_ras1.regs.base = ioremap(SPEAR300_TELECOM_BASE, SZ_4K);
|
||||
if (shirq_ras1.regs.base) {
|
||||
ret = spear_shirq_register(&shirq_ras1);
|
||||
if (ret)
|
||||
pr_err("Error registering Shared IRQ\n");
|
||||
}
|
||||
}
|
||||
|
||||
static const char * const spear300_dt_board_compat[] = {
|
||||
|
|
|
@ -18,7 +18,6 @@
|
|||
#include <linux/of_platform.h>
|
||||
#include <asm/hardware/vic.h>
|
||||
#include <asm/mach/arch.h>
|
||||
#include <plat/shirq.h>
|
||||
#include <mach/generic.h>
|
||||
#include <mach/spear.h>
|
||||
|
||||
|
@ -27,176 +26,6 @@
|
|||
#define SPEAR310_UART3_BASE UL(0xB2100000)
|
||||
#define SPEAR310_UART4_BASE UL(0xB2180000)
|
||||
#define SPEAR310_UART5_BASE UL(0xB2200000)
|
||||
#define SPEAR310_SOC_CONFIG_BASE UL(0xB4000000)
|
||||
|
||||
/* Interrupt registers offsets and masks */
|
||||
#define SPEAR310_INT_STS_MASK_REG 0x04
|
||||
#define SPEAR310_SMII0_IRQ_MASK (1 << 0)
|
||||
#define SPEAR310_SMII1_IRQ_MASK (1 << 1)
|
||||
#define SPEAR310_SMII2_IRQ_MASK (1 << 2)
|
||||
#define SPEAR310_SMII3_IRQ_MASK (1 << 3)
|
||||
#define SPEAR310_WAKEUP_SMII0_IRQ_MASK (1 << 4)
|
||||
#define SPEAR310_WAKEUP_SMII1_IRQ_MASK (1 << 5)
|
||||
#define SPEAR310_WAKEUP_SMII2_IRQ_MASK (1 << 6)
|
||||
#define SPEAR310_WAKEUP_SMII3_IRQ_MASK (1 << 7)
|
||||
#define SPEAR310_UART1_IRQ_MASK (1 << 8)
|
||||
#define SPEAR310_UART2_IRQ_MASK (1 << 9)
|
||||
#define SPEAR310_UART3_IRQ_MASK (1 << 10)
|
||||
#define SPEAR310_UART4_IRQ_MASK (1 << 11)
|
||||
#define SPEAR310_UART5_IRQ_MASK (1 << 12)
|
||||
#define SPEAR310_EMI_IRQ_MASK (1 << 13)
|
||||
#define SPEAR310_TDM_HDLC_IRQ_MASK (1 << 14)
|
||||
#define SPEAR310_RS485_0_IRQ_MASK (1 << 15)
|
||||
#define SPEAR310_RS485_1_IRQ_MASK (1 << 16)
|
||||
|
||||
#define SPEAR310_SHIRQ_RAS1_MASK 0x000FF
|
||||
#define SPEAR310_SHIRQ_RAS2_MASK 0x01F00
|
||||
#define SPEAR310_SHIRQ_RAS3_MASK 0x02000
|
||||
#define SPEAR310_SHIRQ_INTRCOMM_RAS_MASK 0x1C000
|
||||
|
||||
/* SPEAr310 Virtual irq definitions */
|
||||
/* IRQs sharing IRQ_GEN_RAS_1 */
|
||||
#define SPEAR310_VIRQ_SMII0 (SPEAR3XX_VIRQ_START + 0)
|
||||
#define SPEAR310_VIRQ_SMII1 (SPEAR3XX_VIRQ_START + 1)
|
||||
#define SPEAR310_VIRQ_SMII2 (SPEAR3XX_VIRQ_START + 2)
|
||||
#define SPEAR310_VIRQ_SMII3 (SPEAR3XX_VIRQ_START + 3)
|
||||
#define SPEAR310_VIRQ_WAKEUP_SMII0 (SPEAR3XX_VIRQ_START + 4)
|
||||
#define SPEAR310_VIRQ_WAKEUP_SMII1 (SPEAR3XX_VIRQ_START + 5)
|
||||
#define SPEAR310_VIRQ_WAKEUP_SMII2 (SPEAR3XX_VIRQ_START + 6)
|
||||
#define SPEAR310_VIRQ_WAKEUP_SMII3 (SPEAR3XX_VIRQ_START + 7)
|
||||
|
||||
/* IRQs sharing IRQ_GEN_RAS_2 */
|
||||
#define SPEAR310_VIRQ_UART1 (SPEAR3XX_VIRQ_START + 8)
|
||||
#define SPEAR310_VIRQ_UART2 (SPEAR3XX_VIRQ_START + 9)
|
||||
#define SPEAR310_VIRQ_UART3 (SPEAR3XX_VIRQ_START + 10)
|
||||
#define SPEAR310_VIRQ_UART4 (SPEAR3XX_VIRQ_START + 11)
|
||||
#define SPEAR310_VIRQ_UART5 (SPEAR3XX_VIRQ_START + 12)
|
||||
|
||||
/* IRQs sharing IRQ_GEN_RAS_3 */
|
||||
#define SPEAR310_VIRQ_EMI (SPEAR3XX_VIRQ_START + 13)
|
||||
#define SPEAR310_VIRQ_PLGPIO (SPEAR3XX_VIRQ_START + 14)
|
||||
|
||||
/* IRQs sharing IRQ_INTRCOMM_RAS_ARM */
|
||||
#define SPEAR310_VIRQ_TDM_HDLC (SPEAR3XX_VIRQ_START + 15)
|
||||
#define SPEAR310_VIRQ_RS485_0 (SPEAR3XX_VIRQ_START + 16)
|
||||
#define SPEAR310_VIRQ_RS485_1 (SPEAR3XX_VIRQ_START + 17)
|
||||
|
||||
|
||||
/* spear3xx shared irq */
|
||||
static struct shirq_dev_config shirq_ras1_config[] = {
|
||||
{
|
||||
.virq = SPEAR310_VIRQ_SMII0,
|
||||
.status_mask = SPEAR310_SMII0_IRQ_MASK,
|
||||
}, {
|
||||
.virq = SPEAR310_VIRQ_SMII1,
|
||||
.status_mask = SPEAR310_SMII1_IRQ_MASK,
|
||||
}, {
|
||||
.virq = SPEAR310_VIRQ_SMII2,
|
||||
.status_mask = SPEAR310_SMII2_IRQ_MASK,
|
||||
}, {
|
||||
.virq = SPEAR310_VIRQ_SMII3,
|
||||
.status_mask = SPEAR310_SMII3_IRQ_MASK,
|
||||
}, {
|
||||
.virq = SPEAR310_VIRQ_WAKEUP_SMII0,
|
||||
.status_mask = SPEAR310_WAKEUP_SMII0_IRQ_MASK,
|
||||
}, {
|
||||
.virq = SPEAR310_VIRQ_WAKEUP_SMII1,
|
||||
.status_mask = SPEAR310_WAKEUP_SMII1_IRQ_MASK,
|
||||
}, {
|
||||
.virq = SPEAR310_VIRQ_WAKEUP_SMII2,
|
||||
.status_mask = SPEAR310_WAKEUP_SMII2_IRQ_MASK,
|
||||
}, {
|
||||
.virq = SPEAR310_VIRQ_WAKEUP_SMII3,
|
||||
.status_mask = SPEAR310_WAKEUP_SMII3_IRQ_MASK,
|
||||
},
|
||||
};
|
||||
|
||||
static struct spear_shirq shirq_ras1 = {
|
||||
.irq = SPEAR3XX_IRQ_GEN_RAS_1,
|
||||
.dev_config = shirq_ras1_config,
|
||||
.dev_count = ARRAY_SIZE(shirq_ras1_config),
|
||||
.regs = {
|
||||
.enb_reg = -1,
|
||||
.status_reg = SPEAR310_INT_STS_MASK_REG,
|
||||
.status_reg_mask = SPEAR310_SHIRQ_RAS1_MASK,
|
||||
.clear_reg = -1,
|
||||
},
|
||||
};
|
||||
|
||||
static struct shirq_dev_config shirq_ras2_config[] = {
|
||||
{
|
||||
.virq = SPEAR310_VIRQ_UART1,
|
||||
.status_mask = SPEAR310_UART1_IRQ_MASK,
|
||||
}, {
|
||||
.virq = SPEAR310_VIRQ_UART2,
|
||||
.status_mask = SPEAR310_UART2_IRQ_MASK,
|
||||
}, {
|
||||
.virq = SPEAR310_VIRQ_UART3,
|
||||
.status_mask = SPEAR310_UART3_IRQ_MASK,
|
||||
}, {
|
||||
.virq = SPEAR310_VIRQ_UART4,
|
||||
.status_mask = SPEAR310_UART4_IRQ_MASK,
|
||||
}, {
|
||||
.virq = SPEAR310_VIRQ_UART5,
|
||||
.status_mask = SPEAR310_UART5_IRQ_MASK,
|
||||
},
|
||||
};
|
||||
|
||||
static struct spear_shirq shirq_ras2 = {
|
||||
.irq = SPEAR3XX_IRQ_GEN_RAS_2,
|
||||
.dev_config = shirq_ras2_config,
|
||||
.dev_count = ARRAY_SIZE(shirq_ras2_config),
|
||||
.regs = {
|
||||
.enb_reg = -1,
|
||||
.status_reg = SPEAR310_INT_STS_MASK_REG,
|
||||
.status_reg_mask = SPEAR310_SHIRQ_RAS2_MASK,
|
||||
.clear_reg = -1,
|
||||
},
|
||||
};
|
||||
|
||||
static struct shirq_dev_config shirq_ras3_config[] = {
|
||||
{
|
||||
.virq = SPEAR310_VIRQ_EMI,
|
||||
.status_mask = SPEAR310_EMI_IRQ_MASK,
|
||||
},
|
||||
};
|
||||
|
||||
static struct spear_shirq shirq_ras3 = {
|
||||
.irq = SPEAR3XX_IRQ_GEN_RAS_3,
|
||||
.dev_config = shirq_ras3_config,
|
||||
.dev_count = ARRAY_SIZE(shirq_ras3_config),
|
||||
.regs = {
|
||||
.enb_reg = -1,
|
||||
.status_reg = SPEAR310_INT_STS_MASK_REG,
|
||||
.status_reg_mask = SPEAR310_SHIRQ_RAS3_MASK,
|
||||
.clear_reg = -1,
|
||||
},
|
||||
};
|
||||
|
||||
static struct shirq_dev_config shirq_intrcomm_ras_config[] = {
|
||||
{
|
||||
.virq = SPEAR310_VIRQ_TDM_HDLC,
|
||||
.status_mask = SPEAR310_TDM_HDLC_IRQ_MASK,
|
||||
}, {
|
||||
.virq = SPEAR310_VIRQ_RS485_0,
|
||||
.status_mask = SPEAR310_RS485_0_IRQ_MASK,
|
||||
}, {
|
||||
.virq = SPEAR310_VIRQ_RS485_1,
|
||||
.status_mask = SPEAR310_RS485_1_IRQ_MASK,
|
||||
},
|
||||
};
|
||||
|
||||
static struct spear_shirq shirq_intrcomm_ras = {
|
||||
.irq = SPEAR3XX_IRQ_INTRCOMM_RAS_ARM,
|
||||
.dev_config = shirq_intrcomm_ras_config,
|
||||
.dev_count = ARRAY_SIZE(shirq_intrcomm_ras_config),
|
||||
.regs = {
|
||||
.enb_reg = -1,
|
||||
.status_reg = SPEAR310_INT_STS_MASK_REG,
|
||||
.status_reg_mask = SPEAR310_SHIRQ_INTRCOMM_RAS_MASK,
|
||||
.clear_reg = -1,
|
||||
},
|
||||
};
|
||||
|
||||
/* DMAC platform data's slave info */
|
||||
struct pl08x_channel_data spear310_dma_info[] = {
|
||||
|
@ -405,42 +234,11 @@ static struct of_dev_auxdata spear310_auxdata_lookup[] __initdata = {
|
|||
|
||||
static void __init spear310_dt_init(void)
|
||||
{
|
||||
void __iomem *base;
|
||||
int ret;
|
||||
|
||||
pl080_plat_data.slave_channels = spear310_dma_info;
|
||||
pl080_plat_data.num_slave_channels = ARRAY_SIZE(spear310_dma_info);
|
||||
|
||||
of_platform_populate(NULL, of_default_bus_match_table,
|
||||
spear310_auxdata_lookup, NULL);
|
||||
|
||||
/* shared irq registration */
|
||||
base = ioremap(SPEAR310_SOC_CONFIG_BASE, SZ_4K);
|
||||
if (base) {
|
||||
/* shirq 1 */
|
||||
shirq_ras1.regs.base = base;
|
||||
ret = spear_shirq_register(&shirq_ras1);
|
||||
if (ret)
|
||||
pr_err("Error registering Shared IRQ 1\n");
|
||||
|
||||
/* shirq 2 */
|
||||
shirq_ras2.regs.base = base;
|
||||
ret = spear_shirq_register(&shirq_ras2);
|
||||
if (ret)
|
||||
pr_err("Error registering Shared IRQ 2\n");
|
||||
|
||||
/* shirq 3 */
|
||||
shirq_ras3.regs.base = base;
|
||||
ret = spear_shirq_register(&shirq_ras3);
|
||||
if (ret)
|
||||
pr_err("Error registering Shared IRQ 3\n");
|
||||
|
||||
/* shirq 4 */
|
||||
shirq_intrcomm_ras.regs.base = base;
|
||||
ret = spear_shirq_register(&shirq_intrcomm_ras);
|
||||
if (ret)
|
||||
pr_err("Error registering Shared IRQ 4\n");
|
||||
}
|
||||
}
|
||||
|
||||
static const char * const spear310_dt_board_compat[] = {
|
||||
|
|
|
@ -19,7 +19,6 @@
|
|||
#include <linux/of_platform.h>
|
||||
#include <asm/hardware/vic.h>
|
||||
#include <asm/mach/arch.h>
|
||||
#include <plat/shirq.h>
|
||||
#include <mach/generic.h>
|
||||
#include <mach/spear.h>
|
||||
|
||||
|
@ -28,184 +27,6 @@
|
|||
#define SPEAR320_SSP0_BASE UL(0xA5000000)
|
||||
#define SPEAR320_SSP1_BASE UL(0xA6000000)
|
||||
|
||||
/* Interrupt registers offsets and masks */
|
||||
#define SPEAR320_INT_STS_MASK_REG 0x04
|
||||
#define SPEAR320_INT_CLR_MASK_REG 0x04
|
||||
#define SPEAR320_INT_ENB_MASK_REG 0x08
|
||||
#define SPEAR320_GPIO_IRQ_MASK (1 << 0)
|
||||
#define SPEAR320_I2S_PLAY_IRQ_MASK (1 << 1)
|
||||
#define SPEAR320_I2S_REC_IRQ_MASK (1 << 2)
|
||||
#define SPEAR320_EMI_IRQ_MASK (1 << 7)
|
||||
#define SPEAR320_CLCD_IRQ_MASK (1 << 8)
|
||||
#define SPEAR320_SPP_IRQ_MASK (1 << 9)
|
||||
#define SPEAR320_SDHCI_IRQ_MASK (1 << 10)
|
||||
#define SPEAR320_CAN_U_IRQ_MASK (1 << 11)
|
||||
#define SPEAR320_CAN_L_IRQ_MASK (1 << 12)
|
||||
#define SPEAR320_UART1_IRQ_MASK (1 << 13)
|
||||
#define SPEAR320_UART2_IRQ_MASK (1 << 14)
|
||||
#define SPEAR320_SSP1_IRQ_MASK (1 << 15)
|
||||
#define SPEAR320_SSP2_IRQ_MASK (1 << 16)
|
||||
#define SPEAR320_SMII0_IRQ_MASK (1 << 17)
|
||||
#define SPEAR320_MII1_SMII1_IRQ_MASK (1 << 18)
|
||||
#define SPEAR320_WAKEUP_SMII0_IRQ_MASK (1 << 19)
|
||||
#define SPEAR320_WAKEUP_MII1_SMII1_IRQ_MASK (1 << 20)
|
||||
#define SPEAR320_I2C1_IRQ_MASK (1 << 21)
|
||||
|
||||
#define SPEAR320_SHIRQ_RAS1_MASK 0x000380
|
||||
#define SPEAR320_SHIRQ_RAS3_MASK 0x000007
|
||||
#define SPEAR320_SHIRQ_INTRCOMM_RAS_MASK 0x3FF800
|
||||
|
||||
/* SPEAr320 Virtual irq definitions */
|
||||
/* IRQs sharing IRQ_GEN_RAS_1 */
|
||||
#define SPEAR320_VIRQ_EMI (SPEAR3XX_VIRQ_START + 0)
|
||||
#define SPEAR320_VIRQ_CLCD (SPEAR3XX_VIRQ_START + 1)
|
||||
#define SPEAR320_VIRQ_SPP (SPEAR3XX_VIRQ_START + 2)
|
||||
|
||||
/* IRQs sharing IRQ_GEN_RAS_2 */
|
||||
#define SPEAR320_IRQ_SDHCI SPEAR3XX_IRQ_GEN_RAS_2
|
||||
|
||||
/* IRQs sharing IRQ_GEN_RAS_3 */
|
||||
#define SPEAR320_VIRQ_PLGPIO (SPEAR3XX_VIRQ_START + 3)
|
||||
#define SPEAR320_VIRQ_I2S_PLAY (SPEAR3XX_VIRQ_START + 4)
|
||||
#define SPEAR320_VIRQ_I2S_REC (SPEAR3XX_VIRQ_START + 5)
|
||||
|
||||
/* IRQs sharing IRQ_INTRCOMM_RAS_ARM */
|
||||
#define SPEAR320_VIRQ_CANU (SPEAR3XX_VIRQ_START + 6)
|
||||
#define SPEAR320_VIRQ_CANL (SPEAR3XX_VIRQ_START + 7)
|
||||
#define SPEAR320_VIRQ_UART1 (SPEAR3XX_VIRQ_START + 8)
|
||||
#define SPEAR320_VIRQ_UART2 (SPEAR3XX_VIRQ_START + 9)
|
||||
#define SPEAR320_VIRQ_SSP1 (SPEAR3XX_VIRQ_START + 10)
|
||||
#define SPEAR320_VIRQ_SSP2 (SPEAR3XX_VIRQ_START + 11)
|
||||
#define SPEAR320_VIRQ_SMII0 (SPEAR3XX_VIRQ_START + 12)
|
||||
#define SPEAR320_VIRQ_MII1_SMII1 (SPEAR3XX_VIRQ_START + 13)
|
||||
#define SPEAR320_VIRQ_WAKEUP_SMII0 (SPEAR3XX_VIRQ_START + 14)
|
||||
#define SPEAR320_VIRQ_WAKEUP_MII1_SMII1 (SPEAR3XX_VIRQ_START + 15)
|
||||
#define SPEAR320_VIRQ_I2C1 (SPEAR3XX_VIRQ_START + 16)
|
||||
|
||||
/* spear3xx shared irq */
|
||||
static struct shirq_dev_config shirq_ras1_config[] = {
|
||||
{
|
||||
.virq = SPEAR320_VIRQ_EMI,
|
||||
.status_mask = SPEAR320_EMI_IRQ_MASK,
|
||||
.clear_mask = SPEAR320_EMI_IRQ_MASK,
|
||||
}, {
|
||||
.virq = SPEAR320_VIRQ_CLCD,
|
||||
.status_mask = SPEAR320_CLCD_IRQ_MASK,
|
||||
.clear_mask = SPEAR320_CLCD_IRQ_MASK,
|
||||
}, {
|
||||
.virq = SPEAR320_VIRQ_SPP,
|
||||
.status_mask = SPEAR320_SPP_IRQ_MASK,
|
||||
.clear_mask = SPEAR320_SPP_IRQ_MASK,
|
||||
},
|
||||
};
|
||||
|
||||
static struct spear_shirq shirq_ras1 = {
|
||||
.irq = SPEAR3XX_IRQ_GEN_RAS_1,
|
||||
.dev_config = shirq_ras1_config,
|
||||
.dev_count = ARRAY_SIZE(shirq_ras1_config),
|
||||
.regs = {
|
||||
.enb_reg = -1,
|
||||
.status_reg = SPEAR320_INT_STS_MASK_REG,
|
||||
.status_reg_mask = SPEAR320_SHIRQ_RAS1_MASK,
|
||||
.clear_reg = SPEAR320_INT_CLR_MASK_REG,
|
||||
.reset_to_clear = 1,
|
||||
},
|
||||
};
|
||||
|
||||
static struct shirq_dev_config shirq_ras3_config[] = {
|
||||
{
|
||||
.virq = SPEAR320_VIRQ_PLGPIO,
|
||||
.enb_mask = SPEAR320_GPIO_IRQ_MASK,
|
||||
.status_mask = SPEAR320_GPIO_IRQ_MASK,
|
||||
.clear_mask = SPEAR320_GPIO_IRQ_MASK,
|
||||
}, {
|
||||
.virq = SPEAR320_VIRQ_I2S_PLAY,
|
||||
.enb_mask = SPEAR320_I2S_PLAY_IRQ_MASK,
|
||||
.status_mask = SPEAR320_I2S_PLAY_IRQ_MASK,
|
||||
.clear_mask = SPEAR320_I2S_PLAY_IRQ_MASK,
|
||||
}, {
|
||||
.virq = SPEAR320_VIRQ_I2S_REC,
|
||||
.enb_mask = SPEAR320_I2S_REC_IRQ_MASK,
|
||||
.status_mask = SPEAR320_I2S_REC_IRQ_MASK,
|
||||
.clear_mask = SPEAR320_I2S_REC_IRQ_MASK,
|
||||
},
|
||||
};
|
||||
|
||||
static struct spear_shirq shirq_ras3 = {
|
||||
.irq = SPEAR3XX_IRQ_GEN_RAS_3,
|
||||
.dev_config = shirq_ras3_config,
|
||||
.dev_count = ARRAY_SIZE(shirq_ras3_config),
|
||||
.regs = {
|
||||
.enb_reg = SPEAR320_INT_ENB_MASK_REG,
|
||||
.reset_to_enb = 1,
|
||||
.status_reg = SPEAR320_INT_STS_MASK_REG,
|
||||
.status_reg_mask = SPEAR320_SHIRQ_RAS3_MASK,
|
||||
.clear_reg = SPEAR320_INT_CLR_MASK_REG,
|
||||
.reset_to_clear = 1,
|
||||
},
|
||||
};
|
||||
|
||||
static struct shirq_dev_config shirq_intrcomm_ras_config[] = {
|
||||
{
|
||||
.virq = SPEAR320_VIRQ_CANU,
|
||||
.status_mask = SPEAR320_CAN_U_IRQ_MASK,
|
||||
.clear_mask = SPEAR320_CAN_U_IRQ_MASK,
|
||||
}, {
|
||||
.virq = SPEAR320_VIRQ_CANL,
|
||||
.status_mask = SPEAR320_CAN_L_IRQ_MASK,
|
||||
.clear_mask = SPEAR320_CAN_L_IRQ_MASK,
|
||||
}, {
|
||||
.virq = SPEAR320_VIRQ_UART1,
|
||||
.status_mask = SPEAR320_UART1_IRQ_MASK,
|
||||
.clear_mask = SPEAR320_UART1_IRQ_MASK,
|
||||
}, {
|
||||
.virq = SPEAR320_VIRQ_UART2,
|
||||
.status_mask = SPEAR320_UART2_IRQ_MASK,
|
||||
.clear_mask = SPEAR320_UART2_IRQ_MASK,
|
||||
}, {
|
||||
.virq = SPEAR320_VIRQ_SSP1,
|
||||
.status_mask = SPEAR320_SSP1_IRQ_MASK,
|
||||
.clear_mask = SPEAR320_SSP1_IRQ_MASK,
|
||||
}, {
|
||||
.virq = SPEAR320_VIRQ_SSP2,
|
||||
.status_mask = SPEAR320_SSP2_IRQ_MASK,
|
||||
.clear_mask = SPEAR320_SSP2_IRQ_MASK,
|
||||
}, {
|
||||
.virq = SPEAR320_VIRQ_SMII0,
|
||||
.status_mask = SPEAR320_SMII0_IRQ_MASK,
|
||||
.clear_mask = SPEAR320_SMII0_IRQ_MASK,
|
||||
}, {
|
||||
.virq = SPEAR320_VIRQ_MII1_SMII1,
|
||||
.status_mask = SPEAR320_MII1_SMII1_IRQ_MASK,
|
||||
.clear_mask = SPEAR320_MII1_SMII1_IRQ_MASK,
|
||||
}, {
|
||||
.virq = SPEAR320_VIRQ_WAKEUP_SMII0,
|
||||
.status_mask = SPEAR320_WAKEUP_SMII0_IRQ_MASK,
|
||||
.clear_mask = SPEAR320_WAKEUP_SMII0_IRQ_MASK,
|
||||
}, {
|
||||
.virq = SPEAR320_VIRQ_WAKEUP_MII1_SMII1,
|
||||
.status_mask = SPEAR320_WAKEUP_MII1_SMII1_IRQ_MASK,
|
||||
.clear_mask = SPEAR320_WAKEUP_MII1_SMII1_IRQ_MASK,
|
||||
}, {
|
||||
.virq = SPEAR320_VIRQ_I2C1,
|
||||
.status_mask = SPEAR320_I2C1_IRQ_MASK,
|
||||
.clear_mask = SPEAR320_I2C1_IRQ_MASK,
|
||||
},
|
||||
};
|
||||
|
||||
static struct spear_shirq shirq_intrcomm_ras = {
|
||||
.irq = SPEAR3XX_IRQ_INTRCOMM_RAS_ARM,
|
||||
.dev_config = shirq_intrcomm_ras_config,
|
||||
.dev_count = ARRAY_SIZE(shirq_intrcomm_ras_config),
|
||||
.regs = {
|
||||
.enb_reg = -1,
|
||||
.status_reg = SPEAR320_INT_STS_MASK_REG,
|
||||
.status_reg_mask = SPEAR320_SHIRQ_INTRCOMM_RAS_MASK,
|
||||
.clear_reg = SPEAR320_INT_CLR_MASK_REG,
|
||||
.reset_to_clear = 1,
|
||||
},
|
||||
};
|
||||
|
||||
/* DMAC platform data's slave info */
|
||||
struct pl08x_channel_data spear320_dma_info[] = {
|
||||
{
|
||||
|
@ -416,41 +237,17 @@ static struct of_dev_auxdata spear320_auxdata_lookup[] __initdata = {
|
|||
|
||||
static void __init spear320_dt_init(void)
|
||||
{
|
||||
void __iomem *base;
|
||||
int ret;
|
||||
|
||||
pl080_plat_data.slave_channels = spear320_dma_info;
|
||||
pl080_plat_data.num_slave_channels = ARRAY_SIZE(spear320_dma_info);
|
||||
|
||||
of_platform_populate(NULL, of_default_bus_match_table,
|
||||
spear320_auxdata_lookup, NULL);
|
||||
|
||||
/* shared irq registration */
|
||||
base = ioremap(SPEAR320_SOC_CONFIG_BASE, SZ_4K);
|
||||
if (base) {
|
||||
/* shirq 1 */
|
||||
shirq_ras1.regs.base = base;
|
||||
ret = spear_shirq_register(&shirq_ras1);
|
||||
if (ret)
|
||||
pr_err("Error registering Shared IRQ 1\n");
|
||||
|
||||
/* shirq 3 */
|
||||
shirq_ras3.regs.base = base;
|
||||
ret = spear_shirq_register(&shirq_ras3);
|
||||
if (ret)
|
||||
pr_err("Error registering Shared IRQ 3\n");
|
||||
|
||||
/* shirq 4 */
|
||||
shirq_intrcomm_ras.regs.base = base;
|
||||
ret = spear_shirq_register(&shirq_intrcomm_ras);
|
||||
if (ret)
|
||||
pr_err("Error registering Shared IRQ 4\n");
|
||||
}
|
||||
}
|
||||
|
||||
static const char * const spear320_dt_board_compat[] = {
|
||||
"st,spear320",
|
||||
"st,spear320-evb",
|
||||
"st,spear320-hmi",
|
||||
NULL,
|
||||
};
|
||||
|
||||
|
|
|
@ -15,6 +15,7 @@
|
|||
|
||||
#include <linux/amba/pl022.h>
|
||||
#include <linux/amba/pl08x.h>
|
||||
#include <linux/irqchip/spear-shirq.h>
|
||||
#include <linux/of_irq.h>
|
||||
#include <linux/io.h>
|
||||
#include <asm/hardware/pl080.h>
|
||||
|
@ -121,6 +122,9 @@ struct sys_timer spear3xx_timer = {
|
|||
|
||||
static const struct of_device_id vic_of_match[] __initconst = {
|
||||
{ .compatible = "arm,pl190-vic", .data = vic_of_init, },
|
||||
{ .compatible = "st,spear300-shirq", .data = spear300_shirq_of_init, },
|
||||
{ .compatible = "st,spear310-shirq", .data = spear310_shirq_of_init, },
|
||||
{ .compatible = "st,spear320-shirq", .data = spear320_shirq_of_init, },
|
||||
{ /* Sentinel */ }
|
||||
};
|
||||
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -12,6 +12,7 @@ config ARCH_SPEAR13XX
|
|||
bool "ST SPEAr13xx with Device Tree"
|
||||
select ARM_GIC
|
||||
select CPU_V7
|
||||
select GPIO_SPEAR_SPICS
|
||||
select HAVE_SMP
|
||||
select MIGHT_HAVE_CACHE_L2X0
|
||||
select PINCTRL
|
||||
|
|
|
@ -5,5 +5,5 @@
|
|||
# Common support
|
||||
obj-y := restart.o time.o
|
||||
|
||||
obj-$(CONFIG_ARCH_SPEAR3XX) += pl080.o shirq.o
|
||||
obj-$(CONFIG_ARCH_SPEAR3XX) += pl080.o
|
||||
obj-$(CONFIG_ARCH_SPEAR6XX) += pl080.o
|
||||
|
|
|
@ -1,118 +0,0 @@
|
|||
/*
|
||||
* arch/arm/plat-spear/shirq.c
|
||||
*
|
||||
* SPEAr platform shared irq layer source file
|
||||
*
|
||||
* Copyright (C) 2009 ST Microelectronics
|
||||
* Viresh Kumar <viresh.linux@gmail.com>
|
||||
*
|
||||
* This file is licensed under the terms of the GNU General Public
|
||||
* License version 2. This program is licensed "as is" without any
|
||||
* warranty of any kind, whether express or implied.
|
||||
*/
|
||||
|
||||
#include <linux/err.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/irq.h>
|
||||
#include <linux/spinlock.h>
|
||||
#include <plat/shirq.h>
|
||||
|
||||
struct spear_shirq *shirq;
|
||||
static DEFINE_SPINLOCK(lock);
|
||||
|
||||
static void shirq_irq_mask(struct irq_data *d)
|
||||
{
|
||||
struct spear_shirq *shirq = irq_data_get_irq_chip_data(d);
|
||||
u32 val, id = d->irq - shirq->dev_config[0].virq;
|
||||
unsigned long flags;
|
||||
|
||||
if ((shirq->regs.enb_reg == -1) || shirq->dev_config[id].enb_mask == -1)
|
||||
return;
|
||||
|
||||
spin_lock_irqsave(&lock, flags);
|
||||
val = readl(shirq->regs.base + shirq->regs.enb_reg);
|
||||
if (shirq->regs.reset_to_enb)
|
||||
val |= shirq->dev_config[id].enb_mask;
|
||||
else
|
||||
val &= ~(shirq->dev_config[id].enb_mask);
|
||||
writel(val, shirq->regs.base + shirq->regs.enb_reg);
|
||||
spin_unlock_irqrestore(&lock, flags);
|
||||
}
|
||||
|
||||
static void shirq_irq_unmask(struct irq_data *d)
|
||||
{
|
||||
struct spear_shirq *shirq = irq_data_get_irq_chip_data(d);
|
||||
u32 val, id = d->irq - shirq->dev_config[0].virq;
|
||||
unsigned long flags;
|
||||
|
||||
if ((shirq->regs.enb_reg == -1) || shirq->dev_config[id].enb_mask == -1)
|
||||
return;
|
||||
|
||||
spin_lock_irqsave(&lock, flags);
|
||||
val = readl(shirq->regs.base + shirq->regs.enb_reg);
|
||||
if (shirq->regs.reset_to_enb)
|
||||
val &= ~(shirq->dev_config[id].enb_mask);
|
||||
else
|
||||
val |= shirq->dev_config[id].enb_mask;
|
||||
writel(val, shirq->regs.base + shirq->regs.enb_reg);
|
||||
spin_unlock_irqrestore(&lock, flags);
|
||||
}
|
||||
|
||||
static struct irq_chip shirq_chip = {
|
||||
.name = "spear_shirq",
|
||||
.irq_ack = shirq_irq_mask,
|
||||
.irq_mask = shirq_irq_mask,
|
||||
.irq_unmask = shirq_irq_unmask,
|
||||
};
|
||||
|
||||
static void shirq_handler(unsigned irq, struct irq_desc *desc)
|
||||
{
|
||||
u32 i, val, mask;
|
||||
struct spear_shirq *shirq = irq_get_handler_data(irq);
|
||||
|
||||
desc->irq_data.chip->irq_ack(&desc->irq_data);
|
||||
while ((val = readl(shirq->regs.base + shirq->regs.status_reg) &
|
||||
shirq->regs.status_reg_mask)) {
|
||||
for (i = 0; (i < shirq->dev_count) && val; i++) {
|
||||
if (!(shirq->dev_config[i].status_mask & val))
|
||||
continue;
|
||||
|
||||
generic_handle_irq(shirq->dev_config[i].virq);
|
||||
|
||||
/* clear interrupt */
|
||||
val &= ~shirq->dev_config[i].status_mask;
|
||||
if ((shirq->regs.clear_reg == -1) ||
|
||||
shirq->dev_config[i].clear_mask == -1)
|
||||
continue;
|
||||
mask = readl(shirq->regs.base + shirq->regs.clear_reg);
|
||||
if (shirq->regs.reset_to_clear)
|
||||
mask &= ~shirq->dev_config[i].clear_mask;
|
||||
else
|
||||
mask |= shirq->dev_config[i].clear_mask;
|
||||
writel(mask, shirq->regs.base + shirq->regs.clear_reg);
|
||||
}
|
||||
}
|
||||
desc->irq_data.chip->irq_unmask(&desc->irq_data);
|
||||
}
|
||||
|
||||
int spear_shirq_register(struct spear_shirq *shirq)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (!shirq || !shirq->dev_config || !shirq->regs.base)
|
||||
return -EFAULT;
|
||||
|
||||
if (!shirq->dev_count)
|
||||
return -EINVAL;
|
||||
|
||||
irq_set_chained_handler(shirq->irq, shirq_handler);
|
||||
for (i = 0; i < shirq->dev_count; i++) {
|
||||
irq_set_chip_and_handler(shirq->dev_config[i].virq,
|
||||
&shirq_chip, handle_simple_irq);
|
||||
set_irq_flags(shirq->dev_config[i].virq, IRQF_VALID);
|
||||
irq_set_chip_data(shirq->dev_config[i].virq, shirq);
|
||||
}
|
||||
|
||||
irq_set_handler_data(shirq->irq, shirq);
|
||||
return 0;
|
||||
}
|
|
@ -20,6 +20,7 @@
|
|||
#include <mach/spear.h>
|
||||
#include "clk.h"
|
||||
|
||||
#define VA_SPEAR1310_RAS_BASE IOMEM(UL(0xFA400000))
|
||||
/* PLL related registers and bit values */
|
||||
#define SPEAR1310_PLL_CFG (VA_MISC_BASE + 0x210)
|
||||
/* PLL_CFG bit values */
|
||||
|
|
|
@ -86,11 +86,26 @@ config GPIO_DA9052
|
|||
help
|
||||
Say yes here to enable the GPIO driver for the DA9052 chip.
|
||||
|
||||
config GPIO_DA9055
|
||||
tristate "Dialog Semiconductor DA9055 GPIO"
|
||||
depends on MFD_DA9055
|
||||
help
|
||||
Say yes here to enable the GPIO driver for the DA9055 chip.
|
||||
|
||||
The Dialog DA9055 PMIC chip has 3 GPIO pins that can be
|
||||
be controller by this driver.
|
||||
|
||||
If driver is built as a module it will be called gpio-da9055.
|
||||
|
||||
config GPIO_MAX730X
|
||||
tristate
|
||||
|
||||
comment "Memory mapped GPIO drivers:"
|
||||
|
||||
config GPIO_CLPS711X
|
||||
def_bool y
|
||||
depends on ARCH_CLPS711X
|
||||
|
||||
config GPIO_GENERIC_PLATFORM
|
||||
tristate "Generic memory-mapped GPIO controller support (MMIO platform device)"
|
||||
select GPIO_GENERIC
|
||||
|
@ -181,6 +196,13 @@ config GPIO_PXA
|
|||
help
|
||||
Say yes here to support the PXA GPIO device
|
||||
|
||||
config GPIO_SPEAR_SPICS
|
||||
bool "ST SPEAr13xx SPI Chip Select as GPIO support"
|
||||
depends on PLAT_SPEAR
|
||||
select GENERIC_IRQ_CHIP
|
||||
help
|
||||
Say yes here to support ST SPEAr SPI Chip Select as GPIO device
|
||||
|
||||
config GPIO_STA2X11
|
||||
bool "STA2x11/ConneXt GPIO support"
|
||||
depends on MFD_STA2X11
|
||||
|
|
|
@ -16,8 +16,10 @@ obj-$(CONFIG_GPIO_ADP5588) += gpio-adp5588.o
|
|||
obj-$(CONFIG_GPIO_AMD8111) += gpio-amd8111.o
|
||||
obj-$(CONFIG_GPIO_ARIZONA) += gpio-arizona.o
|
||||
obj-$(CONFIG_GPIO_BT8XX) += gpio-bt8xx.o
|
||||
obj-$(CONFIG_GPIO_CLPS711X) += gpio-clps711x.o
|
||||
obj-$(CONFIG_GPIO_CS5535) += gpio-cs5535.o
|
||||
obj-$(CONFIG_GPIO_DA9052) += gpio-da9052.o
|
||||
obj-$(CONFIG_GPIO_DA9055) += gpio-da9055.o
|
||||
obj-$(CONFIG_ARCH_DAVINCI) += gpio-davinci.o
|
||||
obj-$(CONFIG_GPIO_EM) += gpio-em.o
|
||||
obj-$(CONFIG_GPIO_EP93XX) += gpio-ep93xx.o
|
||||
|
@ -57,6 +59,7 @@ obj-$(CONFIG_PLAT_SAMSUNG) += gpio-samsung.o
|
|||
obj-$(CONFIG_ARCH_SA1100) += gpio-sa1100.o
|
||||
obj-$(CONFIG_GPIO_SCH) += gpio-sch.o
|
||||
obj-$(CONFIG_GPIO_SODAVILLE) += gpio-sodaville.o
|
||||
obj-$(CONFIG_GPIO_SPEAR_SPICS) += gpio-spear-spics.o
|
||||
obj-$(CONFIG_GPIO_STA2X11) += gpio-sta2x11.o
|
||||
obj-$(CONFIG_GPIO_STMPE) += gpio-stmpe.o
|
||||
obj-$(CONFIG_GPIO_STP_XWAY) += gpio-stp-xway.o
|
||||
|
|
|
@ -0,0 +1,199 @@
|
|||
/*
|
||||
* CLPS711X GPIO driver
|
||||
*
|
||||
* Copyright (C) 2012 Alexander Shiyan <shc_work@mail.ru>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*/
|
||||
|
||||
#include <linux/io.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/gpio.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/spinlock.h>
|
||||
#include <linux/platform_device.h>
|
||||
|
||||
#include <mach/hardware.h>
|
||||
|
||||
#define CLPS711X_GPIO_PORTS 5
|
||||
#define CLPS711X_GPIO_NAME "gpio-clps711x"
|
||||
|
||||
struct clps711x_gpio {
|
||||
struct gpio_chip chip[CLPS711X_GPIO_PORTS];
|
||||
spinlock_t lock;
|
||||
};
|
||||
|
||||
static void __iomem *clps711x_ports[] = {
|
||||
CLPS711X_VIRT_BASE + PADR,
|
||||
CLPS711X_VIRT_BASE + PBDR,
|
||||
CLPS711X_VIRT_BASE + PCDR,
|
||||
CLPS711X_VIRT_BASE + PDDR,
|
||||
CLPS711X_VIRT_BASE + PEDR,
|
||||
};
|
||||
|
||||
static void __iomem *clps711x_pdirs[] = {
|
||||
CLPS711X_VIRT_BASE + PADDR,
|
||||
CLPS711X_VIRT_BASE + PBDDR,
|
||||
CLPS711X_VIRT_BASE + PCDDR,
|
||||
CLPS711X_VIRT_BASE + PDDDR,
|
||||
CLPS711X_VIRT_BASE + PEDDR,
|
||||
};
|
||||
|
||||
#define clps711x_port(x) clps711x_ports[x->base / 8]
|
||||
#define clps711x_pdir(x) clps711x_pdirs[x->base / 8]
|
||||
|
||||
static int gpio_clps711x_get(struct gpio_chip *chip, unsigned offset)
|
||||
{
|
||||
return !!(readb(clps711x_port(chip)) & (1 << offset));
|
||||
}
|
||||
|
||||
static void gpio_clps711x_set(struct gpio_chip *chip, unsigned offset,
|
||||
int value)
|
||||
{
|
||||
int tmp;
|
||||
unsigned long flags;
|
||||
struct clps711x_gpio *gpio = dev_get_drvdata(chip->dev);
|
||||
|
||||
spin_lock_irqsave(&gpio->lock, flags);
|
||||
tmp = readb(clps711x_port(chip)) & ~(1 << offset);
|
||||
if (value)
|
||||
tmp |= 1 << offset;
|
||||
writeb(tmp, clps711x_port(chip));
|
||||
spin_unlock_irqrestore(&gpio->lock, flags);
|
||||
}
|
||||
|
||||
static int gpio_clps711x_dir_in(struct gpio_chip *chip, unsigned offset)
|
||||
{
|
||||
int tmp;
|
||||
unsigned long flags;
|
||||
struct clps711x_gpio *gpio = dev_get_drvdata(chip->dev);
|
||||
|
||||
spin_lock_irqsave(&gpio->lock, flags);
|
||||
tmp = readb(clps711x_pdir(chip)) & ~(1 << offset);
|
||||
writeb(tmp, clps711x_pdir(chip));
|
||||
spin_unlock_irqrestore(&gpio->lock, flags);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int gpio_clps711x_dir_out(struct gpio_chip *chip, unsigned offset,
|
||||
int value)
|
||||
{
|
||||
int tmp;
|
||||
unsigned long flags;
|
||||
struct clps711x_gpio *gpio = dev_get_drvdata(chip->dev);
|
||||
|
||||
spin_lock_irqsave(&gpio->lock, flags);
|
||||
tmp = readb(clps711x_pdir(chip)) | (1 << offset);
|
||||
writeb(tmp, clps711x_pdir(chip));
|
||||
tmp = readb(clps711x_port(chip)) & ~(1 << offset);
|
||||
if (value)
|
||||
tmp |= 1 << offset;
|
||||
writeb(tmp, clps711x_port(chip));
|
||||
spin_unlock_irqrestore(&gpio->lock, flags);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int gpio_clps711x_dir_in_inv(struct gpio_chip *chip, unsigned offset)
|
||||
{
|
||||
int tmp;
|
||||
unsigned long flags;
|
||||
struct clps711x_gpio *gpio = dev_get_drvdata(chip->dev);
|
||||
|
||||
spin_lock_irqsave(&gpio->lock, flags);
|
||||
tmp = readb(clps711x_pdir(chip)) | (1 << offset);
|
||||
writeb(tmp, clps711x_pdir(chip));
|
||||
spin_unlock_irqrestore(&gpio->lock, flags);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int gpio_clps711x_dir_out_inv(struct gpio_chip *chip, unsigned offset,
|
||||
int value)
|
||||
{
|
||||
int tmp;
|
||||
unsigned long flags;
|
||||
struct clps711x_gpio *gpio = dev_get_drvdata(chip->dev);
|
||||
|
||||
spin_lock_irqsave(&gpio->lock, flags);
|
||||
tmp = readb(clps711x_pdir(chip)) & ~(1 << offset);
|
||||
writeb(tmp, clps711x_pdir(chip));
|
||||
tmp = readb(clps711x_port(chip)) & ~(1 << offset);
|
||||
if (value)
|
||||
tmp |= 1 << offset;
|
||||
writeb(tmp, clps711x_port(chip));
|
||||
spin_unlock_irqrestore(&gpio->lock, flags);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct {
|
||||
char *name;
|
||||
int nr;
|
||||
int inv_dir;
|
||||
} clps711x_gpio_ports[] __initconst = {
|
||||
{ "PORTA", 8, 0, },
|
||||
{ "PORTB", 8, 0, },
|
||||
{ "PORTC", 8, 0, },
|
||||
{ "PORTD", 8, 1, },
|
||||
{ "PORTE", 3, 0, },
|
||||
};
|
||||
|
||||
static int __init gpio_clps711x_init(void)
|
||||
{
|
||||
int i;
|
||||
struct platform_device *pdev;
|
||||
struct clps711x_gpio *gpio;
|
||||
|
||||
pdev = platform_device_alloc(CLPS711X_GPIO_NAME, 0);
|
||||
if (!pdev) {
|
||||
pr_err("Cannot create platform device: %s\n",
|
||||
CLPS711X_GPIO_NAME);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
platform_device_add(pdev);
|
||||
|
||||
gpio = devm_kzalloc(&pdev->dev, sizeof(struct clps711x_gpio),
|
||||
GFP_KERNEL);
|
||||
if (!gpio) {
|
||||
dev_err(&pdev->dev, "GPIO allocating memory error\n");
|
||||
platform_device_unregister(pdev);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
platform_set_drvdata(pdev, gpio);
|
||||
|
||||
spin_lock_init(&gpio->lock);
|
||||
|
||||
for (i = 0; i < CLPS711X_GPIO_PORTS; i++) {
|
||||
gpio->chip[i].owner = THIS_MODULE;
|
||||
gpio->chip[i].dev = &pdev->dev;
|
||||
gpio->chip[i].label = clps711x_gpio_ports[i].name;
|
||||
gpio->chip[i].base = i * 8;
|
||||
gpio->chip[i].ngpio = clps711x_gpio_ports[i].nr;
|
||||
gpio->chip[i].get = gpio_clps711x_get;
|
||||
gpio->chip[i].set = gpio_clps711x_set;
|
||||
if (!clps711x_gpio_ports[i].inv_dir) {
|
||||
gpio->chip[i].direction_input = gpio_clps711x_dir_in;
|
||||
gpio->chip[i].direction_output = gpio_clps711x_dir_out;
|
||||
} else {
|
||||
gpio->chip[i].direction_input = gpio_clps711x_dir_in_inv;
|
||||
gpio->chip[i].direction_output = gpio_clps711x_dir_out_inv;
|
||||
}
|
||||
WARN_ON(gpiochip_add(&gpio->chip[i]));
|
||||
}
|
||||
|
||||
dev_info(&pdev->dev, "GPIO driver initialized\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
arch_initcall(gpio_clps711x_init);
|
||||
|
||||
MODULE_LICENSE("GPL v2");
|
||||
MODULE_AUTHOR("Alexander Shiyan <shc_work@mail.ru>");
|
||||
MODULE_DESCRIPTION("CLPS711X GPIO driver");
|
|
@ -0,0 +1,204 @@
|
|||
/*
|
||||
* GPIO Driver for Dialog DA9055 PMICs.
|
||||
*
|
||||
* Copyright(c) 2012 Dialog Semiconductor Ltd.
|
||||
*
|
||||
* Author: David Dajun Chen <dchen@diasemi.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation; either version 2 of the License, or (at your
|
||||
* option) any later version.
|
||||
*
|
||||
*/
|
||||
#include <linux/module.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/gpio.h>
|
||||
|
||||
#include <linux/mfd/da9055/core.h>
|
||||
#include <linux/mfd/da9055/reg.h>
|
||||
#include <linux/mfd/da9055/pdata.h>
|
||||
|
||||
#define DA9055_VDD_IO 0x0
|
||||
#define DA9055_PUSH_PULL 0x3
|
||||
#define DA9055_ACT_LOW 0x0
|
||||
#define DA9055_GPI 0x1
|
||||
#define DA9055_PORT_MASK 0x3
|
||||
#define DA9055_PORT_SHIFT(offset) (4 * (offset % 2))
|
||||
|
||||
#define DA9055_INPUT DA9055_GPI
|
||||
#define DA9055_OUTPUT DA9055_PUSH_PULL
|
||||
#define DA9055_IRQ_GPI0 3
|
||||
|
||||
struct da9055_gpio {
|
||||
struct da9055 *da9055;
|
||||
struct gpio_chip gp;
|
||||
};
|
||||
|
||||
static inline struct da9055_gpio *to_da9055_gpio(struct gpio_chip *chip)
|
||||
{
|
||||
return container_of(chip, struct da9055_gpio, gp);
|
||||
}
|
||||
|
||||
static int da9055_gpio_get(struct gpio_chip *gc, unsigned offset)
|
||||
{
|
||||
struct da9055_gpio *gpio = to_da9055_gpio(gc);
|
||||
int gpio_direction = 0;
|
||||
int ret;
|
||||
|
||||
/* Get GPIO direction */
|
||||
ret = da9055_reg_read(gpio->da9055, (offset >> 1) + DA9055_REG_GPIO0_1);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
gpio_direction = ret & (DA9055_PORT_MASK) << DA9055_PORT_SHIFT(offset);
|
||||
gpio_direction >>= DA9055_PORT_SHIFT(offset);
|
||||
switch (gpio_direction) {
|
||||
case DA9055_INPUT:
|
||||
ret = da9055_reg_read(gpio->da9055, DA9055_REG_STATUS_B);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
break;
|
||||
case DA9055_OUTPUT:
|
||||
ret = da9055_reg_read(gpio->da9055, DA9055_REG_GPIO_MODE0_2);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
}
|
||||
|
||||
return ret & (1 << offset);
|
||||
|
||||
}
|
||||
|
||||
static void da9055_gpio_set(struct gpio_chip *gc, unsigned offset, int value)
|
||||
{
|
||||
struct da9055_gpio *gpio = to_da9055_gpio(gc);
|
||||
|
||||
da9055_reg_update(gpio->da9055,
|
||||
DA9055_REG_GPIO_MODE0_2,
|
||||
1 << offset,
|
||||
value << offset);
|
||||
}
|
||||
|
||||
static int da9055_gpio_direction_input(struct gpio_chip *gc, unsigned offset)
|
||||
{
|
||||
struct da9055_gpio *gpio = to_da9055_gpio(gc);
|
||||
unsigned char reg_byte;
|
||||
|
||||
reg_byte = (DA9055_ACT_LOW | DA9055_GPI)
|
||||
<< DA9055_PORT_SHIFT(offset);
|
||||
|
||||
return da9055_reg_update(gpio->da9055, (offset >> 1) +
|
||||
DA9055_REG_GPIO0_1,
|
||||
DA9055_PORT_MASK <<
|
||||
DA9055_PORT_SHIFT(offset),
|
||||
reg_byte);
|
||||
}
|
||||
|
||||
static int da9055_gpio_direction_output(struct gpio_chip *gc,
|
||||
unsigned offset, int value)
|
||||
{
|
||||
struct da9055_gpio *gpio = to_da9055_gpio(gc);
|
||||
unsigned char reg_byte;
|
||||
int ret;
|
||||
|
||||
reg_byte = (DA9055_VDD_IO | DA9055_PUSH_PULL)
|
||||
<< DA9055_PORT_SHIFT(offset);
|
||||
|
||||
ret = da9055_reg_update(gpio->da9055, (offset >> 1) +
|
||||
DA9055_REG_GPIO0_1,
|
||||
DA9055_PORT_MASK <<
|
||||
DA9055_PORT_SHIFT(offset),
|
||||
reg_byte);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
da9055_gpio_set(gc, offset, value);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int da9055_gpio_to_irq(struct gpio_chip *gc, u32 offset)
|
||||
{
|
||||
struct da9055_gpio *gpio = to_da9055_gpio(gc);
|
||||
struct da9055 *da9055 = gpio->da9055;
|
||||
|
||||
return regmap_irq_get_virq(da9055->irq_data,
|
||||
DA9055_IRQ_GPI0 + offset);
|
||||
}
|
||||
|
||||
static struct gpio_chip reference_gp __devinitdata = {
|
||||
.label = "da9055-gpio",
|
||||
.owner = THIS_MODULE,
|
||||
.get = da9055_gpio_get,
|
||||
.set = da9055_gpio_set,
|
||||
.direction_input = da9055_gpio_direction_input,
|
||||
.direction_output = da9055_gpio_direction_output,
|
||||
.to_irq = da9055_gpio_to_irq,
|
||||
.can_sleep = 1,
|
||||
.ngpio = 3,
|
||||
.base = -1,
|
||||
};
|
||||
|
||||
static int __devinit da9055_gpio_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct da9055_gpio *gpio;
|
||||
struct da9055_pdata *pdata;
|
||||
int ret;
|
||||
|
||||
gpio = devm_kzalloc(&pdev->dev, sizeof(*gpio), GFP_KERNEL);
|
||||
if (gpio == NULL)
|
||||
return -ENOMEM;
|
||||
|
||||
gpio->da9055 = dev_get_drvdata(pdev->dev.parent);
|
||||
pdata = gpio->da9055->dev->platform_data;
|
||||
|
||||
gpio->gp = reference_gp;
|
||||
if (pdata && pdata->gpio_base)
|
||||
gpio->gp.base = pdata->gpio_base;
|
||||
|
||||
ret = gpiochip_add(&gpio->gp);
|
||||
if (ret < 0) {
|
||||
dev_err(&pdev->dev, "Could not register gpiochip, %d\n", ret);
|
||||
goto err_mem;
|
||||
}
|
||||
|
||||
platform_set_drvdata(pdev, gpio);
|
||||
|
||||
return 0;
|
||||
|
||||
err_mem:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int __devexit da9055_gpio_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct da9055_gpio *gpio = platform_get_drvdata(pdev);
|
||||
|
||||
return gpiochip_remove(&gpio->gp);
|
||||
}
|
||||
|
||||
static struct platform_driver da9055_gpio_driver = {
|
||||
.probe = da9055_gpio_probe,
|
||||
.remove = __devexit_p(da9055_gpio_remove),
|
||||
.driver = {
|
||||
.name = "da9055-gpio",
|
||||
.owner = THIS_MODULE,
|
||||
},
|
||||
};
|
||||
|
||||
static int __init da9055_gpio_init(void)
|
||||
{
|
||||
return platform_driver_register(&da9055_gpio_driver);
|
||||
}
|
||||
subsys_initcall(da9055_gpio_init);
|
||||
|
||||
static void __exit da9055_gpio_exit(void)
|
||||
{
|
||||
platform_driver_unregister(&da9055_gpio_driver);
|
||||
}
|
||||
module_exit(da9055_gpio_exit);
|
||||
|
||||
MODULE_AUTHOR("David Dajun Chen <dchen@diasemi.com>");
|
||||
MODULE_DESCRIPTION("DA9055 GPIO Device Driver");
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_ALIAS("platform:da9055-gpio");
|
|
@ -35,7 +35,6 @@
|
|||
struct em_gio_priv {
|
||||
void __iomem *base0;
|
||||
void __iomem *base1;
|
||||
unsigned int irq_base;
|
||||
spinlock_t sense_lock;
|
||||
struct platform_device *pdev;
|
||||
struct gpio_chip gpio_chip;
|
||||
|
@ -214,7 +213,7 @@ static int em_gio_direction_output(struct gpio_chip *chip, unsigned offset,
|
|||
|
||||
static int em_gio_to_irq(struct gpio_chip *chip, unsigned offset)
|
||||
{
|
||||
return irq_find_mapping(gpio_to_priv(chip)->irq_domain, offset);
|
||||
return irq_create_mapping(gpio_to_priv(chip)->irq_domain, offset);
|
||||
}
|
||||
|
||||
static int em_gio_irq_domain_map(struct irq_domain *h, unsigned int virq,
|
||||
|
@ -234,40 +233,6 @@ static struct irq_domain_ops em_gio_irq_domain_ops = {
|
|||
.map = em_gio_irq_domain_map,
|
||||
};
|
||||
|
||||
static int __devinit em_gio_irq_domain_init(struct em_gio_priv *p)
|
||||
{
|
||||
struct platform_device *pdev = p->pdev;
|
||||
struct gpio_em_config *pdata = pdev->dev.platform_data;
|
||||
|
||||
p->irq_base = irq_alloc_descs(pdata->irq_base, 0,
|
||||
pdata->number_of_pins, numa_node_id());
|
||||
if (p->irq_base < 0) {
|
||||
dev_err(&pdev->dev, "cannot get irq_desc\n");
|
||||
return p->irq_base;
|
||||
}
|
||||
pr_debug("gio: hw base = %d, nr = %d, sw base = %d\n",
|
||||
pdata->gpio_base, pdata->number_of_pins, p->irq_base);
|
||||
|
||||
p->irq_domain = irq_domain_add_legacy(pdev->dev.of_node,
|
||||
pdata->number_of_pins,
|
||||
p->irq_base, 0,
|
||||
&em_gio_irq_domain_ops, p);
|
||||
if (!p->irq_domain) {
|
||||
irq_free_descs(p->irq_base, pdata->number_of_pins);
|
||||
return -ENXIO;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void em_gio_irq_domain_cleanup(struct em_gio_priv *p)
|
||||
{
|
||||
struct gpio_em_config *pdata = p->pdev->dev.platform_data;
|
||||
|
||||
irq_free_descs(p->irq_base, pdata->number_of_pins);
|
||||
/* FIXME: irq domain wants to be freed! */
|
||||
}
|
||||
|
||||
static int __devinit em_gio_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct gpio_em_config *pdata = pdev->dev.platform_data;
|
||||
|
@ -334,8 +299,11 @@ static int __devinit em_gio_probe(struct platform_device *pdev)
|
|||
irq_chip->irq_set_type = em_gio_irq_set_type;
|
||||
irq_chip->flags = IRQCHIP_SKIP_SET_WAKE;
|
||||
|
||||
ret = em_gio_irq_domain_init(p);
|
||||
if (ret) {
|
||||
p->irq_domain = irq_domain_add_linear(pdev->dev.of_node,
|
||||
pdata->number_of_pins,
|
||||
&em_gio_irq_domain_ops, p);
|
||||
if (!p->irq_domain) {
|
||||
ret = -ENXIO;
|
||||
dev_err(&pdev->dev, "cannot initialize irq domain\n");
|
||||
goto err3;
|
||||
}
|
||||
|
@ -364,7 +332,7 @@ err6:
|
|||
err5:
|
||||
free_irq(irq[0]->start, pdev);
|
||||
err4:
|
||||
em_gio_irq_domain_cleanup(p);
|
||||
irq_domain_remove(p->irq_domain);
|
||||
err3:
|
||||
iounmap(p->base1);
|
||||
err2:
|
||||
|
@ -390,7 +358,7 @@ static int __devexit em_gio_remove(struct platform_device *pdev)
|
|||
|
||||
free_irq(irq[1]->start, pdev);
|
||||
free_irq(irq[0]->start, pdev);
|
||||
em_gio_irq_domain_cleanup(p);
|
||||
irq_domain_remove(p->irq_domain);
|
||||
iounmap(p->base1);
|
||||
iounmap(p->base0);
|
||||
kfree(p);
|
||||
|
|
|
@ -167,10 +167,6 @@ int __devinit __max730x_probe(struct max7301 *ts)
|
|||
int i, ret;
|
||||
|
||||
pdata = dev->platform_data;
|
||||
if (!pdata || !pdata->base) {
|
||||
dev_err(dev, "incorrect or missing platform data\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
mutex_init(&ts->lock);
|
||||
dev_set_drvdata(dev, ts);
|
||||
|
@ -178,7 +174,12 @@ int __devinit __max730x_probe(struct max7301 *ts)
|
|||
/* Power up the chip and disable IRQ output */
|
||||
ts->write(dev, 0x04, 0x01);
|
||||
|
||||
ts->input_pullup_active = pdata->input_pullup_active;
|
||||
if (pdata) {
|
||||
ts->input_pullup_active = pdata->input_pullup_active;
|
||||
ts->chip.base = pdata->base;
|
||||
} else {
|
||||
ts->chip.base = -1;
|
||||
}
|
||||
ts->chip.label = dev->driver->name;
|
||||
|
||||
ts->chip.direction_input = max7301_direction_input;
|
||||
|
@ -186,7 +187,6 @@ int __devinit __max730x_probe(struct max7301 *ts)
|
|||
ts->chip.direction_output = max7301_direction_output;
|
||||
ts->chip.set = max7301_set;
|
||||
|
||||
ts->chip.base = pdata->base;
|
||||
ts->chip.ngpio = PIN_NUMBER;
|
||||
ts->chip.can_sleep = 1;
|
||||
ts->chip.dev = dev;
|
||||
|
|
|
@ -168,12 +168,12 @@ static void __iomem *mvebu_gpioreg_level_mask(struct mvebu_gpio_chip *mvchip)
|
|||
* Functions implementing the gpio_chip methods
|
||||
*/
|
||||
|
||||
int mvebu_gpio_request(struct gpio_chip *chip, unsigned pin)
|
||||
static int mvebu_gpio_request(struct gpio_chip *chip, unsigned pin)
|
||||
{
|
||||
return pinctrl_request_gpio(chip->base + pin);
|
||||
}
|
||||
|
||||
void mvebu_gpio_free(struct gpio_chip *chip, unsigned pin)
|
||||
static void mvebu_gpio_free(struct gpio_chip *chip, unsigned pin)
|
||||
{
|
||||
pinctrl_free_gpio(chip->base + pin);
|
||||
}
|
||||
|
@ -546,6 +546,7 @@ static int __devinit mvebu_gpio_probe(struct platform_device *pdev)
|
|||
mvchip->chip.label = dev_name(&pdev->dev);
|
||||
mvchip->chip.dev = &pdev->dev;
|
||||
mvchip->chip.request = mvebu_gpio_request;
|
||||
mvchip->chip.free = mvebu_gpio_free;
|
||||
mvchip->chip.direction_input = mvebu_gpio_direction_input;
|
||||
mvchip->chip.get = mvebu_gpio_get;
|
||||
mvchip->chip.direction_output = mvebu_gpio_direction_output;
|
||||
|
@ -673,8 +674,8 @@ static int __devinit mvebu_gpio_probe(struct platform_device *pdev)
|
|||
IRQ_NOREQUEST, IRQ_LEVEL | IRQ_NOPROBE);
|
||||
|
||||
/* Setup irq domain on top of the generic chip. */
|
||||
mvchip->domain = irq_domain_add_legacy(np, mvchip->chip.ngpio,
|
||||
mvchip->irqbase, 0,
|
||||
mvchip->domain = irq_domain_add_simple(np, mvchip->chip.ngpio,
|
||||
mvchip->irqbase,
|
||||
&irq_domain_simple_ops,
|
||||
mvchip);
|
||||
if (!mvchip->domain) {
|
||||
|
|
|
@ -1105,7 +1105,7 @@ static int __devinit omap_gpio_probe(struct platform_device *pdev)
|
|||
if (!pdata)
|
||||
return -EINVAL;
|
||||
|
||||
bank = devm_kzalloc(&pdev->dev, sizeof(struct gpio_bank), GFP_KERNEL);
|
||||
bank = devm_kzalloc(dev, sizeof(struct gpio_bank), GFP_KERNEL);
|
||||
if (!bank) {
|
||||
dev_err(dev, "Memory alloc failed\n");
|
||||
return -ENOMEM;
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
#include <linux/gpio.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/irq.h>
|
||||
#include <linux/irqdomain.h>
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/i2c/pca953x.h>
|
||||
#include <linux/slab.h>
|
||||
|
@ -83,6 +84,7 @@ struct pca953x_chip {
|
|||
u32 irq_trig_raise;
|
||||
u32 irq_trig_fall;
|
||||
int irq_base;
|
||||
struct irq_domain *domain;
|
||||
#endif
|
||||
|
||||
struct i2c_client *client;
|
||||
|
@ -333,14 +335,14 @@ static void pca953x_irq_mask(struct irq_data *d)
|
|||
{
|
||||
struct pca953x_chip *chip = irq_data_get_irq_chip_data(d);
|
||||
|
||||
chip->irq_mask &= ~(1 << (d->irq - chip->irq_base));
|
||||
chip->irq_mask &= ~(1 << d->hwirq);
|
||||
}
|
||||
|
||||
static void pca953x_irq_unmask(struct irq_data *d)
|
||||
{
|
||||
struct pca953x_chip *chip = irq_data_get_irq_chip_data(d);
|
||||
|
||||
chip->irq_mask |= 1 << (d->irq - chip->irq_base);
|
||||
chip->irq_mask |= 1 << d->hwirq;
|
||||
}
|
||||
|
||||
static void pca953x_irq_bus_lock(struct irq_data *d)
|
||||
|
@ -372,8 +374,7 @@ static void pca953x_irq_bus_sync_unlock(struct irq_data *d)
|
|||
static int pca953x_irq_set_type(struct irq_data *d, unsigned int type)
|
||||
{
|
||||
struct pca953x_chip *chip = irq_data_get_irq_chip_data(d);
|
||||
u32 level = d->irq - chip->irq_base;
|
||||
u32 mask = 1 << level;
|
||||
u32 mask = 1 << d->hwirq;
|
||||
|
||||
if (!(type & IRQ_TYPE_EDGE_BOTH)) {
|
||||
dev_err(&chip->client->dev, "irq %d: unsupported type %d\n",
|
||||
|
@ -454,7 +455,7 @@ static irqreturn_t pca953x_irq_handler(int irq, void *devid)
|
|||
|
||||
do {
|
||||
level = __ffs(pending);
|
||||
handle_nested_irq(level + chip->irq_base);
|
||||
handle_nested_irq(irq_find_mapping(chip->domain, level));
|
||||
|
||||
pending &= ~(1 << level);
|
||||
} while (pending);
|
||||
|
@ -499,6 +500,17 @@ static int pca953x_irq_setup(struct pca953x_chip *chip,
|
|||
if (chip->irq_base < 0)
|
||||
goto out_failed;
|
||||
|
||||
chip->domain = irq_domain_add_legacy(client->dev.of_node,
|
||||
chip->gpio_chip.ngpio,
|
||||
chip->irq_base,
|
||||
0,
|
||||
&irq_domain_simple_ops,
|
||||
NULL);
|
||||
if (!chip->domain) {
|
||||
ret = -ENODEV;
|
||||
goto out_irqdesc_free;
|
||||
}
|
||||
|
||||
for (lvl = 0; lvl < chip->gpio_chip.ngpio; lvl++) {
|
||||
int irq = lvl + chip->irq_base;
|
||||
|
||||
|
@ -521,7 +533,7 @@ static int pca953x_irq_setup(struct pca953x_chip *chip,
|
|||
if (ret) {
|
||||
dev_err(&client->dev, "failed to request irq %d\n",
|
||||
client->irq);
|
||||
goto out_failed;
|
||||
goto out_irqdesc_free;
|
||||
}
|
||||
|
||||
chip->gpio_chip.to_irq = pca953x_gpio_to_irq;
|
||||
|
@ -529,6 +541,8 @@ static int pca953x_irq_setup(struct pca953x_chip *chip,
|
|||
|
||||
return 0;
|
||||
|
||||
out_irqdesc_free:
|
||||
irq_free_descs(chip->irq_base, chip->gpio_chip.ngpio);
|
||||
out_failed:
|
||||
chip->irq_base = -1;
|
||||
return ret;
|
||||
|
@ -751,9 +765,38 @@ static int pca953x_remove(struct i2c_client *client)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static const struct of_device_id pca953x_dt_ids[] = {
|
||||
{ .compatible = "nxp,pca9534", },
|
||||
{ .compatible = "nxp,pca9535", },
|
||||
{ .compatible = "nxp,pca9536", },
|
||||
{ .compatible = "nxp,pca9537", },
|
||||
{ .compatible = "nxp,pca9538", },
|
||||
{ .compatible = "nxp,pca9539", },
|
||||
{ .compatible = "nxp,pca9554", },
|
||||
{ .compatible = "nxp,pca9555", },
|
||||
{ .compatible = "nxp,pca9556", },
|
||||
{ .compatible = "nxp,pca9557", },
|
||||
{ .compatible = "nxp,pca9574", },
|
||||
{ .compatible = "nxp,pca9575", },
|
||||
|
||||
{ .compatible = "maxim,max7310", },
|
||||
{ .compatible = "maxim,max7312", },
|
||||
{ .compatible = "maxim,max7313", },
|
||||
{ .compatible = "maxim,max7315", },
|
||||
|
||||
{ .compatible = "ti,pca6107", },
|
||||
{ .compatible = "ti,tca6408", },
|
||||
{ .compatible = "ti,tca6416", },
|
||||
{ .compatible = "ti,tca6424", },
|
||||
{ }
|
||||
};
|
||||
|
||||
MODULE_DEVICE_TABLE(of, pca953x_dt_ids);
|
||||
|
||||
static struct i2c_driver pca953x_driver = {
|
||||
.driver = {
|
||||
.name = "pca953x",
|
||||
.of_match_table = pca953x_dt_ids,
|
||||
},
|
||||
.probe = pca953x_probe,
|
||||
.remove = pca953x_remove,
|
||||
|
|
|
@ -215,6 +215,7 @@ static void pch_gpio_setup(struct pch_gpio *chip)
|
|||
struct gpio_chip *gpio = &chip->gpio;
|
||||
|
||||
gpio->label = dev_name(chip->dev);
|
||||
gpio->dev = chip->dev;
|
||||
gpio->owner = THIS_MODULE;
|
||||
gpio->direction_input = pch_gpio_direction_input;
|
||||
gpio->get = pch_gpio_get;
|
||||
|
|
|
@ -216,39 +216,34 @@ static void __init pl061_init_gc(struct pl061_gpio *chip, int irq_base)
|
|||
IRQ_GC_INIT_NESTED_LOCK, IRQ_NOREQUEST, 0);
|
||||
}
|
||||
|
||||
static int pl061_probe(struct amba_device *dev, const struct amba_id *id)
|
||||
static int pl061_probe(struct amba_device *adev, const struct amba_id *id)
|
||||
{
|
||||
struct pl061_platform_data *pdata;
|
||||
struct device *dev = &adev->dev;
|
||||
struct pl061_platform_data *pdata = dev->platform_data;
|
||||
struct pl061_gpio *chip;
|
||||
int ret, irq, i;
|
||||
|
||||
chip = kzalloc(sizeof(*chip), GFP_KERNEL);
|
||||
chip = devm_kzalloc(dev, sizeof(*chip), GFP_KERNEL);
|
||||
if (chip == NULL)
|
||||
return -ENOMEM;
|
||||
|
||||
pdata = dev->dev.platform_data;
|
||||
if (pdata) {
|
||||
chip->gc.base = pdata->gpio_base;
|
||||
chip->irq_base = pdata->irq_base;
|
||||
} else if (dev->dev.of_node) {
|
||||
} else if (adev->dev.of_node) {
|
||||
chip->gc.base = -1;
|
||||
chip->irq_base = 0;
|
||||
} else {
|
||||
ret = -ENODEV;
|
||||
goto free_mem;
|
||||
}
|
||||
} else
|
||||
return -ENODEV;
|
||||
|
||||
if (!request_mem_region(dev->res.start,
|
||||
resource_size(&dev->res), "pl061")) {
|
||||
ret = -EBUSY;
|
||||
goto free_mem;
|
||||
}
|
||||
if (!devm_request_mem_region(dev, adev->res.start,
|
||||
resource_size(&adev->res), "pl061"))
|
||||
return -EBUSY;
|
||||
|
||||
chip->base = ioremap(dev->res.start, resource_size(&dev->res));
|
||||
if (chip->base == NULL) {
|
||||
ret = -ENOMEM;
|
||||
goto release_region;
|
||||
}
|
||||
chip->base = devm_ioremap(dev, adev->res.start,
|
||||
resource_size(&adev->res));
|
||||
if (chip->base == NULL)
|
||||
return -ENOMEM;
|
||||
|
||||
spin_lock_init(&chip->lock);
|
||||
|
||||
|
@ -258,13 +253,13 @@ static int pl061_probe(struct amba_device *dev, const struct amba_id *id)
|
|||
chip->gc.set = pl061_set_value;
|
||||
chip->gc.to_irq = pl061_to_irq;
|
||||
chip->gc.ngpio = PL061_GPIO_NR;
|
||||
chip->gc.label = dev_name(&dev->dev);
|
||||
chip->gc.dev = &dev->dev;
|
||||
chip->gc.label = dev_name(dev);
|
||||
chip->gc.dev = dev;
|
||||
chip->gc.owner = THIS_MODULE;
|
||||
|
||||
ret = gpiochip_add(&chip->gc);
|
||||
if (ret)
|
||||
goto iounmap;
|
||||
return ret;
|
||||
|
||||
/*
|
||||
* irq_chip support
|
||||
|
@ -276,11 +271,10 @@ static int pl061_probe(struct amba_device *dev, const struct amba_id *id)
|
|||
pl061_init_gc(chip, chip->irq_base);
|
||||
|
||||
writeb(0, chip->base + GPIOIE); /* disable irqs */
|
||||
irq = dev->irq[0];
|
||||
if (irq < 0) {
|
||||
ret = -ENODEV;
|
||||
goto iounmap;
|
||||
}
|
||||
irq = adev->irq[0];
|
||||
if (irq < 0)
|
||||
return -ENODEV;
|
||||
|
||||
irq_set_chained_handler(irq, pl061_irq_handler);
|
||||
irq_set_handler_data(irq, chip);
|
||||
|
||||
|
@ -294,18 +288,9 @@ static int pl061_probe(struct amba_device *dev, const struct amba_id *id)
|
|||
}
|
||||
}
|
||||
|
||||
amba_set_drvdata(dev, chip);
|
||||
amba_set_drvdata(adev, chip);
|
||||
|
||||
return 0;
|
||||
|
||||
iounmap:
|
||||
iounmap(chip->base);
|
||||
release_region:
|
||||
release_mem_region(dev->res.start, resource_size(&dev->res));
|
||||
free_mem:
|
||||
kfree(chip);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_PM
|
||||
|
|
|
@ -0,0 +1,217 @@
|
|||
/*
|
||||
* SPEAr platform SPI chipselect abstraction over gpiolib
|
||||
*
|
||||
* Copyright (C) 2012 ST Microelectronics
|
||||
* Shiraz Hashim <shiraz.hashim@st.com>
|
||||
*
|
||||
* This file is licensed under the terms of the GNU General Public
|
||||
* License version 2. This program is licensed "as is" without any
|
||||
* warranty of any kind, whether express or implied.
|
||||
*/
|
||||
|
||||
#include <linux/err.h>
|
||||
#include <linux/gpio.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/types.h>
|
||||
|
||||
/* maximum chipselects */
|
||||
#define NUM_OF_GPIO 4
|
||||
|
||||
/*
|
||||
* Provision is available on some SPEAr SoCs to control ARM PL022 spi cs
|
||||
* through system registers. This register lies outside spi (pl022)
|
||||
* address space into system registers.
|
||||
*
|
||||
* It provides control for spi chip select lines so that any chipselect
|
||||
* (out of 4 possible chipselects in pl022) can be made low to select
|
||||
* the particular slave.
|
||||
*/
|
||||
|
||||
/**
|
||||
* struct spear_spics - represents spi chip select control
|
||||
* @base: base address
|
||||
* @perip_cfg: configuration register
|
||||
* @sw_enable_bit: bit to enable s/w control over chipselects
|
||||
* @cs_value_bit: bit to program high or low chipselect
|
||||
* @cs_enable_mask: mask to select bits required to select chipselect
|
||||
* @cs_enable_shift: bit pos of cs_enable_mask
|
||||
* @use_count: use count of a spi controller cs lines
|
||||
* @last_off: stores last offset caller of set_value()
|
||||
* @chip: gpio_chip abstraction
|
||||
*/
|
||||
struct spear_spics {
|
||||
void __iomem *base;
|
||||
u32 perip_cfg;
|
||||
u32 sw_enable_bit;
|
||||
u32 cs_value_bit;
|
||||
u32 cs_enable_mask;
|
||||
u32 cs_enable_shift;
|
||||
unsigned long use_count;
|
||||
int last_off;
|
||||
struct gpio_chip chip;
|
||||
};
|
||||
|
||||
/* gpio framework specific routines */
|
||||
static int spics_get_value(struct gpio_chip *chip, unsigned offset)
|
||||
{
|
||||
return -ENXIO;
|
||||
}
|
||||
|
||||
static void spics_set_value(struct gpio_chip *chip, unsigned offset, int value)
|
||||
{
|
||||
struct spear_spics *spics = container_of(chip, struct spear_spics,
|
||||
chip);
|
||||
u32 tmp;
|
||||
|
||||
/* select chip select from register */
|
||||
tmp = readl_relaxed(spics->base + spics->perip_cfg);
|
||||
if (spics->last_off != offset) {
|
||||
spics->last_off = offset;
|
||||
tmp &= ~(spics->cs_enable_mask << spics->cs_enable_shift);
|
||||
tmp |= offset << spics->cs_enable_shift;
|
||||
}
|
||||
|
||||
/* toggle chip select line */
|
||||
tmp &= ~(0x1 << spics->cs_value_bit);
|
||||
tmp |= value << spics->cs_value_bit;
|
||||
writel_relaxed(tmp, spics->base + spics->perip_cfg);
|
||||
}
|
||||
|
||||
static int spics_direction_input(struct gpio_chip *chip, unsigned offset)
|
||||
{
|
||||
return -ENXIO;
|
||||
}
|
||||
|
||||
static int spics_direction_output(struct gpio_chip *chip, unsigned offset,
|
||||
int value)
|
||||
{
|
||||
spics_set_value(chip, offset, value);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int spics_request(struct gpio_chip *chip, unsigned offset)
|
||||
{
|
||||
struct spear_spics *spics = container_of(chip, struct spear_spics,
|
||||
chip);
|
||||
u32 tmp;
|
||||
|
||||
if (!spics->use_count++) {
|
||||
tmp = readl_relaxed(spics->base + spics->perip_cfg);
|
||||
tmp |= 0x1 << spics->sw_enable_bit;
|
||||
tmp |= 0x1 << spics->cs_value_bit;
|
||||
writel_relaxed(tmp, spics->base + spics->perip_cfg);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void spics_free(struct gpio_chip *chip, unsigned offset)
|
||||
{
|
||||
struct spear_spics *spics = container_of(chip, struct spear_spics,
|
||||
chip);
|
||||
u32 tmp;
|
||||
|
||||
if (!--spics->use_count) {
|
||||
tmp = readl_relaxed(spics->base + spics->perip_cfg);
|
||||
tmp &= ~(0x1 << spics->sw_enable_bit);
|
||||
writel_relaxed(tmp, spics->base + spics->perip_cfg);
|
||||
}
|
||||
}
|
||||
|
||||
static int spics_gpio_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct device_node *np = pdev->dev.of_node;
|
||||
struct spear_spics *spics;
|
||||
struct resource *res;
|
||||
int ret;
|
||||
|
||||
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||
if (!res) {
|
||||
dev_err(&pdev->dev, "invalid IORESOURCE_MEM\n");
|
||||
return -EBUSY;
|
||||
}
|
||||
|
||||
spics = devm_kzalloc(&pdev->dev, sizeof(*spics), GFP_KERNEL);
|
||||
if (!spics) {
|
||||
dev_err(&pdev->dev, "memory allocation fail\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
spics->base = devm_request_and_ioremap(&pdev->dev, res);
|
||||
if (!spics->base) {
|
||||
dev_err(&pdev->dev, "request and ioremap fail\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
if (of_property_read_u32(np, "st-spics,peripcfg-reg",
|
||||
&spics->perip_cfg))
|
||||
goto err_dt_data;
|
||||
if (of_property_read_u32(np, "st-spics,sw-enable-bit",
|
||||
&spics->sw_enable_bit))
|
||||
goto err_dt_data;
|
||||
if (of_property_read_u32(np, "st-spics,cs-value-bit",
|
||||
&spics->cs_value_bit))
|
||||
goto err_dt_data;
|
||||
if (of_property_read_u32(np, "st-spics,cs-enable-mask",
|
||||
&spics->cs_enable_mask))
|
||||
goto err_dt_data;
|
||||
if (of_property_read_u32(np, "st-spics,cs-enable-shift",
|
||||
&spics->cs_enable_shift))
|
||||
goto err_dt_data;
|
||||
|
||||
platform_set_drvdata(pdev, spics);
|
||||
|
||||
spics->chip.ngpio = NUM_OF_GPIO;
|
||||
spics->chip.base = -1;
|
||||
spics->chip.request = spics_request;
|
||||
spics->chip.free = spics_free;
|
||||
spics->chip.direction_input = spics_direction_input;
|
||||
spics->chip.direction_output = spics_direction_output;
|
||||
spics->chip.get = spics_get_value;
|
||||
spics->chip.set = spics_set_value;
|
||||
spics->chip.label = dev_name(&pdev->dev);
|
||||
spics->chip.dev = &pdev->dev;
|
||||
spics->chip.owner = THIS_MODULE;
|
||||
spics->last_off = -1;
|
||||
|
||||
ret = gpiochip_add(&spics->chip);
|
||||
if (ret) {
|
||||
dev_err(&pdev->dev, "unable to add gpio chip\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
dev_info(&pdev->dev, "spear spics registered\n");
|
||||
return 0;
|
||||
|
||||
err_dt_data:
|
||||
dev_err(&pdev->dev, "DT probe failed\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
static const struct of_device_id spics_gpio_of_match[] = {
|
||||
{ .compatible = "st,spear-spics-gpio" },
|
||||
{}
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, spics_gpio_of_match);
|
||||
|
||||
static struct platform_driver spics_gpio_driver = {
|
||||
.probe = spics_gpio_probe,
|
||||
.driver = {
|
||||
.owner = THIS_MODULE,
|
||||
.name = "spear-spics-gpio",
|
||||
.of_match_table = spics_gpio_of_match,
|
||||
},
|
||||
};
|
||||
|
||||
static int __init spics_gpio_init(void)
|
||||
{
|
||||
return platform_driver_register(&spics_gpio_driver);
|
||||
}
|
||||
subsys_initcall(spics_gpio_init);
|
||||
|
||||
MODULE_AUTHOR("Shiraz Hashim <shiraz.hashim@st.com>");
|
||||
MODULE_DESCRIPTION("ST Microlectronics SPEAr SPI Chip Select Abstraction");
|
||||
MODULE_LICENSE("GPL");
|
|
@ -292,17 +292,15 @@ static int tc3589x_gpio_irq_init(struct tc3589x_gpio *tc3589x_gpio,
|
|||
{
|
||||
int base = tc3589x_gpio->irq_base;
|
||||
|
||||
if (base) {
|
||||
tc3589x_gpio->domain = irq_domain_add_legacy(
|
||||
NULL, tc3589x_gpio->chip.ngpio, base,
|
||||
0, &tc3589x_irq_ops, tc3589x_gpio);
|
||||
}
|
||||
else {
|
||||
tc3589x_gpio->domain = irq_domain_add_linear(
|
||||
np, tc3589x_gpio->chip.ngpio,
|
||||
&tc3589x_irq_ops, tc3589x_gpio);
|
||||
}
|
||||
|
||||
/*
|
||||
* If this results in a linear domain, irq_create_mapping() will
|
||||
* take care of allocating IRQ descriptors at runtime. When a base
|
||||
* is provided, the IRQ descriptors will be allocated when the
|
||||
* domain is instantiated.
|
||||
*/
|
||||
tc3589x_gpio->domain = irq_domain_add_simple(np,
|
||||
tc3589x_gpio->chip.ngpio, base, &tc3589x_irq_ops,
|
||||
tc3589x_gpio);
|
||||
if (!tc3589x_gpio->domain) {
|
||||
dev_err(tc3589x_gpio->dev, "Failed to create irqdomain\n");
|
||||
return -ENOSYS;
|
||||
|
|
|
@ -27,6 +27,7 @@
|
|||
#include <linux/module.h>
|
||||
#include <linux/irqdomain.h>
|
||||
#include <linux/pinctrl/consumer.h>
|
||||
#include <linux/pm.h>
|
||||
|
||||
#include <asm/mach/irq.h>
|
||||
|
||||
|
@ -64,7 +65,7 @@ struct tegra_gpio_bank {
|
|||
int bank;
|
||||
int irq;
|
||||
spinlock_t lvl_lock[4];
|
||||
#ifdef CONFIG_PM
|
||||
#ifdef CONFIG_PM_SLEEP
|
||||
u32 cnf[4];
|
||||
u32 out[4];
|
||||
u32 oe[4];
|
||||
|
@ -109,20 +110,18 @@ static void tegra_gpio_enable(int gpio)
|
|||
{
|
||||
tegra_gpio_mask_write(GPIO_MSK_CNF(gpio), gpio, 1);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(tegra_gpio_enable);
|
||||
|
||||
static void tegra_gpio_disable(int gpio)
|
||||
{
|
||||
tegra_gpio_mask_write(GPIO_MSK_CNF(gpio), gpio, 0);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(tegra_gpio_disable);
|
||||
|
||||
int tegra_gpio_request(struct gpio_chip *chip, unsigned offset)
|
||||
static int tegra_gpio_request(struct gpio_chip *chip, unsigned offset)
|
||||
{
|
||||
return pinctrl_request_gpio(offset);
|
||||
}
|
||||
|
||||
void tegra_gpio_free(struct gpio_chip *chip, unsigned offset)
|
||||
static void tegra_gpio_free(struct gpio_chip *chip, unsigned offset)
|
||||
{
|
||||
pinctrl_free_gpio(offset);
|
||||
tegra_gpio_disable(offset);
|
||||
|
@ -135,6 +134,11 @@ static void tegra_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
|
|||
|
||||
static int tegra_gpio_get(struct gpio_chip *chip, unsigned offset)
|
||||
{
|
||||
/* If gpio is in output mode then read from the out value */
|
||||
if ((tegra_gpio_readl(GPIO_OE(offset)) >> GPIO_BIT(offset)) & 1)
|
||||
return (tegra_gpio_readl(GPIO_OUT(offset)) >>
|
||||
GPIO_BIT(offset)) & 0x1;
|
||||
|
||||
return (tegra_gpio_readl(GPIO_IN(offset)) >> GPIO_BIT(offset)) & 0x1;
|
||||
}
|
||||
|
||||
|
@ -285,8 +289,8 @@ static void tegra_gpio_irq_handler(unsigned int irq, struct irq_desc *desc)
|
|||
|
||||
}
|
||||
|
||||
#ifdef CONFIG_PM
|
||||
void tegra_gpio_resume(void)
|
||||
#ifdef CONFIG_PM_SLEEP
|
||||
static int tegra_gpio_resume(struct device *dev)
|
||||
{
|
||||
unsigned long flags;
|
||||
int b;
|
||||
|
@ -308,9 +312,10 @@ void tegra_gpio_resume(void)
|
|||
}
|
||||
|
||||
local_irq_restore(flags);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void tegra_gpio_suspend(void)
|
||||
static int tegra_gpio_suspend(struct device *dev)
|
||||
{
|
||||
unsigned long flags;
|
||||
int b;
|
||||
|
@ -330,6 +335,7 @@ void tegra_gpio_suspend(void)
|
|||
}
|
||||
}
|
||||
local_irq_restore(flags);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int tegra_gpio_wake_enable(struct irq_data *d, unsigned int enable)
|
||||
|
@ -345,11 +351,15 @@ static struct irq_chip tegra_gpio_irq_chip = {
|
|||
.irq_mask = tegra_gpio_irq_mask,
|
||||
.irq_unmask = tegra_gpio_irq_unmask,
|
||||
.irq_set_type = tegra_gpio_irq_set_type,
|
||||
#ifdef CONFIG_PM
|
||||
#ifdef CONFIG_PM_SLEEP
|
||||
.irq_set_wake = tegra_gpio_wake_enable,
|
||||
#endif
|
||||
};
|
||||
|
||||
static const struct dev_pm_ops tegra_gpio_pm_ops = {
|
||||
SET_SYSTEM_SLEEP_PM_OPS(tegra_gpio_suspend, tegra_gpio_resume)
|
||||
};
|
||||
|
||||
struct tegra_gpio_soc_config {
|
||||
u32 bank_stride;
|
||||
u32 upper_offset;
|
||||
|
@ -380,7 +390,6 @@ static int __devinit tegra_gpio_probe(struct platform_device *pdev)
|
|||
{
|
||||
const struct of_device_id *match;
|
||||
struct tegra_gpio_soc_config *config;
|
||||
int irq_base;
|
||||
struct resource *res;
|
||||
struct tegra_gpio_bank *bank;
|
||||
int gpio;
|
||||
|
@ -417,14 +426,11 @@ static int __devinit tegra_gpio_probe(struct platform_device *pdev)
|
|||
return -ENODEV;
|
||||
}
|
||||
|
||||
irq_base = irq_alloc_descs(-1, 0, tegra_gpio_chip.ngpio, 0);
|
||||
if (irq_base < 0) {
|
||||
dev_err(&pdev->dev, "Couldn't allocate IRQ numbers\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
irq_domain = irq_domain_add_legacy(pdev->dev.of_node,
|
||||
tegra_gpio_chip.ngpio, irq_base, 0,
|
||||
irq_domain = irq_domain_add_linear(pdev->dev.of_node,
|
||||
tegra_gpio_chip.ngpio,
|
||||
&irq_domain_simple_ops, NULL);
|
||||
if (!irq_domain)
|
||||
return -ENODEV;
|
||||
|
||||
for (i = 0; i < tegra_gpio_bank_count; i++) {
|
||||
res = platform_get_resource(pdev, IORESOURCE_IRQ, i);
|
||||
|
@ -464,7 +470,7 @@ static int __devinit tegra_gpio_probe(struct platform_device *pdev)
|
|||
gpiochip_add(&tegra_gpio_chip);
|
||||
|
||||
for (gpio = 0; gpio < tegra_gpio_chip.ngpio; gpio++) {
|
||||
int irq = irq_find_mapping(irq_domain, gpio);
|
||||
int irq = irq_create_mapping(irq_domain, gpio);
|
||||
/* No validity check; all Tegra GPIOs are valid IRQs */
|
||||
|
||||
bank = &tegra_gpio_banks[GPIO_BANK(gpio)];
|
||||
|
@ -493,6 +499,7 @@ static struct platform_driver tegra_gpio_driver = {
|
|||
.driver = {
|
||||
.name = "tegra-gpio",
|
||||
.owner = THIS_MODULE,
|
||||
.pm = &tegra_gpio_pm_ops,
|
||||
.of_match_table = tegra_gpio_of_match,
|
||||
},
|
||||
.probe = tegra_gpio_probe,
|
||||
|
|
|
@ -88,11 +88,15 @@ static inline int gpio_twl4030_write(u8 address, u8 data)
|
|||
/*----------------------------------------------------------------------*/
|
||||
|
||||
/*
|
||||
* LED register offsets (use TWL4030_MODULE_{LED,PWMA,PWMB}))
|
||||
* LED register offsets from TWL_MODULE_LED base
|
||||
* PWMs A and B are dedicated to LEDs A and B, respectively.
|
||||
*/
|
||||
|
||||
#define TWL4030_LED_LEDEN 0x0
|
||||
#define TWL4030_LED_LEDEN_REG 0x00
|
||||
#define TWL4030_PWMAON_REG 0x01
|
||||
#define TWL4030_PWMAOFF_REG 0x02
|
||||
#define TWL4030_PWMBON_REG 0x03
|
||||
#define TWL4030_PWMBOFF_REG 0x04
|
||||
|
||||
/* LEDEN bits */
|
||||
#define LEDEN_LEDAON BIT(0)
|
||||
|
@ -104,9 +108,6 @@ static inline int gpio_twl4030_write(u8 address, u8 data)
|
|||
#define LEDEN_PWM_LENGTHA BIT(6)
|
||||
#define LEDEN_PWM_LENGTHB BIT(7)
|
||||
|
||||
#define TWL4030_PWMx_PWMxON 0x0
|
||||
#define TWL4030_PWMx_PWMxOFF 0x1
|
||||
|
||||
#define PWMxON_LENGTH BIT(7)
|
||||
|
||||
/*----------------------------------------------------------------------*/
|
||||
|
@ -145,7 +146,7 @@ static void twl4030_led_set_value(int led, int value)
|
|||
else
|
||||
cached_leden |= mask;
|
||||
status = twl_i2c_write_u8(TWL4030_MODULE_LED, cached_leden,
|
||||
TWL4030_LED_LEDEN);
|
||||
TWL4030_LED_LEDEN_REG);
|
||||
mutex_unlock(&gpio_lock);
|
||||
}
|
||||
|
||||
|
@ -216,33 +217,33 @@ static int twl_request(struct gpio_chip *chip, unsigned offset)
|
|||
if (offset >= TWL4030_GPIO_MAX) {
|
||||
u8 ledclr_mask = LEDEN_LEDAON | LEDEN_LEDAEXT
|
||||
| LEDEN_LEDAPWM | LEDEN_PWM_LENGTHA;
|
||||
u8 module = TWL4030_MODULE_PWMA;
|
||||
u8 reg = TWL4030_PWMAON_REG;
|
||||
|
||||
offset -= TWL4030_GPIO_MAX;
|
||||
if (offset) {
|
||||
ledclr_mask <<= 1;
|
||||
module = TWL4030_MODULE_PWMB;
|
||||
reg = TWL4030_PWMBON_REG;
|
||||
}
|
||||
|
||||
/* initialize PWM to always-drive */
|
||||
status = twl_i2c_write_u8(module, 0x7f,
|
||||
TWL4030_PWMx_PWMxOFF);
|
||||
/* Configure PWM OFF register first */
|
||||
status = twl_i2c_write_u8(TWL4030_MODULE_LED, 0x7f, reg + 1);
|
||||
if (status < 0)
|
||||
goto done;
|
||||
status = twl_i2c_write_u8(module, 0x7f,
|
||||
TWL4030_PWMx_PWMxON);
|
||||
|
||||
/* Followed by PWM ON register */
|
||||
status = twl_i2c_write_u8(TWL4030_MODULE_LED, 0x7f, reg);
|
||||
if (status < 0)
|
||||
goto done;
|
||||
|
||||
/* init LED to not-driven (high) */
|
||||
module = TWL4030_MODULE_LED;
|
||||
status = twl_i2c_read_u8(module, &cached_leden,
|
||||
TWL4030_LED_LEDEN);
|
||||
status = twl_i2c_read_u8(TWL4030_MODULE_LED, &cached_leden,
|
||||
TWL4030_LED_LEDEN_REG);
|
||||
if (status < 0)
|
||||
goto done;
|
||||
cached_leden &= ~ledclr_mask;
|
||||
status = twl_i2c_write_u8(module, cached_leden,
|
||||
TWL4030_LED_LEDEN);
|
||||
status = twl_i2c_write_u8(TWL4030_MODULE_LED, cached_leden,
|
||||
TWL4030_LED_LEDEN_REG);
|
||||
if (status < 0)
|
||||
goto done;
|
||||
|
||||
|
|
|
@ -96,6 +96,7 @@ static struct vt8500_gpio_data wm8505_data = {
|
|||
VT8500_BANK(0x5C, 0x84, 0xAC, 0xD4, 12),
|
||||
VT8500_BANK(0x60, 0x88, 0xB0, 0xD8, 16),
|
||||
VT8500_BANK(0x64, 0x8C, 0xB4, 0xDC, 22),
|
||||
VT8500_BANK(0x500, 0x504, 0x508, 0x50C, 6),
|
||||
},
|
||||
};
|
||||
|
||||
|
@ -115,6 +116,7 @@ static struct vt8500_gpio_data wm8650_data = {
|
|||
VT8500_BANK(0x58, 0x98, 0xD8, 0x18, 32),
|
||||
VT8500_BANK(0x5C, 0x9C, 0xDC, 0x1C, 32),
|
||||
VT8500_BANK(0x7C, 0xBC, 0xFC, 0x3C, 32),
|
||||
VT8500_BANK(0x500, 0x504, 0x508, 0x50C, 6),
|
||||
},
|
||||
};
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -191,6 +191,32 @@ err:
|
|||
return ret;
|
||||
}
|
||||
|
||||
/* caller ensures gpio is valid and requested, chip->get_direction may sleep */
|
||||
static int gpio_get_direction(unsigned gpio)
|
||||
{
|
||||
struct gpio_chip *chip;
|
||||
struct gpio_desc *desc = &gpio_desc[gpio];
|
||||
int status = -EINVAL;
|
||||
|
||||
chip = gpio_to_chip(gpio);
|
||||
gpio -= chip->base;
|
||||
|
||||
if (!chip->get_direction)
|
||||
return status;
|
||||
|
||||
status = chip->get_direction(chip, gpio);
|
||||
if (status > 0) {
|
||||
/* GPIOF_DIR_IN, or other positive */
|
||||
status = 1;
|
||||
clear_bit(FLAG_IS_OUT, &desc->flags);
|
||||
}
|
||||
if (status == 0) {
|
||||
/* GPIOF_DIR_OUT */
|
||||
set_bit(FLAG_IS_OUT, &desc->flags);
|
||||
}
|
||||
return status;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_GPIO_SYSFS
|
||||
|
||||
/* lock protects against unexport_gpio() being called while
|
||||
|
@ -223,6 +249,7 @@ static ssize_t gpio_direction_show(struct device *dev,
|
|||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
const struct gpio_desc *desc = dev_get_drvdata(dev);
|
||||
unsigned gpio = desc - gpio_desc;
|
||||
ssize_t status;
|
||||
|
||||
mutex_lock(&sysfs_lock);
|
||||
|
@ -230,6 +257,7 @@ static ssize_t gpio_direction_show(struct device *dev,
|
|||
if (!test_bit(FLAG_EXPORT, &desc->flags))
|
||||
status = -EIO;
|
||||
else
|
||||
gpio_get_direction(gpio);
|
||||
status = sprintf(buf, "%s\n",
|
||||
test_bit(FLAG_IS_OUT, &desc->flags)
|
||||
? "out" : "in");
|
||||
|
@ -704,8 +732,9 @@ int gpio_export(unsigned gpio, bool direction_may_change)
|
|||
{
|
||||
unsigned long flags;
|
||||
struct gpio_desc *desc;
|
||||
int status = -EINVAL;
|
||||
int status;
|
||||
const char *ioname = NULL;
|
||||
struct device *dev;
|
||||
|
||||
/* can't export until sysfs is available ... */
|
||||
if (!gpio_class.p) {
|
||||
|
@ -713,59 +742,66 @@ int gpio_export(unsigned gpio, bool direction_may_change)
|
|||
return -ENOENT;
|
||||
}
|
||||
|
||||
if (!gpio_is_valid(gpio))
|
||||
goto done;
|
||||
if (!gpio_is_valid(gpio)) {
|
||||
pr_debug("%s: gpio %d is not valid\n", __func__, gpio);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
mutex_lock(&sysfs_lock);
|
||||
|
||||
spin_lock_irqsave(&gpio_lock, flags);
|
||||
desc = &gpio_desc[gpio];
|
||||
if (test_bit(FLAG_REQUESTED, &desc->flags)
|
||||
&& !test_bit(FLAG_EXPORT, &desc->flags)) {
|
||||
status = 0;
|
||||
if (!desc->chip->direction_input
|
||||
|| !desc->chip->direction_output)
|
||||
direction_may_change = false;
|
||||
if (!test_bit(FLAG_REQUESTED, &desc->flags) ||
|
||||
test_bit(FLAG_EXPORT, &desc->flags)) {
|
||||
spin_unlock_irqrestore(&gpio_lock, flags);
|
||||
pr_debug("%s: gpio %d unavailable (requested=%d, exported=%d)\n",
|
||||
__func__, gpio,
|
||||
test_bit(FLAG_REQUESTED, &desc->flags),
|
||||
test_bit(FLAG_EXPORT, &desc->flags));
|
||||
status = -EPERM;
|
||||
goto fail_unlock;
|
||||
}
|
||||
|
||||
if (!desc->chip->direction_input || !desc->chip->direction_output)
|
||||
direction_may_change = false;
|
||||
spin_unlock_irqrestore(&gpio_lock, flags);
|
||||
|
||||
if (desc->chip->names && desc->chip->names[gpio - desc->chip->base])
|
||||
ioname = desc->chip->names[gpio - desc->chip->base];
|
||||
|
||||
if (status == 0) {
|
||||
struct device *dev;
|
||||
|
||||
dev = device_create(&gpio_class, desc->chip->dev, MKDEV(0, 0),
|
||||
desc, ioname ? ioname : "gpio%u", gpio);
|
||||
if (!IS_ERR(dev)) {
|
||||
status = sysfs_create_group(&dev->kobj,
|
||||
&gpio_attr_group);
|
||||
|
||||
if (!status && direction_may_change)
|
||||
status = device_create_file(dev,
|
||||
&dev_attr_direction);
|
||||
|
||||
if (!status && gpio_to_irq(gpio) >= 0
|
||||
&& (direction_may_change
|
||||
|| !test_bit(FLAG_IS_OUT,
|
||||
&desc->flags)))
|
||||
status = device_create_file(dev,
|
||||
&dev_attr_edge);
|
||||
|
||||
if (status != 0)
|
||||
device_unregister(dev);
|
||||
} else
|
||||
status = PTR_ERR(dev);
|
||||
if (status == 0)
|
||||
set_bit(FLAG_EXPORT, &desc->flags);
|
||||
dev = device_create(&gpio_class, desc->chip->dev, MKDEV(0, 0),
|
||||
desc, ioname ? ioname : "gpio%u", gpio);
|
||||
if (IS_ERR(dev)) {
|
||||
status = PTR_ERR(dev);
|
||||
goto fail_unlock;
|
||||
}
|
||||
|
||||
mutex_unlock(&sysfs_lock);
|
||||
|
||||
done:
|
||||
status = sysfs_create_group(&dev->kobj, &gpio_attr_group);
|
||||
if (status)
|
||||
pr_debug("%s: gpio%d status %d\n", __func__, gpio, status);
|
||||
goto fail_unregister_device;
|
||||
|
||||
if (direction_may_change) {
|
||||
status = device_create_file(dev, &dev_attr_direction);
|
||||
if (status)
|
||||
goto fail_unregister_device;
|
||||
}
|
||||
|
||||
if (gpio_to_irq(gpio) >= 0 && (direction_may_change ||
|
||||
!test_bit(FLAG_IS_OUT, &desc->flags))) {
|
||||
status = device_create_file(dev, &dev_attr_edge);
|
||||
if (status)
|
||||
goto fail_unregister_device;
|
||||
}
|
||||
|
||||
set_bit(FLAG_EXPORT, &desc->flags);
|
||||
mutex_unlock(&sysfs_lock);
|
||||
return 0;
|
||||
|
||||
fail_unregister_device:
|
||||
device_unregister(dev);
|
||||
fail_unlock:
|
||||
mutex_unlock(&sysfs_lock);
|
||||
pr_debug("%s: gpio%d status %d\n", __func__, gpio, status);
|
||||
return status;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(gpio_export);
|
||||
|
@ -1075,6 +1111,7 @@ int gpiochip_add(struct gpio_chip *chip)
|
|||
* inputs (often with pullups enabled) so power
|
||||
* usage is minimized. Linux code should set the
|
||||
* gpio direction first thing; but until it does,
|
||||
* and in case chip->get_direction is not set,
|
||||
* we may expose the wrong direction in sysfs.
|
||||
*/
|
||||
gpio_desc[id].flags = !chip->direction_input
|
||||
|
@ -1083,6 +1120,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 +1164,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 +1222,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.
|
||||
|
@ -1228,9 +1311,15 @@ int gpio_request(unsigned gpio, const char *label)
|
|||
desc_set_label(desc, NULL);
|
||||
module_put(chip->owner);
|
||||
clear_bit(FLAG_REQUESTED, &desc->flags);
|
||||
goto done;
|
||||
}
|
||||
}
|
||||
|
||||
if (chip->get_direction) {
|
||||
/* chip->get_direction may sleep */
|
||||
spin_unlock_irqrestore(&gpio_lock, flags);
|
||||
gpio_get_direction(gpio);
|
||||
spin_lock_irqsave(&gpio_lock, flags);
|
||||
}
|
||||
done:
|
||||
if (status)
|
||||
pr_debug("gpio_request: gpio-%d (%s) status %d\n",
|
||||
|
@ -1766,6 +1855,7 @@ static void gpiolib_dbg_show(struct seq_file *s, struct gpio_chip *chip)
|
|||
if (!test_bit(FLAG_REQUESTED, &gdesc->flags))
|
||||
continue;
|
||||
|
||||
gpio_get_direction(gpio);
|
||||
is_out = test_bit(FLAG_IS_OUT, &gdesc->flags);
|
||||
seq_printf(s, " gpio-%-3d (%-20.20s) %s %s",
|
||||
gpio, gdesc->label,
|
||||
|
|
|
@ -1 +1,2 @@
|
|||
obj-$(CONFIG_ARCH_BCM2835) += irq-bcm2835.o
|
||||
obj-$(CONFIG_ARCH_BCM2835) += irq-bcm2835.o
|
||||
obj-$(CONFIG_ARCH_SPEAR3XX) += spear-shirq.o
|
||||
|
|
|
@ -0,0 +1,316 @@
|
|||
/*
|
||||
* SPEAr platform shared irq layer source file
|
||||
*
|
||||
* Copyright (C) 2009-2012 ST Microelectronics
|
||||
* Viresh Kumar <viresh.linux@gmail.com>
|
||||
*
|
||||
* Copyright (C) 2012 ST Microelectronics
|
||||
* Shiraz Hashim <shiraz.hashim@st.com>
|
||||
*
|
||||
* This file is licensed under the terms of the GNU General Public
|
||||
* License version 2. This program is licensed "as is" without any
|
||||
* warranty of any kind, whether express or implied.
|
||||
*/
|
||||
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
|
||||
|
||||
#include <linux/err.h>
|
||||
#include <linux/export.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/irq.h>
|
||||
#include <linux/irqdomain.h>
|
||||
#include <linux/irqchip/spear-shirq.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_address.h>
|
||||
#include <linux/of_irq.h>
|
||||
#include <linux/spinlock.h>
|
||||
|
||||
static DEFINE_SPINLOCK(lock);
|
||||
|
||||
/* spear300 shared irq registers offsets and masks */
|
||||
#define SPEAR300_INT_ENB_MASK_REG 0x54
|
||||
#define SPEAR300_INT_STS_MASK_REG 0x58
|
||||
|
||||
static struct spear_shirq spear300_shirq_ras1 = {
|
||||
.irq_nr = 9,
|
||||
.irq_bit_off = 0,
|
||||
.regs = {
|
||||
.enb_reg = SPEAR300_INT_ENB_MASK_REG,
|
||||
.status_reg = SPEAR300_INT_STS_MASK_REG,
|
||||
.clear_reg = -1,
|
||||
},
|
||||
};
|
||||
|
||||
static struct spear_shirq *spear300_shirq_blocks[] = {
|
||||
&spear300_shirq_ras1,
|
||||
};
|
||||
|
||||
/* spear310 shared irq registers offsets and masks */
|
||||
#define SPEAR310_INT_STS_MASK_REG 0x04
|
||||
|
||||
static struct spear_shirq spear310_shirq_ras1 = {
|
||||
.irq_nr = 8,
|
||||
.irq_bit_off = 0,
|
||||
.regs = {
|
||||
.enb_reg = -1,
|
||||
.status_reg = SPEAR310_INT_STS_MASK_REG,
|
||||
.clear_reg = -1,
|
||||
},
|
||||
};
|
||||
|
||||
static struct spear_shirq spear310_shirq_ras2 = {
|
||||
.irq_nr = 5,
|
||||
.irq_bit_off = 8,
|
||||
.regs = {
|
||||
.enb_reg = -1,
|
||||
.status_reg = SPEAR310_INT_STS_MASK_REG,
|
||||
.clear_reg = -1,
|
||||
},
|
||||
};
|
||||
|
||||
static struct spear_shirq spear310_shirq_ras3 = {
|
||||
.irq_nr = 1,
|
||||
.irq_bit_off = 13,
|
||||
.regs = {
|
||||
.enb_reg = -1,
|
||||
.status_reg = SPEAR310_INT_STS_MASK_REG,
|
||||
.clear_reg = -1,
|
||||
},
|
||||
};
|
||||
|
||||
static struct spear_shirq spear310_shirq_intrcomm_ras = {
|
||||
.irq_nr = 3,
|
||||
.irq_bit_off = 14,
|
||||
.regs = {
|
||||
.enb_reg = -1,
|
||||
.status_reg = SPEAR310_INT_STS_MASK_REG,
|
||||
.clear_reg = -1,
|
||||
},
|
||||
};
|
||||
|
||||
static struct spear_shirq *spear310_shirq_blocks[] = {
|
||||
&spear310_shirq_ras1,
|
||||
&spear310_shirq_ras2,
|
||||
&spear310_shirq_ras3,
|
||||
&spear310_shirq_intrcomm_ras,
|
||||
};
|
||||
|
||||
/* spear320 shared irq registers offsets and masks */
|
||||
#define SPEAR320_INT_STS_MASK_REG 0x04
|
||||
#define SPEAR320_INT_CLR_MASK_REG 0x04
|
||||
#define SPEAR320_INT_ENB_MASK_REG 0x08
|
||||
|
||||
static struct spear_shirq spear320_shirq_ras1 = {
|
||||
.irq_nr = 3,
|
||||
.irq_bit_off = 7,
|
||||
.regs = {
|
||||
.enb_reg = -1,
|
||||
.status_reg = SPEAR320_INT_STS_MASK_REG,
|
||||
.clear_reg = SPEAR320_INT_CLR_MASK_REG,
|
||||
.reset_to_clear = 1,
|
||||
},
|
||||
};
|
||||
|
||||
static struct spear_shirq spear320_shirq_ras2 = {
|
||||
.irq_nr = 1,
|
||||
.irq_bit_off = 10,
|
||||
.regs = {
|
||||
.enb_reg = -1,
|
||||
.status_reg = SPEAR320_INT_STS_MASK_REG,
|
||||
.clear_reg = SPEAR320_INT_CLR_MASK_REG,
|
||||
.reset_to_clear = 1,
|
||||
},
|
||||
};
|
||||
|
||||
static struct spear_shirq spear320_shirq_ras3 = {
|
||||
.irq_nr = 3,
|
||||
.irq_bit_off = 0,
|
||||
.invalid_irq = 1,
|
||||
.regs = {
|
||||
.enb_reg = SPEAR320_INT_ENB_MASK_REG,
|
||||
.reset_to_enb = 1,
|
||||
.status_reg = SPEAR320_INT_STS_MASK_REG,
|
||||
.clear_reg = SPEAR320_INT_CLR_MASK_REG,
|
||||
.reset_to_clear = 1,
|
||||
},
|
||||
};
|
||||
|
||||
static struct spear_shirq spear320_shirq_intrcomm_ras = {
|
||||
.irq_nr = 11,
|
||||
.irq_bit_off = 11,
|
||||
.regs = {
|
||||
.enb_reg = -1,
|
||||
.status_reg = SPEAR320_INT_STS_MASK_REG,
|
||||
.clear_reg = SPEAR320_INT_CLR_MASK_REG,
|
||||
.reset_to_clear = 1,
|
||||
},
|
||||
};
|
||||
|
||||
static struct spear_shirq *spear320_shirq_blocks[] = {
|
||||
&spear320_shirq_ras3,
|
||||
&spear320_shirq_ras1,
|
||||
&spear320_shirq_ras2,
|
||||
&spear320_shirq_intrcomm_ras,
|
||||
};
|
||||
|
||||
static void shirq_irq_mask_unmask(struct irq_data *d, bool mask)
|
||||
{
|
||||
struct spear_shirq *shirq = irq_data_get_irq_chip_data(d);
|
||||
u32 val, offset = d->irq - shirq->irq_base;
|
||||
unsigned long flags;
|
||||
|
||||
if (shirq->regs.enb_reg == -1)
|
||||
return;
|
||||
|
||||
spin_lock_irqsave(&lock, flags);
|
||||
val = readl(shirq->base + shirq->regs.enb_reg);
|
||||
|
||||
if (mask ^ shirq->regs.reset_to_enb)
|
||||
val &= ~(0x1 << shirq->irq_bit_off << offset);
|
||||
else
|
||||
val |= 0x1 << shirq->irq_bit_off << offset;
|
||||
|
||||
writel(val, shirq->base + shirq->regs.enb_reg);
|
||||
spin_unlock_irqrestore(&lock, flags);
|
||||
|
||||
}
|
||||
|
||||
static void shirq_irq_mask(struct irq_data *d)
|
||||
{
|
||||
shirq_irq_mask_unmask(d, 1);
|
||||
}
|
||||
|
||||
static void shirq_irq_unmask(struct irq_data *d)
|
||||
{
|
||||
shirq_irq_mask_unmask(d, 0);
|
||||
}
|
||||
|
||||
static struct irq_chip shirq_chip = {
|
||||
.name = "spear-shirq",
|
||||
.irq_ack = shirq_irq_mask,
|
||||
.irq_mask = shirq_irq_mask,
|
||||
.irq_unmask = shirq_irq_unmask,
|
||||
};
|
||||
|
||||
static void shirq_handler(unsigned irq, struct irq_desc *desc)
|
||||
{
|
||||
u32 i, j, val, mask, tmp;
|
||||
struct irq_chip *chip;
|
||||
struct spear_shirq *shirq = irq_get_handler_data(irq);
|
||||
|
||||
chip = irq_get_chip(irq);
|
||||
chip->irq_ack(&desc->irq_data);
|
||||
|
||||
mask = ((0x1 << shirq->irq_nr) - 1) << shirq->irq_bit_off;
|
||||
while ((val = readl(shirq->base + shirq->regs.status_reg) &
|
||||
mask)) {
|
||||
|
||||
val >>= shirq->irq_bit_off;
|
||||
for (i = 0, j = 1; i < shirq->irq_nr; i++, j <<= 1) {
|
||||
|
||||
if (!(j & val))
|
||||
continue;
|
||||
|
||||
generic_handle_irq(shirq->irq_base + i);
|
||||
|
||||
/* clear interrupt */
|
||||
if (shirq->regs.clear_reg == -1)
|
||||
continue;
|
||||
|
||||
tmp = readl(shirq->base + shirq->regs.clear_reg);
|
||||
if (shirq->regs.reset_to_clear)
|
||||
tmp &= ~(j << shirq->irq_bit_off);
|
||||
else
|
||||
tmp |= (j << shirq->irq_bit_off);
|
||||
writel(tmp, shirq->base + shirq->regs.clear_reg);
|
||||
}
|
||||
}
|
||||
chip->irq_unmask(&desc->irq_data);
|
||||
}
|
||||
|
||||
static void __init spear_shirq_register(struct spear_shirq *shirq)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (shirq->invalid_irq)
|
||||
return;
|
||||
|
||||
irq_set_chained_handler(shirq->irq, shirq_handler);
|
||||
for (i = 0; i < shirq->irq_nr; i++) {
|
||||
irq_set_chip_and_handler(shirq->irq_base + i,
|
||||
&shirq_chip, handle_simple_irq);
|
||||
set_irq_flags(shirq->irq_base + i, IRQF_VALID);
|
||||
irq_set_chip_data(shirq->irq_base + i, shirq);
|
||||
}
|
||||
|
||||
irq_set_handler_data(shirq->irq, shirq);
|
||||
}
|
||||
|
||||
static int __init shirq_init(struct spear_shirq **shirq_blocks, int block_nr,
|
||||
struct device_node *np)
|
||||
{
|
||||
int i, irq_base, hwirq = 0, irq_nr = 0;
|
||||
static struct irq_domain *shirq_domain;
|
||||
void __iomem *base;
|
||||
|
||||
base = of_iomap(np, 0);
|
||||
if (!base) {
|
||||
pr_err("%s: failed to map shirq registers\n", __func__);
|
||||
return -ENXIO;
|
||||
}
|
||||
|
||||
for (i = 0; i < block_nr; i++)
|
||||
irq_nr += shirq_blocks[i]->irq_nr;
|
||||
|
||||
irq_base = irq_alloc_descs(-1, 0, irq_nr, 0);
|
||||
if (IS_ERR_VALUE(irq_base)) {
|
||||
pr_err("%s: irq desc alloc failed\n", __func__);
|
||||
goto err_unmap;
|
||||
}
|
||||
|
||||
shirq_domain = irq_domain_add_legacy(np, irq_nr, irq_base, 0,
|
||||
&irq_domain_simple_ops, NULL);
|
||||
if (WARN_ON(!shirq_domain)) {
|
||||
pr_warn("%s: irq domain init failed\n", __func__);
|
||||
goto err_free_desc;
|
||||
}
|
||||
|
||||
for (i = 0; i < block_nr; i++) {
|
||||
shirq_blocks[i]->base = base;
|
||||
shirq_blocks[i]->irq_base = irq_find_mapping(shirq_domain,
|
||||
hwirq);
|
||||
shirq_blocks[i]->irq = irq_of_parse_and_map(np, i);
|
||||
|
||||
spear_shirq_register(shirq_blocks[i]);
|
||||
hwirq += shirq_blocks[i]->irq_nr;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
err_free_desc:
|
||||
irq_free_descs(irq_base, irq_nr);
|
||||
err_unmap:
|
||||
iounmap(base);
|
||||
return -ENXIO;
|
||||
}
|
||||
|
||||
int __init spear300_shirq_of_init(struct device_node *np,
|
||||
struct device_node *parent)
|
||||
{
|
||||
return shirq_init(spear300_shirq_blocks,
|
||||
ARRAY_SIZE(spear300_shirq_blocks), np);
|
||||
}
|
||||
|
||||
int __init spear310_shirq_of_init(struct device_node *np,
|
||||
struct device_node *parent)
|
||||
{
|
||||
return shirq_init(spear310_shirq_blocks,
|
||||
ARRAY_SIZE(spear310_shirq_blocks), np);
|
||||
}
|
||||
|
||||
int __init spear320_shirq_of_init(struct device_node *np,
|
||||
struct device_node *parent)
|
||||
{
|
||||
return shirq_init(spear320_shirq_blocks,
|
||||
ARRAY_SIZE(spear320_shirq_blocks), np);
|
||||
}
|
|
@ -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"
|
||||
|
||||
|
|
|
@ -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/
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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");
|
|
@ -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 = {
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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,
|
||||
};
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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),
|
||||
};
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
#include <linux/types.h>
|
||||
#include <linux/errno.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/pinctrl/pinctrl.h>
|
||||
|
||||
#ifdef CONFIG_GPIOLIB
|
||||
|
||||
|
@ -56,6 +57,8 @@ struct device_node;
|
|||
* enabling module power and clock; may sleep
|
||||
* @free: optional hook for chip-specific deactivation, such as
|
||||
* disabling module power and clock; may sleep
|
||||
* @get_direction: returns direction for signal "offset", 0=out, 1=in,
|
||||
* (same as GPIOF_DIR_XXX), or negative error
|
||||
* @direction_input: configures signal "offset" as input, or returns error
|
||||
* @get: returns value for signal "offset"; for output signals this
|
||||
* returns either the value actually sensed, or zero
|
||||
|
@ -100,7 +103,8 @@ struct gpio_chip {
|
|||
unsigned offset);
|
||||
void (*free)(struct gpio_chip *chip,
|
||||
unsigned offset);
|
||||
|
||||
int (*get_direction)(struct gpio_chip *chip,
|
||||
unsigned offset);
|
||||
int (*direction_input)(struct gpio_chip *chip,
|
||||
unsigned offset);
|
||||
int (*get)(struct gpio_chip *chip,
|
||||
|
@ -134,6 +138,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 +270,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 */
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -1,9 +1,7 @@
|
|||
/*
|
||||
* arch/arm/plat-spear/include/plat/shirq.h
|
||||
*
|
||||
* SPEAr platform shared irq layer header file
|
||||
*
|
||||
* Copyright (C) 2009 ST Microelectronics
|
||||
* Copyright (C) 2009-2012 ST Microelectronics
|
||||
* Viresh Kumar <viresh.linux@gmail.com>
|
||||
*
|
||||
* This file is licensed under the terms of the GNU General Public
|
||||
|
@ -11,31 +9,15 @@
|
|||
* warranty of any kind, whether express or implied.
|
||||
*/
|
||||
|
||||
#ifndef __PLAT_SHIRQ_H
|
||||
#define __PLAT_SHIRQ_H
|
||||
#ifndef __SPEAR_SHIRQ_H
|
||||
#define __SPEAR_SHIRQ_H
|
||||
|
||||
#include <linux/irq.h>
|
||||
#include <linux/types.h>
|
||||
|
||||
/*
|
||||
* struct shirq_dev_config: shared irq device configuration
|
||||
*
|
||||
* virq: virtual irq number of device
|
||||
* enb_mask: enable mask of device
|
||||
* status_mask: status mask of device
|
||||
* clear_mask: clear mask of device
|
||||
*/
|
||||
struct shirq_dev_config {
|
||||
u32 virq;
|
||||
u32 enb_mask;
|
||||
u32 status_mask;
|
||||
u32 clear_mask;
|
||||
};
|
||||
|
||||
/*
|
||||
* struct shirq_regs: shared irq register configuration
|
||||
*
|
||||
* base: base address of shared irq register
|
||||
* enb_reg: enable register offset
|
||||
* reset_to_enb: val 1 indicates, we need to clear bit for enabling interrupt
|
||||
* status_reg: status register offset
|
||||
|
@ -44,11 +26,9 @@ struct shirq_dev_config {
|
|||
* reset_to_clear: val 1 indicates, we need to clear bit for clearing interrupt
|
||||
*/
|
||||
struct shirq_regs {
|
||||
void __iomem *base;
|
||||
u32 enb_reg;
|
||||
u32 reset_to_enb;
|
||||
u32 status_reg;
|
||||
u32 status_reg_mask;
|
||||
u32 clear_reg;
|
||||
u32 reset_to_clear;
|
||||
};
|
||||
|
@ -57,17 +37,28 @@ struct shirq_regs {
|
|||
* struct spear_shirq: shared irq structure
|
||||
*
|
||||
* irq: hardware irq number
|
||||
* dev_config: array of device config structures which are using "irq" line
|
||||
* dev_count: size of dev_config array
|
||||
* irq_base: base irq in linux domain
|
||||
* irq_nr: no. of shared interrupts in a particular block
|
||||
* irq_bit_off: starting bit offset in the status register
|
||||
* invalid_irq: irq group is currently disabled
|
||||
* base: base address of shared irq register
|
||||
* regs: register configuration for shared irq block
|
||||
*/
|
||||
struct spear_shirq {
|
||||
u32 irq;
|
||||
struct shirq_dev_config *dev_config;
|
||||
u32 dev_count;
|
||||
u32 irq_base;
|
||||
u32 irq_nr;
|
||||
u32 irq_bit_off;
|
||||
int invalid_irq;
|
||||
void __iomem *base;
|
||||
struct shirq_regs regs;
|
||||
};
|
||||
|
||||
int spear_shirq_register(struct spear_shirq *shirq);
|
||||
int __init spear300_shirq_of_init(struct device_node *np,
|
||||
struct device_node *parent);
|
||||
int __init spear310_shirq_of_init(struct device_node *np,
|
||||
struct device_node *parent);
|
||||
int __init spear320_shirq_of_init(struct device_node *np,
|
||||
struct device_node *parent);
|
||||
|
||||
#endif /* __PLAT_SHIRQ_H */
|
||||
#endif /* __SPEAR_SHIRQ_H */
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
};
|
||||
|
||||
|
|
Reference in New Issue