diff options
25 files changed, 4546 insertions, 5 deletions
diff --git a/Documentation/devicetree/bindings/gpio/gpio-mvebu.txt b/Documentation/devicetree/bindings/gpio/gpio-mvebu.txt new file mode 100644 index 000000000000..a6f3bec1da7d --- /dev/null +++ b/Documentation/devicetree/bindings/gpio/gpio-mvebu.txt | |||
| @@ -0,0 +1,53 @@ | |||
| 1 | * Marvell EBU GPIO controller | ||
| 2 | |||
| 3 | Required properties: | ||
| 4 | |||
| 5 | - compatible : Should be "marvell,orion-gpio", "marvell,mv78200-gpio" | ||
| 6 | or "marvell,armadaxp-gpio". "marvell,orion-gpio" should be used for | ||
| 7 | Orion, Kirkwood, Dove, Discovery (except MV78200) and Armada | ||
| 8 | 370. "marvell,mv78200-gpio" should be used for the Discovery | ||
| 9 | MV78200. "marvel,armadaxp-gpio" should be used for all Armada XP | ||
| 10 | SoCs (MV78230, MV78260, MV78460). | ||
| 11 | |||
| 12 | - reg: Address and length of the register set for the device. Only one | ||
| 13 | entry is expected, except for the "marvell,armadaxp-gpio" variant | ||
| 14 | for which two entries are expected: one for the general registers, | ||
| 15 | one for the per-cpu registers. | ||
| 16 | |||
| 17 | - interrupts: The list of interrupts that are used for all the pins | ||
| 18 | managed by this GPIO bank. There can be more than one interrupt | ||
| 19 | (example: 1 interrupt per 8 pins on Armada XP, which means 4 | ||
| 20 | interrupts per bank of 32 GPIOs). | ||
| 21 | |||
| 22 | - interrupt-controller: identifies the node as an interrupt controller | ||
| 23 | |||
| 24 | - #interrupt-cells: specifies the number of cells needed to encode an | ||
| 25 | interrupt source. Should be two. | ||
| 26 | The first cell is the GPIO number. | ||
| 27 | The second cell is used to specify flags: | ||
| 28 | bits[3:0] trigger type and level flags: | ||
| 29 | 1 = low-to-high edge triggered. | ||
| 30 | 2 = high-to-low edge triggered. | ||
| 31 | 4 = active high level-sensitive. | ||
| 32 | 8 = active low level-sensitive. | ||
| 33 | |||
| 34 | - gpio-controller: marks the device node as a gpio controller | ||
| 35 | |||
| 36 | - ngpios: number of GPIOs this controller has | ||
| 37 | |||
| 38 | - #gpio-cells: Should be two. The first cell is the pin number. The | ||
| 39 | second cell is reserved for flags, unused at the moment. | ||
| 40 | |||
| 41 | Example: | ||
| 42 | |||
| 43 | gpio0: gpio@d0018100 { | ||
| 44 | compatible = "marvell,armadaxp-gpio"; | ||
| 45 | reg = <0xd0018100 0x40>, | ||
| 46 | <0xd0018800 0x30>; | ||
| 47 | ngpios = <32>; | ||
| 48 | gpio-controller; | ||
| 49 | #gpio-cells = <2>; | ||
| 50 | interrupt-controller; | ||
| 51 | #interrupt-cells = <2>; | ||
| 52 | interrupts = <16>, <17>, <18>, <19>; | ||
| 53 | }; | ||
diff --git a/Documentation/devicetree/bindings/pinctrl/marvell,armada-370-pinctrl.txt b/Documentation/devicetree/bindings/pinctrl/marvell,armada-370-pinctrl.txt new file mode 100644 index 000000000000..01ef408e205f --- /dev/null +++ b/Documentation/devicetree/bindings/pinctrl/marvell,armada-370-pinctrl.txt | |||
| @@ -0,0 +1,95 @@ | |||
| 1 | * Marvell Armada 370 SoC pinctrl driver for mpp | ||
| 2 | |||
| 3 | Please refer to marvell,mvebu-pinctrl.txt in this directory for common binding | ||
| 4 | part and usage. | ||
| 5 | |||
| 6 | Required properties: | ||
| 7 | - compatible: "marvell,88f6710-pinctrl" | ||
| 8 | |||
| 9 | Available mpp pins/groups and functions: | ||
| 10 | Note: brackets (x) are not part of the mpp name for marvell,function and given | ||
| 11 | only for more detailed description in this document. | ||
| 12 | |||
| 13 | name pins functions | ||
| 14 | ================================================================================ | ||
| 15 | mpp0 0 gpio, uart0(rxd) | ||
| 16 | mpp1 1 gpo, uart0(txd) | ||
| 17 | mpp2 2 gpio, i2c0(sck), uart0(txd) | ||
| 18 | mpp3 3 gpio, i2c0(sda), uart0(rxd) | ||
| 19 | mpp4 4 gpio, cpu_pd(vdd) | ||
| 20 | mpp5 5 gpo, ge0(txclko), uart1(txd), spi1(clk), audio(mclk) | ||
| 21 | mpp6 6 gpio, ge0(txd0), sata0(prsnt), tdm(rst), audio(sdo) | ||
| 22 | mpp7 7 gpo, ge0(txd1), tdm(tdx), audio(lrclk) | ||
| 23 | mpp8 8 gpio, ge0(txd2), uart0(rts), tdm(drx), audio(bclk) | ||
| 24 | mpp9 9 gpo, ge0(txd3), uart1(txd), sd0(clk), audio(spdifo) | ||
| 25 | mpp10 10 gpio, ge0(txctl), uart0(cts), tdm(fsync), audio(sdi) | ||
| 26 | mpp11 11 gpio, ge0(rxd0), uart1(rxd), sd0(cmd), spi0(cs1), | ||
| 27 | sata1(prsnt), spi1(cs1) | ||
| 28 | mpp12 12 gpio, ge0(rxd1), i2c1(sda), sd0(d0), spi1(cs0), | ||
| 29 | audio(spdifi) | ||
| 30 | mpp13 13 gpio, ge0(rxd2), i2c1(sck), sd0(d1), tdm(pclk), | ||
| 31 | audio(rmclk) | ||
| 32 | mpp14 14 gpio, ge0(rxd3), pcie(clkreq0), sd0(d2), spi1(mosi), | ||
| 33 | spi0(cs2) | ||
| 34 | mpp15 15 gpio, ge0(rxctl), pcie(clkreq1), sd0(d3), spi1(miso), | ||
| 35 | spi0(cs3) | ||
| 36 | mpp16 16 gpio, ge0(rxclk), uart1(rxd), tdm(int), audio(extclk) | ||
| 37 | mpp17 17 gpo, ge(mdc) | ||
| 38 | mpp18 18 gpio, ge(mdio) | ||
| 39 | mpp19 19 gpio, ge0(txclk), ge1(txclkout), tdm(pclk) | ||
| 40 | mpp20 20 gpo, ge0(txd4), ge1(txd0) | ||
| 41 | mpp21 21 gpo, ge0(txd5), ge1(txd1), uart1(txd) | ||
| 42 | mpp22 22 gpo, ge0(txd6), ge1(txd2), uart0(rts) | ||
| 43 | mpp23 23 gpo, ge0(txd7), ge1(txd3), spi1(mosi) | ||
| 44 | mpp24 24 gpio, ge0(col), ge1(txctl), spi1(cs0) | ||
| 45 | mpp25 25 gpio, ge0(rxerr), ge1(rxd0), uart1(rxd) | ||
| 46 | mpp26 26 gpio, ge0(crs), ge1(rxd1), spi1(miso) | ||
| 47 | mpp27 27 gpio, ge0(rxd4), ge1(rxd2), uart0(cts) | ||
| 48 | mpp28 28 gpio, ge0(rxd5), ge1(rxd3) | ||
| 49 | mpp29 29 gpio, ge0(rxd6), ge1(rxctl), i2c1(sda) | ||
| 50 | mpp30 30 gpio, ge0(rxd7), ge1(rxclk), i2c1(sck) | ||
| 51 | mpp31 31 gpio, tclk, ge0(txerr) | ||
| 52 | mpp32 32 gpio, spi0(cs0) | ||
| 53 | mpp33 33 gpio, dev(bootcs), spi0(cs0) | ||
| 54 | mpp34 34 gpo, dev(wen0), spi0(mosi) | ||
| 55 | mpp35 35 gpo, dev(oen), spi0(sck) | ||
| 56 | mpp36 36 gpo, dev(a1), spi0(miso) | ||
| 57 | mpp37 37 gpo, dev(a0), sata0(prsnt) | ||
| 58 | mpp38 38 gpio, dev(ready), uart1(cts), uart0(cts) | ||
| 59 | mpp39 39 gpo, dev(ad0), audio(spdifo) | ||
| 60 | mpp40 40 gpio, dev(ad1), uart1(rts), uart0(rts) | ||
| 61 | mpp41 41 gpio, dev(ad2), uart1(rxd) | ||
| 62 | mpp42 42 gpo, dev(ad3), uart1(txd) | ||
| 63 | mpp43 43 gpo, dev(ad4), audio(bclk) | ||
| 64 | mpp44 44 gpo, dev(ad5), audio(mclk) | ||
| 65 | mpp45 45 gpo, dev(ad6), audio(lrclk) | ||
| 66 | mpp46 46 gpo, dev(ad7), audio(sdo) | ||
| 67 | mpp47 47 gpo, dev(ad8), sd0(clk), audio(spdifo) | ||
| 68 | mpp48 48 gpio, dev(ad9), uart0(rts), sd0(cmd), sata1(prsnt), | ||
| 69 | spi0(cs1) | ||
| 70 | mpp49 49 gpio, dev(ad10), pcie(clkreq1), sd0(d0), spi1(cs0), | ||
| 71 | audio(spdifi) | ||
| 72 | mpp50 50 gpio, dev(ad11), uart0(cts), sd0(d1), spi1(miso), | ||
| 73 | audio(rmclk) | ||
| 74 | mpp51 51 gpio, dev(ad12), i2c1(sda), sd0(d2), spi1(mosi) | ||
| 75 | mpp52 52 gpio, dev(ad13), i2c1(sck), sd0(d3), spi1(sck) | ||
| 76 | mpp53 53 gpio, dev(ad14), sd0(clk), tdm(pclk), spi0(cs2), | ||
| 77 | pcie(clkreq1) | ||
| 78 | mpp54 54 gpo, dev(ad15), tdm(dtx) | ||
| 79 | mpp55 55 gpio, dev(cs1), uart1(txd), tdm(rst), sata1(prsnt), | ||
| 80 | sata0(prsnt) | ||
| 81 | mpp56 56 gpio, dev(cs2), uart1(cts), uart0(cts), spi0(cs3), | ||
| 82 | pcie(clkreq0), spi1(cs1) | ||
| 83 | mpp57 57 gpio, dev(cs3), uart1(rxd), tdm(fsync), sata0(prsnt), | ||
| 84 | audio(sdo) | ||
| 85 | mpp58 58 gpio, dev(cs0), uart1(rts), tdm(int), audio(extclk), | ||
| 86 | uart0(rts) | ||
| 87 | mpp59 59 gpo, dev(ale0), uart1(rts), uart0(rts), audio(bclk) | ||
| 88 | mpp60 60 gpio, dev(ale1), uart1(rxd), sata0(prsnt), pcie(rst-out), | ||
| 89 | audio(sdi) | ||
| 90 | mpp61 61 gpo, dev(wen1), uart1(txd), audio(rclk) | ||
| 91 | mpp62 62 gpio, dev(a2), uart1(cts), tdm(drx), pcie(clkreq0), | ||
| 92 | audio(mclk), uart0(cts) | ||
| 93 | mpp63 63 gpo, spi0(sck), tclk | ||
| 94 | mpp64 64 gpio, spi0(miso), spi0-1(cs1) | ||
| 95 | mpp65 65 gpio, spi0(mosi), spi0-1(cs2) | ||
diff --git a/Documentation/devicetree/bindings/pinctrl/marvell,armada-xp-pinctrl.txt b/Documentation/devicetree/bindings/pinctrl/marvell,armada-xp-pinctrl.txt new file mode 100644 index 000000000000..bfa0a2e5e0cb --- /dev/null +++ b/Documentation/devicetree/bindings/pinctrl/marvell,armada-xp-pinctrl.txt | |||
| @@ -0,0 +1,100 @@ | |||
| 1 | * Marvell Armada XP SoC pinctrl driver for mpp | ||
| 2 | |||
| 3 | Please refer to marvell,mvebu-pinctrl.txt in this directory for common binding | ||
| 4 | part and usage. | ||
| 5 | |||
| 6 | Required properties: | ||
| 7 | - compatible: "marvell,mv78230-pinctrl", "marvell,mv78260-pinctrl", | ||
| 8 | "marvell,mv78460-pinctrl" | ||
| 9 | |||
| 10 | This driver supports all Armada XP variants, i.e. mv78230, mv78260, and mv78460. | ||
| 11 | |||
| 12 | Available mpp pins/groups and functions: | ||
| 13 | Note: brackets (x) are not part of the mpp name for marvell,function and given | ||
| 14 | only for more detailed description in this document. | ||
| 15 | |||
| 16 | * Marvell Armada XP (all variants) | ||
| 17 | |||
| 18 | name pins functions | ||
| 19 | ================================================================================ | ||
| 20 | mpp0 0 gpio, ge0(txclko), lcd(d0) | ||
| 21 | mpp1 1 gpio, ge0(txd0), lcd(d1) | ||
| 22 | mpp2 2 gpio, ge0(txd1), lcd(d2) | ||
| 23 | mpp3 3 gpio, ge0(txd2), lcd(d3) | ||
| 24 | mpp4 4 gpio, ge0(txd3), lcd(d4) | ||
| 25 | mpp5 5 gpio, ge0(txctl), lcd(d5) | ||
| 26 | mpp6 6 gpio, ge0(rxd0), lcd(d6) | ||
| 27 | mpp7 7 gpio, ge0(rxd1), lcd(d7) | ||
| 28 | mpp8 8 gpio, ge0(rxd2), lcd(d8) | ||
| 29 | mpp9 9 gpio, ge0(rxd3), lcd(d9) | ||
| 30 | mpp10 10 gpio, ge0(rxctl), lcd(d10) | ||
| 31 | mpp11 11 gpio, ge0(rxclk), lcd(d11) | ||
| 32 | mpp12 12 gpio, ge0(txd4), ge1(txd0), lcd(d12) | ||
| 33 | mpp13 13 gpio, ge0(txd5), ge1(txd1), lcd(d13) | ||
| 34 | mpp14 14 gpio, ge0(txd6), ge1(txd2), lcd(d15) | ||
| 35 | mpp15 15 gpio, ge0(txd7), ge1(txd3), lcd(d16) | ||
| 36 | mpp16 16 gpio, ge0(txd7), ge1(txd3), lcd(d16) | ||
| 37 | mpp17 17 gpio, ge0(col), ge1(txctl), lcd(d17) | ||
| 38 | mpp18 18 gpio, ge0(rxerr), ge1(rxd0), lcd(d18), ptp(trig) | ||
| 39 | mpp19 19 gpio, ge0(crs), ge1(rxd1), lcd(d19), ptp(evreq) | ||
| 40 | mpp20 20 gpio, ge0(rxd4), ge1(rxd2), lcd(d20), ptp(clk) | ||
| 41 | mpp21 21 gpio, ge0(rxd5), ge1(rxd3), lcd(d21), mem(bat) | ||
| 42 | mpp22 22 gpio, ge0(rxd6), ge1(rxctl), lcd(d22), sata0(prsnt) | ||
| 43 | mpp23 23 gpio, ge0(rxd7), ge1(rxclk), lcd(d23), sata1(prsnt) | ||
| 44 | mpp24 24 gpio, lcd(hsync), sata1(prsnt), nf(bootcs-re), tdm(rst) | ||
| 45 | mpp25 25 gpio, lcd(vsync), sata0(prsnt), nf(bootcs-we), tdm(pclk) | ||
| 46 | mpp26 26 gpio, lcd(clk), tdm(fsync), vdd(cpu1-pd) | ||
| 47 | mpp27 27 gpio, lcd(e), tdm(dtx), ptp(trig) | ||
| 48 | mpp28 28 gpio, lcd(pwm), tdm(drx), ptp(evreq) | ||
| 49 | mpp29 29 gpio, lcd(ref-clk), tdm(int0), ptp(clk), vdd(cpu0-pd) | ||
| 50 | mpp30 30 gpio, tdm(int1), sd0(clk) | ||
| 51 | mpp31 31 gpio, tdm(int2), sd0(cmd), vdd(cpu0-pd) | ||
| 52 | mpp32 32 gpio, tdm(int3), sd0(d0), vdd(cpu1-pd) | ||
| 53 | mpp33 33 gpio, tdm(int4), sd0(d1), mem(bat) | ||
| 54 | mpp34 34 gpio, tdm(int5), sd0(d2), sata0(prsnt) | ||
| 55 | mpp35 35 gpio, tdm(int6), sd0(d3), sata1(prsnt) | ||
| 56 | mpp36 36 gpio, spi(mosi) | ||
| 57 | mpp37 37 gpio, spi(miso) | ||
| 58 | mpp38 38 gpio, spi(sck) | ||
| 59 | mpp39 39 gpio, spi(cs0) | ||
| 60 | mpp40 40 gpio, spi(cs1), uart2(cts), lcd(vga-hsync), vdd(cpu1-pd), | ||
| 61 | pcie(clkreq0) | ||
| 62 | mpp41 41 gpio, spi(cs2), uart2(rts), lcd(vga-vsync), sata1(prsnt), | ||
| 63 | pcie(clkreq1) | ||
| 64 | mpp42 42 gpio, uart2(rxd), uart0(cts), tdm(int7), tdm-1(timer), | ||
| 65 | vdd(cpu0-pd) | ||
| 66 | mpp43 43 gpio, uart2(txd), uart0(rts), spi(cs3), pcie(rstout), | ||
| 67 | vdd(cpu2-3-pd){1} | ||
| 68 | mpp44 44 gpio, uart2(cts), uart3(rxd), spi(cs4), pcie(clkreq2), | ||
| 69 | mem(bat) | ||
| 70 | mpp45 45 gpio, uart2(rts), uart3(txd), spi(cs5), sata1(prsnt) | ||
| 71 | mpp46 46 gpio, uart3(rts), uart1(rts), spi(cs6), sata0(prsnt) | ||
| 72 | mpp47 47 gpio, uart3(cts), uart1(cts), spi(cs7), pcie(clkreq3), | ||
| 73 | ref(clkout) | ||
| 74 | mpp48 48 gpio, tclk, dev(burst/last) | ||
| 75 | |||
| 76 | * Marvell Armada XP (mv78260 and mv78460 only) | ||
| 77 | |||
| 78 | name pins functions | ||
| 79 | ================================================================================ | ||
| 80 | mpp49 49 gpio, dev(we3) | ||
| 81 | mpp50 50 gpio, dev(we2) | ||
| 82 | mpp51 51 gpio, dev(ad16) | ||
| 83 | mpp52 52 gpio, dev(ad17) | ||
| 84 | mpp53 53 gpio, dev(ad18) | ||
| 85 | mpp54 54 gpio, dev(ad19) | ||
| 86 | mpp55 55 gpio, dev(ad20), vdd(cpu0-pd) | ||
| 87 | mpp56 56 gpio, dev(ad21), vdd(cpu1-pd) | ||
| 88 | mpp57 57 gpio, dev(ad22), vdd(cpu2-3-pd){1} | ||
| 89 | mpp58 58 gpio, dev(ad23) | ||
| 90 | mpp59 59 gpio, dev(ad24) | ||
| 91 | mpp60 60 gpio, dev(ad25) | ||
| 92 | mpp61 61 gpio, dev(ad26) | ||
| 93 | mpp62 62 gpio, dev(ad27) | ||
| 94 | mpp63 63 gpio, dev(ad28) | ||
| 95 | mpp64 64 gpio, dev(ad29) | ||
| 96 | mpp65 65 gpio, dev(ad30) | ||
| 97 | mpp66 66 gpio, dev(ad31) | ||
| 98 | |||
| 99 | Notes: | ||
| 100 | * {1} vdd(cpu2-3-pd) only available on mv78460. | ||
diff --git a/Documentation/devicetree/bindings/pinctrl/marvell,dove-pinctrl.txt b/Documentation/devicetree/bindings/pinctrl/marvell,dove-pinctrl.txt new file mode 100644 index 000000000000..a648aaad6110 --- /dev/null +++ b/Documentation/devicetree/bindings/pinctrl/marvell,dove-pinctrl.txt | |||
| @@ -0,0 +1,72 @@ | |||
| 1 | * Marvell Dove SoC pinctrl driver for mpp | ||
| 2 | |||
| 3 | Please refer to marvell,mvebu-pinctrl.txt in this directory for common binding | ||
| 4 | part and usage. | ||
| 5 | |||
| 6 | Required properties: | ||
| 7 | - compatible: "marvell,dove-pinctrl" | ||
| 8 | - clocks: (optional) phandle of pdma clock | ||
| 9 | |||
| 10 | Available mpp pins/groups and functions: | ||
| 11 | Note: brackets (x) are not part of the mpp name for marvell,function and given | ||
| 12 | only for more detailed description in this document. | ||
| 13 | |||
| 14 | name pins functions | ||
| 15 | ================================================================================ | ||
| 16 | mpp0 0 gpio, pmu, uart2(rts), sdio0(cd), lcd0(pwm) | ||
| 17 | mpp1 1 gpio, pmu, uart2(cts), sdio0(wp), lcd1(pwm) | ||
| 18 | mpp2 2 gpio, pmu, uart2(txd), sdio0(buspwr), sata(prsnt), | ||
| 19 | uart1(rts) | ||
| 20 | mpp3 3 gpio, pmu, uart2(rxd), sdio0(ledctrl), sata(act), | ||
| 21 | uart1(cts), lcd-spi(cs1) | ||
| 22 | mpp4 4 gpio, pmu, uart3(rts), sdio1(cd), spi1(miso) | ||
| 23 | mpp5 5 gpio, pmu, uart3(cts), sdio1(wp), spi1(cs) | ||
| 24 | mpp6 6 gpio, pmu, uart3(txd), sdio1(buspwr), spi1(mosi) | ||
| 25 | mpp7 7 gpio, pmu, uart3(rxd), sdio1(ledctrl), spi1(sck) | ||
| 26 | mpp8 8 gpio, pmu, watchdog(rstout) | ||
| 27 | mpp9 9 gpio, pmu, pex1(clkreq) | ||
| 28 | mpp10 10 gpio, pmu, ssp(sclk) | ||
| 29 | mpp11 11 gpio, pmu, sata(prsnt), sata-1(act), sdio0(ledctrl), | ||
| 30 | sdio1(ledctrl), pex0(clkreq) | ||
| 31 | mpp12 12 gpio, pmu, uart2(rts), audio0(extclk), sdio1(cd), sata(act) | ||
| 32 | mpp13 13 gpio, pmu, uart2(cts), audio1(extclk), sdio1(wp), | ||
| 33 | ssp(extclk) | ||
| 34 | mpp14 14 gpio, pmu, uart2(txd), sdio1(buspwr), ssp(rxd) | ||
| 35 | mpp15 15 gpio, pmu, uart2(rxd), sdio1(ledctrl), ssp(sfrm) | ||
| 36 | mpp16 16 gpio, uart3(rts), sdio0(cd), ac97(sdi1), lcd-spi(cs1) | ||
| 37 | mpp17 17 gpio, uart3(cts), sdio0(wp), ac97(sdi2), twsi(sda), | ||
| 38 | ac97-1(sysclko) | ||
| 39 | mpp18 18 gpio, uart3(txd), sdio0(buspwr), ac97(sdi3), lcd0(pwm) | ||
| 40 | mpp19 19 gpio, uart3(rxd), sdio0(ledctrl), twsi(sck) | ||
| 41 | mpp20 20 gpio, sdio0(cd), sdio1(cd), spi1(miso), lcd-spi(miso), | ||
| 42 | ac97(sysclko) | ||
| 43 | mpp21 21 gpio, sdio0(wp), sdio1(wp), spi1(cs), lcd-spi(cs0), | ||
| 44 | uart1(cts), ssp(sfrm) | ||
| 45 | mpp22 22 gpio, sdio0(buspwr), sdio1(buspwr), spi1(mosi), | ||
| 46 | lcd-spi(mosi), uart1(cts), ssp(txd) | ||
| 47 | mpp23 23 gpio, sdio0(ledctrl), sdio1(ledctrl), spi1(sck), | ||
| 48 | lcd-spi(sck), ssp(sclk) | ||
| 49 | mpp_camera 24-39 gpio, camera | ||
| 50 | mpp_sdio0 40-45 gpio, sdio0 | ||
| 51 | mpp_sdio1 46-51 gpio, sdio1 | ||
| 52 | mpp_audio1 52-57 gpio, i2s1/spdifo, i2s1, spdifo, twsi, ssp/spdifo, ssp, | ||
| 53 | ssp/twsi | ||
| 54 | mpp_spi0 58-61 gpio, spi0 | ||
| 55 | mpp_uart1 62-63 gpio, uart1 | ||
| 56 | mpp_nand 64-71 gpo, nand | ||
| 57 | audio0 - i2s, ac97 | ||
| 58 | twsi - none, opt1, opt2, opt3 | ||
| 59 | |||
| 60 | Notes: | ||
| 61 | * group "mpp_audio1" allows the following functions and gpio pins: | ||
| 62 | - gpio : gpio on pins 52-57 | ||
| 63 | - i2s1/spdifo : audio1 i2s on pins 52-55 and spdifo on 57, no gpios | ||
| 64 | - i2s1 : audio1 i2s on pins 52-55, gpio on pins 56,57 | ||
| 65 | - spdifo : spdifo on pin 57, gpio on pins 52-55 | ||
| 66 | - twsi : twsi on pins 56,57, gpio on pins 52-55 | ||
| 67 | - ssp/spdifo : ssp on pins 52-55, spdifo on pin 57, no gpios | ||
| 68 | - ssp : ssp on pins 52-55, gpio on pins 56,57 | ||
| 69 | - ssp/twsi : ssp on pins 52-55, twsi on pins 56,57, no gpios | ||
| 70 | * group "audio0" internally muxes i2s0 or ac97 controller to the dedicated | ||
| 71 | audio0 pins. | ||
| 72 | * group "twsi" internally muxes twsi controller to the dedicated or option pins. | ||
diff --git a/Documentation/devicetree/bindings/pinctrl/marvell,kirkwood-pinctrl.txt b/Documentation/devicetree/bindings/pinctrl/marvell,kirkwood-pinctrl.txt new file mode 100644 index 000000000000..361bccb7ec89 --- /dev/null +++ b/Documentation/devicetree/bindings/pinctrl/marvell,kirkwood-pinctrl.txt | |||
| @@ -0,0 +1,279 @@ | |||
| 1 | * Marvell Kirkwood SoC pinctrl driver for mpp | ||
| 2 | |||
| 3 | Please refer to marvell,mvebu-pinctrl.txt in this directory for common binding | ||
| 4 | part and usage. | ||
| 5 | |||
| 6 | Required properties: | ||
| 7 | - compatible: "marvell,88f6180-pinctrl", | ||
| 8 | "marvell,88f6190-pinctrl", "marvell,88f6192-pinctrl", | ||
| 9 | "marvell,88f6281-pinctrl", "marvell,88f6282-pinctrl" | ||
| 10 | |||
| 11 | This driver supports all kirkwood variants, i.e. 88f6180, 88f619x, and 88f628x. | ||
| 12 | |||
| 13 | Available mpp pins/groups and functions: | ||
| 14 | Note: brackets (x) are not part of the mpp name for marvell,function and given | ||
| 15 | only for more detailed description in this document. | ||
| 16 | |||
| 17 | * Marvell Kirkwood 88f6180 | ||
| 18 | |||
| 19 | name pins functions | ||
| 20 | ================================================================================ | ||
| 21 | mpp0 0 gpio, nand(io2), spi(cs) | ||
| 22 | mpp1 1 gpo, nand(io3), spi(mosi) | ||
| 23 | mpp2 2 gpo, nand(io4), spi(sck) | ||
| 24 | mpp3 3 gpo, nand(io5), spi(miso) | ||
| 25 | mpp4 4 gpio, nand(io6), uart0(rxd), ptp(clk) | ||
| 26 | mpp5 5 gpo, nand(io7), uart0(txd), ptp(trig) | ||
| 27 | mpp6 6 sysrst(out), spi(mosi), ptp(trig) | ||
| 28 | mpp7 7 gpo, pex(rsto), spi(cs), ptp(trig) | ||
| 29 | mpp8 8 gpio, twsi0(sda), uart0(rts), uart1(rts), ptp(clk), | ||
| 30 | mii(col) | ||
| 31 | mpp9 9 gpio, twsi(sck), uart0(cts), uart1(cts), ptp(evreq), | ||
| 32 | mii(crs) | ||
| 33 | mpp10 10 gpo, spi(sck), uart0(txd), ptp(trig) | ||
| 34 | mpp11 11 gpio, spi(miso), uart0(rxd), ptp(clk), ptp-1(evreq), | ||
| 35 | ptp-2(trig) | ||
| 36 | mpp12 12 gpo, sdio(clk) | ||
| 37 | mpp13 13 gpio, sdio(cmd), uart1(txd) | ||
| 38 | mpp14 14 gpio, sdio(d0), uart1(rxd), mii(col) | ||
| 39 | mpp15 15 gpio, sdio(d1), uart0(rts), uart1(txd) | ||
| 40 | mpp16 16 gpio, sdio(d2), uart0(cts), uart1(rxd), mii(crs) | ||
| 41 | mpp17 17 gpio, sdio(d3) | ||
| 42 | mpp18 18 gpo, nand(io0) | ||
| 43 | mpp19 19 gpo, nand(io1) | ||
| 44 | mpp20 20 gpio, mii(rxerr) | ||
| 45 | mpp21 21 gpio, audio(spdifi) | ||
| 46 | mpp22 22 gpio, audio(spdifo) | ||
| 47 | mpp23 23 gpio, audio(rmclk) | ||
| 48 | mpp24 24 gpio, audio(bclk) | ||
| 49 | mpp25 25 gpio, audio(sdo) | ||
| 50 | mpp26 26 gpio, audio(lrclk) | ||
| 51 | mpp27 27 gpio, audio(mclk) | ||
| 52 | mpp28 28 gpio, audio(sdi) | ||
| 53 | mpp29 29 gpio, audio(extclk) | ||
| 54 | |||
| 55 | * Marvell Kirkwood 88f6190 | ||
| 56 | |||
| 57 | name pins functions | ||
| 58 | ================================================================================ | ||
| 59 | mpp0 0 gpio, nand(io2), spi(cs) | ||
| 60 | mpp1 1 gpo, nand(io3), spi(mosi) | ||
| 61 | mpp2 2 gpo, nand(io4), spi(sck) | ||
| 62 | mpp3 3 gpo, nand(io5), spi(miso) | ||
| 63 | mpp4 4 gpio, nand(io6), uart0(rxd), ptp(clk) | ||
| 64 | mpp5 5 gpo, nand(io7), uart0(txd), ptp(trig), sata0(act) | ||
| 65 | mpp6 6 sysrst(out), spi(mosi), ptp(trig) | ||
| 66 | mpp7 7 gpo, pex(rsto), spi(cs), ptp(trig) | ||
| 67 | mpp8 8 gpio, twsi0(sda), uart0(rts), uart1(rts), ptp(clk), | ||
| 68 | mii(col), mii-1(rxerr) | ||
| 69 | mpp9 9 gpio, twsi(sck), uart0(cts), uart1(cts), ptp(evreq), | ||
| 70 | mii(crs), sata0(prsnt) | ||
| 71 | mpp10 10 gpo, spi(sck), uart0(txd), ptp(trig) | ||
| 72 | mpp11 11 gpio, spi(miso), uart0(rxd), ptp(clk), ptp-1(evreq), | ||
| 73 | ptp-2(trig), sata0(act) | ||
| 74 | mpp12 12 gpo, sdio(clk) | ||
| 75 | mpp13 13 gpio, sdio(cmd), uart1(txd) | ||
| 76 | mpp14 14 gpio, sdio(d0), uart1(rxd), mii(col) | ||
| 77 | mpp15 15 gpio, sdio(d1), uart0(rts), uart1(txd), sata0(act) | ||
| 78 | mpp16 16 gpio, sdio(d2), uart0(cts), uart1(rxd), mii(crs) | ||
| 79 | mpp17 17 gpio, sdio(d3), sata0(prsnt) | ||
| 80 | mpp18 18 gpo, nand(io0) | ||
| 81 | mpp19 19 gpo, nand(io1) | ||
| 82 | mpp20 20 gpio, ge1(txd0) | ||
| 83 | mpp21 21 gpio, ge1(txd1), sata0(act) | ||
| 84 | mpp22 22 gpio, ge1(txd2) | ||
| 85 | mpp23 23 gpio, ge1(txd3), sata0(prsnt) | ||
| 86 | mpp24 24 gpio, ge1(rxd0) | ||
| 87 | mpp25 25 gpio, ge1(rxd1) | ||
| 88 | mpp26 26 gpio, ge1(rxd2) | ||
| 89 | mpp27 27 gpio, ge1(rxd3) | ||
| 90 | mpp28 28 gpio, ge1(col) | ||
| 91 | mpp29 29 gpio, ge1(txclk) | ||
| 92 | mpp30 30 gpio, ge1(rxclk) | ||
| 93 | mpp31 31 gpio, ge1(rxclk) | ||
| 94 | mpp32 32 gpio, ge1(txclko) | ||
| 95 | mpp33 33 gpo, ge1(txclk) | ||
| 96 | mpp34 34 gpio, ge1(txen) | ||
| 97 | mpp35 35 gpio, ge1(rxerr), sata0(act), mii(rxerr) | ||
| 98 | |||
| 99 | * Marvell Kirkwood 88f6192 | ||
| 100 | |||
| 101 | name pins functions | ||
| 102 | ================================================================================ | ||
| 103 | mpp0 0 gpio, nand(io2), spi(cs) | ||
| 104 | mpp1 1 gpo, nand(io3), spi(mosi) | ||
| 105 | mpp2 2 gpo, nand(io4), spi(sck) | ||
| 106 | mpp3 3 gpo, nand(io5), spi(miso) | ||
| 107 | mpp4 4 gpio, nand(io6), uart0(rxd), ptp(clk), sata1(act) | ||
| 108 | mpp5 5 gpo, nand(io7), uart0(txd), ptp(trig), sata0(act) | ||
| 109 | mpp6 6 sysrst(out), spi(mosi), ptp(trig) | ||
| 110 | mpp7 7 gpo, pex(rsto), spi(cs), ptp(trig) | ||
| 111 | mpp8 8 gpio, twsi0(sda), uart0(rts), uart1(rts), ptp(clk), | ||
| 112 | mii(col), mii-1(rxerr), sata1(prsnt) | ||
| 113 | mpp9 9 gpio, twsi(sck), uart0(cts), uart1(cts), ptp(evreq), | ||
| 114 | mii(crs), sata0(prsnt) | ||
| 115 | mpp10 10 gpo, spi(sck), uart0(txd), ptp(trig), sata1(act) | ||
| 116 | mpp11 11 gpio, spi(miso), uart0(rxd), ptp(clk), ptp-1(evreq), | ||
| 117 | ptp-2(trig), sata0(act) | ||
| 118 | mpp12 12 gpo, sdio(clk) | ||
| 119 | mpp13 13 gpio, sdio(cmd), uart1(txd) | ||
| 120 | mpp14 14 gpio, sdio(d0), uart1(rxd), mii(col), sata1(prsnt) | ||
| 121 | mpp15 15 gpio, sdio(d1), uart0(rts), uart1(txd), sata0(act) | ||
| 122 | mpp16 16 gpio, sdio(d2), uart0(cts), uart1(rxd), mii(crs), | ||
| 123 | sata1(act) | ||
| 124 | mpp17 17 gpio, sdio(d3), sata0(prsnt) | ||
| 125 | mpp18 18 gpo, nand(io0) | ||
| 126 | mpp19 19 gpo, nand(io1) | ||
| 127 | mpp20 20 gpio, ge1(txd0), ts(mp0), tdm(tx0ql), audio(spdifi), | ||
| 128 | sata1(act) | ||
| 129 | mpp21 21 gpio, ge1(txd1), sata0(act), ts(mp1), tdm(rx0ql), | ||
| 130 | audio(spdifo) | ||
| 131 | mpp22 22 gpio, ge1(txd2), ts(mp2), tdm(tx2ql), audio(rmclk), | ||
| 132 | sata1(prsnt) | ||
| 133 | mpp23 23 gpio, ge1(txd3), sata0(prsnt), ts(mp3), tdm(rx2ql), | ||
| 134 | audio(bclk) | ||
| 135 | mpp24 24 gpio, ge1(rxd0), ts(mp4), tdm(spi-cs0), audio(sdo) | ||
| 136 | mpp25 25 gpio, ge1(rxd1), ts(mp5), tdm(spi-sck), audio(lrclk) | ||
| 137 | mpp26 26 gpio, ge1(rxd2), ts(mp6), tdm(spi-miso), audio(mclk) | ||
| 138 | mpp27 27 gpio, ge1(rxd3), ts(mp7), tdm(spi-mosi), audio(sdi) | ||
| 139 | mpp28 28 gpio, ge1(col), ts(mp8), tdm(int), audio(extclk) | ||
| 140 | mpp29 29 gpio, ge1(txclk), ts(mp9), tdm(rst) | ||
| 141 | mpp30 30 gpio, ge1(rxclk), ts(mp10), tdm(pclk) | ||
| 142 | mpp31 31 gpio, ge1(rxclk), ts(mp11), tdm(fs) | ||
| 143 | mpp32 32 gpio, ge1(txclko), ts(mp12), tdm(drx) | ||
| 144 | mpp33 33 gpo, ge1(txclk), tdm(drx) | ||
| 145 | mpp34 34 gpio, ge1(txen), tdm(spi-cs1) | ||
| 146 | mpp35 35 gpio, ge1(rxerr), sata0(act), mii(rxerr), tdm(tx0ql) | ||
| 147 | |||
| 148 | * Marvell Kirkwood 88f6281 | ||
| 149 | |||
| 150 | name pins functions | ||
| 151 | ================================================================================ | ||
| 152 | mpp0 0 gpio, nand(io2), spi(cs) | ||
| 153 | mpp1 1 gpo, nand(io3), spi(mosi) | ||
| 154 | mpp2 2 gpo, nand(io4), spi(sck) | ||
| 155 | mpp3 3 gpo, nand(io5), spi(miso) | ||
| 156 | mpp4 4 gpio, nand(io6), uart0(rxd), ptp(clk), sata1(act) | ||
| 157 | mpp5 5 gpo, nand(io7), uart0(txd), ptp(trig), sata0(act) | ||
| 158 | mpp6 6 sysrst(out), spi(mosi), ptp(trig) | ||
| 159 | mpp7 7 gpo, pex(rsto), spi(cs), ptp(trig) | ||
| 160 | mpp8 8 gpio, twsi0(sda), uart0(rts), uart1(rts), ptp(clk), | ||
| 161 | mii(col), mii-1(rxerr), sata1(prsnt) | ||
| 162 | mpp9 9 gpio, twsi(sck), uart0(cts), uart1(cts), ptp(evreq), | ||
| 163 | mii(crs), sata0(prsnt) | ||
| 164 | mpp10 10 gpo, spi(sck), uart0(txd), ptp(trig), sata1(act) | ||
| 165 | mpp11 11 gpio, spi(miso), uart0(rxd), ptp(clk), ptp-1(evreq), | ||
| 166 | ptp-2(trig), sata0(act) | ||
| 167 | mpp12 12 gpio, sdio(clk) | ||
| 168 | mpp13 13 gpio, sdio(cmd), uart1(txd) | ||
| 169 | mpp14 14 gpio, sdio(d0), uart1(rxd), mii(col), sata1(prsnt) | ||
| 170 | mpp15 15 gpio, sdio(d1), uart0(rts), uart1(txd), sata0(act) | ||
| 171 | mpp16 16 gpio, sdio(d2), uart0(cts), uart1(rxd), mii(crs), | ||
| 172 | sata1(act) | ||
| 173 | mpp17 17 gpio, sdio(d3), sata0(prsnt) | ||
| 174 | mpp18 18 gpo, nand(io0) | ||
| 175 | mpp19 19 gpo, nand(io1) | ||
| 176 | mpp20 20 gpio, ge1(txd0), ts(mp0), tdm(tx0ql), audio(spdifi), | ||
| 177 | sata1(act) | ||
| 178 | mpp21 21 gpio, ge1(txd1), sata0(act), ts(mp1), tdm(rx0ql), | ||
| 179 | audio(spdifo) | ||
| 180 | mpp22 22 gpio, ge1(txd2), ts(mp2), tdm(tx2ql), audio(rmclk), | ||
| 181 | sata1(prsnt) | ||
| 182 | mpp23 23 gpio, ge1(txd3), sata0(prsnt), ts(mp3), tdm(rx2ql), | ||
| 183 | audio(bclk) | ||
| 184 | mpp24 24 gpio, ge1(rxd0), ts(mp4), tdm(spi-cs0), audio(sdo) | ||
| 185 | mpp25 25 gpio, ge1(rxd1), ts(mp5), tdm(spi-sck), audio(lrclk) | ||
| 186 | mpp26 26 gpio, ge1(rxd2), ts(mp6), tdm(spi-miso), audio(mclk) | ||
| 187 | mpp27 27 gpio, ge1(rxd3), ts(mp7), tdm(spi-mosi), audio(sdi) | ||
| 188 | mpp28 28 gpio, ge1(col), ts(mp8), tdm(int), audio(extclk) | ||
| 189 | mpp29 29 gpio, ge1(txclk), ts(mp9), tdm(rst) | ||
| 190 | mpp30 30 gpio, ge1(rxclk), ts(mp10), tdm(pclk) | ||
| 191 | mpp31 31 gpio, ge1(rxclk), ts(mp11), tdm(fs) | ||
| 192 | mpp32 32 gpio, ge1(txclko), ts(mp12), tdm(drx) | ||
| 193 | mpp33 33 gpo, ge1(txclk), tdm(drx) | ||
| 194 | mpp34 34 gpio, ge1(txen), tdm(spi-cs1), sata1(act) | ||
| 195 | mpp35 35 gpio, ge1(rxerr), sata0(act), mii(rxerr), tdm(tx0ql) | ||
| 196 | mpp36 36 gpio, ts(mp0), tdm(spi-cs1), audio(spdifi) | ||
| 197 | mpp37 37 gpio, ts(mp1), tdm(tx2ql), audio(spdifo) | ||
| 198 | mpp38 38 gpio, ts(mp2), tdm(rx2ql), audio(rmclk) | ||
| 199 | mpp39 39 gpio, ts(mp3), tdm(spi-cs0), audio(bclk) | ||
| 200 | mpp40 40 gpio, ts(mp4), tdm(spi-sck), audio(sdo) | ||
| 201 | mpp41 41 gpio, ts(mp5), tdm(spi-miso), audio(lrclk) | ||
| 202 | mpp42 42 gpio, ts(mp6), tdm(spi-mosi), audio(mclk) | ||
| 203 | mpp43 43 gpio, ts(mp7), tdm(int), audio(sdi) | ||
| 204 | mpp44 44 gpio, ts(mp8), tdm(rst), audio(extclk) | ||
| 205 | mpp45 45 gpio, ts(mp9), tdm(pclk) | ||
| 206 | mpp46 46 gpio, ts(mp10), tdm(fs) | ||
| 207 | mpp47 47 gpio, ts(mp11), tdm(drx) | ||
| 208 | mpp48 48 gpio, ts(mp12), tdm(dtx) | ||
| 209 | mpp49 49 gpio, ts(mp9), tdm(rx0ql), ptp(clk) | ||
| 210 | |||
| 211 | * Marvell Kirkwood 88f6282 | ||
| 212 | |||
| 213 | name pins functions | ||
| 214 | ================================================================================ | ||
| 215 | mpp0 0 gpio, nand(io2), spi(cs) | ||
| 216 | mpp1 1 gpo, nand(io3), spi(mosi) | ||
| 217 | mpp2 2 gpo, nand(io4), spi(sck) | ||
| 218 | mpp3 3 gpo, nand(io5), spi(miso) | ||
| 219 | mpp4 4 gpio, nand(io6), uart0(rxd), sata1(act), lcd(hsync) | ||
| 220 | mpp5 5 gpo, nand(io7), uart0(txd), sata0(act), lcd(vsync) | ||
| 221 | mpp6 6 sysrst(out), spi(mosi) | ||
| 222 | mpp7 7 gpo, spi(cs), lcd(pwm) | ||
| 223 | mpp8 8 gpio, twsi0(sda), uart0(rts), uart1(rts), mii(col), | ||
| 224 | mii-1(rxerr), sata1(prsnt) | ||
| 225 | mpp9 9 gpio, twsi(sck), uart0(cts), uart1(cts), mii(crs), | ||
| 226 | sata0(prsnt) | ||
| 227 | mpp10 10 gpo, spi(sck), uart0(txd), sata1(act) | ||
| 228 | mpp11 11 gpio, spi(miso), uart0(rxd), sata0(act) | ||
| 229 | mpp12 12 gpo, sdio(clk), audio(spdifo), spi(mosi), twsi(sda) | ||
| 230 | mpp13 13 gpio, sdio(cmd), uart1(txd), audio(rmclk), lcd(pwm) | ||
| 231 | mpp14 14 gpio, sdio(d0), uart1(rxd), mii(col), sata1(prsnt), | ||
| 232 | audio(spdifi), audio-1(sdi) | ||
| 233 | mpp15 15 gpio, sdio(d1), uart0(rts), uart1(txd), sata0(act), | ||
| 234 | spi(cs) | ||
| 235 | mpp16 16 gpio, sdio(d2), uart0(cts), uart1(rxd), mii(crs), | ||
| 236 | sata1(act), lcd(extclk) | ||
| 237 | mpp17 17 gpio, sdio(d3), sata0(prsnt), sata1(act), twsi1(sck) | ||
| 238 | mpp18 18 gpo, nand(io0), pex(clkreq) | ||
| 239 | mpp19 19 gpo, nand(io1) | ||
| 240 | mpp20 20 gpio, ge1(txd0), ts(mp0), tdm(tx0ql), audio(spdifi), | ||
| 241 | sata1(act), lcd(d0) | ||
| 242 | mpp21 21 gpio, ge1(txd1), sata0(act), ts(mp1), tdm(rx0ql), | ||
| 243 | audio(spdifo), lcd(d1) | ||
| 244 | mpp22 22 gpio, ge1(txd2), ts(mp2), tdm(tx2ql), audio(rmclk), | ||
| 245 | sata1(prsnt), lcd(d2) | ||
| 246 | mpp23 23 gpio, ge1(txd3), sata0(prsnt), ts(mp3), tdm(rx2ql), | ||
| 247 | audio(bclk), lcd(d3) | ||
| 248 | mpp24 24 gpio, ge1(rxd0), ts(mp4), tdm(spi-cs0), audio(sdo), | ||
| 249 | lcd(d4) | ||
| 250 | mpp25 25 gpio, ge1(rxd1), ts(mp5), tdm(spi-sck), audio(lrclk), | ||
| 251 | lcd(d5) | ||
| 252 | mpp26 26 gpio, ge1(rxd2), ts(mp6), tdm(spi-miso), audio(mclk), | ||
| 253 | lcd(d6) | ||
| 254 | mpp27 27 gpio, ge1(rxd3), ts(mp7), tdm(spi-mosi), audio(sdi), | ||
| 255 | lcd(d7) | ||
| 256 | mpp28 28 gpio, ge1(col), ts(mp8), tdm(int), audio(extclk), | ||
| 257 | lcd(d8) | ||
| 258 | mpp29 29 gpio, ge1(txclk), ts(mp9), tdm(rst), lcd(d9) | ||
| 259 | mpp30 30 gpio, ge1(rxclk), ts(mp10), tdm(pclk), lcd(d10) | ||
| 260 | mpp31 31 gpio, ge1(rxclk), ts(mp11), tdm(fs), lcd(d11) | ||
| 261 | mpp32 32 gpio, ge1(txclko), ts(mp12), tdm(drx), lcd(d12) | ||
| 262 | mpp33 33 gpo, ge1(txclk), tdm(drx), lcd(d13) | ||
| 263 | mpp34 34 gpio, ge1(txen), tdm(spi-cs1), sata1(act), lcd(d14) | ||
| 264 | mpp35 35 gpio, ge1(rxerr), sata0(act), mii(rxerr), tdm(tx0ql), | ||
| 265 | lcd(d15) | ||
| 266 | mpp36 36 gpio, ts(mp0), tdm(spi-cs1), audio(spdifi), twsi1(sda) | ||
| 267 | mpp37 37 gpio, ts(mp1), tdm(tx2ql), audio(spdifo), twsi1(sck) | ||
| 268 | mpp38 38 gpio, ts(mp2), tdm(rx2ql), audio(rmclk), lcd(d18) | ||
| 269 | mpp39 39 gpio, ts(mp3), tdm(spi-cs0), audio(bclk), lcd(d19) | ||
| 270 | mpp40 40 gpio, ts(mp4), tdm(spi-sck), audio(sdo), lcd(d20) | ||
| 271 | mpp41 41 gpio, ts(mp5), tdm(spi-miso), audio(lrclk), lcd(d21) | ||
| 272 | mpp42 42 gpio, ts(mp6), tdm(spi-mosi), audio(mclk), lcd(d22) | ||
| 273 | mpp43 43 gpio, ts(mp7), tdm(int), audio(sdi), lcd(d23) | ||
| 274 | mpp44 44 gpio, ts(mp8), tdm(rst), audio(extclk), lcd(clk) | ||
| 275 | mpp45 45 gpio, ts(mp9), tdm(pclk), lcd(e) | ||
| 276 | mpp46 46 gpio, ts(mp10), tdm(fs), lcd(hsync) | ||
| 277 | mpp47 47 gpio, ts(mp11), tdm(drx), lcd(vsync) | ||
| 278 | mpp48 48 gpio, ts(mp12), tdm(dtx), lcd(d16) | ||
| 279 | mpp49 49 gpo, tdm(rx0ql), pex(clkreq), lcd(d17) | ||
diff --git a/Documentation/devicetree/bindings/pinctrl/marvell,mvebu-pinctrl.txt b/Documentation/devicetree/bindings/pinctrl/marvell,mvebu-pinctrl.txt new file mode 100644 index 000000000000..0a26c3aa4e6d --- /dev/null +++ b/Documentation/devicetree/bindings/pinctrl/marvell,mvebu-pinctrl.txt | |||
| @@ -0,0 +1,46 @@ | |||
| 1 | * Marvell SoC pinctrl core driver for mpp | ||
| 2 | |||
| 3 | The pinctrl driver enables Marvell SoCs to configure the multi-purpose pins | ||
| 4 | (mpp) to a specific function. For each SoC family there is a SoC specific | ||
| 5 | driver using this core driver. | ||
| 6 | |||
| 7 | Please refer to pinctrl-bindings.txt in this directory for details of the | ||
| 8 | common pinctrl bindings used by client devices, including the meaning of the | ||
| 9 | phrase "pin configuration node". | ||
| 10 | |||
| 11 | A Marvell SoC pin configuration node is a node of a group of pins which can | ||
| 12 | be used for a specific device or function. Each node requires one or more | ||
| 13 | mpp pins or group of pins and a mpp function common to all pins. | ||
| 14 | |||
| 15 | Required properties for pinctrl driver: | ||
| 16 | - compatible: "marvell,<soc>-pinctrl" | ||
| 17 | Please refer to each marvell,<soc>-pinctrl.txt binding doc for supported SoCs. | ||
| 18 | |||
| 19 | Required properties for pin configuration node: | ||
| 20 | - marvell,pins: string array of mpp pins or group of pins to be muxed. | ||
| 21 | - marvell,function: string representing a function to mux to for all | ||
| 22 | marvell,pins given in this pin configuration node. The function has to be | ||
| 23 | common for all marvell,pins. Please refer to marvell,<soc>-pinctrl.txt for | ||
| 24 | valid pin/pin group names and available function names for each SoC. | ||
| 25 | |||
| 26 | Examples: | ||
| 27 | |||
| 28 | uart1: serial@12100 { | ||
| 29 | compatible = "ns16550a"; | ||
| 30 | reg = <0x12100 0x100>; | ||
| 31 | reg-shift = <2>; | ||
| 32 | interrupts = <7>; | ||
| 33 | |||
| 34 | pinctrl-0 = <&pmx_uart1_sw>; | ||
| 35 | pinctrl-names = "default"; | ||
| 36 | }; | ||
| 37 | |||
| 38 | pinctrl: pinctrl@d0200 { | ||
| 39 | compatible = "marvell,dove-pinctrl"; | ||
| 40 | reg = <0xd0200 0x20>; | ||
| 41 | |||
| 42 | pmx_uart1_sw: pmx-uart1-sw { | ||
| 43 | marvell,pins = "mpp_uart1"; | ||
| 44 | marvell,function = "uart1"; | ||
| 45 | }; | ||
| 46 | }; | ||
diff --git a/arch/arm/boot/dts/armada-370.dtsi b/arch/arm/boot/dts/armada-370.dtsi index 3228ccc83332..2069151afe01 100644 --- a/arch/arm/boot/dts/armada-370.dtsi +++ b/arch/arm/boot/dts/armada-370.dtsi | |||
| @@ -21,6 +21,12 @@ | |||
| 21 | model = "Marvell Armada 370 family SoC"; | 21 | model = "Marvell Armada 370 family SoC"; |
| 22 | compatible = "marvell,armada370", "marvell,armada-370-xp"; | 22 | compatible = "marvell,armada370", "marvell,armada-370-xp"; |
| 23 | 23 | ||
| 24 | aliases { | ||
| 25 | gpio0 = &gpio0; | ||
| 26 | gpio1 = &gpio1; | ||
| 27 | gpio2 = &gpio2; | ||
| 28 | }; | ||
| 29 | |||
| 24 | mpic: interrupt-controller@d0020000 { | 30 | mpic: interrupt-controller@d0020000 { |
| 25 | reg = <0xd0020a00 0x1d0>, | 31 | reg = <0xd0020a00 0x1d0>, |
| 26 | <0xd0021870 0x58>; | 32 | <0xd0021870 0x58>; |
| @@ -31,5 +37,43 @@ | |||
| 31 | compatible = "marvell,armada-370-xp-system-controller"; | 37 | compatible = "marvell,armada-370-xp-system-controller"; |
| 32 | reg = <0xd0018200 0x100>; | 38 | reg = <0xd0018200 0x100>; |
| 33 | }; | 39 | }; |
| 40 | |||
| 41 | pinctrl { | ||
| 42 | compatible = "marvell,mv88f6710-pinctrl"; | ||
| 43 | reg = <0xd0018000 0x38>; | ||
| 44 | }; | ||
| 45 | |||
| 46 | gpio0: gpio@d0018100 { | ||
| 47 | compatible = "marvell,orion-gpio"; | ||
| 48 | reg = <0xd0018100 0x40>; | ||
| 49 | ngpios = <32>; | ||
| 50 | gpio-controller; | ||
| 51 | #gpio-cells = <2>; | ||
| 52 | interrupt-controller; | ||
| 53 | #interrupts-cells = <2>; | ||
| 54 | interrupts = <82>, <83>, <84>, <85>; | ||
| 55 | }; | ||
| 56 | |||
| 57 | gpio1: gpio@d0018140 { | ||
| 58 | compatible = "marvell,orion-gpio"; | ||
| 59 | reg = <0xd0018140 0x40>; | ||
| 60 | ngpios = <32>; | ||
| 61 | gpio-controller; | ||
| 62 | #gpio-cells = <2>; | ||
| 63 | interrupt-controller; | ||
| 64 | #interrupts-cells = <2>; | ||
| 65 | interrupts = <87>, <88>, <89>, <90>; | ||
| 66 | }; | ||
| 67 | |||
| 68 | gpio2: gpio@d0018180 { | ||
| 69 | compatible = "marvell,orion-gpio"; | ||
| 70 | reg = <0xd0018180 0x40>; | ||
| 71 | ngpios = <2>; | ||
| 72 | gpio-controller; | ||
| 73 | #gpio-cells = <2>; | ||
| 74 | interrupt-controller; | ||
| 75 | #interrupts-cells = <2>; | ||
| 76 | interrupts = <91>; | ||
| 77 | }; | ||
| 34 | }; | 78 | }; |
| 35 | }; | 79 | }; |
diff --git a/arch/arm/boot/dts/armada-xp-db.dts b/arch/arm/boot/dts/armada-xp-db.dts index f97040d4258d..b1fc728515e9 100644 --- a/arch/arm/boot/dts/armada-xp-db.dts +++ b/arch/arm/boot/dts/armada-xp-db.dts | |||
| @@ -14,11 +14,11 @@ | |||
| 14 | */ | 14 | */ |
| 15 | 15 | ||
| 16 | /dts-v1/; | 16 | /dts-v1/; |
| 17 | /include/ "armada-xp.dtsi" | 17 | /include/ "armada-xp-mv78460.dtsi" |
| 18 | 18 | ||
| 19 | / { | 19 | / { |
| 20 | model = "Marvell Armada XP Evaluation Board"; | 20 | model = "Marvell Armada XP Evaluation Board"; |
| 21 | compatible = "marvell,axp-db", "marvell,armadaxp", "marvell,armada-370-xp"; | 21 | compatible = "marvell,axp-db", "marvell,armadaxp-mv78460", "marvell,armadaxp", "marvell,armada-370-xp"; |
| 22 | 22 | ||
| 23 | chosen { | 23 | chosen { |
| 24 | bootargs = "console=ttyS0,115200 earlyprintk"; | 24 | bootargs = "console=ttyS0,115200 earlyprintk"; |
diff --git a/arch/arm/boot/dts/armada-xp-mv78230.dtsi b/arch/arm/boot/dts/armada-xp-mv78230.dtsi new file mode 100644 index 000000000000..ea355192be6f --- /dev/null +++ b/arch/arm/boot/dts/armada-xp-mv78230.dtsi | |||
| @@ -0,0 +1,57 @@ | |||
| 1 | /* | ||
| 2 | * Device Tree Include file for Marvell Armada XP family SoC | ||
| 3 | * | ||
| 4 | * Copyright (C) 2012 Marvell | ||
| 5 | * | ||
| 6 | * Thomas Petazzoni <thomas.petazzoni@free-electrons.com> | ||
| 7 | * | ||
| 8 | * This file is licensed under the terms of the GNU General Public | ||
| 9 | * License version 2. This program is licensed "as is" without any | ||
| 10 | * warranty of any kind, whether express or implied. | ||
| 11 | * | ||
| 12 | * Contains definitions specific to the Armada XP MV78230 SoC that are not | ||
| 13 | * common to all Armada XP SoCs. | ||
| 14 | */ | ||
| 15 | |||
| 16 | /include/ "armada-xp.dtsi" | ||
| 17 | |||
| 18 | / { | ||
| 19 | model = "Marvell Armada XP MV78230 SoC"; | ||
| 20 | compatible = "marvell,armadaxp-mv78230", "marvell,armadaxp", "marvell,armada-370-xp"; | ||
| 21 | |||
| 22 | aliases { | ||
| 23 | gpio0 = &gpio0; | ||
| 24 | gpio1 = &gpio1; | ||
| 25 | }; | ||
| 26 | |||
| 27 | soc { | ||
| 28 | pinctrl { | ||
| 29 | compatible = "marvell,mv78230-pinctrl"; | ||
| 30 | reg = <0xd0018000 0x38>; | ||
| 31 | }; | ||
| 32 | |||
| 33 | gpio0: gpio@d0018100 { | ||
| 34 | compatible = "marvell,armadaxp-gpio"; | ||
| 35 | reg = <0xd0018100 0x40>, | ||
| 36 | <0xd0018800 0x30>; | ||
| 37 | ngpios = <32>; | ||
| 38 | gpio-controller; | ||
| 39 | #gpio-cells = <2>; | ||
| 40 | interrupt-controller; | ||
| 41 | #interrupts-cells = <2>; | ||
| 42 | interrupts = <16>, <17>, <18>, <19>; | ||
| 43 | }; | ||
| 44 | |||
| 45 | gpio1: gpio@d0018140 { | ||
| 46 | compatible = "marvell,armadaxp-gpio"; | ||
| 47 | reg = <0xd0018140 0x40>, | ||
| 48 | <0xd0018840 0x30>; | ||
| 49 | ngpios = <17>; | ||
| 50 | gpio-controller; | ||
| 51 | #gpio-cells = <2>; | ||
| 52 | interrupt-controller; | ||
| 53 | #interrupts-cells = <2>; | ||
| 54 | interrupts = <20>, <21>, <22>; | ||
| 55 | }; | ||
| 56 | }; | ||
| 57 | }; | ||
diff --git a/arch/arm/boot/dts/armada-xp-mv78260.dtsi b/arch/arm/boot/dts/armada-xp-mv78260.dtsi new file mode 100644 index 000000000000..2057863f3dfa --- /dev/null +++ b/arch/arm/boot/dts/armada-xp-mv78260.dtsi | |||
| @@ -0,0 +1,70 @@ | |||
| 1 | /* | ||
| 2 | * Device Tree Include file for Marvell Armada XP family SoC | ||
| 3 | * | ||
| 4 | * Copyright (C) 2012 Marvell | ||
| 5 | * | ||
| 6 | * Thomas Petazzoni <thomas.petazzoni@free-electrons.com> | ||
| 7 | * | ||
| 8 | * This file is licensed under the terms of the GNU General Public | ||
| 9 | * License version 2. This program is licensed "as is" without any | ||
| 10 | * warranty of any kind, whether express or implied. | ||
| 11 | * | ||
| 12 | * Contains definitions specific to the Armada XP MV78260 SoC that are not | ||
| 13 | * common to all Armada XP SoCs. | ||
| 14 | */ | ||
| 15 | |||
| 16 | /include/ "armada-xp.dtsi" | ||
| 17 | |||
| 18 | / { | ||
| 19 | model = "Marvell Armada XP MV78260 SoC"; | ||
| 20 | compatible = "marvell,armadaxp-mv78260", "marvell,armadaxp", "marvell,armada-370-xp"; | ||
| 21 | |||
| 22 | aliases { | ||
| 23 | gpio0 = &gpio0; | ||
| 24 | gpio1 = &gpio1; | ||
| 25 | gpio2 = &gpio2; | ||
| 26 | }; | ||
| 27 | |||
| 28 | soc { | ||
| 29 | pinctrl { | ||
| 30 | compatible = "marvell,mv78260-pinctrl"; | ||
| 31 | reg = <0xd0018000 0x38>; | ||
| 32 | }; | ||
| 33 | |||
| 34 | gpio0: gpio@d0018100 { | ||
| 35 | compatible = "marvell,armadaxp-gpio"; | ||
| 36 | reg = <0xd0018100 0x40>, | ||
| 37 | <0xd0018800 0x30>; | ||
| 38 | ngpios = <32>; | ||
| 39 | gpio-controller; | ||
| 40 | #gpio-cells = <2>; | ||
| 41 | interrupt-controller; | ||
| 42 | #interrupts-cells = <2>; | ||
| 43 | interrupts = <16>, <17>, <18>, <19>; | ||
| 44 | }; | ||
| 45 | |||
| 46 | gpio1: gpio@d0018140 { | ||
| 47 | compatible = "marvell,armadaxp-gpio"; | ||
| 48 | reg = <0xd0018140 0x40>, | ||
| 49 | <0xd0018840 0x30>; | ||
| 50 | ngpios = <32>; | ||
| 51 | gpio-controller; | ||
| 52 | #gpio-cells = <2>; | ||
| 53 | interrupt-controller; | ||
| 54 | #interrupts-cells = <2>; | ||
| 55 | interrupts = <20>, <21>, <22>, <23>; | ||
| 56 | }; | ||
| 57 | |||
| 58 | gpio2: gpio@d0018180 { | ||
| 59 | compatible = "marvell,armadaxp-gpio"; | ||
| 60 | reg = <0xd0018180 0x40>, | ||
| 61 | <0xd0018870 0x30>; | ||
| 62 | ngpios = <3>; | ||
| 63 | gpio-controller; | ||
| 64 | #gpio-cells = <2>; | ||
| 65 | interrupt-controller; | ||
| 66 | #interrupts-cells = <2>; | ||
| 67 | interrupts = <24>; | ||
| 68 | }; | ||
| 69 | }; | ||
| 70 | }; | ||
diff --git a/arch/arm/boot/dts/armada-xp-mv78460.dtsi b/arch/arm/boot/dts/armada-xp-mv78460.dtsi new file mode 100644 index 000000000000..ffac98373792 --- /dev/null +++ b/arch/arm/boot/dts/armada-xp-mv78460.dtsi | |||
| @@ -0,0 +1,70 @@ | |||
| 1 | /* | ||
| 2 | * Device Tree Include file for Marvell Armada XP family SoC | ||
| 3 | * | ||
| 4 | * Copyright (C) 2012 Marvell | ||
| 5 | * | ||
| 6 | * Thomas Petazzoni <thomas.petazzoni@free-electrons.com> | ||
| 7 | * | ||
| 8 | * This file is licensed under the terms of the GNU General Public | ||
| 9 | * License version 2. This program is licensed "as is" without any | ||
| 10 | * warranty of any kind, whether express or implied. | ||
| 11 | * | ||
| 12 | * Contains definitions specific to the Armada XP MV78460 SoC that are not | ||
| 13 | * common to all Armada XP SoCs. | ||
| 14 | */ | ||
| 15 | |||
| 16 | /include/ "armada-xp.dtsi" | ||
| 17 | |||
| 18 | / { | ||
| 19 | model = "Marvell Armada XP MV78460 SoC"; | ||
| 20 | compatible = "marvell,armadaxp-mv78460", "marvell,armadaxp", "marvell,armada-370-xp"; | ||
| 21 | |||
| 22 | aliases { | ||
| 23 | gpio0 = &gpio0; | ||
| 24 | gpio1 = &gpio1; | ||
| 25 | gpio2 = &gpio2; | ||
| 26 | }; | ||
| 27 | |||
| 28 | soc { | ||
| 29 | pinctrl { | ||
| 30 | compatible = "marvell,mv78460-pinctrl"; | ||
| 31 | reg = <0xd0018000 0x38>; | ||
| 32 | }; | ||
| 33 | |||
| 34 | gpio0: gpio@d0018100 { | ||
| 35 | compatible = "marvell,armadaxp-gpio"; | ||
| 36 | reg = <0xd0018100 0x40>, | ||
| 37 | <0xd0018800 0x30>; | ||
| 38 | ngpios = <32>; | ||
| 39 | gpio-controller; | ||
| 40 | #gpio-cells = <2>; | ||
| 41 | interrupt-controller; | ||
| 42 | #interrupts-cells = <2>; | ||
| 43 | interrupts = <16>, <17>, <18>, <19>; | ||
| 44 | }; | ||
| 45 | |||
| 46 | gpio1: gpio@d0018140 { | ||
| 47 | compatible = "marvell,armadaxp-gpio"; | ||
| 48 | reg = <0xd0018140 0x40>, | ||
| 49 | <0xd0018840 0x30>; | ||
| 50 | ngpios = <32>; | ||
| 51 | gpio-controller; | ||
| 52 | #gpio-cells = <2>; | ||
| 53 | interrupt-controller; | ||
| 54 | #interrupts-cells = <2>; | ||
| 55 | interrupts = <20>, <21>, <22>, <23>; | ||
| 56 | }; | ||
| 57 | |||
| 58 | gpio2: gpio@d0018180 { | ||
| 59 | compatible = "marvell,armadaxp-gpio"; | ||
| 60 | reg = <0xd0018180 0x40>, | ||
| 61 | <0xd0018870 0x30>; | ||
| 62 | ngpios = <3>; | ||
| 63 | gpio-controller; | ||
| 64 | #gpio-cells = <2>; | ||
| 65 | interrupt-controller; | ||
| 66 | #interrupts-cells = <2>; | ||
| 67 | interrupts = <24>; | ||
| 68 | }; | ||
| 69 | }; | ||
| 70 | }; | ||
diff --git a/arch/arm/configs/mvebu_defconfig b/arch/arm/configs/mvebu_defconfig index 2e86b31c33cf..7bcf850eddcd 100644 --- a/arch/arm/configs/mvebu_defconfig +++ b/arch/arm/configs/mvebu_defconfig | |||
| @@ -21,6 +21,8 @@ CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug" | |||
| 21 | CONFIG_SERIAL_8250=y | 21 | CONFIG_SERIAL_8250=y |
| 22 | CONFIG_SERIAL_8250_CONSOLE=y | 22 | CONFIG_SERIAL_8250_CONSOLE=y |
| 23 | CONFIG_SERIAL_OF_PLATFORM=y | 23 | CONFIG_SERIAL_OF_PLATFORM=y |
| 24 | CONFIG_GPIOLIB=y | ||
| 25 | CONFIG_GPIO_SYSFS=y | ||
| 24 | CONFIG_EXT2_FS=y | 26 | CONFIG_EXT2_FS=y |
| 25 | CONFIG_EXT3_FS=y | 27 | CONFIG_EXT3_FS=y |
| 26 | # CONFIG_EXT3_FS_XATTR is not set | 28 | # CONFIG_EXT3_FS_XATTR is not set |
diff --git a/arch/arm/mach-mvebu/Kconfig b/arch/arm/mach-mvebu/Kconfig index 7b270358536e..26a817d81a70 100644 --- a/arch/arm/mach-mvebu/Kconfig +++ b/arch/arm/mach-mvebu/Kconfig | |||
| @@ -13,13 +13,25 @@ if ARCH_MVEBU | |||
| 13 | menu "Marvell SOC with device tree" | 13 | menu "Marvell SOC with device tree" |
| 14 | 14 | ||
| 15 | config MACH_ARMADA_370_XP | 15 | config MACH_ARMADA_370_XP |
| 16 | bool "Marvell Armada 370 and Aramada XP boards" | 16 | bool |
| 17 | select ARMADA_370_XP_TIMER | 17 | select ARMADA_370_XP_TIMER |
| 18 | select CPU_V7 | 18 | select CPU_V7 |
| 19 | |||
| 20 | config MACH_ARMADA_370 | ||
| 21 | bool "Marvell Armada 370 boards" | ||
| 22 | select MACH_ARMADA_370_XP | ||
| 23 | select PINCTRL_ARMADA_370 | ||
| 19 | help | 24 | help |
| 25 | Say 'Y' here if you want your kernel to support boards based | ||
| 26 | on the Marvell Armada 370 SoC with device tree. | ||
| 20 | 27 | ||
| 21 | Say 'Y' here if you want your kernel to support boards based on | 28 | config MACH_ARMADA_XP |
| 22 | Marvell Armada 370 or Armada XP with device tree. | 29 | bool "Marvell Armada XP boards" |
| 30 | select MACH_ARMADA_370_XP | ||
| 31 | select PINCTRL_ARMADA_XP | ||
| 32 | help | ||
| 33 | Say 'Y' here if you want your kernel to support boards based | ||
| 34 | on the Marvell Armada XP SoC with device tree. | ||
| 23 | 35 | ||
| 24 | endmenu | 36 | endmenu |
| 25 | 37 | ||
diff --git a/arch/arm/mach-mvebu/include/mach/gpio.h b/arch/arm/mach-mvebu/include/mach/gpio.h new file mode 100644 index 000000000000..40a8c178f10d --- /dev/null +++ b/arch/arm/mach-mvebu/include/mach/gpio.h | |||
| @@ -0,0 +1 @@ | |||
| /* empty */ | |||
diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig index ba7926f5c099..66a59510887f 100644 --- a/drivers/gpio/Kconfig +++ b/drivers/gpio/Kconfig | |||
| @@ -150,6 +150,12 @@ config GPIO_MSM_V2 | |||
| 150 | Qualcomm MSM chips. Most of the pins on the MSM can be | 150 | Qualcomm MSM chips. Most of the pins on the MSM can be |
| 151 | selected for GPIO, and are controlled by this driver. | 151 | selected for GPIO, and are controlled by this driver. |
| 152 | 152 | ||
| 153 | config GPIO_MVEBU | ||
| 154 | def_bool y | ||
| 155 | depends on ARCH_MVEBU | ||
| 156 | select GPIO_GENERIC | ||
| 157 | select GENERIC_IRQ_CHIP | ||
| 158 | |||
| 153 | config GPIO_MXC | 159 | config GPIO_MXC |
| 154 | def_bool y | 160 | def_bool y |
| 155 | depends on ARCH_MXC | 161 | depends on ARCH_MXC |
diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile index 153caceeb053..1a33e6716e10 100644 --- a/drivers/gpio/Makefile +++ b/drivers/gpio/Makefile | |||
| @@ -41,6 +41,7 @@ obj-$(CONFIG_GPIO_MPC8XXX) += gpio-mpc8xxx.o | |||
| 41 | obj-$(CONFIG_GPIO_MSIC) += gpio-msic.o | 41 | obj-$(CONFIG_GPIO_MSIC) += gpio-msic.o |
| 42 | obj-$(CONFIG_GPIO_MSM_V1) += gpio-msm-v1.o | 42 | obj-$(CONFIG_GPIO_MSM_V1) += gpio-msm-v1.o |
| 43 | obj-$(CONFIG_GPIO_MSM_V2) += gpio-msm-v2.o | 43 | obj-$(CONFIG_GPIO_MSM_V2) += gpio-msm-v2.o |
| 44 | obj-$(CONFIG_GPIO_MVEBU) += gpio-mvebu.o | ||
| 44 | obj-$(CONFIG_GPIO_MXC) += gpio-mxc.o | 45 | obj-$(CONFIG_GPIO_MXC) += gpio-mxc.o |
| 45 | obj-$(CONFIG_GPIO_MXS) += gpio-mxs.o | 46 | obj-$(CONFIG_GPIO_MXS) += gpio-mxs.o |
| 46 | obj-$(CONFIG_ARCH_OMAP) += gpio-omap.o | 47 | obj-$(CONFIG_ARCH_OMAP) += gpio-omap.o |
diff --git a/drivers/gpio/gpio-mvebu.c b/drivers/gpio/gpio-mvebu.c new file mode 100644 index 000000000000..902af437eaf2 --- /dev/null +++ b/drivers/gpio/gpio-mvebu.c | |||
| @@ -0,0 +1,679 @@ | |||
| 1 | /* | ||
| 2 | * GPIO driver for Marvell SoCs | ||
| 3 | * | ||
| 4 | * Copyright (C) 2012 Marvell | ||
| 5 | * | ||
| 6 | * Thomas Petazzoni <thomas.petazzoni@free-electrons.com> | ||
| 7 | * Andrew Lunn <andrew@lunn.ch> | ||
| 8 | * Sebastian Hesselbarth <sebastian.hesselbarth@gmail.com> | ||
| 9 | * | ||
| 10 | * This file is licensed under the terms of the GNU General Public | ||
| 11 | * License version 2. This program is licensed "as is" without any | ||
| 12 | * warranty of any kind, whether express or implied. | ||
| 13 | * | ||
| 14 | * This driver is a fairly straightforward GPIO driver for the | ||
| 15 | * complete family of Marvell EBU SoC platforms (Orion, Dove, | ||
| 16 | * Kirkwood, Discovery, Armada 370/XP). The only complexity of this | ||
| 17 | * driver is the different register layout that exists between the | ||
| 18 | * non-SMP platforms (Orion, Dove, Kirkwood, Armada 370) and the SMP | ||
| 19 | * platforms (MV78200 from the Discovery family and the Armada | ||
| 20 | * XP). Therefore, this driver handles three variants of the GPIO | ||
| 21 | * block: | ||
| 22 | * - the basic variant, called "orion-gpio", with the simplest | ||
| 23 | * register set. Used on Orion, Dove, Kirkwoord, Armada 370 and | ||
| 24 | * non-SMP Discovery systems | ||
| 25 | * - the mv78200 variant for MV78200 Discovery systems. This variant | ||
| 26 | * turns the edge mask and level mask registers into CPU0 edge | ||
| 27 | * mask/level mask registers, and adds CPU1 edge mask/level mask | ||
| 28 | * registers. | ||
| 29 | * - the armadaxp variant for Armada XP systems. This variant keeps | ||
| 30 | * the normal cause/edge mask/level mask registers when the global | ||
| 31 | * interrupts are used, but adds per-CPU cause/edge mask/level mask | ||
| 32 | * registers n a separate memory area for the per-CPU GPIO | ||
| 33 | * interrupts. | ||
| 34 | */ | ||
| 35 | |||
| 36 | #include <linux/module.h> | ||
| 37 | #include <linux/gpio.h> | ||
| 38 | #include <linux/irq.h> | ||
| 39 | #include <linux/slab.h> | ||
| 40 | #include <linux/irqdomain.h> | ||
| 41 | #include <linux/io.h> | ||
| 42 | #include <linux/of_irq.h> | ||
| 43 | #include <linux/of_device.h> | ||
| 44 | #include <linux/platform_device.h> | ||
| 45 | #include <linux/pinctrl/consumer.h> | ||
| 46 | |||
| 47 | /* | ||
| 48 | * GPIO unit register offsets. | ||
| 49 | */ | ||
| 50 | #define GPIO_OUT_OFF 0x0000 | ||
| 51 | #define GPIO_IO_CONF_OFF 0x0004 | ||
| 52 | #define GPIO_BLINK_EN_OFF 0x0008 | ||
| 53 | #define GPIO_IN_POL_OFF 0x000c | ||
| 54 | #define GPIO_DATA_IN_OFF 0x0010 | ||
| 55 | #define GPIO_EDGE_CAUSE_OFF 0x0014 | ||
| 56 | #define GPIO_EDGE_MASK_OFF 0x0018 | ||
| 57 | #define GPIO_LEVEL_MASK_OFF 0x001c | ||
| 58 | |||
| 59 | /* The MV78200 has per-CPU registers for edge mask and level mask */ | ||
| 60 | #define GPIO_EDGE_MASK_MV78200_OFF(cpu) ((cpu) ? 0x30 : 0x18) | ||
| 61 | #define GPIO_LEVEL_MASK_MV78200_OFF(cpu) ((cpu) ? 0x34 : 0x1C) | ||
| 62 | |||
| 63 | /* The Armada XP has per-CPU registers for interrupt cause, interrupt | ||
| 64 | * mask and interrupt level mask. Those are relative to the | ||
| 65 | * percpu_membase. */ | ||
| 66 | #define GPIO_EDGE_CAUSE_ARMADAXP_OFF(cpu) ((cpu) * 0x4) | ||
| 67 | #define GPIO_EDGE_MASK_ARMADAXP_OFF(cpu) (0x10 + (cpu) * 0x4) | ||
| 68 | #define GPIO_LEVEL_MASK_ARMADAXP_OFF(cpu) (0x20 + (cpu) * 0x4) | ||
| 69 | |||
| 70 | #define MVEBU_GPIO_SOC_VARIANT_ORION 0x1 | ||
| 71 | #define MVEBU_GPIO_SOC_VARIANT_MV78200 0x2 | ||
| 72 | #define MVEBU_GPIO_SOC_VARIANT_ARMADAXP 0x3 | ||
| 73 | |||
| 74 | #define MVEBU_MAX_GPIO_PER_BANK 32 | ||
| 75 | |||
| 76 | struct mvebu_gpio_chip { | ||
| 77 | struct gpio_chip chip; | ||
| 78 | spinlock_t lock; | ||
| 79 | void __iomem *membase; | ||
| 80 | void __iomem *percpu_membase; | ||
| 81 | unsigned int irqbase; | ||
| 82 | struct irq_domain *domain; | ||
| 83 | int soc_variant; | ||
| 84 | }; | ||
| 85 | |||
| 86 | /* | ||
| 87 | * Functions returning addresses of individual registers for a given | ||
| 88 | * GPIO controller. | ||
| 89 | */ | ||
| 90 | static inline void __iomem *mvebu_gpioreg_out(struct mvebu_gpio_chip *mvchip) | ||
| 91 | { | ||
| 92 | return mvchip->membase + GPIO_OUT_OFF; | ||
| 93 | } | ||
| 94 | |||
| 95 | static inline void __iomem *mvebu_gpioreg_io_conf(struct mvebu_gpio_chip *mvchip) | ||
| 96 | { | ||
| 97 | return mvchip->membase + GPIO_IO_CONF_OFF; | ||
| 98 | } | ||
| 99 | |||
| 100 | static inline void __iomem *mvebu_gpioreg_in_pol(struct mvebu_gpio_chip *mvchip) | ||
| 101 | { | ||
| 102 | return mvchip->membase + GPIO_IN_POL_OFF; | ||
| 103 | } | ||
| 104 | |||
| 105 | static inline void __iomem *mvebu_gpioreg_data_in(struct mvebu_gpio_chip *mvchip) | ||
| 106 | { | ||
| 107 | return mvchip->membase + GPIO_DATA_IN_OFF; | ||
| 108 | } | ||
| 109 | |||
| 110 | static inline void __iomem *mvebu_gpioreg_edge_cause(struct mvebu_gpio_chip *mvchip) | ||
| 111 | { | ||
| 112 | int cpu; | ||
| 113 | |||
| 114 | switch(mvchip->soc_variant) { | ||
| 115 | case MVEBU_GPIO_SOC_VARIANT_ORION: | ||
| 116 | case MVEBU_GPIO_SOC_VARIANT_MV78200: | ||
| 117 | return mvchip->membase + GPIO_EDGE_CAUSE_OFF; | ||
| 118 | case MVEBU_GPIO_SOC_VARIANT_ARMADAXP: | ||
| 119 | cpu = smp_processor_id(); | ||
| 120 | return mvchip->percpu_membase + GPIO_EDGE_CAUSE_ARMADAXP_OFF(cpu); | ||
| 121 | default: | ||
| 122 | BUG(); | ||
| 123 | } | ||
| 124 | } | ||
| 125 | |||
| 126 | static inline void __iomem *mvebu_gpioreg_edge_mask(struct mvebu_gpio_chip *mvchip) | ||
| 127 | { | ||
| 128 | int cpu; | ||
| 129 | |||
| 130 | switch(mvchip->soc_variant) { | ||
| 131 | case MVEBU_GPIO_SOC_VARIANT_ORION: | ||
| 132 | return mvchip->membase + GPIO_EDGE_MASK_OFF; | ||
| 133 | case MVEBU_GPIO_SOC_VARIANT_MV78200: | ||
| 134 | cpu = smp_processor_id(); | ||
| 135 | return mvchip->membase + GPIO_EDGE_MASK_MV78200_OFF(cpu); | ||
| 136 | case MVEBU_GPIO_SOC_VARIANT_ARMADAXP: | ||
| 137 | cpu = smp_processor_id(); | ||
| 138 | return mvchip->percpu_membase + GPIO_EDGE_MASK_ARMADAXP_OFF(cpu); | ||
| 139 | default: | ||
| 140 | BUG(); | ||
| 141 | } | ||
| 142 | } | ||
| 143 | |||
| 144 | static void __iomem *mvebu_gpioreg_level_mask(struct mvebu_gpio_chip *mvchip) | ||
| 145 | { | ||
| 146 | int cpu; | ||
| 147 | |||
| 148 | switch(mvchip->soc_variant) { | ||
| 149 | case MVEBU_GPIO_SOC_VARIANT_ORION: | ||
| 150 | return mvchip->membase + GPIO_LEVEL_MASK_OFF; | ||
| 151 | case MVEBU_GPIO_SOC_VARIANT_MV78200: | ||
| 152 | cpu = smp_processor_id(); | ||
| 153 | return mvchip->membase + GPIO_LEVEL_MASK_MV78200_OFF(cpu); | ||
| 154 | case MVEBU_GPIO_SOC_VARIANT_ARMADAXP: | ||
| 155 | cpu = smp_processor_id(); | ||
| 156 | return mvchip->percpu_membase + GPIO_LEVEL_MASK_ARMADAXP_OFF(cpu); | ||
| 157 | default: | ||
| 158 | BUG(); | ||
| 159 | } | ||
| 160 | } | ||
| 161 | |||
| 162 | /* | ||
| 163 | * Functions implementing the gpio_chip methods | ||
| 164 | */ | ||
| 165 | |||
| 166 | int mvebu_gpio_request(struct gpio_chip *chip, unsigned pin) | ||
| 167 | { | ||
| 168 | return pinctrl_request_gpio(chip->base + pin); | ||
| 169 | } | ||
| 170 | |||
| 171 | void mvebu_gpio_free(struct gpio_chip *chip, unsigned pin) | ||
| 172 | { | ||
| 173 | pinctrl_free_gpio(chip->base + pin); | ||
| 174 | } | ||
| 175 | |||
| 176 | static void mvebu_gpio_set(struct gpio_chip *chip, unsigned pin, int value) | ||
| 177 | { | ||
| 178 | struct mvebu_gpio_chip *mvchip = | ||
| 179 | container_of(chip, struct mvebu_gpio_chip, chip); | ||
| 180 | unsigned long flags; | ||
| 181 | u32 u; | ||
| 182 | |||
| 183 | spin_lock_irqsave(&mvchip->lock, flags); | ||
| 184 | u = readl_relaxed(mvebu_gpioreg_out(mvchip)); | ||
| 185 | if (value) | ||
| 186 | u |= 1 << pin; | ||
| 187 | else | ||
| 188 | u &= ~(1 << pin); | ||
| 189 | writel_relaxed(u, mvebu_gpioreg_out(mvchip)); | ||
| 190 | spin_unlock_irqrestore(&mvchip->lock, flags); | ||
| 191 | } | ||
| 192 | |||
| 193 | static int mvebu_gpio_get(struct gpio_chip *chip, unsigned pin) | ||
| 194 | { | ||
| 195 | struct mvebu_gpio_chip *mvchip = | ||
| 196 | container_of(chip, struct mvebu_gpio_chip, chip); | ||
| 197 | u32 u; | ||
| 198 | |||
| 199 | if (readl_relaxed(mvebu_gpioreg_io_conf(mvchip)) & (1 << pin)) { | ||
| 200 | u = readl_relaxed(mvebu_gpioreg_data_in(mvchip)) ^ | ||
| 201 | readl_relaxed(mvebu_gpioreg_in_pol(mvchip)); | ||
| 202 | } else { | ||
| 203 | u = readl_relaxed(mvebu_gpioreg_out(mvchip)); | ||
| 204 | } | ||
| 205 | |||
| 206 | return (u >> pin) & 1; | ||
| 207 | } | ||
| 208 | |||
| 209 | static int mvebu_gpio_direction_input(struct gpio_chip *chip, unsigned pin) | ||
| 210 | { | ||
| 211 | struct mvebu_gpio_chip *mvchip = | ||
| 212 | container_of(chip, struct mvebu_gpio_chip, chip); | ||
| 213 | unsigned long flags; | ||
| 214 | int ret; | ||
| 215 | u32 u; | ||
| 216 | |||
| 217 | /* Check with the pinctrl driver whether this pin is usable as | ||
| 218 | * an input GPIO */ | ||
| 219 | ret = pinctrl_gpio_direction_input(chip->base + pin); | ||
| 220 | if (ret) | ||
| 221 | return ret; | ||
| 222 | |||
| 223 | spin_lock_irqsave(&mvchip->lock, flags); | ||
| 224 | u = readl_relaxed(mvebu_gpioreg_io_conf(mvchip)); | ||
| 225 | u |= 1 << pin; | ||
| 226 | writel_relaxed(u, mvebu_gpioreg_io_conf(mvchip)); | ||
| 227 | spin_unlock_irqrestore(&mvchip->lock, flags); | ||
| 228 | |||
| 229 | return 0; | ||
| 230 | } | ||
| 231 | |||
| 232 | static int mvebu_gpio_direction_output(struct gpio_chip *chip, unsigned pin, | ||
| 233 | int value) | ||
| 234 | { | ||
| 235 | struct mvebu_gpio_chip *mvchip = | ||
| 236 | container_of(chip, struct mvebu_gpio_chip, chip); | ||
| 237 | unsigned long flags; | ||
| 238 | int ret; | ||
| 239 | u32 u; | ||
| 240 | |||
| 241 | /* Check with the pinctrl driver whether this pin is usable as | ||
| 242 | * an output GPIO */ | ||
| 243 | ret = pinctrl_gpio_direction_output(chip->base + pin); | ||
| 244 | if (ret) | ||
| 245 | return ret; | ||
| 246 | |||
| 247 | spin_lock_irqsave(&mvchip->lock, flags); | ||
| 248 | u = readl_relaxed(mvebu_gpioreg_io_conf(mvchip)); | ||
| 249 | u &= ~(1 << pin); | ||
| 250 | writel_relaxed(u, mvebu_gpioreg_io_conf(mvchip)); | ||
| 251 | spin_unlock_irqrestore(&mvchip->lock, flags); | ||
| 252 | |||
| 253 | return 0; | ||
| 254 | } | ||
| 255 | |||
| 256 | static int mvebu_gpio_to_irq(struct gpio_chip *chip, unsigned pin) | ||
| 257 | { | ||
| 258 | struct mvebu_gpio_chip *mvchip = | ||
| 259 | container_of(chip, struct mvebu_gpio_chip, chip); | ||
| 260 | return irq_create_mapping(mvchip->domain, pin); | ||
| 261 | } | ||
| 262 | |||
| 263 | /* | ||
| 264 | * Functions implementing the irq_chip methods | ||
| 265 | */ | ||
| 266 | static void mvebu_gpio_irq_ack(struct irq_data *d) | ||
| 267 | { | ||
| 268 | struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d); | ||
| 269 | struct mvebu_gpio_chip *mvchip = gc->private; | ||
| 270 | u32 mask = ~(1 << (d->irq - gc->irq_base)); | ||
| 271 | |||
| 272 | irq_gc_lock(gc); | ||
| 273 | writel_relaxed(mask, mvebu_gpioreg_edge_cause(mvchip)); | ||
| 274 | irq_gc_unlock(gc); | ||
| 275 | } | ||
| 276 | |||
| 277 | static void mvebu_gpio_edge_irq_mask(struct irq_data *d) | ||
| 278 | { | ||
| 279 | struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d); | ||
| 280 | struct mvebu_gpio_chip *mvchip = gc->private; | ||
| 281 | u32 mask = 1 << (d->irq - gc->irq_base); | ||
| 282 | |||
| 283 | irq_gc_lock(gc); | ||
| 284 | gc->mask_cache &= ~mask; | ||
| 285 | writel_relaxed(gc->mask_cache, mvebu_gpioreg_edge_mask(mvchip)); | ||
| 286 | irq_gc_unlock(gc); | ||
| 287 | } | ||
| 288 | |||
| 289 | static void mvebu_gpio_edge_irq_unmask(struct irq_data *d) | ||
| 290 | { | ||
| 291 | struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d); | ||
| 292 | struct mvebu_gpio_chip *mvchip = gc->private; | ||
| 293 | u32 mask = 1 << (d->irq - gc->irq_base); | ||
| 294 | |||
| 295 | irq_gc_lock(gc); | ||
| 296 | gc->mask_cache |= mask; | ||
| 297 | writel_relaxed(gc->mask_cache, mvebu_gpioreg_edge_mask(mvchip)); | ||
| 298 | irq_gc_unlock(gc); | ||
| 299 | } | ||
| 300 | |||
| 301 | static void mvebu_gpio_level_irq_mask(struct irq_data *d) | ||
| 302 | { | ||
| 303 | struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d); | ||
| 304 | struct mvebu_gpio_chip *mvchip = gc->private; | ||
| 305 | u32 mask = 1 << (d->irq - gc->irq_base); | ||
| 306 | |||
| 307 | irq_gc_lock(gc); | ||
| 308 | gc->mask_cache &= ~mask; | ||
| 309 | writel_relaxed(gc->mask_cache, mvebu_gpioreg_level_mask(mvchip)); | ||
| 310 | irq_gc_unlock(gc); | ||
| 311 | } | ||
| 312 | |||
| 313 | static void mvebu_gpio_level_irq_unmask(struct irq_data *d) | ||
| 314 | { | ||
| 315 | struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d); | ||
| 316 | struct mvebu_gpio_chip *mvchip = gc->private; | ||
| 317 | u32 mask = 1 << (d->irq - gc->irq_base); | ||
| 318 | |||
| 319 | irq_gc_lock(gc); | ||
| 320 | gc->mask_cache |= mask; | ||
| 321 | writel_relaxed(gc->mask_cache, mvebu_gpioreg_level_mask(mvchip)); | ||
| 322 | irq_gc_unlock(gc); | ||
| 323 | } | ||
| 324 | |||
| 325 | /***************************************************************************** | ||
| 326 | * MVEBU GPIO IRQ | ||
| 327 | * | ||
| 328 | * GPIO_IN_POL register controls whether GPIO_DATA_IN will hold the same | ||
| 329 | * value of the line or the opposite value. | ||
| 330 | * | ||
| 331 | * Level IRQ handlers: DATA_IN is used directly as cause register. | ||
| 332 | * Interrupt are masked by LEVEL_MASK registers. | ||
| 333 | * Edge IRQ handlers: Change in DATA_IN are latched in EDGE_CAUSE. | ||
| 334 | * Interrupt are masked by EDGE_MASK registers. | ||
| 335 | * Both-edge handlers: Similar to regular Edge handlers, but also swaps | ||
| 336 | * the polarity to catch the next line transaction. | ||
| 337 | * This is a race condition that might not perfectly | ||
| 338 | * work on some use cases. | ||
| 339 | * | ||
| 340 | * Every eight GPIO lines are grouped (OR'ed) before going up to main | ||
| 341 | * cause register. | ||
| 342 | * | ||
| 343 | * EDGE cause mask | ||
| 344 | * data-in /--------| |-----| |----\ | ||
| 345 | * -----| |----- ---- to main cause reg | ||
| 346 | * X \----------------| |----/ | ||
| 347 | * polarity LEVEL mask | ||
| 348 | * | ||
| 349 | ****************************************************************************/ | ||
| 350 | |||
| 351 | static int mvebu_gpio_irq_set_type(struct irq_data *d, unsigned int type) | ||
| 352 | { | ||
| 353 | struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d); | ||
| 354 | struct irq_chip_type *ct = irq_data_get_chip_type(d); | ||
| 355 | struct mvebu_gpio_chip *mvchip = gc->private; | ||
| 356 | int pin; | ||
| 357 | u32 u; | ||
| 358 | |||
| 359 | pin = d->hwirq; | ||
| 360 | |||
| 361 | u = readl_relaxed(mvebu_gpioreg_io_conf(mvchip)) & (1 << pin); | ||
| 362 | if (!u) { | ||
| 363 | return -EINVAL; | ||
| 364 | } | ||
| 365 | |||
| 366 | type &= IRQ_TYPE_SENSE_MASK; | ||
| 367 | if (type == IRQ_TYPE_NONE) | ||
| 368 | return -EINVAL; | ||
| 369 | |||
| 370 | /* Check if we need to change chip and handler */ | ||
| 371 | if (!(ct->type & type)) | ||
| 372 | if (irq_setup_alt_chip(d, type)) | ||
| 373 | return -EINVAL; | ||
| 374 | |||
| 375 | /* | ||
| 376 | * Configure interrupt polarity. | ||
| 377 | */ | ||
| 378 | switch(type) { | ||
| 379 | case IRQ_TYPE_EDGE_RISING: | ||
| 380 | case IRQ_TYPE_LEVEL_HIGH: | ||
| 381 | u = readl_relaxed(mvebu_gpioreg_in_pol(mvchip)); | ||
| 382 | u &= ~(1 << pin); | ||
| 383 | writel_relaxed(u, mvebu_gpioreg_in_pol(mvchip)); | ||
| 384 | case IRQ_TYPE_EDGE_FALLING: | ||
| 385 | case IRQ_TYPE_LEVEL_LOW: | ||
| 386 | u = readl_relaxed(mvebu_gpioreg_in_pol(mvchip)); | ||
| 387 | u |= 1 << pin; | ||
| 388 | writel_relaxed(u, mvebu_gpioreg_in_pol(mvchip)); | ||
| 389 | case IRQ_TYPE_EDGE_BOTH: { | ||
| 390 | u32 v; | ||
| 391 | |||
| 392 | v = readl_relaxed(mvebu_gpioreg_in_pol(mvchip)) ^ | ||
| 393 | readl_relaxed(mvebu_gpioreg_data_in(mvchip)); | ||
| 394 | |||
| 395 | /* | ||
| 396 | * set initial polarity based on current input level | ||
| 397 | */ | ||
| 398 | u = readl_relaxed(mvebu_gpioreg_in_pol(mvchip)); | ||
| 399 | if (v & (1 << pin)) | ||
| 400 | u |= 1 << pin; /* falling */ | ||
| 401 | else | ||
| 402 | u &= ~(1 << pin); /* rising */ | ||
| 403 | writel_relaxed(u, mvebu_gpioreg_in_pol(mvchip)); | ||
| 404 | } | ||
| 405 | } | ||
| 406 | return 0; | ||
| 407 | } | ||
| 408 | |||
| 409 | static void mvebu_gpio_irq_handler(unsigned int irq, struct irq_desc *desc) | ||
| 410 | { | ||
| 411 | struct mvebu_gpio_chip *mvchip = irq_get_handler_data(irq); | ||
| 412 | u32 cause, type; | ||
| 413 | int i; | ||
| 414 | |||
| 415 | if (mvchip == NULL) | ||
| 416 | return; | ||
| 417 | |||
| 418 | cause = readl_relaxed(mvebu_gpioreg_data_in(mvchip)) & | ||
| 419 | readl_relaxed(mvebu_gpioreg_level_mask(mvchip)); | ||
| 420 | cause |= readl_relaxed(mvebu_gpioreg_edge_cause(mvchip)) & | ||
| 421 | readl_relaxed(mvebu_gpioreg_edge_mask(mvchip)); | ||
| 422 | |||
| 423 | for (i = 0; i < mvchip->chip.ngpio; i++) { | ||
| 424 | int irq; | ||
| 425 | |||
| 426 | irq = mvchip->irqbase + i; | ||
| 427 | |||
| 428 | if (!(cause & (1 << i))) | ||
| 429 | continue; | ||
| 430 | |||
| 431 | type = irqd_get_trigger_type(irq_get_irq_data(irq)); | ||
| 432 | if ((type & IRQ_TYPE_SENSE_MASK) == IRQ_TYPE_EDGE_BOTH) { | ||
| 433 | /* Swap polarity (race with GPIO line) */ | ||
| 434 | u32 polarity; | ||
| 435 | |||
| 436 | polarity = readl_relaxed(mvebu_gpioreg_in_pol(mvchip)); | ||
| 437 | polarity ^= 1 << i; | ||
| 438 | writel_relaxed(polarity, mvebu_gpioreg_in_pol(mvchip)); | ||
| 439 | } | ||
| 440 | generic_handle_irq(irq); | ||
| 441 | } | ||
| 442 | } | ||
| 443 | |||
| 444 | static struct platform_device_id mvebu_gpio_ids[] = { | ||
| 445 | { | ||
| 446 | .name = "orion-gpio", | ||
| 447 | }, { | ||
| 448 | .name = "mv78200-gpio", | ||
| 449 | }, { | ||
| 450 | .name = "armadaxp-gpio", | ||
| 451 | }, { | ||
| 452 | /* sentinel */ | ||
| 453 | }, | ||
| 454 | }; | ||
| 455 | MODULE_DEVICE_TABLE(platform, mvebu_gpio_ids); | ||
| 456 | |||
| 457 | static struct of_device_id mvebu_gpio_of_match[] __devinitdata = { | ||
| 458 | { | ||
| 459 | .compatible = "marvell,orion-gpio", | ||
| 460 | .data = (void*) MVEBU_GPIO_SOC_VARIANT_ORION, | ||
| 461 | }, | ||
| 462 | { | ||
| 463 | .compatible = "marvell,mv78200-gpio", | ||
| 464 | .data = (void*) MVEBU_GPIO_SOC_VARIANT_MV78200, | ||
| 465 | }, | ||
| 466 | { | ||
| 467 | .compatible = "marvell,armadaxp-gpio", | ||
| 468 | .data = (void*) MVEBU_GPIO_SOC_VARIANT_ARMADAXP, | ||
| 469 | }, | ||
| 470 | { | ||
| 471 | /* sentinel */ | ||
| 472 | }, | ||
| 473 | }; | ||
| 474 | MODULE_DEVICE_TABLE(of, mvebu_gpio_of_match); | ||
| 475 | |||
| 476 | static int __devinit mvebu_gpio_probe(struct platform_device *pdev) | ||
| 477 | { | ||
| 478 | struct mvebu_gpio_chip *mvchip; | ||
| 479 | const struct of_device_id *match; | ||
| 480 | struct device_node *np = pdev->dev.of_node; | ||
| 481 | struct resource *res; | ||
| 482 | struct irq_chip_generic *gc; | ||
| 483 | struct irq_chip_type *ct; | ||
| 484 | unsigned int ngpios; | ||
| 485 | int soc_variant; | ||
| 486 | int i, cpu, id; | ||
| 487 | |||
| 488 | match = of_match_device(mvebu_gpio_of_match, &pdev->dev); | ||
| 489 | if (match) | ||
| 490 | soc_variant = (int) match->data; | ||
| 491 | else | ||
| 492 | soc_variant = MVEBU_GPIO_SOC_VARIANT_ORION; | ||
| 493 | |||
| 494 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
| 495 | if (! res) { | ||
| 496 | dev_err(&pdev->dev, "Cannot get memory resource\n"); | ||
| 497 | return -ENODEV; | ||
| 498 | } | ||
| 499 | |||
| 500 | mvchip = devm_kzalloc(&pdev->dev, sizeof(struct mvebu_gpio_chip), GFP_KERNEL); | ||
| 501 | if (! mvchip){ | ||
| 502 | dev_err(&pdev->dev, "Cannot allocate memory\n"); | ||
| 503 | return -ENOMEM; | ||
| 504 | } | ||
| 505 | |||
| 506 | if (of_property_read_u32(pdev->dev.of_node, "ngpios", &ngpios)) { | ||
| 507 | dev_err(&pdev->dev, "Missing ngpios OF property\n"); | ||
| 508 | return -ENODEV; | ||
| 509 | } | ||
| 510 | |||
| 511 | id = of_alias_get_id(pdev->dev.of_node, "gpio"); | ||
| 512 | if (id < 0) { | ||
| 513 | dev_err(&pdev->dev, "Couldn't get OF id\n"); | ||
| 514 | return id; | ||
| 515 | } | ||
| 516 | |||
| 517 | mvchip->soc_variant = soc_variant; | ||
| 518 | mvchip->chip.label = dev_name(&pdev->dev); | ||
| 519 | mvchip->chip.dev = &pdev->dev; | ||
| 520 | mvchip->chip.request = mvebu_gpio_request; | ||
| 521 | mvchip->chip.direction_input = mvebu_gpio_direction_input; | ||
| 522 | mvchip->chip.get = mvebu_gpio_get; | ||
| 523 | mvchip->chip.direction_output = mvebu_gpio_direction_output; | ||
| 524 | mvchip->chip.set = mvebu_gpio_set; | ||
| 525 | mvchip->chip.to_irq = mvebu_gpio_to_irq; | ||
| 526 | mvchip->chip.base = id * MVEBU_MAX_GPIO_PER_BANK; | ||
| 527 | mvchip->chip.ngpio = ngpios; | ||
| 528 | mvchip->chip.can_sleep = 0; | ||
| 529 | #ifdef CONFIG_OF | ||
| 530 | mvchip->chip.of_node = np; | ||
| 531 | #endif | ||
| 532 | |||
| 533 | spin_lock_init(&mvchip->lock); | ||
| 534 | mvchip->membase = devm_request_and_ioremap(&pdev->dev, res); | ||
| 535 | if (! mvchip->membase) { | ||
| 536 | dev_err(&pdev->dev, "Cannot ioremap\n"); | ||
| 537 | kfree(mvchip->chip.label); | ||
| 538 | return -ENOMEM; | ||
| 539 | } | ||
| 540 | |||
| 541 | /* The Armada XP has a second range of registers for the | ||
| 542 | * per-CPU registers */ | ||
| 543 | if (soc_variant == MVEBU_GPIO_SOC_VARIANT_ARMADAXP) { | ||
| 544 | res = platform_get_resource(pdev, IORESOURCE_MEM, 1); | ||
| 545 | if (! res) { | ||
| 546 | dev_err(&pdev->dev, "Cannot get memory resource\n"); | ||
| 547 | kfree(mvchip->chip.label); | ||
| 548 | return -ENODEV; | ||
| 549 | } | ||
| 550 | |||
| 551 | mvchip->percpu_membase = devm_request_and_ioremap(&pdev->dev, res); | ||
| 552 | if (! mvchip->percpu_membase) { | ||
| 553 | dev_err(&pdev->dev, "Cannot ioremap\n"); | ||
| 554 | kfree(mvchip->chip.label); | ||
| 555 | return -ENOMEM; | ||
| 556 | } | ||
| 557 | } | ||
| 558 | |||
| 559 | /* | ||
| 560 | * Mask and clear GPIO interrupts. | ||
| 561 | */ | ||
| 562 | switch(soc_variant) { | ||
| 563 | case MVEBU_GPIO_SOC_VARIANT_ORION: | ||
| 564 | writel_relaxed(0, mvchip->membase + GPIO_EDGE_CAUSE_OFF); | ||
| 565 | writel_relaxed(0, mvchip->membase + GPIO_EDGE_MASK_OFF); | ||
| 566 | writel_relaxed(0, mvchip->membase + GPIO_LEVEL_MASK_OFF); | ||
| 567 | break; | ||
| 568 | case MVEBU_GPIO_SOC_VARIANT_MV78200: | ||
| 569 | writel_relaxed(0, mvchip->membase + GPIO_EDGE_CAUSE_OFF); | ||
| 570 | for (cpu = 0; cpu < 2; cpu++) { | ||
| 571 | writel_relaxed(0, mvchip->membase + | ||
| 572 | GPIO_EDGE_MASK_MV78200_OFF(cpu)); | ||
| 573 | writel_relaxed(0, mvchip->membase + | ||
| 574 | GPIO_LEVEL_MASK_MV78200_OFF(cpu)); | ||
| 575 | } | ||
| 576 | break; | ||
| 577 | case MVEBU_GPIO_SOC_VARIANT_ARMADAXP: | ||
| 578 | writel_relaxed(0, mvchip->membase + GPIO_EDGE_CAUSE_OFF); | ||
| 579 | writel_relaxed(0, mvchip->membase + GPIO_EDGE_MASK_OFF); | ||
| 580 | writel_relaxed(0, mvchip->membase + GPIO_LEVEL_MASK_OFF); | ||
| 581 | for (cpu = 0; cpu < 4; cpu++) { | ||
| 582 | writel_relaxed(0, mvchip->percpu_membase + | ||
| 583 | GPIO_EDGE_CAUSE_ARMADAXP_OFF(cpu)); | ||
| 584 | writel_relaxed(0, mvchip->percpu_membase + | ||
| 585 | GPIO_EDGE_MASK_ARMADAXP_OFF(cpu)); | ||
| 586 | writel_relaxed(0, mvchip->percpu_membase + | ||
| 587 | GPIO_LEVEL_MASK_ARMADAXP_OFF(cpu)); | ||
| 588 | } | ||
| 589 | break; | ||
| 590 | default: | ||
| 591 | BUG(); | ||
| 592 | } | ||
| 593 | |||
| 594 | gpiochip_add(&mvchip->chip); | ||
| 595 | |||
| 596 | /* Some gpio controllers do not provide irq support */ | ||
| 597 | if (!of_irq_count(np)) | ||
| 598 | return 0; | ||
| 599 | |||
| 600 | /* Setup the interrupt handlers. Each chip can have up to 4 | ||
| 601 | * interrupt handlers, with each handler dealing with 8 GPIO | ||
| 602 | * pins. */ | ||
| 603 | for (i = 0; i < 4; i++) { | ||
| 604 | int irq; | ||
| 605 | irq = platform_get_irq(pdev, i); | ||
| 606 | if (irq < 0) | ||
| 607 | continue; | ||
| 608 | irq_set_handler_data(irq, mvchip); | ||
| 609 | irq_set_chained_handler(irq, mvebu_gpio_irq_handler); | ||
| 610 | } | ||
| 611 | |||
| 612 | mvchip->irqbase = irq_alloc_descs(-1, 0, ngpios, -1); | ||
| 613 | if (mvchip->irqbase < 0) { | ||
| 614 | dev_err(&pdev->dev, "no irqs\n"); | ||
| 615 | kfree(mvchip->chip.label); | ||
| 616 | return -ENOMEM; | ||
| 617 | } | ||
| 618 | |||
| 619 | gc = irq_alloc_generic_chip("mvebu_gpio_irq", 2, mvchip->irqbase, | ||
| 620 | mvchip->membase, handle_level_irq); | ||
| 621 | if (! gc) { | ||
| 622 | dev_err(&pdev->dev, "Cannot allocate generic irq_chip\n"); | ||
| 623 | kfree(mvchip->chip.label); | ||
| 624 | return -ENOMEM; | ||
| 625 | } | ||
| 626 | |||
| 627 | gc->private = mvchip; | ||
| 628 | ct = &gc->chip_types[0]; | ||
| 629 | ct->type = IRQ_TYPE_LEVEL_HIGH | IRQ_TYPE_LEVEL_LOW; | ||
| 630 | ct->chip.irq_mask = mvebu_gpio_level_irq_mask; | ||
| 631 | ct->chip.irq_unmask = mvebu_gpio_level_irq_unmask; | ||
| 632 | ct->chip.irq_set_type = mvebu_gpio_irq_set_type; | ||
| 633 | ct->chip.name = mvchip->chip.label; | ||
| 634 | |||
| 635 | ct = &gc->chip_types[1]; | ||
| 636 | ct->type = IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING; | ||
| 637 | ct->chip.irq_ack = mvebu_gpio_irq_ack; | ||
| 638 | ct->chip.irq_mask = mvebu_gpio_edge_irq_mask; | ||
| 639 | ct->chip.irq_unmask = mvebu_gpio_edge_irq_unmask; | ||
| 640 | ct->chip.irq_set_type = mvebu_gpio_irq_set_type; | ||
| 641 | ct->handler = handle_edge_irq; | ||
| 642 | ct->chip.name = mvchip->chip.label; | ||
| 643 | |||
| 644 | irq_setup_generic_chip(gc, IRQ_MSK(ngpios), IRQ_GC_INIT_MASK_CACHE, | ||
| 645 | IRQ_NOREQUEST, IRQ_LEVEL | IRQ_NOPROBE); | ||
| 646 | |||
| 647 | /* Setup irq domain on top of the generic chip. */ | ||
| 648 | mvchip->domain = irq_domain_add_legacy(np, mvchip->chip.ngpio, | ||
| 649 | mvchip->irqbase, 0, | ||
| 650 | &irq_domain_simple_ops, | ||
| 651 | mvchip); | ||
| 652 | if (!mvchip->domain) { | ||
| 653 | dev_err(&pdev->dev, "couldn't allocate irq domain %s (DT).\n", | ||
| 654 | mvchip->chip.label); | ||
| 655 | irq_remove_generic_chip(gc, IRQ_MSK(ngpios), IRQ_NOREQUEST, | ||
| 656 | IRQ_LEVEL | IRQ_NOPROBE); | ||
| 657 | kfree(gc); | ||
| 658 | kfree(mvchip->chip.label); | ||
| 659 | return -ENODEV; | ||
| 660 | } | ||
| 661 | |||
| 662 | return 0; | ||
| 663 | } | ||
| 664 | |||
| 665 | static struct platform_driver mvebu_gpio_driver = { | ||
| 666 | .driver = { | ||
| 667 | .name = "mvebu-gpio", | ||
| 668 | .owner = THIS_MODULE, | ||
| 669 | .of_match_table = mvebu_gpio_of_match, | ||
| 670 | }, | ||
| 671 | .probe = mvebu_gpio_probe, | ||
| 672 | .id_table = mvebu_gpio_ids, | ||
| 673 | }; | ||
| 674 | |||
| 675 | static int __init mvebu_gpio_init(void) | ||
| 676 | { | ||
| 677 | return platform_driver_register(&mvebu_gpio_driver); | ||
| 678 | } | ||
| 679 | postcore_initcall(mvebu_gpio_init); | ||
diff --git a/drivers/pinctrl/Kconfig b/drivers/pinctrl/Kconfig index 54e3588bef62..a75414496369 100644 --- a/drivers/pinctrl/Kconfig +++ b/drivers/pinctrl/Kconfig | |||
| @@ -145,6 +145,28 @@ config PINCTRL_COH901 | |||
| 145 | COH 901 335 and COH 901 571/3. They contain 3, 5 or 7 | 145 | COH 901 335 and COH 901 571/3. They contain 3, 5 or 7 |
| 146 | ports of 8 GPIO pins each. | 146 | ports of 8 GPIO pins each. |
| 147 | 147 | ||
| 148 | config PINCTRL_MVEBU | ||
| 149 | bool | ||
| 150 | depends on ARCH_MVEBU | ||
| 151 | select PINMUX | ||
| 152 | select PINCONF | ||
| 153 | |||
| 154 | config PINCTRL_DOVE | ||
| 155 | bool | ||
| 156 | select PINCTRL_MVEBU | ||
| 157 | |||
| 158 | config PINCTRL_KIRKWOOD | ||
| 159 | bool | ||
| 160 | select PINCTRL_MVEBU | ||
| 161 | |||
| 162 | config PINCTRL_ARMADA_370 | ||
| 163 | bool | ||
| 164 | select PINCTRL_MVEBU | ||
| 165 | |||
| 166 | config PINCTRL_ARMADA_XP | ||
| 167 | bool | ||
| 168 | select PINCTRL_MVEBU | ||
| 169 | |||
| 148 | source "drivers/pinctrl/spear/Kconfig" | 170 | source "drivers/pinctrl/spear/Kconfig" |
| 149 | 171 | ||
| 150 | endmenu | 172 | endmenu |
diff --git a/drivers/pinctrl/Makefile b/drivers/pinctrl/Makefile index f40b1f81ff2c..f2ea0504efc7 100644 --- a/drivers/pinctrl/Makefile +++ b/drivers/pinctrl/Makefile | |||
| @@ -29,5 +29,10 @@ obj-$(CONFIG_PINCTRL_TEGRA20) += pinctrl-tegra20.o | |||
| 29 | obj-$(CONFIG_PINCTRL_TEGRA30) += pinctrl-tegra30.o | 29 | obj-$(CONFIG_PINCTRL_TEGRA30) += pinctrl-tegra30.o |
| 30 | obj-$(CONFIG_PINCTRL_U300) += pinctrl-u300.o | 30 | obj-$(CONFIG_PINCTRL_U300) += pinctrl-u300.o |
| 31 | obj-$(CONFIG_PINCTRL_COH901) += pinctrl-coh901.o | 31 | obj-$(CONFIG_PINCTRL_COH901) += pinctrl-coh901.o |
| 32 | obj-$(CONFIG_PINCTRL_MVEBU) += pinctrl-mvebu.o | ||
| 33 | obj-$(CONFIG_PINCTRL_DOVE) += pinctrl-dove.o | ||
| 34 | obj-$(CONFIG_PINCTRL_KIRKWOOD) += pinctrl-kirkwood.o | ||
| 35 | obj-$(CONFIG_PINCTRL_ARMADA_370) += pinctrl-armada-370.o | ||
| 36 | obj-$(CONFIG_PINCTRL_ARMADA_XP) += pinctrl-armada-xp.o | ||
| 32 | 37 | ||
| 33 | obj-$(CONFIG_PLAT_SPEAR) += spear/ | 38 | obj-$(CONFIG_PLAT_SPEAR) += spear/ |
diff --git a/drivers/pinctrl/pinctrl-armada-370.c b/drivers/pinctrl/pinctrl-armada-370.c new file mode 100644 index 000000000000..c907647de6ad --- /dev/null +++ b/drivers/pinctrl/pinctrl-armada-370.c | |||
| @@ -0,0 +1,421 @@ | |||
| 1 | /* | ||
| 2 | * Marvell Armada 370 pinctrl driver based on mvebu pinctrl core | ||
| 3 | * | ||
| 4 | * Copyright (C) 2012 Marvell | ||
| 5 | * | ||
| 6 | * Thomas Petazzoni <thomas.petazzoni@free-electrons.com> | ||
| 7 | * | ||
| 8 | * This program is free software; you can redistribute it and/or modify | ||
| 9 | * it under the terms of the GNU General Public License as published by | ||
| 10 | * the Free Software Foundation; either version 2 of the License, or | ||
| 11 | * (at your option) any later version. | ||
| 12 | */ | ||
| 13 | |||
| 14 | #include <linux/err.h> | ||
| 15 | #include <linux/init.h> | ||
| 16 | #include <linux/io.h> | ||
| 17 | #include <linux/module.h> | ||
| 18 | #include <linux/platform_device.h> | ||
| 19 | #include <linux/clk.h> | ||
| 20 | #include <linux/of.h> | ||
| 21 | #include <linux/of_device.h> | ||
| 22 | #include <linux/pinctrl/pinctrl.h> | ||
| 23 | |||
| 24 | #include "pinctrl-mvebu.h" | ||
| 25 | |||
| 26 | static struct mvebu_mpp_mode mv88f6710_mpp_modes[] = { | ||
| 27 | MPP_MODE(0, | ||
| 28 | MPP_FUNCTION(0x0, "gpio", NULL), | ||
| 29 | MPP_FUNCTION(0x1, "uart0", "rxd")), | ||
| 30 | MPP_MODE(1, | ||
| 31 | MPP_FUNCTION(0x0, "gpo", NULL), | ||
| 32 | MPP_FUNCTION(0x1, "uart0", "txd")), | ||
| 33 | MPP_MODE(2, | ||
| 34 | MPP_FUNCTION(0x0, "gpio", NULL), | ||
| 35 | MPP_FUNCTION(0x1, "i2c0", "sck"), | ||
| 36 | MPP_FUNCTION(0x2, "uart0", "txd")), | ||
| 37 | MPP_MODE(3, | ||
| 38 | MPP_FUNCTION(0x0, "gpio", NULL), | ||
| 39 | MPP_FUNCTION(0x1, "i2c0", "sda"), | ||
| 40 | MPP_FUNCTION(0x2, "uart0", "rxd")), | ||
| 41 | MPP_MODE(4, | ||
| 42 | MPP_FUNCTION(0x0, "gpio", NULL), | ||
| 43 | MPP_FUNCTION(0x1, "cpu_pd", "vdd")), | ||
| 44 | MPP_MODE(5, | ||
| 45 | MPP_FUNCTION(0x0, "gpo", NULL), | ||
| 46 | MPP_FUNCTION(0x1, "ge0", "txclko"), | ||
| 47 | MPP_FUNCTION(0x2, "uart1", "txd"), | ||
| 48 | MPP_FUNCTION(0x4, "spi1", "clk"), | ||
| 49 | MPP_FUNCTION(0x5, "audio", "mclk")), | ||
| 50 | MPP_MODE(6, | ||
| 51 | MPP_FUNCTION(0x0, "gpio", NULL), | ||
| 52 | MPP_FUNCTION(0x1, "ge0", "txd0"), | ||
| 53 | MPP_FUNCTION(0x2, "sata0", "prsnt"), | ||
| 54 | MPP_FUNCTION(0x4, "tdm", "rst"), | ||
| 55 | MPP_FUNCTION(0x5, "audio", "sdo")), | ||
| 56 | MPP_MODE(7, | ||
| 57 | MPP_FUNCTION(0x0, "gpo", NULL), | ||
| 58 | MPP_FUNCTION(0x1, "ge0", "txd1"), | ||
| 59 | MPP_FUNCTION(0x4, "tdm", "tdx"), | ||
| 60 | MPP_FUNCTION(0x5, "audio", "lrclk")), | ||
| 61 | MPP_MODE(8, | ||
| 62 | MPP_FUNCTION(0x0, "gpio", NULL), | ||
| 63 | MPP_FUNCTION(0x1, "ge0", "txd2"), | ||
| 64 | MPP_FUNCTION(0x2, "uart0", "rts"), | ||
| 65 | MPP_FUNCTION(0x4, "tdm", "drx"), | ||
| 66 | MPP_FUNCTION(0x5, "audio", "bclk")), | ||
| 67 | MPP_MODE(9, | ||
| 68 | MPP_FUNCTION(0x0, "gpo", NULL), | ||
| 69 | MPP_FUNCTION(0x1, "ge0", "txd3"), | ||
| 70 | MPP_FUNCTION(0x2, "uart1", "txd"), | ||
| 71 | MPP_FUNCTION(0x3, "sd0", "clk"), | ||
| 72 | MPP_FUNCTION(0x5, "audio", "spdifo")), | ||
| 73 | MPP_MODE(10, | ||
| 74 | MPP_FUNCTION(0x0, "gpio", NULL), | ||
| 75 | MPP_FUNCTION(0x1, "ge0", "txctl"), | ||
| 76 | MPP_FUNCTION(0x2, "uart0", "cts"), | ||
| 77 | MPP_FUNCTION(0x4, "tdm", "fsync"), | ||
| 78 | MPP_FUNCTION(0x5, "audio", "sdi")), | ||
| 79 | MPP_MODE(11, | ||
| 80 | MPP_FUNCTION(0x0, "gpio", NULL), | ||
| 81 | MPP_FUNCTION(0x1, "ge0", "rxd0"), | ||
| 82 | MPP_FUNCTION(0x2, "uart1", "rxd"), | ||
| 83 | MPP_FUNCTION(0x3, "sd0", "cmd"), | ||
| 84 | MPP_FUNCTION(0x4, "spi0", "cs1"), | ||
| 85 | MPP_FUNCTION(0x5, "sata1", "prsnt"), | ||
| 86 | MPP_FUNCTION(0x6, "spi1", "cs1")), | ||
| 87 | MPP_MODE(12, | ||
| 88 | MPP_FUNCTION(0x0, "gpio", NULL), | ||
| 89 | MPP_FUNCTION(0x1, "ge0", "rxd1"), | ||
| 90 | MPP_FUNCTION(0x2, "i2c1", "sda"), | ||
| 91 | MPP_FUNCTION(0x3, "sd0", "d0"), | ||
| 92 | MPP_FUNCTION(0x4, "spi1", "cs0"), | ||
| 93 | MPP_FUNCTION(0x5, "audio", "spdifi")), | ||
| 94 | MPP_MODE(13, | ||
| 95 | MPP_FUNCTION(0x0, "gpio", NULL), | ||
| 96 | MPP_FUNCTION(0x1, "ge0", "rxd2"), | ||
| 97 | MPP_FUNCTION(0x2, "i2c1", "sck"), | ||
| 98 | MPP_FUNCTION(0x3, "sd0", "d1"), | ||
| 99 | MPP_FUNCTION(0x4, "tdm", "pclk"), | ||
| 100 | MPP_FUNCTION(0x5, "audio", "rmclk")), | ||
| 101 | MPP_MODE(14, | ||
| 102 | MPP_FUNCTION(0x0, "gpio", NULL), | ||
| 103 | MPP_FUNCTION(0x1, "ge0", "rxd3"), | ||
| 104 | MPP_FUNCTION(0x2, "pcie", "clkreq0"), | ||
| 105 | MPP_FUNCTION(0x3, "sd0", "d2"), | ||
| 106 | MPP_FUNCTION(0x4, "spi1", "mosi"), | ||
| 107 | MPP_FUNCTION(0x5, "spi0", "cs2")), | ||
| 108 | MPP_MODE(15, | ||
| 109 | MPP_FUNCTION(0x0, "gpio", NULL), | ||
| 110 | MPP_FUNCTION(0x1, "ge0", "rxctl"), | ||
| 111 | MPP_FUNCTION(0x2, "pcie", "clkreq1"), | ||
| 112 | MPP_FUNCTION(0x3, "sd0", "d3"), | ||
| 113 | MPP_FUNCTION(0x4, "spi1", "miso"), | ||
| 114 | MPP_FUNCTION(0x5, "spi0", "cs3")), | ||
| 115 | MPP_MODE(16, | ||
| 116 | MPP_FUNCTION(0x0, "gpio", NULL), | ||
| 117 | MPP_FUNCTION(0x1, "ge0", "rxclk"), | ||
| 118 | MPP_FUNCTION(0x2, "uart1", "rxd"), | ||
| 119 | MPP_FUNCTION(0x4, "tdm", "int"), | ||
| 120 | MPP_FUNCTION(0x5, "audio", "extclk")), | ||
| 121 | MPP_MODE(17, | ||
| 122 | MPP_FUNCTION(0x0, "gpo", NULL), | ||
| 123 | MPP_FUNCTION(0x1, "ge", "mdc")), | ||
| 124 | MPP_MODE(18, | ||
| 125 | MPP_FUNCTION(0x0, "gpio", NULL), | ||
| 126 | MPP_FUNCTION(0x1, "ge", "mdio")), | ||
| 127 | MPP_MODE(19, | ||
| 128 | MPP_FUNCTION(0x0, "gpio", NULL), | ||
| 129 | MPP_FUNCTION(0x1, "ge0", "txclk"), | ||
| 130 | MPP_FUNCTION(0x2, "ge1", "txclkout"), | ||
| 131 | MPP_FUNCTION(0x4, "tdm", "pclk")), | ||
| 132 | MPP_MODE(20, | ||
| 133 | MPP_FUNCTION(0x0, "gpo", NULL), | ||
| 134 | MPP_FUNCTION(0x1, "ge0", "txd4"), | ||
| 135 | MPP_FUNCTION(0x2, "ge1", "txd0")), | ||
| 136 | MPP_MODE(21, | ||
| 137 | MPP_FUNCTION(0x0, "gpo", NULL), | ||
| 138 | MPP_FUNCTION(0x1, "ge0", "txd5"), | ||
| 139 | MPP_FUNCTION(0x2, "ge1", "txd1"), | ||
| 140 | MPP_FUNCTION(0x4, "uart1", "txd")), | ||
| 141 | MPP_MODE(22, | ||
| 142 | MPP_FUNCTION(0x0, "gpo", NULL), | ||
| 143 | MPP_FUNCTION(0x1, "ge0", "txd6"), | ||
| 144 | MPP_FUNCTION(0x2, "ge1", "txd2"), | ||
| 145 | MPP_FUNCTION(0x4, "uart0", "rts")), | ||
| 146 | MPP_MODE(23, | ||
| 147 | MPP_FUNCTION(0x0, "gpo", NULL), | ||
| 148 | MPP_FUNCTION(0x1, "ge0", "txd7"), | ||
| 149 | MPP_FUNCTION(0x2, "ge1", "txd3"), | ||
| 150 | MPP_FUNCTION(0x4, "spi1", "mosi")), | ||
| 151 | MPP_MODE(24, | ||
| 152 | MPP_FUNCTION(0x0, "gpio", NULL), | ||
| 153 | MPP_FUNCTION(0x1, "ge0", "col"), | ||
| 154 | MPP_FUNCTION(0x2, "ge1", "txctl"), | ||
| 155 | MPP_FUNCTION(0x4, "spi1", "cs0")), | ||
| 156 | MPP_MODE(25, | ||
| 157 | MPP_FUNCTION(0x0, "gpio", NULL), | ||
| 158 | MPP_FUNCTION(0x1, "ge0", "rxerr"), | ||
| 159 | MPP_FUNCTION(0x2, "ge1", "rxd0"), | ||
| 160 | MPP_FUNCTION(0x4, "uart1", "rxd")), | ||
| 161 | MPP_MODE(26, | ||
| 162 | MPP_FUNCTION(0x0, "gpio", NULL), | ||
| 163 | MPP_FUNCTION(0x1, "ge0", "crs"), | ||
| 164 | MPP_FUNCTION(0x2, "ge1", "rxd1"), | ||
| 165 | MPP_FUNCTION(0x4, "spi1", "miso")), | ||
| 166 | MPP_MODE(27, | ||
| 167 | MPP_FUNCTION(0x0, "gpio", NULL), | ||
| 168 | MPP_FUNCTION(0x1, "ge0", "rxd4"), | ||
| 169 | MPP_FUNCTION(0x2, "ge1", "rxd2"), | ||
| 170 | MPP_FUNCTION(0x4, "uart0", "cts")), | ||
| 171 | MPP_MODE(28, | ||
| 172 | MPP_FUNCTION(0x0, "gpio", NULL), | ||
| 173 | MPP_FUNCTION(0x1, "ge0", "rxd5"), | ||
| 174 | MPP_FUNCTION(0x2, "ge1", "rxd3")), | ||
| 175 | MPP_MODE(29, | ||
| 176 | MPP_FUNCTION(0x0, "gpio", NULL), | ||
| 177 | MPP_FUNCTION(0x1, "ge0", "rxd6"), | ||
| 178 | MPP_FUNCTION(0x2, "ge1", "rxctl"), | ||
| 179 | MPP_FUNCTION(0x4, "i2c1", "sda")), | ||
| 180 | MPP_MODE(30, | ||
| 181 | MPP_FUNCTION(0x0, "gpio", NULL), | ||
| 182 | MPP_FUNCTION(0x1, "ge0", "rxd7"), | ||
| 183 | MPP_FUNCTION(0x2, "ge1", "rxclk"), | ||
| 184 | MPP_FUNCTION(0x4, "i2c1", "sck")), | ||
| 185 | MPP_MODE(31, | ||
| 186 | MPP_FUNCTION(0x0, "gpio", NULL), | ||
| 187 | MPP_FUNCTION(0x3, "tclk", NULL), | ||
| 188 | MPP_FUNCTION(0x4, "ge0", "txerr")), | ||
| 189 | MPP_MODE(32, | ||
| 190 | MPP_FUNCTION(0x0, "gpio", NULL), | ||
| 191 | MPP_FUNCTION(0x1, "spi0", "cs0")), | ||
| 192 | MPP_MODE(33, | ||
| 193 | MPP_FUNCTION(0x0, "gpio", NULL), | ||
| 194 | MPP_FUNCTION(0x1, "dev", "bootcs"), | ||
| 195 | MPP_FUNCTION(0x2, "spi0", "cs0")), | ||
| 196 | MPP_MODE(34, | ||
| 197 | MPP_FUNCTION(0x0, "gpo", NULL), | ||
| 198 | MPP_FUNCTION(0x1, "dev", "wen0"), | ||
| 199 | MPP_FUNCTION(0x2, "spi0", "mosi")), | ||
| 200 | MPP_MODE(35, | ||
| 201 | MPP_FUNCTION(0x0, "gpo", NULL), | ||
| 202 | MPP_FUNCTION(0x1, "dev", "oen"), | ||
| 203 | MPP_FUNCTION(0x2, "spi0", "sck")), | ||
| 204 | MPP_MODE(36, | ||
| 205 | MPP_FUNCTION(0x0, "gpo", NULL), | ||
| 206 | MPP_FUNCTION(0x1, "dev", "a1"), | ||
| 207 | MPP_FUNCTION(0x2, "spi0", "miso")), | ||
| 208 | MPP_MODE(37, | ||
| 209 | MPP_FUNCTION(0x0, "gpo", NULL), | ||
| 210 | MPP_FUNCTION(0x1, "dev", "a0"), | ||
| 211 | MPP_FUNCTION(0x2, "sata0", "prsnt")), | ||
| 212 | MPP_MODE(38, | ||
| 213 | MPP_FUNCTION(0x0, "gpio", NULL), | ||
| 214 | MPP_FUNCTION(0x1, "dev", "ready"), | ||
| 215 | MPP_FUNCTION(0x2, "uart1", "cts"), | ||
| 216 | MPP_FUNCTION(0x3, "uart0", "cts")), | ||
| 217 | MPP_MODE(39, | ||
| 218 | MPP_FUNCTION(0x0, "gpo", NULL), | ||
| 219 | MPP_FUNCTION(0x1, "dev", "ad0"), | ||
| 220 | MPP_FUNCTION(0x2, "audio", "spdifo")), | ||
| 221 | MPP_MODE(40, | ||
| 222 | MPP_FUNCTION(0x0, "gpio", NULL), | ||
| 223 | MPP_FUNCTION(0x1, "dev", "ad1"), | ||
| 224 | MPP_FUNCTION(0x2, "uart1", "rts"), | ||
| 225 | MPP_FUNCTION(0x3, "uart0", "rts")), | ||
| 226 | MPP_MODE(41, | ||
| 227 | MPP_FUNCTION(0x0, "gpio", NULL), | ||
| 228 | MPP_FUNCTION(0x1, "dev", "ad2"), | ||
| 229 | MPP_FUNCTION(0x2, "uart1", "rxd")), | ||
| 230 | MPP_MODE(42, | ||
| 231 | MPP_FUNCTION(0x0, "gpo", NULL), | ||
| 232 | MPP_FUNCTION(0x1, "dev", "ad3"), | ||
| 233 | MPP_FUNCTION(0x2, "uart1", "txd")), | ||
| 234 | MPP_MODE(43, | ||
| 235 | MPP_FUNCTION(0x0, "gpo", NULL), | ||
| 236 | MPP_FUNCTION(0x1, "dev", "ad4"), | ||
| 237 | MPP_FUNCTION(0x2, "audio", "bclk")), | ||
| 238 | MPP_MODE(44, | ||
| 239 | MPP_FUNCTION(0x0, "gpo", NULL), | ||
| 240 | MPP_FUNCTION(0x1, "dev", "ad5"), | ||
| 241 | MPP_FUNCTION(0x2, "audio", "mclk")), | ||
| 242 | MPP_MODE(45, | ||
| 243 | MPP_FUNCTION(0x0, "gpo", NULL), | ||
| 244 | MPP_FUNCTION(0x1, "dev", "ad6"), | ||
| 245 | MPP_FUNCTION(0x2, "audio", "lrclk")), | ||
| 246 | MPP_MODE(46, | ||
| 247 | MPP_FUNCTION(0x0, "gpo", NULL), | ||
| 248 | MPP_FUNCTION(0x1, "dev", "ad7"), | ||
| 249 | MPP_FUNCTION(0x2, "audio", "sdo")), | ||
| 250 | MPP_MODE(47, | ||
| 251 | MPP_FUNCTION(0x0, "gpo", NULL), | ||
| 252 | MPP_FUNCTION(0x1, "dev", "ad8"), | ||
| 253 | MPP_FUNCTION(0x3, "sd0", "clk"), | ||
| 254 | MPP_FUNCTION(0x5, "audio", "spdifo")), | ||
| 255 | MPP_MODE(48, | ||
| 256 | MPP_FUNCTION(0x0, "gpio", NULL), | ||
| 257 | MPP_FUNCTION(0x1, "dev", "ad9"), | ||
| 258 | MPP_FUNCTION(0x2, "uart0", "rts"), | ||
| 259 | MPP_FUNCTION(0x3, "sd0", "cmd"), | ||
| 260 | MPP_FUNCTION(0x4, "sata1", "prsnt"), | ||
| 261 | MPP_FUNCTION(0x5, "spi0", "cs1")), | ||
| 262 | MPP_MODE(49, | ||
| 263 | MPP_FUNCTION(0x0, "gpio", NULL), | ||
| 264 | MPP_FUNCTION(0x1, "dev", "ad10"), | ||
| 265 | MPP_FUNCTION(0x2, "pcie", "clkreq1"), | ||
| 266 | MPP_FUNCTION(0x3, "sd0", "d0"), | ||
| 267 | MPP_FUNCTION(0x4, "spi1", "cs0"), | ||
| 268 | MPP_FUNCTION(0x5, "audio", "spdifi")), | ||
| 269 | MPP_MODE(50, | ||
| 270 | MPP_FUNCTION(0x0, "gpio", NULL), | ||
| 271 | MPP_FUNCTION(0x1, "dev", "ad11"), | ||
| 272 | MPP_FUNCTION(0x2, "uart0", "cts"), | ||
| 273 | MPP_FUNCTION(0x3, "sd0", "d1"), | ||
| 274 | MPP_FUNCTION(0x4, "spi1", "miso"), | ||
| 275 | MPP_FUNCTION(0x5, "audio", "rmclk")), | ||
| 276 | MPP_MODE(51, | ||
| 277 | MPP_FUNCTION(0x0, "gpio", NULL), | ||
| 278 | MPP_FUNCTION(0x1, "dev", "ad12"), | ||
| 279 | MPP_FUNCTION(0x2, "i2c1", "sda"), | ||
| 280 | MPP_FUNCTION(0x3, "sd0", "d2"), | ||
| 281 | MPP_FUNCTION(0x4, "spi1", "mosi")), | ||
| 282 | MPP_MODE(52, | ||
| 283 | MPP_FUNCTION(0x0, "gpio", NULL), | ||
| 284 | MPP_FUNCTION(0x1, "dev", "ad13"), | ||
| 285 | MPP_FUNCTION(0x2, "i2c1", "sck"), | ||
| 286 | MPP_FUNCTION(0x3, "sd0", "d3"), | ||
| 287 | MPP_FUNCTION(0x4, "spi1", "sck")), | ||
| 288 | MPP_MODE(53, | ||
| 289 | MPP_FUNCTION(0x0, "gpio", NULL), | ||
| 290 | MPP_FUNCTION(0x1, "dev", "ad14"), | ||
| 291 | MPP_FUNCTION(0x2, "sd0", "clk"), | ||
| 292 | MPP_FUNCTION(0x3, "tdm", "pclk"), | ||
| 293 | MPP_FUNCTION(0x4, "spi0", "cs2"), | ||
| 294 | MPP_FUNCTION(0x5, "pcie", "clkreq1")), | ||
| 295 | MPP_MODE(54, | ||
| 296 | MPP_FUNCTION(0x0, "gpo", NULL), | ||
| 297 | MPP_FUNCTION(0x1, "dev", "ad15"), | ||
| 298 | MPP_FUNCTION(0x3, "tdm", "dtx")), | ||
| 299 | MPP_MODE(55, | ||
| 300 | MPP_FUNCTION(0x0, "gpio", NULL), | ||
| 301 | MPP_FUNCTION(0x1, "dev", "cs1"), | ||
| 302 | MPP_FUNCTION(0x2, "uart1", "txd"), | ||
| 303 | MPP_FUNCTION(0x3, "tdm", "rst"), | ||
| 304 | MPP_FUNCTION(0x4, "sata1", "prsnt"), | ||
| 305 | MPP_FUNCTION(0x5, "sata0", "prsnt")), | ||
| 306 | MPP_MODE(56, | ||
| 307 | MPP_FUNCTION(0x0, "gpio", NULL), | ||
| 308 | MPP_FUNCTION(0x1, "dev", "cs2"), | ||
| 309 | MPP_FUNCTION(0x2, "uart1", "cts"), | ||
| 310 | MPP_FUNCTION(0x3, "uart0", "cts"), | ||
| 311 | MPP_FUNCTION(0x4, "spi0", "cs3"), | ||
| 312 | MPP_FUNCTION(0x5, "pcie", "clkreq0"), | ||
| 313 | MPP_FUNCTION(0x6, "spi1", "cs1")), | ||
| 314 | MPP_MODE(57, | ||
| 315 | MPP_FUNCTION(0x0, "gpio", NULL), | ||
| 316 | MPP_FUNCTION(0x1, "dev", "cs3"), | ||
| 317 | MPP_FUNCTION(0x2, "uart1", "rxd"), | ||
| 318 | MPP_FUNCTION(0x3, "tdm", "fsync"), | ||
| 319 | MPP_FUNCTION(0x4, "sata0", "prsnt"), | ||
| 320 | MPP_FUNCTION(0x5, "audio", "sdo")), | ||
| 321 | MPP_MODE(58, | ||
| 322 | MPP_FUNCTION(0x0, "gpio", NULL), | ||
| 323 | MPP_FUNCTION(0x1, "dev", "cs0"), | ||
| 324 | MPP_FUNCTION(0x2, "uart1", "rts"), | ||
| 325 | MPP_FUNCTION(0x3, "tdm", "int"), | ||
| 326 | MPP_FUNCTION(0x5, "audio", "extclk"), | ||
| 327 | MPP_FUNCTION(0x6, "uart0", "rts")), | ||
| 328 | MPP_MODE(59, | ||
| 329 | MPP_FUNCTION(0x0, "gpo", NULL), | ||
| 330 | MPP_FUNCTION(0x1, "dev", "ale0"), | ||
| 331 | MPP_FUNCTION(0x2, "uart1", "rts"), | ||
| 332 | MPP_FUNCTION(0x3, "uart0", "rts"), | ||
| 333 | MPP_FUNCTION(0x5, "audio", "bclk")), | ||
| 334 | MPP_MODE(60, | ||
| 335 | MPP_FUNCTION(0x0, "gpio", NULL), | ||
| 336 | MPP_FUNCTION(0x1, "dev", "ale1"), | ||
| 337 | MPP_FUNCTION(0x2, "uart1", "rxd"), | ||
| 338 | MPP_FUNCTION(0x3, "sata0", "prsnt"), | ||
| 339 | MPP_FUNCTION(0x4, "pcie", "rst-out"), | ||
| 340 | MPP_FUNCTION(0x5, "audio", "sdi")), | ||
| 341 | MPP_MODE(61, | ||
| 342 | MPP_FUNCTION(0x0, "gpo", NULL), | ||
| 343 | MPP_FUNCTION(0x1, "dev", "wen1"), | ||
| 344 | MPP_FUNCTION(0x2, "uart1", "txd"), | ||
| 345 | MPP_FUNCTION(0x5, "audio", "rclk")), | ||
| 346 | MPP_MODE(62, | ||
| 347 | MPP_FUNCTION(0x0, "gpio", NULL), | ||
| 348 | MPP_FUNCTION(0x1, "dev", "a2"), | ||
| 349 | MPP_FUNCTION(0x2, "uart1", "cts"), | ||
| 350 | MPP_FUNCTION(0x3, "tdm", "drx"), | ||
| 351 | MPP_FUNCTION(0x4, "pcie", "clkreq0"), | ||
| 352 | MPP_FUNCTION(0x5, "audio", "mclk"), | ||
| 353 | MPP_FUNCTION(0x6, "uart0", "cts")), | ||
| 354 | MPP_MODE(63, | ||
| 355 | MPP_FUNCTION(0x0, "gpo", NULL), | ||
| 356 | MPP_FUNCTION(0x1, "spi0", "sck"), | ||
| 357 | MPP_FUNCTION(0x2, "tclk", NULL)), | ||
| 358 | MPP_MODE(64, | ||
| 359 | MPP_FUNCTION(0x0, "gpio", NULL), | ||
| 360 | MPP_FUNCTION(0x1, "spi0", "miso"), | ||
| 361 | MPP_FUNCTION(0x2, "spi0-1", "cs1")), | ||
| 362 | MPP_MODE(65, | ||
| 363 | MPP_FUNCTION(0x0, "gpio", NULL), | ||
| 364 | MPP_FUNCTION(0x1, "spi0", "mosi"), | ||
| 365 | MPP_FUNCTION(0x2, "spi0-1", "cs2")), | ||
| 366 | }; | ||
| 367 | |||
| 368 | static struct mvebu_pinctrl_soc_info armada_370_pinctrl_info; | ||
| 369 | |||
| 370 | static struct of_device_id armada_370_pinctrl_of_match[] __devinitdata = { | ||
| 371 | { .compatible = "marvell,mv88f6710-pinctrl" }, | ||
| 372 | { }, | ||
| 373 | }; | ||
| 374 | |||
| 375 | static struct mvebu_mpp_ctrl mv88f6710_mpp_controls[] = { | ||
| 376 | MPP_REG_CTRL(0, 65), | ||
| 377 | }; | ||
| 378 | |||
| 379 | static struct pinctrl_gpio_range mv88f6710_mpp_gpio_ranges[] = { | ||
| 380 | MPP_GPIO_RANGE(0, 0, 0, 32), | ||
| 381 | MPP_GPIO_RANGE(1, 32, 32, 32), | ||
| 382 | MPP_GPIO_RANGE(2, 64, 64, 2), | ||
| 383 | }; | ||
| 384 | |||
| 385 | static int __devinit armada_370_pinctrl_probe(struct platform_device *pdev) | ||
| 386 | { | ||
| 387 | struct mvebu_pinctrl_soc_info *soc = &armada_370_pinctrl_info; | ||
| 388 | |||
| 389 | soc->variant = 0; /* no variants for Armada 370 */ | ||
| 390 | soc->controls = mv88f6710_mpp_controls; | ||
| 391 | soc->ncontrols = ARRAY_SIZE(mv88f6710_mpp_controls); | ||
| 392 | soc->modes = mv88f6710_mpp_modes; | ||
| 393 | soc->nmodes = ARRAY_SIZE(mv88f6710_mpp_modes); | ||
| 394 | soc->gpioranges = mv88f6710_mpp_gpio_ranges; | ||
| 395 | soc->ngpioranges = ARRAY_SIZE(mv88f6710_mpp_gpio_ranges); | ||
| 396 | |||
| 397 | pdev->dev.platform_data = soc; | ||
| 398 | |||
| 399 | return mvebu_pinctrl_probe(pdev); | ||
| 400 | } | ||
| 401 | |||
| 402 | static int __devexit armada_370_pinctrl_remove(struct platform_device *pdev) | ||
| 403 | { | ||
| 404 | return mvebu_pinctrl_remove(pdev); | ||
| 405 | } | ||
| 406 | |||
| 407 | static struct platform_driver armada_370_pinctrl_driver = { | ||
| 408 | .driver = { | ||
| 409 | .name = "armada-370-pinctrl", | ||
| 410 | .owner = THIS_MODULE, | ||
| 411 | .of_match_table = of_match_ptr(armada_370_pinctrl_of_match), | ||
| 412 | }, | ||
| 413 | .probe = armada_370_pinctrl_probe, | ||
| 414 | .remove = __devexit_p(armada_370_pinctrl_remove), | ||
| 415 | }; | ||
| 416 | |||
| 417 | module_platform_driver(armada_370_pinctrl_driver); | ||
| 418 | |||
| 419 | MODULE_AUTHOR("Thomas Petazzoni <thomas.petazzoni@free-electrons.com>"); | ||
| 420 | MODULE_DESCRIPTION("Marvell Armada 370 pinctrl driver"); | ||
| 421 | MODULE_LICENSE("GPL v2"); | ||
diff --git a/drivers/pinctrl/pinctrl-armada-xp.c b/drivers/pinctrl/pinctrl-armada-xp.c new file mode 100644 index 000000000000..40bd52a46b4e --- /dev/null +++ b/drivers/pinctrl/pinctrl-armada-xp.c | |||
| @@ -0,0 +1,468 @@ | |||
| 1 | /* | ||
| 2 | * Marvell Armada XP pinctrl driver based on mvebu pinctrl core | ||
| 3 | * | ||
| 4 | * Copyright (C) 2012 Marvell | ||
| 5 | * | ||
| 6 | * Thomas Petazzoni <thomas.petazzoni@free-electrons.com> | ||
| 7 | * | ||
| 8 | * This program is free software; you can redistribute it and/or modify | ||
| 9 | * it under the terms of the GNU General Public License as published by | ||
| 10 | * the Free Software Foundation; either version 2 of the License, or | ||
| 11 | * (at your option) any later version. | ||
| 12 | * | ||
| 13 | * This file supports the three variants of Armada XP SoCs that are | ||
| 14 | * available: mv78230, mv78260 and mv78460. From a pin muxing | ||
| 15 | * perspective, the mv78230 has 49 MPP pins. The mv78260 and mv78460 | ||
| 16 | * both have 67 MPP pins (more GPIOs and address lines for the memory | ||
| 17 | * bus mainly). The only difference between the mv78260 and the | ||
| 18 | * mv78460 in terms of pin muxing is the addition of two functions on | ||
| 19 | * pins 43 and 56 to access the VDD of the CPU2 and 3 (mv78260 has two | ||
| 20 | * cores, mv78460 has four cores). | ||
| 21 | */ | ||
| 22 | |||
| 23 | #include <linux/err.h> | ||
| 24 | #include <linux/init.h> | ||
| 25 | #include <linux/io.h> | ||
| 26 | #include <linux/module.h> | ||
| 27 | #include <linux/platform_device.h> | ||
| 28 | #include <linux/clk.h> | ||
| 29 | #include <linux/of.h> | ||
| 30 | #include <linux/of_device.h> | ||
| 31 | #include <linux/pinctrl/pinctrl.h> | ||
| 32 | #include <linux/bitops.h> | ||
| 33 | |||
| 34 | #include "pinctrl-mvebu.h" | ||
| 35 | |||
| 36 | enum armada_xp_variant { | ||
| 37 | V_MV78230 = BIT(0), | ||
| 38 | V_MV78260 = BIT(1), | ||
| 39 | V_MV78460 = BIT(2), | ||
| 40 | V_MV78230_PLUS = (V_MV78230 | V_MV78260 | V_MV78460), | ||
| 41 | V_MV78260_PLUS = (V_MV78260 | V_MV78460), | ||
| 42 | }; | ||
| 43 | |||
| 44 | static struct mvebu_mpp_mode armada_xp_mpp_modes[] = { | ||
| 45 | MPP_MODE(0, | ||
| 46 | MPP_VAR_FUNCTION(0x0, "gpio", NULL, V_MV78230_PLUS), | ||
| 47 | MPP_VAR_FUNCTION(0x1, "ge0", "txclko", V_MV78230_PLUS), | ||
| 48 | MPP_VAR_FUNCTION(0x4, "lcd", "d0", V_MV78230_PLUS)), | ||
| 49 | MPP_MODE(1, | ||
| 50 | MPP_VAR_FUNCTION(0x0, "gpio", NULL, V_MV78230_PLUS), | ||
| 51 | MPP_VAR_FUNCTION(0x1, "ge0", "txd0", V_MV78230_PLUS), | ||
| 52 | MPP_VAR_FUNCTION(0x4, "lcd", "d1", V_MV78230_PLUS)), | ||
| 53 | MPP_MODE(2, | ||
| 54 | MPP_VAR_FUNCTION(0x0, "gpio", NULL, V_MV78230_PLUS), | ||
| 55 | MPP_VAR_FUNCTION(0x1, "ge0", "txd1", V_MV78230_PLUS), | ||
| 56 | MPP_VAR_FUNCTION(0x4, "lcd", "d2", V_MV78230_PLUS)), | ||
| 57 | MPP_MODE(3, | ||
| 58 | MPP_VAR_FUNCTION(0x0, "gpio", NULL, V_MV78230_PLUS), | ||
| 59 | MPP_VAR_FUNCTION(0x1, "ge0", "txd2", V_MV78230_PLUS), | ||
| 60 | MPP_VAR_FUNCTION(0x4, "lcd", "d3", V_MV78230_PLUS)), | ||
| 61 | MPP_MODE(4, | ||
| 62 | MPP_VAR_FUNCTION(0x0, "gpio", NULL, V_MV78230_PLUS), | ||
| 63 | MPP_VAR_FUNCTION(0x1, "ge0", "txd3", V_MV78230_PLUS), | ||
| 64 | MPP_VAR_FUNCTION(0x4, "lcd", "d4", V_MV78230_PLUS)), | ||
| 65 | MPP_MODE(5, | ||
| 66 | MPP_VAR_FUNCTION(0x0, "gpio", NULL, V_MV78230_PLUS), | ||
| 67 | MPP_VAR_FUNCTION(0x1, "ge0", "txctl", V_MV78230_PLUS), | ||
| 68 | MPP_VAR_FUNCTION(0x4, "lcd", "d5", V_MV78230_PLUS)), | ||
| 69 | MPP_MODE(6, | ||
| 70 | MPP_VAR_FUNCTION(0x0, "gpio", NULL, V_MV78230_PLUS), | ||
| 71 | MPP_VAR_FUNCTION(0x1, "ge0", "rxd0", V_MV78230_PLUS), | ||
| 72 | MPP_VAR_FUNCTION(0x4, "lcd", "d6", V_MV78230_PLUS)), | ||
| 73 | MPP_MODE(7, | ||
| 74 | MPP_VAR_FUNCTION(0x0, "gpio", NULL, V_MV78230_PLUS), | ||
| 75 | MPP_VAR_FUNCTION(0x1, "ge0", "rxd1", V_MV78230_PLUS), | ||
| 76 | MPP_VAR_FUNCTION(0x4, "lcd", "d7", V_MV78230_PLUS)), | ||
| 77 | MPP_MODE(8, | ||
| 78 | MPP_VAR_FUNCTION(0x0, "gpio", NULL, V_MV78230_PLUS), | ||
| 79 | MPP_VAR_FUNCTION(0x1, "ge0", "rxd2", V_MV78230_PLUS), | ||
| 80 | MPP_VAR_FUNCTION(0x4, "lcd", "d8", V_MV78230_PLUS)), | ||
| 81 | MPP_MODE(9, | ||
| 82 | MPP_VAR_FUNCTION(0x0, "gpio", NULL, V_MV78230_PLUS), | ||
| 83 | MPP_VAR_FUNCTION(0x1, "ge0", "rxd3", V_MV78230_PLUS), | ||
| 84 | MPP_VAR_FUNCTION(0x4, "lcd", "d9", V_MV78230_PLUS)), | ||
| 85 | MPP_MODE(10, | ||
| 86 | MPP_VAR_FUNCTION(0x0, "gpio", NULL, V_MV78230_PLUS), | ||
| 87 | MPP_VAR_FUNCTION(0x1, "ge0", "rxctl", V_MV78230_PLUS), | ||
| 88 | MPP_VAR_FUNCTION(0x4, "lcd", "d10", V_MV78230_PLUS)), | ||
| 89 | MPP_MODE(11, | ||
| 90 | MPP_VAR_FUNCTION(0x0, "gpio", NULL, V_MV78230_PLUS), | ||
| 91 | MPP_VAR_FUNCTION(0x1, "ge0", "rxclk", V_MV78230_PLUS), | ||
| 92 | MPP_VAR_FUNCTION(0x4, "lcd", "d11", V_MV78230_PLUS)), | ||
| 93 | MPP_MODE(12, | ||
| 94 | MPP_VAR_FUNCTION(0x0, "gpio", NULL, V_MV78230_PLUS), | ||
| 95 | MPP_VAR_FUNCTION(0x1, "ge0", "txd4", V_MV78230_PLUS), | ||
| 96 | MPP_VAR_FUNCTION(0x2, "ge1", "clkout", V_MV78230_PLUS), | ||
| 97 | MPP_VAR_FUNCTION(0x4, "lcd", "d12", V_MV78230_PLUS)), | ||
| 98 | MPP_MODE(13, | ||
| 99 | MPP_VAR_FUNCTION(0x0, "gpio", NULL, V_MV78230_PLUS), | ||
| 100 | MPP_VAR_FUNCTION(0x1, "ge0", "txd5", V_MV78230_PLUS), | ||
| 101 | MPP_VAR_FUNCTION(0x2, "ge1", "txd0", V_MV78230_PLUS), | ||
| 102 | MPP_VAR_FUNCTION(0x4, "lcd", "d13", V_MV78230_PLUS)), | ||
| 103 | MPP_MODE(14, | ||
| 104 | MPP_VAR_FUNCTION(0x0, "gpio", NULL, V_MV78230_PLUS), | ||
| 105 | MPP_VAR_FUNCTION(0x1, "ge0", "txd6", V_MV78230_PLUS), | ||
| 106 | MPP_VAR_FUNCTION(0x2, "ge1", "txd1", V_MV78230_PLUS), | ||
| 107 | MPP_VAR_FUNCTION(0x4, "lcd", "d14", V_MV78230_PLUS)), | ||
| 108 | MPP_MODE(15, | ||
| 109 | MPP_VAR_FUNCTION(0x0, "gpio", NULL, V_MV78230_PLUS), | ||
| 110 | MPP_VAR_FUNCTION(0x1, "ge0", "txd7", V_MV78230_PLUS), | ||
| 111 | MPP_VAR_FUNCTION(0x2, "ge1", "txd2", V_MV78230_PLUS), | ||
| 112 | MPP_VAR_FUNCTION(0x4, "lcd", "d15", V_MV78230_PLUS)), | ||
| 113 | MPP_MODE(16, | ||
| 114 | MPP_VAR_FUNCTION(0x0, "gpio", NULL, V_MV78230_PLUS), | ||
| 115 | MPP_VAR_FUNCTION(0x1, "ge0", "txclk", V_MV78230_PLUS), | ||
| 116 | MPP_VAR_FUNCTION(0x2, "ge1", "txd3", V_MV78230_PLUS), | ||
| 117 | MPP_VAR_FUNCTION(0x4, "lcd", "d16", V_MV78230_PLUS)), | ||
| 118 | MPP_MODE(17, | ||
| 119 | MPP_VAR_FUNCTION(0x0, "gpio", NULL, V_MV78230_PLUS), | ||
| 120 | MPP_VAR_FUNCTION(0x1, "ge0", "col", V_MV78230_PLUS), | ||
| 121 | MPP_VAR_FUNCTION(0x2, "ge1", "txctl", V_MV78230_PLUS), | ||
| 122 | MPP_VAR_FUNCTION(0x4, "lcd", "d17", V_MV78230_PLUS)), | ||
| 123 | MPP_MODE(18, | ||
| 124 | MPP_VAR_FUNCTION(0x0, "gpio", NULL, V_MV78230_PLUS), | ||
| 125 | MPP_VAR_FUNCTION(0x1, "ge0", "rxerr", V_MV78230_PLUS), | ||
| 126 | MPP_VAR_FUNCTION(0x2, "ge1", "rxd0", V_MV78230_PLUS), | ||
| 127 | MPP_VAR_FUNCTION(0x3, "ptp", "trig", V_MV78230_PLUS), | ||
| 128 | MPP_VAR_FUNCTION(0x4, "lcd", "d18", V_MV78230_PLUS)), | ||
| 129 | MPP_MODE(19, | ||
| 130 | MPP_VAR_FUNCTION(0x0, "gpio", NULL, V_MV78230_PLUS), | ||
| 131 | MPP_VAR_FUNCTION(0x1, "ge0", "crs", V_MV78230_PLUS), | ||
| 132 | MPP_VAR_FUNCTION(0x2, "ge1", "rxd1", V_MV78230_PLUS), | ||
| 133 | MPP_VAR_FUNCTION(0x3, "ptp", "evreq", V_MV78230_PLUS), | ||
| 134 | MPP_VAR_FUNCTION(0x4, "lcd", "d19", V_MV78230_PLUS)), | ||
| 135 | MPP_MODE(20, | ||
| 136 | MPP_VAR_FUNCTION(0x0, "gpio", NULL, V_MV78230_PLUS), | ||
| 137 | MPP_VAR_FUNCTION(0x1, "ge0", "rxd4", V_MV78230_PLUS), | ||
| 138 | MPP_VAR_FUNCTION(0x2, "ge1", "rxd2", V_MV78230_PLUS), | ||
| 139 | MPP_VAR_FUNCTION(0x3, "ptp", "clk", V_MV78230_PLUS), | ||
| 140 | MPP_VAR_FUNCTION(0x4, "lcd", "d20", V_MV78230_PLUS)), | ||
| 141 | MPP_MODE(21, | ||
| 142 | MPP_VAR_FUNCTION(0x0, "gpio", NULL, V_MV78230_PLUS), | ||
| 143 | MPP_VAR_FUNCTION(0x1, "ge0", "rxd5", V_MV78230_PLUS), | ||
| 144 | MPP_VAR_FUNCTION(0x2, "ge1", "rxd3", V_MV78230_PLUS), | ||
| 145 | MPP_VAR_FUNCTION(0x3, "mem", "bat", V_MV78230_PLUS), | ||
| 146 | MPP_VAR_FUNCTION(0x4, "lcd", "d21", V_MV78230_PLUS)), | ||
| 147 | MPP_MODE(22, | ||
| 148 | MPP_VAR_FUNCTION(0x0, "gpio", NULL, V_MV78230_PLUS), | ||
| 149 | MPP_VAR_FUNCTION(0x1, "ge0", "rxd6", V_MV78230_PLUS), | ||
| 150 | MPP_VAR_FUNCTION(0x2, "ge1", "rxctl", V_MV78230_PLUS), | ||
| 151 | MPP_VAR_FUNCTION(0x3, "sata0", "prsnt", V_MV78230_PLUS), | ||
| 152 | MPP_VAR_FUNCTION(0x4, "lcd", "d22", V_MV78230_PLUS)), | ||
| 153 | MPP_MODE(23, | ||
| 154 | MPP_VAR_FUNCTION(0x0, "gpio", NULL, V_MV78230_PLUS), | ||
| 155 | MPP_VAR_FUNCTION(0x1, "ge0", "rxd7", V_MV78230_PLUS), | ||
| 156 | MPP_VAR_FUNCTION(0x2, "ge1", "rxclk", V_MV78230_PLUS), | ||
| 157 | MPP_VAR_FUNCTION(0x3, "sata1", "prsnt", V_MV78230_PLUS), | ||
| 158 | MPP_VAR_FUNCTION(0x4, "lcd", "d23", V_MV78230_PLUS)), | ||
| 159 | MPP_MODE(24, | ||
| 160 | MPP_VAR_FUNCTION(0x0, "gpio", NULL, V_MV78230_PLUS), | ||
| 161 | MPP_VAR_FUNCTION(0x1, "sata1", "prsnt", V_MV78230_PLUS), | ||
| 162 | MPP_VAR_FUNCTION(0x2, "nf", "bootcs-re", V_MV78230_PLUS), | ||
| 163 | MPP_VAR_FUNCTION(0x3, "tdm", "rst", V_MV78230_PLUS), | ||
| 164 | MPP_VAR_FUNCTION(0x4, "lcd", "hsync", V_MV78230_PLUS)), | ||
| 165 | MPP_MODE(25, | ||
| 166 | MPP_VAR_FUNCTION(0x0, "gpio", NULL, V_MV78230_PLUS), | ||
| 167 | MPP_VAR_FUNCTION(0x1, "sata0", "prsnt", V_MV78230_PLUS), | ||
| 168 | MPP_VAR_FUNCTION(0x2, "nf", "bootcs-we", V_MV78230_PLUS), | ||
| 169 | MPP_VAR_FUNCTION(0x3, "tdm", "pclk", V_MV78230_PLUS), | ||
| 170 | MPP_VAR_FUNCTION(0x4, "lcd", "vsync", V_MV78230_PLUS)), | ||
| 171 | MPP_MODE(26, | ||
| 172 | MPP_VAR_FUNCTION(0x0, "gpio", NULL, V_MV78230_PLUS), | ||
| 173 | MPP_VAR_FUNCTION(0x3, "tdm", "fsync", V_MV78230_PLUS), | ||
| 174 | MPP_VAR_FUNCTION(0x4, "lcd", "clk", V_MV78230_PLUS), | ||
| 175 | MPP_VAR_FUNCTION(0x5, "vdd", "cpu1-pd", V_MV78230_PLUS)), | ||
| 176 | MPP_MODE(27, | ||
| 177 | MPP_VAR_FUNCTION(0x0, "gpio", NULL, V_MV78230_PLUS), | ||
| 178 | MPP_VAR_FUNCTION(0x1, "ptp", "trig", V_MV78230_PLUS), | ||
| 179 | MPP_VAR_FUNCTION(0x3, "tdm", "dtx", V_MV78230_PLUS), | ||
| 180 | MPP_VAR_FUNCTION(0x4, "lcd", "e", V_MV78230_PLUS)), | ||
| 181 | MPP_MODE(28, | ||
| 182 | MPP_VAR_FUNCTION(0x0, "gpio", NULL, V_MV78230_PLUS), | ||
| 183 | MPP_VAR_FUNCTION(0x1, "ptp", "evreq", V_MV78230_PLUS), | ||
| 184 | MPP_VAR_FUNCTION(0x3, "tdm", "drx", V_MV78230_PLUS), | ||
| 185 | MPP_VAR_FUNCTION(0x4, "lcd", "pwm", V_MV78230_PLUS)), | ||
| 186 | MPP_MODE(29, | ||
| 187 | MPP_VAR_FUNCTION(0x0, "gpio", NULL, V_MV78230_PLUS), | ||
| 188 | MPP_VAR_FUNCTION(0x1, "ptp", "clk", V_MV78230_PLUS), | ||
| 189 | MPP_VAR_FUNCTION(0x3, "tdm", "int0", V_MV78230_PLUS), | ||
| 190 | MPP_VAR_FUNCTION(0x4, "lcd", "ref-clk", V_MV78230_PLUS), | ||
| 191 | MPP_VAR_FUNCTION(0x5, "vdd", "cpu0-pd", V_MV78230_PLUS)), | ||
| 192 | MPP_MODE(30, | ||
| 193 | MPP_VAR_FUNCTION(0x0, "gpio", NULL, V_MV78230_PLUS), | ||
| 194 | MPP_VAR_FUNCTION(0x1, "sd0", "clk", V_MV78230_PLUS), | ||
| 195 | MPP_VAR_FUNCTION(0x3, "tdm", "int1", V_MV78230_PLUS)), | ||
| 196 | MPP_MODE(31, | ||
| 197 | MPP_VAR_FUNCTION(0x0, "gpio", NULL, V_MV78230_PLUS), | ||
| 198 | MPP_VAR_FUNCTION(0x1, "sd0", "cmd", V_MV78230_PLUS), | ||
| 199 | MPP_VAR_FUNCTION(0x3, "tdm", "int2", V_MV78230_PLUS), | ||
| 200 | MPP_VAR_FUNCTION(0x5, "vdd", "cpu0-pd", V_MV78230_PLUS)), | ||
| 201 | MPP_MODE(32, | ||
| 202 | MPP_VAR_FUNCTION(0x0, "gpio", NULL, V_MV78230_PLUS), | ||
| 203 | MPP_VAR_FUNCTION(0x1, "sd0", "d0", V_MV78230_PLUS), | ||
| 204 | MPP_VAR_FUNCTION(0x3, "tdm", "int3", V_MV78230_PLUS), | ||
| 205 | MPP_VAR_FUNCTION(0x5, "vdd", "cpu1-pd", V_MV78230_PLUS)), | ||
| 206 | MPP_MODE(33, | ||
| 207 | MPP_VAR_FUNCTION(0x0, "gpio", NULL, V_MV78230_PLUS), | ||
| 208 | MPP_VAR_FUNCTION(0x1, "sd0", "d1", V_MV78230_PLUS), | ||
| 209 | MPP_VAR_FUNCTION(0x3, "tdm", "int4", V_MV78230_PLUS), | ||
| 210 | MPP_VAR_FUNCTION(0x4, "mem", "bat", V_MV78230_PLUS)), | ||
| 211 | MPP_MODE(34, | ||
| 212 | MPP_VAR_FUNCTION(0x0, "gpio", NULL, V_MV78230_PLUS), | ||
| 213 | MPP_VAR_FUNCTION(0x1, "sd0", "d2", V_MV78230_PLUS), | ||
| 214 | MPP_VAR_FUNCTION(0x2, "sata0", "prsnt", V_MV78230_PLUS), | ||
| 215 | MPP_VAR_FUNCTION(0x3, "tdm", "int5", V_MV78230_PLUS)), | ||
| 216 | MPP_MODE(35, | ||
| 217 | MPP_VAR_FUNCTION(0x0, "gpio", NULL, V_MV78230_PLUS), | ||
| 218 | MPP_VAR_FUNCTION(0x1, "sd0", "d3", V_MV78230_PLUS), | ||
| 219 | MPP_VAR_FUNCTION(0x2, "sata1", "prsnt", V_MV78230_PLUS), | ||
| 220 | MPP_VAR_FUNCTION(0x3, "tdm", "int6", V_MV78230_PLUS)), | ||
| 221 | MPP_MODE(36, | ||
| 222 | MPP_VAR_FUNCTION(0x0, "gpio", NULL, V_MV78230_PLUS), | ||
| 223 | MPP_VAR_FUNCTION(0x1, "spi", "mosi", V_MV78230_PLUS)), | ||
| 224 | MPP_MODE(37, | ||
| 225 | MPP_VAR_FUNCTION(0x0, "gpio", NULL, V_MV78230_PLUS), | ||
| 226 | MPP_VAR_FUNCTION(0x1, "spi", "miso", V_MV78230_PLUS)), | ||
| 227 | MPP_MODE(38, | ||
| 228 | MPP_VAR_FUNCTION(0x0, "gpio", NULL, V_MV78230_PLUS), | ||
| 229 | MPP_VAR_FUNCTION(0x1, "spi", "sck", V_MV78230_PLUS)), | ||
| 230 | MPP_MODE(39, | ||
| 231 | MPP_VAR_FUNCTION(0x0, "gpio", NULL, V_MV78230_PLUS), | ||
| 232 | MPP_VAR_FUNCTION(0x1, "spi", "cs0", V_MV78230_PLUS)), | ||
| 233 | MPP_MODE(40, | ||
| 234 | MPP_VAR_FUNCTION(0x0, "gpio", NULL, V_MV78230_PLUS), | ||
| 235 | MPP_VAR_FUNCTION(0x1, "spi", "cs1", V_MV78230_PLUS), | ||
| 236 | MPP_VAR_FUNCTION(0x2, "uart2", "cts", V_MV78230_PLUS), | ||
| 237 | MPP_VAR_FUNCTION(0x3, "vdd", "cpu1-pd", V_MV78230_PLUS), | ||
| 238 | MPP_VAR_FUNCTION(0x4, "lcd", "vga-hsync", V_MV78230_PLUS), | ||
| 239 | MPP_VAR_FUNCTION(0x5, "pcie", "clkreq0", V_MV78230_PLUS)), | ||
| 240 | MPP_MODE(41, | ||
| 241 | MPP_VAR_FUNCTION(0x0, "gpio", NULL, V_MV78230_PLUS), | ||
| 242 | MPP_VAR_FUNCTION(0x1, "spi", "cs2", V_MV78230_PLUS), | ||
| 243 | MPP_VAR_FUNCTION(0x2, "uart2", "rts", V_MV78230_PLUS), | ||
| 244 | MPP_VAR_FUNCTION(0x3, "sata1", "prsnt", V_MV78230_PLUS), | ||
| 245 | MPP_VAR_FUNCTION(0x4, "lcd", "vga-vsync", V_MV78230_PLUS), | ||
| 246 | MPP_VAR_FUNCTION(0x5, "pcie", "clkreq1", V_MV78230_PLUS)), | ||
| 247 | MPP_MODE(42, | ||
| 248 | MPP_VAR_FUNCTION(0x0, "gpio", NULL, V_MV78230_PLUS), | ||
| 249 | MPP_VAR_FUNCTION(0x1, "uart2", "rxd", V_MV78230_PLUS), | ||
| 250 | MPP_VAR_FUNCTION(0x2, "uart0", "cts", V_MV78230_PLUS), | ||
| 251 | MPP_VAR_FUNCTION(0x3, "tdm", "int7", V_MV78230_PLUS), | ||
| 252 | MPP_VAR_FUNCTION(0x4, "tdm-1", "timer", V_MV78230_PLUS), | ||
| 253 | MPP_VAR_FUNCTION(0x5, "vdd", "cpu0-pd", V_MV78230_PLUS)), | ||
| 254 | MPP_MODE(43, | ||
| 255 | MPP_VAR_FUNCTION(0x0, "gpio", NULL, V_MV78230_PLUS), | ||
| 256 | MPP_VAR_FUNCTION(0x1, "uart2", "txd", V_MV78230_PLUS), | ||
| 257 | MPP_VAR_FUNCTION(0x2, "uart0", "rts", V_MV78230_PLUS), | ||
| 258 | MPP_VAR_FUNCTION(0x3, "spi", "cs3", V_MV78230_PLUS), | ||
| 259 | MPP_VAR_FUNCTION(0x4, "pcie", "rstout", V_MV78230_PLUS), | ||
| 260 | MPP_VAR_FUNCTION(0x5, "vdd", "cpu2-3-pd", V_MV78460)), | ||
| 261 | MPP_MODE(44, | ||
| 262 | MPP_VAR_FUNCTION(0x0, "gpio", NULL, V_MV78230_PLUS), | ||
| 263 | MPP_VAR_FUNCTION(0x1, "uart2", "cts", V_MV78230_PLUS), | ||
| 264 | MPP_VAR_FUNCTION(0x2, "uart3", "rxd", V_MV78230_PLUS), | ||
| 265 | MPP_VAR_FUNCTION(0x3, "spi", "cs4", V_MV78230_PLUS), | ||
| 266 | MPP_VAR_FUNCTION(0x4, "mem", "bat", V_MV78230_PLUS), | ||
| 267 | MPP_VAR_FUNCTION(0x5, "pcie", "clkreq2", V_MV78230_PLUS)), | ||
| 268 | MPP_MODE(45, | ||
| 269 | MPP_VAR_FUNCTION(0x0, "gpio", NULL, V_MV78230_PLUS), | ||
| 270 | MPP_VAR_FUNCTION(0x1, "uart2", "rts", V_MV78230_PLUS), | ||
| 271 | MPP_VAR_FUNCTION(0x2, "uart3", "txd", V_MV78230_PLUS), | ||
| 272 | MPP_VAR_FUNCTION(0x3, "spi", "cs5", V_MV78230_PLUS), | ||
| 273 | MPP_VAR_FUNCTION(0x4, "sata1", "prsnt", V_MV78230_PLUS)), | ||
| 274 | MPP_MODE(46, | ||
| 275 | MPP_VAR_FUNCTION(0x0, "gpio", NULL, V_MV78230_PLUS), | ||
| 276 | MPP_VAR_FUNCTION(0x1, "uart3", "rts", V_MV78230_PLUS), | ||
| 277 | MPP_VAR_FUNCTION(0x2, "uart1", "rts", V_MV78230_PLUS), | ||
| 278 | MPP_VAR_FUNCTION(0x3, "spi", "cs6", V_MV78230_PLUS), | ||
| 279 | MPP_VAR_FUNCTION(0x4, "sata0", "prsnt", V_MV78230_PLUS)), | ||
| 280 | MPP_MODE(47, | ||
| 281 | MPP_VAR_FUNCTION(0x0, "gpio", NULL, V_MV78230_PLUS), | ||
| 282 | MPP_VAR_FUNCTION(0x1, "uart3", "cts", V_MV78230_PLUS), | ||
| 283 | MPP_VAR_FUNCTION(0x2, "uart1", "cts", V_MV78230_PLUS), | ||
| 284 | MPP_VAR_FUNCTION(0x3, "spi", "cs7", V_MV78230_PLUS), | ||
| 285 | MPP_VAR_FUNCTION(0x4, "ref", "clkout", V_MV78230_PLUS), | ||
| 286 | MPP_VAR_FUNCTION(0x5, "pcie", "clkreq3", V_MV78230_PLUS)), | ||
| 287 | MPP_MODE(48, | ||
| 288 | MPP_VAR_FUNCTION(0x0, "gpio", NULL, V_MV78230_PLUS), | ||
| 289 | MPP_VAR_FUNCTION(0x1, "tclk", NULL, V_MV78230_PLUS), | ||
| 290 | MPP_VAR_FUNCTION(0x2, "dev", "burst/last", V_MV78230_PLUS)), | ||
| 291 | MPP_MODE(49, | ||
| 292 | MPP_VAR_FUNCTION(0x0, "gpio", NULL, V_MV78260_PLUS), | ||
| 293 | MPP_VAR_FUNCTION(0x1, "dev", "we3", V_MV78260_PLUS)), | ||
| 294 | MPP_MODE(50, | ||
| 295 | MPP_VAR_FUNCTION(0x0, "gpio", NULL, V_MV78260_PLUS), | ||
| 296 | MPP_VAR_FUNCTION(0x1, "dev", "we2", V_MV78260_PLUS)), | ||
| 297 | MPP_MODE(51, | ||
| 298 | MPP_VAR_FUNCTION(0x0, "gpio", NULL, V_MV78260_PLUS), | ||
| 299 | MPP_VAR_FUNCTION(0x1, "dev", "ad16", V_MV78260_PLUS)), | ||
| 300 | MPP_MODE(52, | ||
| 301 | MPP_VAR_FUNCTION(0x0, "gpio", NULL, V_MV78260_PLUS), | ||
| 302 | MPP_VAR_FUNCTION(0x1, "dev", "ad17", V_MV78260_PLUS)), | ||
| 303 | MPP_MODE(53, | ||
| 304 | MPP_VAR_FUNCTION(0x0, "gpio", NULL, V_MV78260_PLUS), | ||
| 305 | MPP_VAR_FUNCTION(0x1, "dev", "ad18", V_MV78260_PLUS)), | ||
| 306 | MPP_MODE(54, | ||
| 307 | MPP_VAR_FUNCTION(0x0, "gpio", NULL, V_MV78260_PLUS), | ||
| 308 | MPP_VAR_FUNCTION(0x1, "dev", "ad19", V_MV78260_PLUS)), | ||
| 309 | MPP_MODE(55, | ||
| 310 | MPP_VAR_FUNCTION(0x0, "gpio", NULL, V_MV78260_PLUS), | ||
| 311 | MPP_VAR_FUNCTION(0x1, "dev", "ad20", V_MV78260_PLUS), | ||
| 312 | MPP_VAR_FUNCTION(0x2, "vdd", "cpu0-pd", V_MV78260_PLUS)), | ||
| 313 | MPP_MODE(56, | ||
| 314 | MPP_VAR_FUNCTION(0x0, "gpio", NULL, V_MV78260_PLUS), | ||
| 315 | MPP_VAR_FUNCTION(0x1, "dev", "ad21", V_MV78260_PLUS), | ||
| 316 | MPP_VAR_FUNCTION(0x2, "vdd", "cpu1-pd", V_MV78260_PLUS)), | ||
| 317 | MPP_MODE(57, | ||
| 318 | MPP_VAR_FUNCTION(0x0, "gpio", NULL, V_MV78260_PLUS), | ||
| 319 | MPP_VAR_FUNCTION(0x1, "dev", "ad22", V_MV78260_PLUS), | ||
| 320 | MPP_VAR_FUNCTION(0x2, "vdd", "cpu2-3-pd", V_MV78460)), | ||
| 321 | MPP_MODE(58, | ||
| 322 | MPP_VAR_FUNCTION(0x0, "gpio", NULL, V_MV78260_PLUS), | ||
| 323 | MPP_VAR_FUNCTION(0x1, "dev", "ad23", V_MV78260_PLUS)), | ||
| 324 | MPP_MODE(59, | ||
| 325 | MPP_VAR_FUNCTION(0x0, "gpio", NULL, V_MV78260_PLUS), | ||
| 326 | MPP_VAR_FUNCTION(0x1, "dev", "ad24", V_MV78260_PLUS)), | ||
| 327 | MPP_MODE(60, | ||
| 328 | MPP_VAR_FUNCTION(0x0, "gpio", NULL, V_MV78260_PLUS), | ||
| 329 | MPP_VAR_FUNCTION(0x1, "dev", "ad25", V_MV78260_PLUS)), | ||
| 330 | MPP_MODE(61, | ||
| 331 | MPP_VAR_FUNCTION(0x0, "gpio", NULL, V_MV78260_PLUS), | ||
| 332 | MPP_VAR_FUNCTION(0x1, "dev", "ad26", V_MV78260_PLUS)), | ||
| 333 | MPP_MODE(62, | ||
| 334 | MPP_VAR_FUNCTION(0x0, "gpio", NULL, V_MV78260_PLUS), | ||
| 335 | MPP_VAR_FUNCTION(0x1, "dev", "ad27", V_MV78260_PLUS)), | ||
| 336 | MPP_MODE(63, | ||
| 337 | MPP_VAR_FUNCTION(0x0, "gpio", NULL, V_MV78260_PLUS), | ||
| 338 | MPP_VAR_FUNCTION(0x1, "dev", "ad28", V_MV78260_PLUS)), | ||
| 339 | MPP_MODE(64, | ||
| 340 | MPP_VAR_FUNCTION(0x0, "gpio", NULL, V_MV78260_PLUS), | ||
| 341 | MPP_VAR_FUNCTION(0x1, "dev", "ad29", V_MV78260_PLUS)), | ||
| 342 | MPP_MODE(65, | ||
| 343 | MPP_VAR_FUNCTION(0x0, "gpio", NULL, V_MV78260_PLUS), | ||
| 344 | MPP_VAR_FUNCTION(0x1, "dev", "ad30", V_MV78260_PLUS)), | ||
| 345 | MPP_MODE(66, | ||
| 346 | MPP_VAR_FUNCTION(0x0, "gpio", NULL, V_MV78260_PLUS), | ||
| 347 | MPP_VAR_FUNCTION(0x1, "dev", "ad31", V_MV78260_PLUS)), | ||
| 348 | }; | ||
| 349 | |||
| 350 | static struct mvebu_pinctrl_soc_info armada_xp_pinctrl_info; | ||
| 351 | |||
| 352 | static struct of_device_id armada_xp_pinctrl_of_match[] __devinitdata = { | ||
| 353 | { | ||
| 354 | .compatible = "marvell,mv78230-pinctrl", | ||
| 355 | .data = (void *) V_MV78230, | ||
| 356 | }, | ||
| 357 | { | ||
| 358 | .compatible = "marvell,mv78260-pinctrl", | ||
| 359 | .data = (void *) V_MV78260, | ||
| 360 | }, | ||
| 361 | { | ||
| 362 | .compatible = "marvell,mv78460-pinctrl", | ||
| 363 | .data = (void *) V_MV78460, | ||
| 364 | }, | ||
| 365 | { }, | ||
| 366 | }; | ||
| 367 | |||
| 368 | static struct mvebu_mpp_ctrl mv78230_mpp_controls[] = { | ||
| 369 | MPP_REG_CTRL(0, 48), | ||
| 370 | }; | ||
| 371 | |||
| 372 | static struct pinctrl_gpio_range mv78230_mpp_gpio_ranges[] = { | ||
| 373 | MPP_GPIO_RANGE(0, 0, 0, 32), | ||
| 374 | MPP_GPIO_RANGE(1, 32, 32, 17), | ||
| 375 | }; | ||
| 376 | |||
| 377 | static struct mvebu_mpp_ctrl mv78260_mpp_controls[] = { | ||
| 378 | MPP_REG_CTRL(0, 66), | ||
| 379 | }; | ||
| 380 | |||
| 381 | static struct pinctrl_gpio_range mv78260_mpp_gpio_ranges[] = { | ||
| 382 | MPP_GPIO_RANGE(0, 0, 0, 32), | ||
| 383 | MPP_GPIO_RANGE(1, 32, 32, 32), | ||
| 384 | MPP_GPIO_RANGE(2, 64, 64, 3), | ||
| 385 | }; | ||
| 386 | |||
| 387 | static struct mvebu_mpp_ctrl mv78460_mpp_controls[] = { | ||
| 388 | MPP_REG_CTRL(0, 66), | ||
| 389 | }; | ||
| 390 | |||
| 391 | static struct pinctrl_gpio_range mv78460_mpp_gpio_ranges[] = { | ||
| 392 | MPP_GPIO_RANGE(0, 0, 0, 32), | ||
| 393 | MPP_GPIO_RANGE(1, 32, 32, 32), | ||
| 394 | MPP_GPIO_RANGE(2, 64, 64, 3), | ||
| 395 | }; | ||
| 396 | |||
| 397 | static int __devinit armada_xp_pinctrl_probe(struct platform_device *pdev) | ||
| 398 | { | ||
| 399 | struct mvebu_pinctrl_soc_info *soc = &armada_xp_pinctrl_info; | ||
| 400 | const struct of_device_id *match = | ||
| 401 | of_match_device(armada_xp_pinctrl_of_match, &pdev->dev); | ||
| 402 | |||
| 403 | if (!match) | ||
| 404 | return -ENODEV; | ||
| 405 | |||
| 406 | soc->variant = (unsigned) match->data & 0xff; | ||
| 407 | |||
| 408 | switch (soc->variant) { | ||
| 409 | case V_MV78230: | ||
| 410 | soc->controls = mv78230_mpp_controls; | ||
| 411 | soc->ncontrols = ARRAY_SIZE(mv78230_mpp_controls); | ||
| 412 | soc->modes = armada_xp_mpp_modes; | ||
| 413 | /* We don't necessarily want the full list of the | ||
| 414 | * armada_xp_mpp_modes, but only the first 'n' ones | ||
| 415 | * that are available on this SoC */ | ||
| 416 | soc->nmodes = mv78230_mpp_controls[0].npins; | ||
| 417 | soc->gpioranges = mv78230_mpp_gpio_ranges; | ||
| 418 | soc->ngpioranges = ARRAY_SIZE(mv78230_mpp_gpio_ranges); | ||
| 419 | break; | ||
| 420 | case V_MV78260: | ||
| 421 | soc->controls = mv78260_mpp_controls; | ||
| 422 | soc->ncontrols = ARRAY_SIZE(mv78260_mpp_controls); | ||
| 423 | soc->modes = armada_xp_mpp_modes; | ||
| 424 | /* We don't necessarily want the full list of the | ||
| 425 | * armada_xp_mpp_modes, but only the first 'n' ones | ||
| 426 | * that are available on this SoC */ | ||
| 427 | soc->nmodes = mv78260_mpp_controls[0].npins; | ||
| 428 | soc->gpioranges = mv78260_mpp_gpio_ranges; | ||
| 429 | soc->ngpioranges = ARRAY_SIZE(mv78260_mpp_gpio_ranges); | ||
| 430 | break; | ||
| 431 | case V_MV78460: | ||
| 432 | soc->controls = mv78460_mpp_controls; | ||
| 433 | soc->ncontrols = ARRAY_SIZE(mv78460_mpp_controls); | ||
| 434 | soc->modes = armada_xp_mpp_modes; | ||
| 435 | /* We don't necessarily want the full list of the | ||
| 436 | * armada_xp_mpp_modes, but only the first 'n' ones | ||
| 437 | * that are available on this SoC */ | ||
| 438 | soc->nmodes = mv78460_mpp_controls[0].npins; | ||
| 439 | soc->gpioranges = mv78460_mpp_gpio_ranges; | ||
| 440 | soc->ngpioranges = ARRAY_SIZE(mv78460_mpp_gpio_ranges); | ||
| 441 | break; | ||
| 442 | } | ||
| 443 | |||
| 444 | pdev->dev.platform_data = soc; | ||
| 445 | |||
| 446 | return mvebu_pinctrl_probe(pdev); | ||
| 447 | } | ||
| 448 | |||
| 449 | static int __devexit armada_xp_pinctrl_remove(struct platform_device *pdev) | ||
| 450 | { | ||
| 451 | return mvebu_pinctrl_remove(pdev); | ||
| 452 | } | ||
| 453 | |||
| 454 | static struct platform_driver armada_xp_pinctrl_driver = { | ||
| 455 | .driver = { | ||
| 456 | .name = "armada-xp-pinctrl", | ||
| 457 | .owner = THIS_MODULE, | ||
| 458 | .of_match_table = of_match_ptr(armada_xp_pinctrl_of_match), | ||
| 459 | }, | ||
| 460 | .probe = armada_xp_pinctrl_probe, | ||
| 461 | .remove = __devexit_p(armada_xp_pinctrl_remove), | ||
| 462 | }; | ||
| 463 | |||
| 464 | module_platform_driver(armada_xp_pinctrl_driver); | ||
| 465 | |||
| 466 | MODULE_AUTHOR("Thomas Petazzoni <thomas.petazzoni@free-electrons.com>"); | ||
| 467 | MODULE_DESCRIPTION("Marvell Armada XP pinctrl driver"); | ||
| 468 | MODULE_LICENSE("GPL v2"); | ||
diff --git a/drivers/pinctrl/pinctrl-dove.c b/drivers/pinctrl/pinctrl-dove.c new file mode 100644 index 000000000000..ffe74b27d66d --- /dev/null +++ b/drivers/pinctrl/pinctrl-dove.c | |||
| @@ -0,0 +1,620 @@ | |||
| 1 | /* | ||
| 2 | * Marvell Dove pinctrl driver based on mvebu pinctrl core | ||
| 3 | * | ||
| 4 | * Author: Sebastian Hesselbarth <sebastian.hesselbarth@gmail.com> | ||
| 5 | * | ||
| 6 | * This program is free software; you can redistribute it and/or modify | ||
| 7 | * it under the terms of the GNU General Public License as published by | ||
| 8 | * the Free Software Foundation; either version 2 of the License, or | ||
| 9 | * (at your option) any later version. | ||
| 10 | */ | ||
| 11 | |||
| 12 | #include <linux/err.h> | ||
| 13 | #include <linux/init.h> | ||
| 14 | #include <linux/io.h> | ||
| 15 | #include <linux/module.h> | ||
| 16 | #include <linux/bitops.h> | ||
| 17 | #include <linux/platform_device.h> | ||
| 18 | #include <linux/clk.h> | ||
| 19 | #include <linux/of.h> | ||
| 20 | #include <linux/of_device.h> | ||
| 21 | #include <linux/pinctrl/pinctrl.h> | ||
| 22 | |||
| 23 | #include "pinctrl-mvebu.h" | ||
| 24 | |||
| 25 | #define DOVE_SB_REGS_VIRT_BASE 0xfde00000 | ||
| 26 | #define DOVE_MPP_VIRT_BASE (DOVE_SB_REGS_VIRT_BASE | 0xd0200) | ||
| 27 | #define DOVE_PMU_MPP_GENERAL_CTRL (DOVE_MPP_VIRT_BASE + 0x10) | ||
| 28 | #define DOVE_AU0_AC97_SEL BIT(16) | ||
| 29 | #define DOVE_GLOBAL_CONFIG_1 (DOVE_SB_REGS_VIRT_BASE | 0xe802C) | ||
| 30 | #define DOVE_TWSI_ENABLE_OPTION1 BIT(7) | ||
| 31 | #define DOVE_GLOBAL_CONFIG_2 (DOVE_SB_REGS_VIRT_BASE | 0xe8030) | ||
| 32 | #define DOVE_TWSI_ENABLE_OPTION2 BIT(20) | ||
| 33 | #define DOVE_TWSI_ENABLE_OPTION3 BIT(21) | ||
| 34 | #define DOVE_TWSI_OPTION3_GPIO BIT(22) | ||
| 35 | #define DOVE_SSP_CTRL_STATUS_1 (DOVE_SB_REGS_VIRT_BASE | 0xe8034) | ||
| 36 | #define DOVE_SSP_ON_AU1 BIT(0) | ||
| 37 | #define DOVE_MPP_GENERAL_VIRT_BASE (DOVE_SB_REGS_VIRT_BASE | 0xe803c) | ||
| 38 | #define DOVE_AU1_SPDIFO_GPIO_EN BIT(1) | ||
| 39 | #define DOVE_NAND_GPIO_EN BIT(0) | ||
| 40 | #define DOVE_GPIO_LO_VIRT_BASE (DOVE_SB_REGS_VIRT_BASE | 0xd0400) | ||
| 41 | #define DOVE_MPP_CTRL4_VIRT_BASE (DOVE_GPIO_LO_VIRT_BASE + 0x40) | ||
| 42 | #define DOVE_SPI_GPIO_SEL BIT(5) | ||
| 43 | #define DOVE_UART1_GPIO_SEL BIT(4) | ||
| 44 | #define DOVE_AU1_GPIO_SEL BIT(3) | ||
| 45 | #define DOVE_CAM_GPIO_SEL BIT(2) | ||
| 46 | #define DOVE_SD1_GPIO_SEL BIT(1) | ||
| 47 | #define DOVE_SD0_GPIO_SEL BIT(0) | ||
| 48 | |||
| 49 | #define MPPS_PER_REG 8 | ||
| 50 | #define MPP_BITS 4 | ||
| 51 | #define MPP_MASK 0xf | ||
| 52 | |||
| 53 | #define CONFIG_PMU BIT(4) | ||
| 54 | |||
| 55 | static int dove_pmu_mpp_ctrl_get(struct mvebu_mpp_ctrl *ctrl, | ||
| 56 | unsigned long *config) | ||
| 57 | { | ||
| 58 | unsigned off = (ctrl->pid / MPPS_PER_REG) * MPP_BITS; | ||
| 59 | unsigned shift = (ctrl->pid % MPPS_PER_REG) * MPP_BITS; | ||
| 60 | unsigned long pmu = readl(DOVE_PMU_MPP_GENERAL_CTRL); | ||
| 61 | unsigned long mpp = readl(DOVE_MPP_VIRT_BASE + off); | ||
| 62 | |||
| 63 | if (pmu & (1 << ctrl->pid)) | ||
| 64 | *config = CONFIG_PMU; | ||
| 65 | else | ||
| 66 | *config = (mpp >> shift) & MPP_MASK; | ||
| 67 | return 0; | ||
| 68 | } | ||
| 69 | |||
| 70 | static int dove_pmu_mpp_ctrl_set(struct mvebu_mpp_ctrl *ctrl, | ||
| 71 | unsigned long config) | ||
| 72 | { | ||
| 73 | unsigned off = (ctrl->pid / MPPS_PER_REG) * MPP_BITS; | ||
| 74 | unsigned shift = (ctrl->pid % MPPS_PER_REG) * MPP_BITS; | ||
| 75 | unsigned long pmu = readl(DOVE_PMU_MPP_GENERAL_CTRL); | ||
| 76 | unsigned long mpp = readl(DOVE_MPP_VIRT_BASE + off); | ||
| 77 | |||
| 78 | if (config == CONFIG_PMU) | ||
| 79 | writel(pmu | (1 << ctrl->pid), DOVE_PMU_MPP_GENERAL_CTRL); | ||
| 80 | else { | ||
| 81 | writel(pmu & ~(1 << ctrl->pid), DOVE_PMU_MPP_GENERAL_CTRL); | ||
| 82 | mpp &= ~(MPP_MASK << shift); | ||
| 83 | mpp |= config << shift; | ||
| 84 | writel(mpp, DOVE_MPP_VIRT_BASE + off); | ||
| 85 | } | ||
| 86 | return 0; | ||
| 87 | } | ||
| 88 | |||
| 89 | static int dove_mpp4_ctrl_get(struct mvebu_mpp_ctrl *ctrl, | ||
| 90 | unsigned long *config) | ||
| 91 | { | ||
| 92 | unsigned long mpp4 = readl(DOVE_MPP_CTRL4_VIRT_BASE); | ||
| 93 | unsigned long mask; | ||
| 94 | |||
| 95 | switch (ctrl->pid) { | ||
| 96 | case 24: /* mpp_camera */ | ||
| 97 | mask = DOVE_CAM_GPIO_SEL; | ||
| 98 | break; | ||
| 99 | case 40: /* mpp_sdio0 */ | ||
| 100 | mask = DOVE_SD0_GPIO_SEL; | ||
| 101 | break; | ||
| 102 | case 46: /* mpp_sdio1 */ | ||
| 103 | mask = DOVE_SD1_GPIO_SEL; | ||
| 104 | break; | ||
| 105 | case 58: /* mpp_spi0 */ | ||
| 106 | mask = DOVE_SPI_GPIO_SEL; | ||
| 107 | break; | ||
| 108 | case 62: /* mpp_uart1 */ | ||
| 109 | mask = DOVE_UART1_GPIO_SEL; | ||
| 110 | break; | ||
| 111 | default: | ||
| 112 | return -EINVAL; | ||
| 113 | } | ||
| 114 | |||
| 115 | *config = ((mpp4 & mask) != 0); | ||
| 116 | |||
| 117 | return 0; | ||
| 118 | } | ||
| 119 | |||
| 120 | static int dove_mpp4_ctrl_set(struct mvebu_mpp_ctrl *ctrl, | ||
| 121 | unsigned long config) | ||
| 122 | { | ||
| 123 | unsigned long mpp4 = readl(DOVE_MPP_CTRL4_VIRT_BASE); | ||
| 124 | unsigned long mask; | ||
| 125 | |||
| 126 | switch (ctrl->pid) { | ||
| 127 | case 24: /* mpp_camera */ | ||
| 128 | mask = DOVE_CAM_GPIO_SEL; | ||
| 129 | break; | ||
| 130 | case 40: /* mpp_sdio0 */ | ||
| 131 | mask = DOVE_SD0_GPIO_SEL; | ||
| 132 | break; | ||
| 133 | case 46: /* mpp_sdio1 */ | ||
| 134 | mask = DOVE_SD1_GPIO_SEL; | ||
| 135 | break; | ||
| 136 | case 58: /* mpp_spi0 */ | ||
| 137 | mask = DOVE_SPI_GPIO_SEL; | ||
| 138 | break; | ||
| 139 | case 62: /* mpp_uart1 */ | ||
| 140 | mask = DOVE_UART1_GPIO_SEL; | ||
| 141 | break; | ||
| 142 | default: | ||
| 143 | return -EINVAL; | ||
| 144 | } | ||
| 145 | |||
| 146 | mpp4 &= ~mask; | ||
| 147 | if (config) | ||
| 148 | mpp4 |= mask; | ||
| 149 | |||
| 150 | writel(mpp4, DOVE_MPP_CTRL4_VIRT_BASE); | ||
| 151 | |||
| 152 | return 0; | ||
| 153 | } | ||
| 154 | |||
| 155 | static int dove_nand_ctrl_get(struct mvebu_mpp_ctrl *ctrl, | ||
| 156 | unsigned long *config) | ||
| 157 | { | ||
| 158 | unsigned long gmpp = readl(DOVE_MPP_GENERAL_VIRT_BASE); | ||
| 159 | |||
| 160 | *config = ((gmpp & DOVE_NAND_GPIO_EN) != 0); | ||
| 161 | |||
| 162 | return 0; | ||
| 163 | } | ||
| 164 | |||
| 165 | static int dove_nand_ctrl_set(struct mvebu_mpp_ctrl *ctrl, | ||
| 166 | unsigned long config) | ||
| 167 | { | ||
| 168 | unsigned long gmpp = readl(DOVE_MPP_GENERAL_VIRT_BASE); | ||
| 169 | |||
| 170 | gmpp &= ~DOVE_NAND_GPIO_EN; | ||
| 171 | if (config) | ||
| 172 | gmpp |= DOVE_NAND_GPIO_EN; | ||
| 173 | |||
| 174 | writel(gmpp, DOVE_MPP_GENERAL_VIRT_BASE); | ||
| 175 | |||
| 176 | return 0; | ||
| 177 | } | ||
| 178 | |||
| 179 | static int dove_audio0_ctrl_get(struct mvebu_mpp_ctrl *ctrl, | ||
| 180 | unsigned long *config) | ||
| 181 | { | ||
| 182 | unsigned long pmu = readl(DOVE_PMU_MPP_GENERAL_CTRL); | ||
| 183 | |||
| 184 | *config = ((pmu & DOVE_AU0_AC97_SEL) != 0); | ||
| 185 | |||
| 186 | return 0; | ||
| 187 | } | ||
| 188 | |||
| 189 | static int dove_audio0_ctrl_set(struct mvebu_mpp_ctrl *ctrl, | ||
| 190 | unsigned long config) | ||
| 191 | { | ||
| 192 | unsigned long pmu = readl(DOVE_PMU_MPP_GENERAL_CTRL); | ||
| 193 | |||
| 194 | pmu &= ~DOVE_AU0_AC97_SEL; | ||
| 195 | if (config) | ||
| 196 | pmu |= DOVE_AU0_AC97_SEL; | ||
| 197 | writel(pmu, DOVE_PMU_MPP_GENERAL_CTRL); | ||
| 198 | |||
| 199 | return 0; | ||
| 200 | } | ||
| 201 | |||
| 202 | static int dove_audio1_ctrl_get(struct mvebu_mpp_ctrl *ctrl, | ||
| 203 | unsigned long *config) | ||
| 204 | { | ||
| 205 | unsigned long mpp4 = readl(DOVE_MPP_CTRL4_VIRT_BASE); | ||
| 206 | unsigned long sspc1 = readl(DOVE_SSP_CTRL_STATUS_1); | ||
| 207 | unsigned long gmpp = readl(DOVE_MPP_GENERAL_VIRT_BASE); | ||
| 208 | unsigned long gcfg2 = readl(DOVE_GLOBAL_CONFIG_2); | ||
| 209 | |||
| 210 | *config = 0; | ||
| 211 | if (mpp4 & DOVE_AU1_GPIO_SEL) | ||
| 212 | *config |= BIT(3); | ||
| 213 | if (sspc1 & DOVE_SSP_ON_AU1) | ||
| 214 | *config |= BIT(2); | ||
| 215 | if (gmpp & DOVE_AU1_SPDIFO_GPIO_EN) | ||
| 216 | *config |= BIT(1); | ||
| 217 | if (gcfg2 & DOVE_TWSI_OPTION3_GPIO) | ||
| 218 | *config |= BIT(0); | ||
| 219 | |||
| 220 | /* SSP/TWSI only if I2S1 not set*/ | ||
| 221 | if ((*config & BIT(3)) == 0) | ||
| 222 | *config &= ~(BIT(2) | BIT(0)); | ||
| 223 | /* TWSI only if SPDIFO not set*/ | ||
| 224 | if ((*config & BIT(1)) == 0) | ||
| 225 | *config &= ~BIT(0); | ||
| 226 | return 0; | ||
| 227 | } | ||
| 228 | |||
| 229 | static int dove_audio1_ctrl_set(struct mvebu_mpp_ctrl *ctrl, | ||
| 230 | unsigned long config) | ||
| 231 | { | ||
| 232 | unsigned long mpp4 = readl(DOVE_MPP_CTRL4_VIRT_BASE); | ||
| 233 | unsigned long sspc1 = readl(DOVE_SSP_CTRL_STATUS_1); | ||
| 234 | unsigned long gmpp = readl(DOVE_MPP_GENERAL_VIRT_BASE); | ||
| 235 | unsigned long gcfg2 = readl(DOVE_GLOBAL_CONFIG_2); | ||
| 236 | |||
| 237 | if (config & BIT(0)) | ||
| 238 | gcfg2 |= DOVE_TWSI_OPTION3_GPIO; | ||
| 239 | if (config & BIT(1)) | ||
| 240 | gmpp |= DOVE_AU1_SPDIFO_GPIO_EN; | ||
| 241 | if (config & BIT(2)) | ||
| 242 | sspc1 |= DOVE_SSP_ON_AU1; | ||
| 243 | if (config & BIT(3)) | ||
| 244 | mpp4 |= DOVE_AU1_GPIO_SEL; | ||
| 245 | |||
| 246 | writel(mpp4, DOVE_MPP_CTRL4_VIRT_BASE); | ||
| 247 | writel(sspc1, DOVE_SSP_CTRL_STATUS_1); | ||
| 248 | writel(gmpp, DOVE_MPP_GENERAL_VIRT_BASE); | ||
| 249 | writel(gcfg2, DOVE_GLOBAL_CONFIG_2); | ||
| 250 | |||
| 251 | return 0; | ||
| 252 | } | ||
| 253 | |||
| 254 | /* mpp[52:57] gpio pins depend heavily on current config; | ||
| 255 | * gpio_req does not try to mux in gpio capabilities to not | ||
| 256 | * break other functions. If you require all mpps as gpio | ||
| 257 | * enforce gpio setting by pinctrl mapping. | ||
| 258 | */ | ||
| 259 | static int dove_audio1_ctrl_gpio_req(struct mvebu_mpp_ctrl *ctrl, u8 pid) | ||
| 260 | { | ||
| 261 | unsigned long config; | ||
| 262 | |||
| 263 | dove_audio1_ctrl_get(ctrl, &config); | ||
| 264 | |||
| 265 | switch (config) { | ||
| 266 | case 0x02: /* i2s1 : gpio[56:57] */ | ||
| 267 | case 0x0e: /* ssp : gpio[56:57] */ | ||
| 268 | if (pid >= 56) | ||
| 269 | return 0; | ||
| 270 | return -ENOTSUPP; | ||
| 271 | case 0x08: /* spdifo : gpio[52:55] */ | ||
| 272 | case 0x0b: /* twsi : gpio[52:55] */ | ||
| 273 | if (pid <= 55) | ||
| 274 | return 0; | ||
| 275 | return -ENOTSUPP; | ||
| 276 | case 0x0a: /* all gpio */ | ||
| 277 | return 0; | ||
| 278 | /* 0x00 : i2s1/spdifo : no gpio */ | ||
| 279 | /* 0x0c : ssp/spdifo : no gpio */ | ||
| 280 | /* 0x0f : ssp/twsi : no gpio */ | ||
| 281 | } | ||
| 282 | return -ENOTSUPP; | ||
| 283 | } | ||
| 284 | |||
| 285 | /* mpp[52:57] has gpio pins capable of in and out */ | ||
| 286 | static int dove_audio1_ctrl_gpio_dir(struct mvebu_mpp_ctrl *ctrl, u8 pid, | ||
| 287 | bool input) | ||
| 288 | { | ||
| 289 | if (pid < 52 || pid > 57) | ||
| 290 | return -ENOTSUPP; | ||
| 291 | return 0; | ||
| 292 | } | ||
| 293 | |||
| 294 | static int dove_twsi_ctrl_get(struct mvebu_mpp_ctrl *ctrl, | ||
| 295 | unsigned long *config) | ||
| 296 | { | ||
| 297 | unsigned long gcfg1 = readl(DOVE_GLOBAL_CONFIG_1); | ||
| 298 | unsigned long gcfg2 = readl(DOVE_GLOBAL_CONFIG_2); | ||
| 299 | |||
| 300 | *config = 0; | ||
| 301 | if (gcfg1 & DOVE_TWSI_ENABLE_OPTION1) | ||
| 302 | *config = 1; | ||
| 303 | else if (gcfg2 & DOVE_TWSI_ENABLE_OPTION2) | ||
| 304 | *config = 2; | ||
| 305 | else if (gcfg2 & DOVE_TWSI_ENABLE_OPTION3) | ||
| 306 | *config = 3; | ||
| 307 | |||
| 308 | return 0; | ||
| 309 | } | ||
| 310 | |||
| 311 | static int dove_twsi_ctrl_set(struct mvebu_mpp_ctrl *ctrl, | ||
| 312 | unsigned long config) | ||
| 313 | { | ||
| 314 | unsigned long gcfg1 = readl(DOVE_GLOBAL_CONFIG_1); | ||
| 315 | unsigned long gcfg2 = readl(DOVE_GLOBAL_CONFIG_2); | ||
| 316 | |||
| 317 | gcfg1 &= ~DOVE_TWSI_ENABLE_OPTION1; | ||
| 318 | gcfg2 &= ~(DOVE_TWSI_ENABLE_OPTION2 | DOVE_TWSI_ENABLE_OPTION2); | ||
| 319 | |||
| 320 | switch (config) { | ||
| 321 | case 1: | ||
| 322 | gcfg1 |= DOVE_TWSI_ENABLE_OPTION1; | ||
| 323 | break; | ||
| 324 | case 2: | ||
| 325 | gcfg2 |= DOVE_TWSI_ENABLE_OPTION2; | ||
| 326 | break; | ||
| 327 | case 3: | ||
| 328 | gcfg2 |= DOVE_TWSI_ENABLE_OPTION3; | ||
| 329 | break; | ||
| 330 | } | ||
| 331 | |||
| 332 | writel(gcfg1, DOVE_GLOBAL_CONFIG_1); | ||
| 333 | writel(gcfg2, DOVE_GLOBAL_CONFIG_2); | ||
| 334 | |||
| 335 | return 0; | ||
| 336 | } | ||
| 337 | |||
| 338 | static struct mvebu_mpp_ctrl dove_mpp_controls[] = { | ||
| 339 | MPP_FUNC_CTRL(0, 0, "mpp0", dove_pmu_mpp_ctrl), | ||
| 340 | MPP_FUNC_CTRL(1, 1, "mpp1", dove_pmu_mpp_ctrl), | ||
| 341 | MPP_FUNC_CTRL(2, 2, "mpp2", dove_pmu_mpp_ctrl), | ||
| 342 | MPP_FUNC_CTRL(3, 3, "mpp3", dove_pmu_mpp_ctrl), | ||
| 343 | MPP_FUNC_CTRL(4, 4, "mpp4", dove_pmu_mpp_ctrl), | ||
| 344 | MPP_FUNC_CTRL(5, 5, "mpp5", dove_pmu_mpp_ctrl), | ||
| 345 | MPP_FUNC_CTRL(6, 6, "mpp6", dove_pmu_mpp_ctrl), | ||
| 346 | MPP_FUNC_CTRL(7, 7, "mpp7", dove_pmu_mpp_ctrl), | ||
| 347 | MPP_FUNC_CTRL(8, 8, "mpp8", dove_pmu_mpp_ctrl), | ||
| 348 | MPP_FUNC_CTRL(9, 9, "mpp9", dove_pmu_mpp_ctrl), | ||
| 349 | MPP_FUNC_CTRL(10, 10, "mpp10", dove_pmu_mpp_ctrl), | ||
| 350 | MPP_FUNC_CTRL(11, 11, "mpp11", dove_pmu_mpp_ctrl), | ||
| 351 | MPP_FUNC_CTRL(12, 12, "mpp12", dove_pmu_mpp_ctrl), | ||
| 352 | MPP_FUNC_CTRL(13, 13, "mpp13", dove_pmu_mpp_ctrl), | ||
| 353 | MPP_FUNC_CTRL(14, 14, "mpp14", dove_pmu_mpp_ctrl), | ||
| 354 | MPP_FUNC_CTRL(15, 15, "mpp15", dove_pmu_mpp_ctrl), | ||
| 355 | MPP_REG_CTRL(16, 23), | ||
| 356 | MPP_FUNC_CTRL(24, 39, "mpp_camera", dove_mpp4_ctrl), | ||
| 357 | MPP_FUNC_CTRL(40, 45, "mpp_sdio0", dove_mpp4_ctrl), | ||
| 358 | MPP_FUNC_CTRL(46, 51, "mpp_sdio1", dove_mpp4_ctrl), | ||
| 359 | MPP_FUNC_GPIO_CTRL(52, 57, "mpp_audio1", dove_audio1_ctrl), | ||
| 360 | MPP_FUNC_CTRL(58, 61, "mpp_spi0", dove_mpp4_ctrl), | ||
| 361 | MPP_FUNC_CTRL(62, 63, "mpp_uart1", dove_mpp4_ctrl), | ||
| 362 | MPP_FUNC_CTRL(64, 71, "mpp_nand", dove_nand_ctrl), | ||
| 363 | MPP_FUNC_CTRL(72, 72, "audio0", dove_audio0_ctrl), | ||
| 364 | MPP_FUNC_CTRL(73, 73, "twsi", dove_twsi_ctrl), | ||
| 365 | }; | ||
| 366 | |||
| 367 | static struct mvebu_mpp_mode dove_mpp_modes[] = { | ||
| 368 | MPP_MODE(0, | ||
| 369 | MPP_FUNCTION(0x00, "gpio", NULL), | ||
| 370 | MPP_FUNCTION(0x02, "uart2", "rts"), | ||
| 371 | MPP_FUNCTION(0x03, "sdio0", "cd"), | ||
| 372 | MPP_FUNCTION(0x0f, "lcd0", "pwm"), | ||
| 373 | MPP_FUNCTION(0x10, "pmu", NULL)), | ||
| 374 | MPP_MODE(1, | ||
| 375 | MPP_FUNCTION(0x00, "gpio", NULL), | ||
| 376 | MPP_FUNCTION(0x02, "uart2", "cts"), | ||
| 377 | MPP_FUNCTION(0x03, "sdio0", "wp"), | ||
| 378 | MPP_FUNCTION(0x0f, "lcd1", "pwm"), | ||
| 379 | MPP_FUNCTION(0x10, "pmu", NULL)), | ||
| 380 | MPP_MODE(2, | ||
| 381 | MPP_FUNCTION(0x00, "gpio", NULL), | ||
| 382 | MPP_FUNCTION(0x01, "sata", "prsnt"), | ||
| 383 | MPP_FUNCTION(0x02, "uart2", "txd"), | ||
| 384 | MPP_FUNCTION(0x03, "sdio0", "buspwr"), | ||
| 385 | MPP_FUNCTION(0x04, "uart1", "rts"), | ||
| 386 | MPP_FUNCTION(0x10, "pmu", NULL)), | ||
| 387 | MPP_MODE(3, | ||
| 388 | MPP_FUNCTION(0x00, "gpio", NULL), | ||
| 389 | MPP_FUNCTION(0x01, "sata", "act"), | ||
| 390 | MPP_FUNCTION(0x02, "uart2", "rxd"), | ||
| 391 | MPP_FUNCTION(0x03, "sdio0", "ledctrl"), | ||
| 392 | MPP_FUNCTION(0x04, "uart1", "cts"), | ||
| 393 | MPP_FUNCTION(0x0f, "lcd-spi", "cs1"), | ||
| 394 | MPP_FUNCTION(0x10, "pmu", NULL)), | ||
| 395 | MPP_MODE(4, | ||
| 396 | MPP_FUNCTION(0x00, "gpio", NULL), | ||
| 397 | MPP_FUNCTION(0x02, "uart3", "rts"), | ||
| 398 | MPP_FUNCTION(0x03, "sdio1", "cd"), | ||
| 399 | MPP_FUNCTION(0x04, "spi1", "miso"), | ||
| 400 | MPP_FUNCTION(0x10, "pmu", NULL)), | ||
| 401 | MPP_MODE(5, | ||
| 402 | MPP_FUNCTION(0x00, "gpio", NULL), | ||
| 403 | MPP_FUNCTION(0x02, "uart3", "cts"), | ||
| 404 | MPP_FUNCTION(0x03, "sdio1", "wp"), | ||
| 405 | MPP_FUNCTION(0x04, "spi1", "cs"), | ||
| 406 | MPP_FUNCTION(0x10, "pmu", NULL)), | ||
| 407 | MPP_MODE(6, | ||
| 408 | MPP_FUNCTION(0x00, "gpio", NULL), | ||
| 409 | MPP_FUNCTION(0x02, "uart3", "txd"), | ||
| 410 | MPP_FUNCTION(0x03, "sdio1", "buspwr"), | ||
| 411 | MPP_FUNCTION(0x04, "spi1", "mosi"), | ||
| 412 | MPP_FUNCTION(0x10, "pmu", NULL)), | ||
| 413 | MPP_MODE(7, | ||
| 414 | MPP_FUNCTION(0x00, "gpio", NULL), | ||
| 415 | MPP_FUNCTION(0x02, "uart3", "rxd"), | ||
| 416 | MPP_FUNCTION(0x03, "sdio1", "ledctrl"), | ||
| 417 | MPP_FUNCTION(0x04, "spi1", "sck"), | ||
| 418 | MPP_FUNCTION(0x10, "pmu", NULL)), | ||
| 419 | MPP_MODE(8, | ||
| 420 | MPP_FUNCTION(0x00, "gpio", NULL), | ||
| 421 | MPP_FUNCTION(0x01, "watchdog", "rstout"), | ||
| 422 | MPP_FUNCTION(0x10, "pmu", NULL)), | ||
| 423 | MPP_MODE(9, | ||
| 424 | MPP_FUNCTION(0x00, "gpio", NULL), | ||
| 425 | MPP_FUNCTION(0x05, "pex1", "clkreq"), | ||
| 426 | MPP_FUNCTION(0x10, "pmu", NULL)), | ||
| 427 | MPP_MODE(10, | ||
| 428 | MPP_FUNCTION(0x00, "gpio", NULL), | ||
| 429 | MPP_FUNCTION(0x05, "ssp", "sclk"), | ||
| 430 | MPP_FUNCTION(0x10, "pmu", NULL)), | ||
| 431 | MPP_MODE(11, | ||
| 432 | MPP_FUNCTION(0x00, "gpio", NULL), | ||
| 433 | MPP_FUNCTION(0x01, "sata", "prsnt"), | ||
| 434 | MPP_FUNCTION(0x02, "sata-1", "act"), | ||
| 435 | MPP_FUNCTION(0x03, "sdio0", "ledctrl"), | ||
| 436 | MPP_FUNCTION(0x04, "sdio1", "ledctrl"), | ||
| 437 | MPP_FUNCTION(0x05, "pex0", "clkreq"), | ||
| 438 | MPP_FUNCTION(0x10, "pmu", NULL)), | ||
| 439 | MPP_MODE(12, | ||
| 440 | MPP_FUNCTION(0x00, "gpio", NULL), | ||
| 441 | MPP_FUNCTION(0x01, "sata", "act"), | ||
| 442 | MPP_FUNCTION(0x02, "uart2", "rts"), | ||
| 443 | MPP_FUNCTION(0x03, "audio0", "extclk"), | ||
| 444 | MPP_FUNCTION(0x04, "sdio1", "cd"), | ||
| 445 | MPP_FUNCTION(0x10, "pmu", NULL)), | ||
| 446 | MPP_MODE(13, | ||
| 447 | MPP_FUNCTION(0x00, "gpio", NULL), | ||
| 448 | MPP_FUNCTION(0x02, "uart2", "cts"), | ||
| 449 | MPP_FUNCTION(0x03, "audio1", "extclk"), | ||
| 450 | MPP_FUNCTION(0x04, "sdio1", "wp"), | ||
| 451 | MPP_FUNCTION(0x05, "ssp", "extclk"), | ||
| 452 | MPP_FUNCTION(0x10, "pmu", NULL)), | ||
| 453 | MPP_MODE(14, | ||
| 454 | MPP_FUNCTION(0x00, "gpio", NULL), | ||
| 455 | MPP_FUNCTION(0x02, "uart2", "txd"), | ||
| 456 | MPP_FUNCTION(0x04, "sdio1", "buspwr"), | ||
| 457 | MPP_FUNCTION(0x05, "ssp", "rxd"), | ||
| 458 | MPP_FUNCTION(0x10, "pmu", NULL)), | ||
| 459 | MPP_MODE(15, | ||
| 460 | MPP_FUNCTION(0x00, "gpio", NULL), | ||
| 461 | MPP_FUNCTION(0x02, "uart2", "rxd"), | ||
| 462 | MPP_FUNCTION(0x04, "sdio1", "ledctrl"), | ||
| 463 | MPP_FUNCTION(0x05, "ssp", "sfrm"), | ||
| 464 | MPP_FUNCTION(0x10, "pmu", NULL)), | ||
| 465 | MPP_MODE(16, | ||
| 466 | MPP_FUNCTION(0x00, "gpio", NULL), | ||
| 467 | MPP_FUNCTION(0x02, "uart3", "rts"), | ||
| 468 | MPP_FUNCTION(0x03, "sdio0", "cd"), | ||
| 469 | MPP_FUNCTION(0x04, "lcd-spi", "cs1"), | ||
| 470 | MPP_FUNCTION(0x05, "ac97", "sdi1")), | ||
| 471 | MPP_MODE(17, | ||
| 472 | MPP_FUNCTION(0x00, "gpio", NULL), | ||
| 473 | MPP_FUNCTION(0x01, "ac97-1", "sysclko"), | ||
| 474 | MPP_FUNCTION(0x02, "uart3", "cts"), | ||
| 475 | MPP_FUNCTION(0x03, "sdio0", "wp"), | ||
| 476 | MPP_FUNCTION(0x04, "twsi", "sda"), | ||
| 477 | MPP_FUNCTION(0x05, "ac97", "sdi2")), | ||
| 478 | MPP_MODE(18, | ||
| 479 | MPP_FUNCTION(0x00, "gpio", NULL), | ||
| 480 | MPP_FUNCTION(0x02, "uart3", "txd"), | ||
| 481 | MPP_FUNCTION(0x03, "sdio0", "buspwr"), | ||
| 482 | MPP_FUNCTION(0x04, "lcd0", "pwm"), | ||
| 483 | MPP_FUNCTION(0x05, "ac97", "sdi3")), | ||
| 484 | MPP_MODE(19, | ||
| 485 | MPP_FUNCTION(0x00, "gpio", NULL), | ||
| 486 | MPP_FUNCTION(0x02, "uart3", "rxd"), | ||
| 487 | MPP_FUNCTION(0x03, "sdio0", "ledctrl"), | ||
| 488 | MPP_FUNCTION(0x04, "twsi", "sck")), | ||
| 489 | MPP_MODE(20, | ||
| 490 | MPP_FUNCTION(0x00, "gpio", NULL), | ||
| 491 | MPP_FUNCTION(0x01, "ac97", "sysclko"), | ||
| 492 | MPP_FUNCTION(0x02, "lcd-spi", "miso"), | ||
| 493 | MPP_FUNCTION(0x03, "sdio1", "cd"), | ||
| 494 | MPP_FUNCTION(0x05, "sdio0", "cd"), | ||
| 495 | MPP_FUNCTION(0x06, "spi1", "miso")), | ||
| 496 | MPP_MODE(21, | ||
| 497 | MPP_FUNCTION(0x00, "gpio", NULL), | ||
| 498 | MPP_FUNCTION(0x01, "uart1", "rts"), | ||
| 499 | MPP_FUNCTION(0x02, "lcd-spi", "cs0"), | ||
| 500 | MPP_FUNCTION(0x03, "sdio1", "wp"), | ||
| 501 | MPP_FUNCTION(0x04, "ssp", "sfrm"), | ||
| 502 | MPP_FUNCTION(0x05, "sdio0", "wp"), | ||
| 503 | MPP_FUNCTION(0x06, "spi1", "cs")), | ||
| 504 | MPP_MODE(22, | ||
| 505 | MPP_FUNCTION(0x00, "gpio", NULL), | ||
| 506 | MPP_FUNCTION(0x01, "uart1", "cts"), | ||
| 507 | MPP_FUNCTION(0x02, "lcd-spi", "mosi"), | ||
| 508 | MPP_FUNCTION(0x03, "sdio1", "buspwr"), | ||
| 509 | MPP_FUNCTION(0x04, "ssp", "txd"), | ||
| 510 | MPP_FUNCTION(0x05, "sdio0", "buspwr"), | ||
| 511 | MPP_FUNCTION(0x06, "spi1", "mosi")), | ||
| 512 | MPP_MODE(23, | ||
| 513 | MPP_FUNCTION(0x00, "gpio", NULL), | ||
| 514 | MPP_FUNCTION(0x02, "lcd-spi", "sck"), | ||
| 515 | MPP_FUNCTION(0x03, "sdio1", "ledctrl"), | ||
| 516 | MPP_FUNCTION(0x04, "ssp", "sclk"), | ||
| 517 | MPP_FUNCTION(0x05, "sdio0", "ledctrl"), | ||
| 518 | MPP_FUNCTION(0x06, "spi1", "sck")), | ||
| 519 | MPP_MODE(24, | ||
| 520 | MPP_FUNCTION(0x00, "camera", NULL), | ||
| 521 | MPP_FUNCTION(0x01, "gpio", NULL)), | ||
| 522 | MPP_MODE(40, | ||
| 523 | MPP_FUNCTION(0x00, "sdio0", NULL), | ||
| 524 | MPP_FUNCTION(0x01, "gpio", NULL)), | ||
| 525 | MPP_MODE(46, | ||
| 526 | MPP_FUNCTION(0x00, "sdio1", NULL), | ||
| 527 | MPP_FUNCTION(0x01, "gpio", NULL)), | ||
| 528 | MPP_MODE(52, | ||
| 529 | MPP_FUNCTION(0x00, "i2s1/spdifo", NULL), | ||
| 530 | MPP_FUNCTION(0x02, "i2s1", NULL), | ||
| 531 | MPP_FUNCTION(0x08, "spdifo", NULL), | ||
| 532 | MPP_FUNCTION(0x0a, "gpio", NULL), | ||
| 533 | MPP_FUNCTION(0x0b, "twsi", NULL), | ||
| 534 | MPP_FUNCTION(0x0c, "ssp/spdifo", NULL), | ||
| 535 | MPP_FUNCTION(0x0e, "ssp", NULL), | ||
| 536 | MPP_FUNCTION(0x0f, "ssp/twsi", NULL)), | ||
| 537 | MPP_MODE(58, | ||
| 538 | MPP_FUNCTION(0x00, "spi0", NULL), | ||
| 539 | MPP_FUNCTION(0x01, "gpio", NULL)), | ||
| 540 | MPP_MODE(62, | ||
| 541 | MPP_FUNCTION(0x00, "uart1", NULL), | ||
| 542 | MPP_FUNCTION(0x01, "gpio", NULL)), | ||
| 543 | MPP_MODE(64, | ||
| 544 | MPP_FUNCTION(0x00, "nand", NULL), | ||
| 545 | MPP_FUNCTION(0x01, "gpo", NULL)), | ||
| 546 | MPP_MODE(72, | ||
| 547 | MPP_FUNCTION(0x00, "i2s", NULL), | ||
| 548 | MPP_FUNCTION(0x01, "ac97", NULL)), | ||
| 549 | MPP_MODE(73, | ||
| 550 | MPP_FUNCTION(0x00, "twsi-none", NULL), | ||
| 551 | MPP_FUNCTION(0x01, "twsi-opt1", NULL), | ||
| 552 | MPP_FUNCTION(0x02, "twsi-opt2", NULL), | ||
| 553 | MPP_FUNCTION(0x03, "twsi-opt3", NULL)), | ||
| 554 | }; | ||
| 555 | |||
| 556 | static struct pinctrl_gpio_range dove_mpp_gpio_ranges[] = { | ||
| 557 | MPP_GPIO_RANGE(0, 0, 0, 32), | ||
| 558 | MPP_GPIO_RANGE(1, 32, 32, 32), | ||
| 559 | MPP_GPIO_RANGE(2, 64, 64, 8), | ||
| 560 | }; | ||
| 561 | |||
| 562 | static struct mvebu_pinctrl_soc_info dove_pinctrl_info = { | ||
| 563 | .controls = dove_mpp_controls, | ||
| 564 | .ncontrols = ARRAY_SIZE(dove_mpp_controls), | ||
| 565 | .modes = dove_mpp_modes, | ||
| 566 | .nmodes = ARRAY_SIZE(dove_mpp_modes), | ||
| 567 | .gpioranges = dove_mpp_gpio_ranges, | ||
| 568 | .ngpioranges = ARRAY_SIZE(dove_mpp_gpio_ranges), | ||
| 569 | .variant = 0, | ||
| 570 | }; | ||
| 571 | |||
| 572 | static struct clk *clk; | ||
| 573 | |||
| 574 | static struct of_device_id dove_pinctrl_of_match[] __devinitdata = { | ||
| 575 | { .compatible = "marvell,dove-pinctrl", .data = &dove_pinctrl_info }, | ||
| 576 | { } | ||
| 577 | }; | ||
| 578 | |||
| 579 | static int __devinit dove_pinctrl_probe(struct platform_device *pdev) | ||
| 580 | { | ||
| 581 | const struct of_device_id *match = | ||
| 582 | of_match_device(dove_pinctrl_of_match, &pdev->dev); | ||
| 583 | pdev->dev.platform_data = match->data; | ||
| 584 | |||
| 585 | /* | ||
| 586 | * General MPP Configuration Register is part of pdma registers. | ||
| 587 | * grab clk to make sure it is ticking. | ||
| 588 | */ | ||
| 589 | clk = devm_clk_get(&pdev->dev, NULL); | ||
| 590 | if (!IS_ERR(clk)) | ||
| 591 | clk_prepare_enable(clk); | ||
| 592 | |||
| 593 | return mvebu_pinctrl_probe(pdev); | ||
| 594 | } | ||
| 595 | |||
| 596 | static int __devexit dove_pinctrl_remove(struct platform_device *pdev) | ||
| 597 | { | ||
| 598 | int ret; | ||
| 599 | |||
| 600 | ret = mvebu_pinctrl_remove(pdev); | ||
| 601 | if (!IS_ERR(clk)) | ||
| 602 | clk_disable_unprepare(clk); | ||
| 603 | return ret; | ||
| 604 | } | ||
| 605 | |||
| 606 | static struct platform_driver dove_pinctrl_driver = { | ||
| 607 | .driver = { | ||
| 608 | .name = "dove-pinctrl", | ||
| 609 | .owner = THIS_MODULE, | ||
| 610 | .of_match_table = of_match_ptr(dove_pinctrl_of_match), | ||
| 611 | }, | ||
| 612 | .probe = dove_pinctrl_probe, | ||
| 613 | .remove = __devexit_p(dove_pinctrl_remove), | ||
| 614 | }; | ||
| 615 | |||
| 616 | module_platform_driver(dove_pinctrl_driver); | ||
| 617 | |||
| 618 | MODULE_AUTHOR("Sebastian Hesselbarth <sebastian.hesselbarth@gmail.com>"); | ||
| 619 | MODULE_DESCRIPTION("Marvell Dove pinctrl driver"); | ||
| 620 | MODULE_LICENSE("GPL v2"); | ||
diff --git a/drivers/pinctrl/pinctrl-kirkwood.c b/drivers/pinctrl/pinctrl-kirkwood.c new file mode 100644 index 000000000000..9a74ef674a0e --- /dev/null +++ b/drivers/pinctrl/pinctrl-kirkwood.c | |||
| @@ -0,0 +1,472 @@ | |||
| 1 | /* | ||
| 2 | * Marvell Kirkwood pinctrl driver based on mvebu pinctrl core | ||
| 3 | * | ||
| 4 | * Author: Sebastian Hesselbarth <sebastian.hesselbarth@gmail.com> | ||
| 5 | * | ||
| 6 | * This program is free software; you can redistribute it and/or modify | ||
| 7 | * it under the terms of the GNU General Public License as published by | ||
| 8 | * the Free Software Foundation; either version 2 of the License, or | ||
| 9 | * (at your option) any later version. | ||
| 10 | */ | ||
| 11 | |||
| 12 | #include <linux/err.h> | ||
| 13 | #include <linux/init.h> | ||
| 14 | #include <linux/io.h> | ||
| 15 | #include <linux/module.h> | ||
| 16 | #include <linux/platform_device.h> | ||
| 17 | #include <linux/clk.h> | ||
| 18 | #include <linux/of.h> | ||
| 19 | #include <linux/of_device.h> | ||
| 20 | #include <linux/pinctrl/pinctrl.h> | ||
| 21 | |||
| 22 | #include "pinctrl-mvebu.h" | ||
| 23 | |||
| 24 | #define V(f6180, f6190, f6192, f6281, f6282) \ | ||
| 25 | ((f6180 << 0) | (f6190 << 1) | (f6192 << 2) | \ | ||
| 26 | (f6281 << 3) | (f6282 << 4)) | ||
| 27 | |||
| 28 | enum kirkwood_variant { | ||
| 29 | VARIANT_MV88F6180 = V(1, 0, 0, 0, 0), | ||
| 30 | VARIANT_MV88F6190 = V(0, 1, 0, 0, 0), | ||
| 31 | VARIANT_MV88F6192 = V(0, 0, 1, 0, 0), | ||
| 32 | VARIANT_MV88F6281 = V(0, 0, 0, 1, 0), | ||
| 33 | VARIANT_MV88F6282 = V(0, 0, 0, 0, 1), | ||
| 34 | }; | ||
| 35 | |||
| 36 | static struct mvebu_mpp_mode mv88f6xxx_mpp_modes[] = { | ||
| 37 | MPP_MODE(0, | ||
| 38 | MPP_VAR_FUNCTION(0x0, "gpio", NULL, V(1, 1, 1, 1, 1)), | ||
| 39 | MPP_VAR_FUNCTION(0x1, "nand", "io2", V(1, 1, 1, 1, 1)), | ||
| 40 | MPP_VAR_FUNCTION(0x2, "spi", "cs", V(1, 1, 1, 1, 1))), | ||
| 41 | MPP_MODE(1, | ||
| 42 | MPP_VAR_FUNCTION(0x0, "gpo", NULL, V(1, 1, 1, 1, 1)), | ||
| 43 | MPP_VAR_FUNCTION(0x1, "nand", "io3", V(1, 1, 1, 1, 1)), | ||
| 44 | MPP_VAR_FUNCTION(0x2, "spi", "mosi", V(1, 1, 1, 1, 1))), | ||
| 45 | MPP_MODE(2, | ||
| 46 | MPP_VAR_FUNCTION(0x0, "gpo", NULL, V(1, 1, 1, 1, 1)), | ||
| 47 | MPP_VAR_FUNCTION(0x1, "nand", "io4", V(1, 1, 1, 1, 1)), | ||
| 48 | MPP_VAR_FUNCTION(0x2, "spi", "sck", V(1, 1, 1, 1, 1))), | ||
| 49 | MPP_MODE(3, | ||
| 50 | MPP_VAR_FUNCTION(0x0, "gpo", NULL, V(1, 1, 1, 1, 1)), | ||
| 51 | MPP_VAR_FUNCTION(0x1, "nand", "io5", V(1, 1, 1, 1, 1)), | ||
| 52 | MPP_VAR_FUNCTION(0x2, "spi", "miso", V(1, 1, 1, 1, 1))), | ||
| 53 | MPP_MODE(4, | ||
| 54 | MPP_VAR_FUNCTION(0x0, "gpio", NULL, V(1, 1, 1, 1, 1)), | ||
| 55 | MPP_VAR_FUNCTION(0x1, "nand", "io6", V(1, 1, 1, 1, 1)), | ||
| 56 | MPP_VAR_FUNCTION(0x2, "uart0", "rxd", V(1, 1, 1, 1, 1)), | ||
| 57 | MPP_VAR_FUNCTION(0x5, "sata1", "act", V(0, 0, 1, 1, 1)), | ||
| 58 | MPP_VAR_FUNCTION(0xb, "lcd", "hsync", V(0, 0, 0, 0, 1)), | ||
| 59 | MPP_VAR_FUNCTION(0xd, "ptp", "clk", V(1, 1, 1, 1, 0))), | ||
| 60 | MPP_MODE(5, | ||
| 61 | MPP_VAR_FUNCTION(0x0, "gpo", NULL, V(1, 1, 1, 1, 1)), | ||
| 62 | MPP_VAR_FUNCTION(0x1, "nand", "io7", V(1, 1, 1, 1, 1)), | ||
| 63 | MPP_VAR_FUNCTION(0x2, "uart0", "txd", V(1, 1, 1, 1, 1)), | ||
| 64 | MPP_VAR_FUNCTION(0x4, "ptp", "trig", V(1, 1, 1, 1, 0)), | ||
| 65 | MPP_VAR_FUNCTION(0x5, "sata0", "act", V(0, 1, 1, 1, 1)), | ||
| 66 | MPP_VAR_FUNCTION(0xb, "lcd", "vsync", V(0, 0, 0, 0, 1))), | ||
| 67 | MPP_MODE(6, | ||
| 68 | MPP_VAR_FUNCTION(0x0, "sysrst", "out", V(1, 1, 1, 1, 1)), | ||
| 69 | MPP_VAR_FUNCTION(0x1, "spi", "mosi", V(1, 1, 1, 1, 1)), | ||
| 70 | MPP_VAR_FUNCTION(0x2, "ptp", "trig", V(1, 1, 1, 1, 0))), | ||
| 71 | MPP_MODE(7, | ||
| 72 | MPP_VAR_FUNCTION(0x0, "gpo", NULL, V(1, 1, 1, 1, 1)), | ||
| 73 | MPP_VAR_FUNCTION(0x1, "pex", "rsto", V(1, 1, 1, 1, 0)), | ||
| 74 | MPP_VAR_FUNCTION(0x2, "spi", "cs", V(1, 1, 1, 1, 1)), | ||
| 75 | MPP_VAR_FUNCTION(0x3, "ptp", "trig", V(1, 1, 1, 1, 0)), | ||
| 76 | MPP_VAR_FUNCTION(0xb, "lcd", "pwm", V(0, 0, 0, 0, 1))), | ||
| 77 | MPP_MODE(8, | ||
| 78 | MPP_VAR_FUNCTION(0x0, "gpio", NULL, V(1, 1, 1, 1, 1)), | ||
| 79 | MPP_VAR_FUNCTION(0x1, "twsi0", "sda", V(1, 1, 1, 1, 1)), | ||
| 80 | MPP_VAR_FUNCTION(0x2, "uart0", "rts", V(1, 1, 1, 1, 1)), | ||
| 81 | MPP_VAR_FUNCTION(0x3, "uart1", "rts", V(1, 1, 1, 1, 1)), | ||
| 82 | MPP_VAR_FUNCTION(0x4, "mii-1", "rxerr", V(0, 1, 1, 1, 1)), | ||
| 83 | MPP_VAR_FUNCTION(0x5, "sata1", "prsnt", V(0, 0, 1, 1, 1)), | ||
| 84 | MPP_VAR_FUNCTION(0xc, "ptp", "clk", V(1, 1, 1, 1, 0)), | ||
| 85 | MPP_VAR_FUNCTION(0xd, "mii", "col", V(1, 1, 1, 1, 1))), | ||
| 86 | MPP_MODE(9, | ||
| 87 | MPP_VAR_FUNCTION(0x0, "gpio", NULL, V(1, 1, 1, 1, 1)), | ||
| 88 | MPP_VAR_FUNCTION(0x1, "twsi0", "sck", V(1, 1, 1, 1, 1)), | ||
| 89 | MPP_VAR_FUNCTION(0x2, "uart0", "cts", V(1, 1, 1, 1, 1)), | ||
| 90 | MPP_VAR_FUNCTION(0x3, "uart1", "cts", V(1, 1, 1, 1, 1)), | ||
| 91 | MPP_VAR_FUNCTION(0x5, "sata0", "prsnt", V(0, 1, 1, 1, 1)), | ||
| 92 | MPP_VAR_FUNCTION(0xc, "ptp", "evreq", V(1, 1, 1, 1, 0)), | ||
| 93 | MPP_VAR_FUNCTION(0xd, "mii", "crs", V(1, 1, 1, 1, 1))), | ||
| 94 | MPP_MODE(10, | ||
| 95 | MPP_VAR_FUNCTION(0x0, "gpo", NULL, V(1, 1, 1, 1, 1)), | ||
| 96 | MPP_VAR_FUNCTION(0x2, "spi", "sck", V(1, 1, 1, 1, 1)), | ||
| 97 | MPP_VAR_FUNCTION(0X3, "uart0", "txd", V(1, 1, 1, 1, 1)), | ||
| 98 | MPP_VAR_FUNCTION(0x5, "sata1", "act", V(0, 0, 1, 1, 1)), | ||
| 99 | MPP_VAR_FUNCTION(0xc, "ptp", "trig", V(1, 1, 1, 1, 0))), | ||
| 100 | MPP_MODE(11, | ||
| 101 | MPP_VAR_FUNCTION(0x0, "gpio", NULL, V(1, 1, 1, 1, 1)), | ||
| 102 | MPP_VAR_FUNCTION(0x2, "spi", "miso", V(1, 1, 1, 1, 1)), | ||
| 103 | MPP_VAR_FUNCTION(0x3, "uart0", "rxd", V(1, 1, 1, 1, 1)), | ||
| 104 | MPP_VAR_FUNCTION(0x4, "ptp-1", "evreq", V(1, 1, 1, 1, 0)), | ||
| 105 | MPP_VAR_FUNCTION(0xc, "ptp-2", "trig", V(1, 1, 1, 1, 0)), | ||
| 106 | MPP_VAR_FUNCTION(0xd, "ptp", "clk", V(1, 1, 1, 1, 0)), | ||
| 107 | MPP_VAR_FUNCTION(0x5, "sata0", "act", V(0, 1, 1, 1, 1))), | ||
| 108 | MPP_MODE(12, | ||
| 109 | MPP_VAR_FUNCTION(0x0, "gpo", NULL, V(1, 1, 1, 0, 1)), | ||
| 110 | MPP_VAR_FUNCTION(0x0, "gpio", NULL, V(0, 0, 0, 1, 0)), | ||
| 111 | MPP_VAR_FUNCTION(0x1, "sdio", "clk", V(1, 1, 1, 1, 1)), | ||
| 112 | MPP_VAR_FUNCTION(0xa, "audio", "spdifo", V(0, 0, 0, 0, 1)), | ||
| 113 | MPP_VAR_FUNCTION(0xb, "spi", "mosi", V(0, 0, 0, 0, 1)), | ||
| 114 | MPP_VAR_FUNCTION(0xd, "twsi1", "sda", V(0, 0, 0, 0, 1))), | ||
| 115 | MPP_MODE(13, | ||
| 116 | MPP_VAR_FUNCTION(0x0, "gpio", NULL, V(1, 1, 1, 1, 1)), | ||
| 117 | MPP_VAR_FUNCTION(0x1, "sdio", "cmd", V(1, 1, 1, 1, 1)), | ||
| 118 | MPP_VAR_FUNCTION(0x3, "uart1", "txd", V(1, 1, 1, 1, 1)), | ||
| 119 | MPP_VAR_FUNCTION(0xa, "audio", "rmclk", V(0, 0, 0, 0, 1)), | ||
| 120 | MPP_VAR_FUNCTION(0xb, "lcd", "pwm", V(0, 0, 0, 0, 1))), | ||
| 121 | MPP_MODE(14, | ||
| 122 | MPP_VAR_FUNCTION(0x0, "gpio", NULL, V(1, 1, 1, 1, 1)), | ||
| 123 | MPP_VAR_FUNCTION(0x1, "sdio", "d0", V(1, 1, 1, 1, 1)), | ||
| 124 | MPP_VAR_FUNCTION(0x3, "uart1", "rxd", V(1, 1, 1, 1, 1)), | ||
| 125 | MPP_VAR_FUNCTION(0x4, "sata1", "prsnt", V(0, 0, 1, 1, 1)), | ||
| 126 | MPP_VAR_FUNCTION(0xa, "audio", "spdifi", V(0, 0, 0, 0, 1)), | ||
| 127 | MPP_VAR_FUNCTION(0xb, "audio-1", "sdi", V(0, 0, 0, 0, 1)), | ||
| 128 | MPP_VAR_FUNCTION(0xd, "mii", "col", V(1, 1, 1, 1, 1))), | ||
| 129 | MPP_MODE(15, | ||
| 130 | MPP_VAR_FUNCTION(0x0, "gpio", NULL, V(1, 1, 1, 1, 1)), | ||
| 131 | MPP_VAR_FUNCTION(0x1, "sdio", "d1", V(1, 1, 1, 1, 1)), | ||
| 132 | MPP_VAR_FUNCTION(0x2, "uart0", "rts", V(1, 1, 1, 1, 1)), | ||
| 133 | MPP_VAR_FUNCTION(0x3, "uart1", "txd", V(1, 1, 1, 1, 1)), | ||
| 134 | MPP_VAR_FUNCTION(0x4, "sata0", "act", V(0, 1, 1, 1, 1)), | ||
| 135 | MPP_VAR_FUNCTION(0xb, "spi", "cs", V(0, 0, 0, 0, 1))), | ||
| 136 | MPP_MODE(16, | ||
| 137 | MPP_VAR_FUNCTION(0x0, "gpio", NULL, V(1, 1, 1, 1, 1)), | ||
| 138 | MPP_VAR_FUNCTION(0x1, "sdio", "d2", V(1, 1, 1, 1, 1)), | ||
| 139 | MPP_VAR_FUNCTION(0x2, "uart0", "cts", V(1, 1, 1, 1, 1)), | ||
| 140 | MPP_VAR_FUNCTION(0x3, "uart1", "rxd", V(1, 1, 1, 1, 1)), | ||
| 141 | MPP_VAR_FUNCTION(0x4, "sata1", "act", V(0, 0, 1, 1, 1)), | ||
| 142 | MPP_VAR_FUNCTION(0xb, "lcd", "extclk", V(0, 0, 0, 0, 1)), | ||
| 143 | MPP_VAR_FUNCTION(0xd, "mii", "crs", V(1, 1, 1, 1, 1))), | ||
| 144 | MPP_MODE(17, | ||
| 145 | MPP_VAR_FUNCTION(0x0, "gpio", NULL, V(1, 1, 1, 1, 1)), | ||
| 146 | MPP_VAR_FUNCTION(0x1, "sdio", "d3", V(1, 1, 1, 1, 1)), | ||
| 147 | MPP_VAR_FUNCTION(0x4, "sata0", "prsnt", V(0, 1, 1, 1, 1)), | ||
| 148 | MPP_VAR_FUNCTION(0xa, "sata1", "act", V(0, 0, 0, 0, 1)), | ||
| 149 | MPP_VAR_FUNCTION(0xd, "twsi1", "sck", V(0, 0, 0, 0, 1))), | ||
| 150 | MPP_MODE(18, | ||
| 151 | MPP_VAR_FUNCTION(0x0, "gpo", NULL, V(1, 1, 1, 1, 1)), | ||
| 152 | MPP_VAR_FUNCTION(0x1, "nand", "io0", V(1, 1, 1, 1, 1)), | ||
| 153 | MPP_VAR_FUNCTION(0x2, "pex", "clkreq", V(0, 0, 0, 0, 1))), | ||
| 154 | MPP_MODE(19, | ||
| 155 | MPP_VAR_FUNCTION(0x0, "gpo", NULL, V(1, 1, 1, 1, 1)), | ||
| 156 | MPP_VAR_FUNCTION(0x1, "nand", "io1", V(1, 1, 1, 1, 1))), | ||
| 157 | MPP_MODE(20, | ||
| 158 | MPP_VAR_FUNCTION(0x0, "gpio", NULL, V(1, 1, 1, 1, 1)), | ||
| 159 | MPP_VAR_FUNCTION(0x1, "ts", "mp0", V(0, 0, 1, 1, 1)), | ||
| 160 | MPP_VAR_FUNCTION(0x2, "tdm", "tx0ql", V(0, 0, 1, 1, 1)), | ||
| 161 | MPP_VAR_FUNCTION(0x3, "ge1", "txd0", V(0, 1, 1, 1, 1)), | ||
| 162 | MPP_VAR_FUNCTION(0x4, "audio", "spdifi", V(0, 0, 1, 1, 1)), | ||
| 163 | MPP_VAR_FUNCTION(0x5, "sata1", "act", V(0, 0, 1, 1, 1)), | ||
| 164 | MPP_VAR_FUNCTION(0xb, "lcd", "d0", V(0, 0, 0, 0, 1)), | ||
| 165 | MPP_VAR_FUNCTION(0xc, "mii", "rxerr", V(1, 0, 0, 0, 0))), | ||
| 166 | MPP_MODE(21, | ||
| 167 | MPP_VAR_FUNCTION(0x0, "gpio", NULL, V(1, 1, 1, 1, 1)), | ||
| 168 | MPP_VAR_FUNCTION(0x1, "ts", "mp1", V(0, 0, 1, 1, 1)), | ||
| 169 | MPP_VAR_FUNCTION(0x2, "tdm", "rx0ql", V(0, 0, 1, 1, 1)), | ||
| 170 | MPP_VAR_FUNCTION(0x3, "ge1", "txd1", V(0, 1, 1, 1, 1)), | ||
| 171 | MPP_VAR_FUNCTION(0x4, "audio", "spdifi", V(1, 0, 0, 0, 0)), | ||
| 172 | MPP_VAR_FUNCTION(0x4, "audio", "spdifo", V(0, 0, 1, 1, 1)), | ||
| 173 | MPP_VAR_FUNCTION(0x5, "sata0", "act", V(0, 1, 1, 1, 1)), | ||
| 174 | MPP_VAR_FUNCTION(0xb, "lcd", "d1", V(0, 0, 0, 0, 1))), | ||
| 175 | MPP_MODE(22, | ||
| 176 | MPP_VAR_FUNCTION(0x0, "gpio", NULL, V(1, 1, 1, 1, 1)), | ||
| 177 | MPP_VAR_FUNCTION(0x1, "ts", "mp2", V(0, 0, 1, 1, 1)), | ||
| 178 | MPP_VAR_FUNCTION(0x2, "tdm", "tx2ql", V(0, 0, 1, 1, 1)), | ||
| 179 | MPP_VAR_FUNCTION(0x3, "ge1", "txd2", V(0, 1, 1, 1, 1)), | ||
| 180 | MPP_VAR_FUNCTION(0x4, "audio", "spdifo", V(1, 0, 0, 0, 0)), | ||
| 181 | MPP_VAR_FUNCTION(0x4, "audio", "rmclk", V(0, 0, 1, 1, 1)), | ||
| 182 | MPP_VAR_FUNCTION(0x5, "sata1", "prsnt", V(0, 0, 1, 1, 1)), | ||
| 183 | MPP_VAR_FUNCTION(0xb, "lcd", "d2", V(0, 0, 0, 0, 1))), | ||
| 184 | MPP_MODE(23, | ||
| 185 | MPP_VAR_FUNCTION(0x0, "gpio", NULL, V(1, 1, 1, 1, 1)), | ||
| 186 | MPP_VAR_FUNCTION(0x1, "ts", "mp3", V(0, 0, 1, 1, 1)), | ||
| 187 | MPP_VAR_FUNCTION(0x2, "tdm", "rx2ql", V(0, 0, 1, 1, 1)), | ||
| 188 | MPP_VAR_FUNCTION(0x3, "ge1", "txd3", V(0, 1, 1, 1, 1)), | ||
| 189 | MPP_VAR_FUNCTION(0x4, "audio", "rmclk", V(1, 0, 0, 0, 0)), | ||
| 190 | MPP_VAR_FUNCTION(0x4, "audio", "bclk", V(0, 0, 1, 1, 1)), | ||
| 191 | MPP_VAR_FUNCTION(0x5, "sata0", "prsnt", V(0, 1, 1, 1, 1)), | ||
| 192 | MPP_VAR_FUNCTION(0xb, "lcd", "d3", V(0, 0, 0, 0, 1))), | ||
| 193 | MPP_MODE(24, | ||
| 194 | MPP_VAR_FUNCTION(0x0, "gpio", NULL, V(1, 1, 1, 1, 1)), | ||
| 195 | MPP_VAR_FUNCTION(0x1, "ts", "mp4", V(0, 0, 1, 1, 1)), | ||
| 196 | MPP_VAR_FUNCTION(0x2, "tdm", "spi-cs0", V(0, 0, 1, 1, 1)), | ||
| 197 | MPP_VAR_FUNCTION(0x3, "ge1", "rxd0", V(0, 1, 1, 1, 1)), | ||
| 198 | MPP_VAR_FUNCTION(0x4, "audio", "bclk", V(1, 0, 0, 0, 0)), | ||
| 199 | MPP_VAR_FUNCTION(0x4, "audio", "sdo", V(0, 0, 1, 1, 1)), | ||
| 200 | MPP_VAR_FUNCTION(0xb, "lcd", "d4", V(0, 0, 0, 0, 1))), | ||
| 201 | MPP_MODE(25, | ||
| 202 | MPP_VAR_FUNCTION(0x0, "gpio", NULL, V(1, 1, 1, 1, 1)), | ||
| 203 | MPP_VAR_FUNCTION(0x1, "ts", "mp5", V(0, 0, 1, 1, 1)), | ||
| 204 | MPP_VAR_FUNCTION(0x2, "tdm", "spi-sck", V(0, 0, 1, 1, 1)), | ||
| 205 | MPP_VAR_FUNCTION(0x3, "ge1", "rxd1", V(0, 1, 1, 1, 1)), | ||
| 206 | MPP_VAR_FUNCTION(0x4, "audio", "sdo", V(1, 0, 0, 0, 0)), | ||
| 207 | MPP_VAR_FUNCTION(0x4, "audio", "lrclk", V(0, 0, 1, 1, 1)), | ||
| 208 | MPP_VAR_FUNCTION(0xb, "lcd", "d5", V(0, 0, 0, 0, 1))), | ||
| 209 | MPP_MODE(26, | ||
| 210 | MPP_VAR_FUNCTION(0x0, "gpio", NULL, V(1, 1, 1, 1, 1)), | ||
| 211 | MPP_VAR_FUNCTION(0x1, "ts", "mp6", V(0, 0, 1, 1, 1)), | ||
| 212 | MPP_VAR_FUNCTION(0x2, "tdm", "spi-miso", V(0, 0, 1, 1, 1)), | ||
| 213 | MPP_VAR_FUNCTION(0x3, "ge1", "rxd2", V(0, 1, 1, 1, 1)), | ||
| 214 | MPP_VAR_FUNCTION(0x4, "audio", "lrclk", V(1, 0, 0, 0, 0)), | ||
| 215 | MPP_VAR_FUNCTION(0x4, "audio", "mclk", V(0, 0, 1, 1, 1)), | ||
| 216 | MPP_VAR_FUNCTION(0xb, "lcd", "d6", V(0, 0, 0, 0, 1))), | ||
| 217 | MPP_MODE(27, | ||
| 218 | MPP_VAR_FUNCTION(0x0, "gpio", NULL, V(1, 1, 1, 1, 1)), | ||
| 219 | MPP_VAR_FUNCTION(0x1, "ts", "mp7", V(0, 0, 1, 1, 1)), | ||
| 220 | MPP_VAR_FUNCTION(0x2, "tdm", "spi-mosi", V(0, 0, 1, 1, 1)), | ||
| 221 | MPP_VAR_FUNCTION(0x3, "ge1", "rxd3", V(0, 1, 1, 1, 1)), | ||
| 222 | MPP_VAR_FUNCTION(0x4, "audio", "mclk", V(1, 0, 0, 0, 0)), | ||
| 223 | MPP_VAR_FUNCTION(0x4, "audio", "sdi", V(0, 0, 1, 1, 1)), | ||
| 224 | MPP_VAR_FUNCTION(0xb, "lcd", "d7", V(0, 0, 0, 0, 1))), | ||
| 225 | MPP_MODE(28, | ||
| 226 | MPP_VAR_FUNCTION(0x0, "gpio", NULL, V(1, 1, 1, 1, 1)), | ||
| 227 | MPP_VAR_FUNCTION(0x1, "ts", "mp8", V(0, 0, 1, 1, 1)), | ||
| 228 | MPP_VAR_FUNCTION(0x2, "tdm", "int", V(0, 0, 1, 1, 1)), | ||
| 229 | MPP_VAR_FUNCTION(0x3, "ge1", "col", V(0, 1, 1, 1, 1)), | ||
| 230 | MPP_VAR_FUNCTION(0x4, "audio", "sdi", V(1, 0, 0, 0, 0)), | ||
| 231 | MPP_VAR_FUNCTION(0x4, "audio", "extclk", V(0, 0, 1, 1, 1)), | ||
| 232 | MPP_VAR_FUNCTION(0xb, "lcd", "d8", V(0, 0, 0, 0, 1))), | ||
| 233 | MPP_MODE(29, | ||
| 234 | MPP_VAR_FUNCTION(0x0, "gpio", NULL, V(1, 1, 1, 1, 1)), | ||
| 235 | MPP_VAR_FUNCTION(0x1, "ts", "mp9", V(0, 0, 1, 1, 1)), | ||
| 236 | MPP_VAR_FUNCTION(0x2, "tdm", "rst", V(0, 0, 1, 1, 1)), | ||
| 237 | MPP_VAR_FUNCTION(0x3, "ge1", "txclk", V(0, 1, 1, 1, 1)), | ||
| 238 | MPP_VAR_FUNCTION(0x4, "audio", "extclk", V(1, 0, 0, 0, 0)), | ||
| 239 | MPP_VAR_FUNCTION(0xb, "lcd", "d9", V(0, 0, 0, 0, 1))), | ||
| 240 | MPP_MODE(30, | ||
| 241 | MPP_VAR_FUNCTION(0x0, "gpio", NULL, V(0, 1, 1, 1, 1)), | ||
| 242 | MPP_VAR_FUNCTION(0x1, "ts", "mp10", V(0, 0, 1, 1, 1)), | ||
| 243 | MPP_VAR_FUNCTION(0x2, "tdm", "pclk", V(0, 0, 1, 1, 1)), | ||
| 244 | MPP_VAR_FUNCTION(0x3, "ge1", "rxctl", V(0, 1, 1, 1, 1)), | ||
| 245 | MPP_VAR_FUNCTION(0xb, "lcd", "d10", V(0, 0, 0, 0, 1))), | ||
| 246 | MPP_MODE(31, | ||
| 247 | MPP_VAR_FUNCTION(0x0, "gpio", NULL, V(0, 1, 1, 1, 1)), | ||
| 248 | MPP_VAR_FUNCTION(0x1, "ts", "mp11", V(0, 0, 1, 1, 1)), | ||
| 249 | MPP_VAR_FUNCTION(0x2, "tdm", "fs", V(0, 0, 1, 1, 1)), | ||
| 250 | MPP_VAR_FUNCTION(0x3, "ge1", "rxclk", V(0, 1, 1, 1, 1)), | ||
| 251 | MPP_VAR_FUNCTION(0xb, "lcd", "d11", V(0, 0, 0, 0, 1))), | ||
| 252 | MPP_MODE(32, | ||
| 253 | MPP_VAR_FUNCTION(0x0, "gpio", NULL, V(0, 1, 1, 1, 1)), | ||
| 254 | MPP_VAR_FUNCTION(0x1, "ts", "mp12", V(0, 0, 1, 1, 1)), | ||
| 255 | MPP_VAR_FUNCTION(0x2, "tdm", "drx", V(0, 0, 1, 1, 1)), | ||
| 256 | MPP_VAR_FUNCTION(0x3, "ge1", "txclko", V(0, 1, 1, 1, 1)), | ||
| 257 | MPP_VAR_FUNCTION(0xb, "lcd", "d12", V(0, 0, 0, 0, 1))), | ||
| 258 | MPP_MODE(33, | ||
| 259 | MPP_VAR_FUNCTION(0x0, "gpo", NULL, V(0, 1, 1, 1, 1)), | ||
| 260 | MPP_VAR_FUNCTION(0x2, "tdm", "dtx", V(0, 0, 1, 1, 1)), | ||
| 261 | MPP_VAR_FUNCTION(0x3, "ge1", "txctl", V(0, 1, 1, 1, 1)), | ||
| 262 | MPP_VAR_FUNCTION(0xb, "lcd", "d13", V(0, 0, 0, 0, 1))), | ||
| 263 | MPP_MODE(34, | ||
| 264 | MPP_VAR_FUNCTION(0x0, "gpio", NULL, V(0, 1, 1, 1, 1)), | ||
| 265 | MPP_VAR_FUNCTION(0x2, "tdm", "spi-cs1", V(0, 0, 1, 1, 1)), | ||
| 266 | MPP_VAR_FUNCTION(0x3, "ge1", "txen", V(0, 1, 1, 1, 1)), | ||
| 267 | MPP_VAR_FUNCTION(0x5, "sata1", "act", V(0, 0, 0, 1, 1)), | ||
| 268 | MPP_VAR_FUNCTION(0xb, "lcd", "d14", V(0, 0, 0, 0, 1))), | ||
| 269 | MPP_MODE(35, | ||
| 270 | MPP_VAR_FUNCTION(0x0, "gpio", NULL, V(0, 1, 1, 1, 1)), | ||
| 271 | MPP_VAR_FUNCTION(0x2, "tdm", "tx0ql", V(0, 0, 1, 1, 1)), | ||
| 272 | MPP_VAR_FUNCTION(0x3, "ge1", "rxerr", V(0, 1, 1, 1, 1)), | ||
| 273 | MPP_VAR_FUNCTION(0x5, "sata0", "act", V(0, 1, 1, 1, 1)), | ||
| 274 | MPP_VAR_FUNCTION(0xb, "lcd", "d15", V(0, 0, 0, 0, 1)), | ||
| 275 | MPP_VAR_FUNCTION(0xc, "mii", "rxerr", V(0, 1, 1, 1, 1))), | ||
| 276 | MPP_MODE(36, | ||
| 277 | MPP_VAR_FUNCTION(0x0, "gpio", NULL, V(0, 0, 0, 1, 1)), | ||
| 278 | MPP_VAR_FUNCTION(0x1, "ts", "mp0", V(0, 0, 0, 1, 1)), | ||
| 279 | MPP_VAR_FUNCTION(0x2, "tdm", "spi-cs1", V(0, 0, 0, 1, 1)), | ||
| 280 | MPP_VAR_FUNCTION(0x4, "audio", "spdifi", V(0, 0, 0, 1, 1)), | ||
| 281 | MPP_VAR_FUNCTION(0xb, "twsi1", "sda", V(0, 0, 0, 0, 1))), | ||
| 282 | MPP_MODE(37, | ||
| 283 | MPP_VAR_FUNCTION(0x0, "gpio", NULL, V(0, 0, 0, 1, 1)), | ||
| 284 | MPP_VAR_FUNCTION(0x1, "ts", "mp1", V(0, 0, 0, 1, 1)), | ||
| 285 | MPP_VAR_FUNCTION(0x2, "tdm", "tx2ql", V(0, 0, 0, 1, 1)), | ||
| 286 | MPP_VAR_FUNCTION(0x4, "audio", "spdifo", V(0, 0, 0, 1, 1)), | ||
| 287 | MPP_VAR_FUNCTION(0xb, "twsi1", "sck", V(0, 0, 0, 0, 1))), | ||
| 288 | MPP_MODE(38, | ||
| 289 | MPP_VAR_FUNCTION(0x0, "gpio", NULL, V(0, 0, 0, 1, 1)), | ||
| 290 | MPP_VAR_FUNCTION(0x1, "ts", "mp2", V(0, 0, 0, 1, 1)), | ||
| 291 | MPP_VAR_FUNCTION(0x2, "tdm", "rx2ql", V(0, 0, 0, 1, 1)), | ||
| 292 | MPP_VAR_FUNCTION(0x4, "audio", "rmclk", V(0, 0, 0, 1, 1)), | ||
| 293 | MPP_VAR_FUNCTION(0xb, "lcd", "d18", V(0, 0, 0, 0, 1))), | ||
| 294 | MPP_MODE(39, | ||
| 295 | MPP_VAR_FUNCTION(0x0, "gpio", NULL, V(0, 0, 0, 1, 1)), | ||
| 296 | MPP_VAR_FUNCTION(0x1, "ts", "mp3", V(0, 0, 0, 1, 1)), | ||
| 297 | MPP_VAR_FUNCTION(0x2, "tdm", "spi-cs0", V(0, 0, 0, 1, 1)), | ||
| 298 | MPP_VAR_FUNCTION(0x4, "audio", "bclk", V(0, 0, 0, 1, 1)), | ||
| 299 | MPP_VAR_FUNCTION(0xb, "lcd", "d19", V(0, 0, 0, 0, 1))), | ||
| 300 | MPP_MODE(40, | ||
| 301 | MPP_VAR_FUNCTION(0x0, "gpio", NULL, V(0, 0, 0, 1, 1)), | ||
| 302 | MPP_VAR_FUNCTION(0x1, "ts", "mp4", V(0, 0, 0, 1, 1)), | ||
| 303 | MPP_VAR_FUNCTION(0x2, "tdm", "spi-sck", V(0, 0, 0, 1, 1)), | ||
| 304 | MPP_VAR_FUNCTION(0x4, "audio", "sdo", V(0, 0, 0, 1, 1)), | ||
| 305 | MPP_VAR_FUNCTION(0xb, "lcd", "d20", V(0, 0, 0, 0, 1))), | ||
| 306 | MPP_MODE(41, | ||
| 307 | MPP_VAR_FUNCTION(0x0, "gpio", NULL, V(0, 0, 0, 1, 1)), | ||
| 308 | MPP_VAR_FUNCTION(0x1, "ts", "mp5", V(0, 0, 0, 1, 1)), | ||
| 309 | MPP_VAR_FUNCTION(0x2, "tdm", "spi-miso", V(0, 0, 0, 1, 1)), | ||
| 310 | MPP_VAR_FUNCTION(0x4, "audio", "lrclk", V(0, 0, 0, 1, 1)), | ||
| 311 | MPP_VAR_FUNCTION(0xb, "lcd", "d21", V(0, 0, 0, 0, 1))), | ||
| 312 | MPP_MODE(42, | ||
| 313 | MPP_VAR_FUNCTION(0x0, "gpio", NULL, V(0, 0, 0, 1, 1)), | ||
| 314 | MPP_VAR_FUNCTION(0x1, "ts", "mp6", V(0, 0, 0, 1, 1)), | ||
| 315 | MPP_VAR_FUNCTION(0x2, "tdm", "spi-mosi", V(0, 0, 0, 1, 1)), | ||
| 316 | MPP_VAR_FUNCTION(0x4, "audio", "mclk", V(0, 0, 0, 1, 1)), | ||
| 317 | MPP_VAR_FUNCTION(0xb, "lcd", "d22", V(0, 0, 0, 0, 1))), | ||
| 318 | MPP_MODE(43, | ||
| 319 | MPP_VAR_FUNCTION(0x0, "gpio", NULL, V(0, 0, 0, 1, 1)), | ||
| 320 | MPP_VAR_FUNCTION(0x1, "ts", "mp7", V(0, 0, 0, 1, 1)), | ||
| 321 | MPP_VAR_FUNCTION(0x2, "tdm", "int", V(0, 0, 0, 1, 1)), | ||
| 322 | MPP_VAR_FUNCTION(0x4, "audio", "sdi", V(0, 0, 0, 1, 1)), | ||
| 323 | MPP_VAR_FUNCTION(0xb, "lcd", "d23", V(0, 0, 0, 0, 1))), | ||
| 324 | MPP_MODE(44, | ||
| 325 | MPP_VAR_FUNCTION(0x0, "gpio", NULL, V(0, 0, 0, 1, 1)), | ||
| 326 | MPP_VAR_FUNCTION(0x1, "ts", "mp8", V(0, 0, 0, 1, 1)), | ||
| 327 | MPP_VAR_FUNCTION(0x2, "tdm", "rst", V(0, 0, 0, 1, 1)), | ||
| 328 | MPP_VAR_FUNCTION(0x4, "audio", "extclk", V(0, 0, 0, 1, 1)), | ||
| 329 | MPP_VAR_FUNCTION(0xb, "lcd", "clk", V(0, 0, 0, 0, 1))), | ||
| 330 | MPP_MODE(45, | ||
| 331 | MPP_VAR_FUNCTION(0x0, "gpio", NULL, V(0, 0, 0, 1, 1)), | ||
| 332 | MPP_VAR_FUNCTION(0x1, "ts", "mp9", V(0, 0, 0, 1, 1)), | ||
| 333 | MPP_VAR_FUNCTION(0x2, "tdm", "pclk", V(0, 0, 0, 1, 1)), | ||
| 334 | MPP_VAR_FUNCTION(0xb, "lcd", "e", V(0, 0, 0, 0, 1))), | ||
| 335 | MPP_MODE(46, | ||
| 336 | MPP_VAR_FUNCTION(0x0, "gpio", NULL, V(0, 0, 0, 1, 1)), | ||
| 337 | MPP_VAR_FUNCTION(0x1, "ts", "mp10", V(0, 0, 0, 1, 1)), | ||
| 338 | MPP_VAR_FUNCTION(0x2, "tdm", "fs", V(0, 0, 0, 1, 1)), | ||
| 339 | MPP_VAR_FUNCTION(0xb, "lcd", "hsync", V(0, 0, 0, 0, 1))), | ||
| 340 | MPP_MODE(47, | ||
| 341 | MPP_VAR_FUNCTION(0x0, "gpio", NULL, V(0, 0, 0, 1, 1)), | ||
| 342 | MPP_VAR_FUNCTION(0x1, "ts", "mp11", V(0, 0, 0, 1, 1)), | ||
| 343 | MPP_VAR_FUNCTION(0x2, "tdm", "drx", V(0, 0, 0, 1, 1)), | ||
| 344 | MPP_VAR_FUNCTION(0xb, "lcd", "vsync", V(0, 0, 0, 0, 1))), | ||
| 345 | MPP_MODE(48, | ||
| 346 | MPP_VAR_FUNCTION(0x0, "gpio", NULL, V(0, 0, 0, 1, 1)), | ||
| 347 | MPP_VAR_FUNCTION(0x1, "ts", "mp12", V(0, 0, 0, 1, 1)), | ||
| 348 | MPP_VAR_FUNCTION(0x2, "tdm", "dtx", V(0, 0, 0, 1, 1)), | ||
| 349 | MPP_VAR_FUNCTION(0xb, "lcd", "d16", V(0, 0, 0, 0, 1))), | ||
| 350 | MPP_MODE(49, | ||
| 351 | MPP_VAR_FUNCTION(0x0, "gpio", NULL, V(0, 0, 0, 1, 0)), | ||
| 352 | MPP_VAR_FUNCTION(0x0, "gpo", NULL, V(0, 0, 0, 0, 1)), | ||
| 353 | MPP_VAR_FUNCTION(0x1, "ts", "mp9", V(0, 0, 0, 1, 0)), | ||
| 354 | MPP_VAR_FUNCTION(0x2, "tdm", "rx0ql", V(0, 0, 0, 1, 1)), | ||
| 355 | MPP_VAR_FUNCTION(0x5, "ptp", "clk", V(0, 0, 0, 1, 0)), | ||
| 356 | MPP_VAR_FUNCTION(0xa, "pex", "clkreq", V(0, 0, 0, 0, 1)), | ||
| 357 | MPP_VAR_FUNCTION(0xb, "lcd", "d17", V(0, 0, 0, 0, 1))), | ||
| 358 | }; | ||
| 359 | |||
| 360 | static struct mvebu_mpp_ctrl mv88f6180_mpp_controls[] = { | ||
| 361 | MPP_REG_CTRL(0, 29), | ||
| 362 | }; | ||
| 363 | |||
| 364 | static struct pinctrl_gpio_range mv88f6180_gpio_ranges[] = { | ||
| 365 | MPP_GPIO_RANGE(0, 0, 0, 30), | ||
| 366 | }; | ||
| 367 | |||
| 368 | static struct mvebu_mpp_ctrl mv88f619x_mpp_controls[] = { | ||
| 369 | MPP_REG_CTRL(0, 35), | ||
| 370 | }; | ||
| 371 | |||
| 372 | static struct pinctrl_gpio_range mv88f619x_gpio_ranges[] = { | ||
| 373 | MPP_GPIO_RANGE(0, 0, 0, 32), | ||
| 374 | MPP_GPIO_RANGE(1, 32, 32, 4), | ||
| 375 | }; | ||
| 376 | |||
| 377 | static struct mvebu_mpp_ctrl mv88f628x_mpp_controls[] = { | ||
| 378 | MPP_REG_CTRL(0, 49), | ||
| 379 | }; | ||
| 380 | |||
| 381 | static struct pinctrl_gpio_range mv88f628x_gpio_ranges[] = { | ||
| 382 | MPP_GPIO_RANGE(0, 0, 0, 32), | ||
| 383 | MPP_GPIO_RANGE(1, 32, 32, 18), | ||
| 384 | }; | ||
| 385 | |||
| 386 | static struct mvebu_pinctrl_soc_info mv88f6180_info = { | ||
| 387 | .variant = VARIANT_MV88F6180, | ||
| 388 | .controls = mv88f6180_mpp_controls, | ||
| 389 | .ncontrols = ARRAY_SIZE(mv88f6180_mpp_controls), | ||
| 390 | .modes = mv88f6xxx_mpp_modes, | ||
| 391 | .nmodes = ARRAY_SIZE(mv88f6xxx_mpp_modes), | ||
| 392 | .gpioranges = mv88f6180_gpio_ranges, | ||
| 393 | .ngpioranges = ARRAY_SIZE(mv88f6180_gpio_ranges), | ||
| 394 | }; | ||
| 395 | |||
| 396 | static struct mvebu_pinctrl_soc_info mv88f6190_info = { | ||
| 397 | .variant = VARIANT_MV88F6190, | ||
| 398 | .controls = mv88f619x_mpp_controls, | ||
| 399 | .ncontrols = ARRAY_SIZE(mv88f619x_mpp_controls), | ||
| 400 | .modes = mv88f6xxx_mpp_modes, | ||
| 401 | .nmodes = ARRAY_SIZE(mv88f6xxx_mpp_modes), | ||
| 402 | .gpioranges = mv88f619x_gpio_ranges, | ||
| 403 | .ngpioranges = ARRAY_SIZE(mv88f619x_gpio_ranges), | ||
| 404 | }; | ||
| 405 | |||
| 406 | static struct mvebu_pinctrl_soc_info mv88f6192_info = { | ||
| 407 | .variant = VARIANT_MV88F6192, | ||
| 408 | .controls = mv88f619x_mpp_controls, | ||
| 409 | .ncontrols = ARRAY_SIZE(mv88f619x_mpp_controls), | ||
| 410 | .modes = mv88f6xxx_mpp_modes, | ||
| 411 | .nmodes = ARRAY_SIZE(mv88f6xxx_mpp_modes), | ||
| 412 | .gpioranges = mv88f619x_gpio_ranges, | ||
| 413 | .ngpioranges = ARRAY_SIZE(mv88f619x_gpio_ranges), | ||
| 414 | }; | ||
| 415 | |||
| 416 | static struct mvebu_pinctrl_soc_info mv88f6281_info = { | ||
| 417 | .variant = VARIANT_MV88F6281, | ||
| 418 | .controls = mv88f628x_mpp_controls, | ||
| 419 | .ncontrols = ARRAY_SIZE(mv88f628x_mpp_controls), | ||
| 420 | .modes = mv88f6xxx_mpp_modes, | ||
| 421 | .nmodes = ARRAY_SIZE(mv88f6xxx_mpp_modes), | ||
| 422 | .gpioranges = mv88f628x_gpio_ranges, | ||
| 423 | .ngpioranges = ARRAY_SIZE(mv88f628x_gpio_ranges), | ||
| 424 | }; | ||
| 425 | |||
| 426 | static struct mvebu_pinctrl_soc_info mv88f6282_info = { | ||
| 427 | .variant = VARIANT_MV88F6282, | ||
| 428 | .controls = mv88f628x_mpp_controls, | ||
| 429 | .ncontrols = ARRAY_SIZE(mv88f628x_mpp_controls), | ||
| 430 | .modes = mv88f6xxx_mpp_modes, | ||
| 431 | .nmodes = ARRAY_SIZE(mv88f6xxx_mpp_modes), | ||
| 432 | .gpioranges = mv88f628x_gpio_ranges, | ||
| 433 | .ngpioranges = ARRAY_SIZE(mv88f628x_gpio_ranges), | ||
| 434 | }; | ||
| 435 | |||
| 436 | static struct of_device_id kirkwood_pinctrl_of_match[] __devinitdata = { | ||
| 437 | { .compatible = "marvell,88f6180-pinctrl", .data = &mv88f6180_info }, | ||
| 438 | { .compatible = "marvell,88f6190-pinctrl", .data = &mv88f6190_info }, | ||
| 439 | { .compatible = "marvell,88f6192-pinctrl", .data = &mv88f6192_info }, | ||
| 440 | { .compatible = "marvell,88f6281-pinctrl", .data = &mv88f6281_info }, | ||
| 441 | { .compatible = "marvell,88f6282-pinctrl", .data = &mv88f6282_info }, | ||
| 442 | { } | ||
| 443 | }; | ||
| 444 | |||
| 445 | static int __devinit kirkwood_pinctrl_probe(struct platform_device *pdev) | ||
| 446 | { | ||
| 447 | const struct of_device_id *match = | ||
| 448 | of_match_device(kirkwood_pinctrl_of_match, &pdev->dev); | ||
| 449 | pdev->dev.platform_data = match->data; | ||
| 450 | return mvebu_pinctrl_probe(pdev); | ||
| 451 | } | ||
| 452 | |||
| 453 | static int __devexit kirkwood_pinctrl_remove(struct platform_device *pdev) | ||
| 454 | { | ||
| 455 | return mvebu_pinctrl_remove(pdev); | ||
| 456 | } | ||
| 457 | |||
| 458 | static struct platform_driver kirkwood_pinctrl_driver = { | ||
| 459 | .driver = { | ||
| 460 | .name = "kirkwood-pinctrl", | ||
| 461 | .owner = THIS_MODULE, | ||
| 462 | .of_match_table = of_match_ptr(kirkwood_pinctrl_of_match), | ||
| 463 | }, | ||
| 464 | .probe = kirkwood_pinctrl_probe, | ||
| 465 | .remove = __devexit_p(kirkwood_pinctrl_remove), | ||
| 466 | }; | ||
| 467 | |||
| 468 | module_platform_driver(kirkwood_pinctrl_driver); | ||
| 469 | |||
| 470 | MODULE_AUTHOR("Sebastian Hesselbarth <sebastian.hesselbarth@gmail.com>"); | ||
| 471 | MODULE_DESCRIPTION("Marvell Kirkwood pinctrl driver"); | ||
| 472 | MODULE_LICENSE("GPL v2"); | ||
diff --git a/drivers/pinctrl/pinctrl-mvebu.c b/drivers/pinctrl/pinctrl-mvebu.c new file mode 100644 index 000000000000..8e6266c6249a --- /dev/null +++ b/drivers/pinctrl/pinctrl-mvebu.c | |||
| @@ -0,0 +1,754 @@ | |||
| 1 | /* | ||
| 2 | * Marvell MVEBU pinctrl core driver | ||
| 3 | * | ||
| 4 | * Authors: Sebastian Hesselbarth <sebastian.hesselbarth@gmail.com> | ||
| 5 | * Thomas Petazzoni <thomas.petazzoni@free-electrons.com> | ||
| 6 | * | ||
| 7 | * This program is free software; you can redistribute it and/or modify | ||
| 8 | * it under the terms of the GNU General Public License as published by | ||
| 9 | * the Free Software Foundation; either version 2 of the License, or | ||
| 10 | * (at your option) any later version. | ||
| 11 | */ | ||
| 12 | |||
| 13 | #include <linux/platform_device.h> | ||
| 14 | #include <linux/module.h> | ||
| 15 | #include <linux/slab.h> | ||
| 16 | #include <linux/io.h> | ||
| 17 | #include <linux/of.h> | ||
| 18 | #include <linux/of_address.h> | ||
| 19 | #include <linux/of_platform.h> | ||
| 20 | #include <linux/err.h> | ||
| 21 | #include <linux/gpio.h> | ||
| 22 | #include <linux/pinctrl/machine.h> | ||
| 23 | #include <linux/pinctrl/pinconf.h> | ||
| 24 | #include <linux/pinctrl/pinctrl.h> | ||
| 25 | #include <linux/pinctrl/pinmux.h> | ||
| 26 | |||
| 27 | #include "core.h" | ||
| 28 | #include "pinctrl-mvebu.h" | ||
| 29 | |||
| 30 | #define MPPS_PER_REG 8 | ||
| 31 | #define MPP_BITS 4 | ||
| 32 | #define MPP_MASK 0xf | ||
| 33 | |||
| 34 | struct mvebu_pinctrl_function { | ||
| 35 | const char *name; | ||
| 36 | const char **groups; | ||
| 37 | unsigned num_groups; | ||
| 38 | }; | ||
| 39 | |||
| 40 | struct mvebu_pinctrl_group { | ||
| 41 | const char *name; | ||
| 42 | struct mvebu_mpp_ctrl *ctrl; | ||
| 43 | struct mvebu_mpp_ctrl_setting *settings; | ||
| 44 | unsigned num_settings; | ||
| 45 | unsigned gid; | ||
| 46 | unsigned *pins; | ||
| 47 | unsigned npins; | ||
| 48 | }; | ||
| 49 | |||
| 50 | struct mvebu_pinctrl { | ||
| 51 | struct device *dev; | ||
| 52 | struct pinctrl_dev *pctldev; | ||
| 53 | struct pinctrl_desc desc; | ||
| 54 | void __iomem *base; | ||
| 55 | struct mvebu_pinctrl_group *groups; | ||
| 56 | unsigned num_groups; | ||
| 57 | struct mvebu_pinctrl_function *functions; | ||
| 58 | unsigned num_functions; | ||
| 59 | u8 variant; | ||
| 60 | }; | ||
| 61 | |||
| 62 | static struct mvebu_pinctrl_group *mvebu_pinctrl_find_group_by_pid( | ||
| 63 | struct mvebu_pinctrl *pctl, unsigned pid) | ||
| 64 | { | ||
| 65 | unsigned n; | ||
| 66 | for (n = 0; n < pctl->num_groups; n++) { | ||
| 67 | if (pid >= pctl->groups[n].pins[0] && | ||
| 68 | pid < pctl->groups[n].pins[0] + | ||
| 69 | pctl->groups[n].npins) | ||
| 70 | return &pctl->groups[n]; | ||
| 71 | } | ||
| 72 | return NULL; | ||
| 73 | } | ||
| 74 | |||
| 75 | static struct mvebu_pinctrl_group *mvebu_pinctrl_find_group_by_name( | ||
| 76 | struct mvebu_pinctrl *pctl, const char *name) | ||
| 77 | { | ||
| 78 | unsigned n; | ||
| 79 | for (n = 0; n < pctl->num_groups; n++) { | ||
| 80 | if (strcmp(name, pctl->groups[n].name) == 0) | ||
| 81 | return &pctl->groups[n]; | ||
| 82 | } | ||
| 83 | return NULL; | ||
| 84 | } | ||
| 85 | |||
| 86 | static struct mvebu_mpp_ctrl_setting *mvebu_pinctrl_find_setting_by_val( | ||
| 87 | struct mvebu_pinctrl *pctl, struct mvebu_pinctrl_group *grp, | ||
| 88 | unsigned long config) | ||
| 89 | { | ||
| 90 | unsigned n; | ||
| 91 | for (n = 0; n < grp->num_settings; n++) { | ||
| 92 | if (config == grp->settings[n].val) { | ||
| 93 | if (!pctl->variant || (pctl->variant & | ||
| 94 | grp->settings[n].variant)) | ||
| 95 | return &grp->settings[n]; | ||
| 96 | } | ||
| 97 | } | ||
| 98 | return NULL; | ||
| 99 | } | ||
| 100 | |||
| 101 | static struct mvebu_mpp_ctrl_setting *mvebu_pinctrl_find_setting_by_name( | ||
| 102 | struct mvebu_pinctrl *pctl, struct mvebu_pinctrl_group *grp, | ||
| 103 | const char *name) | ||
| 104 | { | ||
| 105 | unsigned n; | ||
| 106 | for (n = 0; n < grp->num_settings; n++) { | ||
| 107 | if (strcmp(name, grp->settings[n].name) == 0) { | ||
| 108 | if (!pctl->variant || (pctl->variant & | ||
| 109 | grp->settings[n].variant)) | ||
| 110 | return &grp->settings[n]; | ||
| 111 | } | ||
| 112 | } | ||
| 113 | return NULL; | ||
| 114 | } | ||
| 115 | |||
| 116 | static struct mvebu_mpp_ctrl_setting *mvebu_pinctrl_find_gpio_setting( | ||
| 117 | struct mvebu_pinctrl *pctl, struct mvebu_pinctrl_group *grp) | ||
| 118 | { | ||
| 119 | unsigned n; | ||
| 120 | for (n = 0; n < grp->num_settings; n++) { | ||
| 121 | if (grp->settings[n].flags & | ||
| 122 | (MVEBU_SETTING_GPO | MVEBU_SETTING_GPI)) { | ||
| 123 | if (!pctl->variant || (pctl->variant & | ||
| 124 | grp->settings[n].variant)) | ||
| 125 | return &grp->settings[n]; | ||
| 126 | } | ||
| 127 | } | ||
| 128 | return NULL; | ||
| 129 | } | ||
| 130 | |||
| 131 | static struct mvebu_pinctrl_function *mvebu_pinctrl_find_function_by_name( | ||
| 132 | struct mvebu_pinctrl *pctl, const char *name) | ||
| 133 | { | ||
| 134 | unsigned n; | ||
| 135 | for (n = 0; n < pctl->num_functions; n++) { | ||
| 136 | if (strcmp(name, pctl->functions[n].name) == 0) | ||
| 137 | return &pctl->functions[n]; | ||
| 138 | } | ||
| 139 | return NULL; | ||
| 140 | } | ||
| 141 | |||
| 142 | /* | ||
| 143 | * Common mpp pin configuration registers on MVEBU are | ||
| 144 | * registers of eight 4-bit values for each mpp setting. | ||
| 145 | * Register offset and bit mask are calculated accordingly below. | ||
| 146 | */ | ||
| 147 | static int mvebu_common_mpp_get(struct mvebu_pinctrl *pctl, | ||
| 148 | struct mvebu_pinctrl_group *grp, | ||
| 149 | unsigned long *config) | ||
| 150 | { | ||
| 151 | unsigned pin = grp->gid; | ||
| 152 | unsigned off = (pin / MPPS_PER_REG) * MPP_BITS; | ||
| 153 | unsigned shift = (pin % MPPS_PER_REG) * MPP_BITS; | ||
| 154 | |||
| 155 | *config = readl(pctl->base + off); | ||
| 156 | *config >>= shift; | ||
| 157 | *config &= MPP_MASK; | ||
| 158 | |||
| 159 | return 0; | ||
| 160 | } | ||
| 161 | |||
| 162 | static int mvebu_common_mpp_set(struct mvebu_pinctrl *pctl, | ||
| 163 | struct mvebu_pinctrl_group *grp, | ||
| 164 | unsigned long config) | ||
| 165 | { | ||
| 166 | unsigned pin = grp->gid; | ||
| 167 | unsigned off = (pin / MPPS_PER_REG) * MPP_BITS; | ||
| 168 | unsigned shift = (pin % MPPS_PER_REG) * MPP_BITS; | ||
| 169 | unsigned long reg; | ||
| 170 | |||
| 171 | reg = readl(pctl->base + off); | ||
| 172 | reg &= ~(MPP_MASK << shift); | ||
| 173 | reg |= (config << shift); | ||
| 174 | writel(reg, pctl->base + off); | ||
| 175 | |||
| 176 | return 0; | ||
| 177 | } | ||
| 178 | |||
| 179 | static int mvebu_pinconf_group_get(struct pinctrl_dev *pctldev, | ||
| 180 | unsigned gid, unsigned long *config) | ||
| 181 | { | ||
| 182 | struct mvebu_pinctrl *pctl = pinctrl_dev_get_drvdata(pctldev); | ||
| 183 | struct mvebu_pinctrl_group *grp = &pctl->groups[gid]; | ||
| 184 | |||
| 185 | if (!grp->ctrl) | ||
| 186 | return -EINVAL; | ||
| 187 | |||
| 188 | if (grp->ctrl->mpp_get) | ||
| 189 | return grp->ctrl->mpp_get(grp->ctrl, config); | ||
| 190 | |||
| 191 | return mvebu_common_mpp_get(pctl, grp, config); | ||
| 192 | } | ||
| 193 | |||
| 194 | static int mvebu_pinconf_group_set(struct pinctrl_dev *pctldev, | ||
| 195 | unsigned gid, unsigned long config) | ||
| 196 | { | ||
| 197 | struct mvebu_pinctrl *pctl = pinctrl_dev_get_drvdata(pctldev); | ||
| 198 | struct mvebu_pinctrl_group *grp = &pctl->groups[gid]; | ||
| 199 | |||
| 200 | if (!grp->ctrl) | ||
| 201 | return -EINVAL; | ||
| 202 | |||
| 203 | if (grp->ctrl->mpp_set) | ||
| 204 | return grp->ctrl->mpp_set(grp->ctrl, config); | ||
| 205 | |||
| 206 | return mvebu_common_mpp_set(pctl, grp, config); | ||
| 207 | } | ||
| 208 | |||
| 209 | static void mvebu_pinconf_group_dbg_show(struct pinctrl_dev *pctldev, | ||
| 210 | struct seq_file *s, unsigned gid) | ||
| 211 | { | ||
| 212 | struct mvebu_pinctrl *pctl = pinctrl_dev_get_drvdata(pctldev); | ||
| 213 | struct mvebu_pinctrl_group *grp = &pctl->groups[gid]; | ||
| 214 | struct mvebu_mpp_ctrl_setting *curr; | ||
| 215 | unsigned long config; | ||
| 216 | unsigned n; | ||
| 217 | |||
| 218 | if (mvebu_pinconf_group_get(pctldev, gid, &config)) | ||
| 219 | return; | ||
| 220 | |||
| 221 | curr = mvebu_pinctrl_find_setting_by_val(pctl, grp, config); | ||
| 222 | |||
| 223 | if (curr) { | ||
| 224 | seq_printf(s, "current: %s", curr->name); | ||
| 225 | if (curr->subname) | ||
| 226 | seq_printf(s, "(%s)", curr->subname); | ||
| 227 | if (curr->flags & (MVEBU_SETTING_GPO | MVEBU_SETTING_GPI)) { | ||
| 228 | seq_printf(s, "("); | ||
| 229 | if (curr->flags & MVEBU_SETTING_GPI) | ||
| 230 | seq_printf(s, "i"); | ||
| 231 | if (curr->flags & MVEBU_SETTING_GPO) | ||
| 232 | seq_printf(s, "o"); | ||
| 233 | seq_printf(s, ")"); | ||
| 234 | } | ||
| 235 | } else | ||
| 236 | seq_printf(s, "current: UNKNOWN"); | ||
| 237 | |||
| 238 | if (grp->num_settings > 1) { | ||
| 239 | seq_printf(s, ", available = ["); | ||
| 240 | for (n = 0; n < grp->num_settings; n++) { | ||
| 241 | if (curr == &grp->settings[n]) | ||
| 242 | continue; | ||
| 243 | |||
| 244 | /* skip unsupported settings for this variant */ | ||
| 245 | if (pctl->variant && | ||
| 246 | !(pctl->variant & grp->settings[n].variant)) | ||
| 247 | continue; | ||
| 248 | |||
| 249 | seq_printf(s, " %s", grp->settings[n].name); | ||
| 250 | if (grp->settings[n].subname) | ||
| 251 | seq_printf(s, "(%s)", grp->settings[n].subname); | ||
| 252 | if (grp->settings[n].flags & | ||
| 253 | (MVEBU_SETTING_GPO | MVEBU_SETTING_GPI)) { | ||
| 254 | seq_printf(s, "("); | ||
| 255 | if (grp->settings[n].flags & MVEBU_SETTING_GPI) | ||
| 256 | seq_printf(s, "i"); | ||
| 257 | if (grp->settings[n].flags & MVEBU_SETTING_GPO) | ||
| 258 | seq_printf(s, "o"); | ||
| 259 | seq_printf(s, ")"); | ||
| 260 | } | ||
| 261 | } | ||
| 262 | seq_printf(s, " ]"); | ||
| 263 | } | ||
| 264 | return; | ||
| 265 | } | ||
| 266 | |||
| 267 | static struct pinconf_ops mvebu_pinconf_ops = { | ||
| 268 | .pin_config_group_get = mvebu_pinconf_group_get, | ||
| 269 | .pin_config_group_set = mvebu_pinconf_group_set, | ||
| 270 | .pin_config_group_dbg_show = mvebu_pinconf_group_dbg_show, | ||
| 271 | }; | ||
| 272 | |||
| 273 | static int mvebu_pinmux_get_funcs_count(struct pinctrl_dev *pctldev) | ||
| 274 | { | ||
| 275 | struct mvebu_pinctrl *pctl = pinctrl_dev_get_drvdata(pctldev); | ||
| 276 | |||
| 277 | return pctl->num_functions; | ||
| 278 | } | ||
| 279 | |||
| 280 | static const char *mvebu_pinmux_get_func_name(struct pinctrl_dev *pctldev, | ||
| 281 | unsigned fid) | ||
| 282 | { | ||
| 283 | struct mvebu_pinctrl *pctl = pinctrl_dev_get_drvdata(pctldev); | ||
| 284 | |||
| 285 | return pctl->functions[fid].name; | ||
| 286 | } | ||
| 287 | |||
| 288 | static int mvebu_pinmux_get_groups(struct pinctrl_dev *pctldev, unsigned fid, | ||
| 289 | const char * const **groups, | ||
| 290 | unsigned * const num_groups) | ||
| 291 | { | ||
| 292 | struct mvebu_pinctrl *pctl = pinctrl_dev_get_drvdata(pctldev); | ||
| 293 | |||
| 294 | *groups = pctl->functions[fid].groups; | ||
| 295 | *num_groups = pctl->functions[fid].num_groups; | ||
| 296 | return 0; | ||
| 297 | } | ||
| 298 | |||
| 299 | static int mvebu_pinmux_enable(struct pinctrl_dev *pctldev, unsigned fid, | ||
| 300 | unsigned gid) | ||
| 301 | { | ||
| 302 | struct mvebu_pinctrl *pctl = pinctrl_dev_get_drvdata(pctldev); | ||
| 303 | struct mvebu_pinctrl_function *func = &pctl->functions[fid]; | ||
| 304 | struct mvebu_pinctrl_group *grp = &pctl->groups[gid]; | ||
| 305 | struct mvebu_mpp_ctrl_setting *setting; | ||
| 306 | int ret; | ||
| 307 | |||
| 308 | setting = mvebu_pinctrl_find_setting_by_name(pctl, grp, | ||
| 309 | func->name); | ||
| 310 | if (!setting) { | ||
| 311 | dev_err(pctl->dev, | ||
| 312 | "unable to find setting %s in group %s\n", | ||
| 313 | func->name, func->groups[gid]); | ||
| 314 | return -EINVAL; | ||
| 315 | } | ||
| 316 | |||
| 317 | ret = mvebu_pinconf_group_set(pctldev, grp->gid, setting->val); | ||
| 318 | if (ret) { | ||
| 319 | dev_err(pctl->dev, "cannot set group %s to %s\n", | ||
| 320 | func->groups[gid], func->name); | ||
| 321 | return ret; | ||
| 322 | } | ||
| 323 | |||
| 324 | return 0; | ||
| 325 | } | ||
| 326 | |||
| 327 | static int mvebu_pinmux_gpio_request_enable(struct pinctrl_dev *pctldev, | ||
| 328 | struct pinctrl_gpio_range *range, unsigned offset) | ||
| 329 | { | ||
| 330 | struct mvebu_pinctrl *pctl = pinctrl_dev_get_drvdata(pctldev); | ||
| 331 | struct mvebu_pinctrl_group *grp; | ||
| 332 | struct mvebu_mpp_ctrl_setting *setting; | ||
| 333 | |||
| 334 | grp = mvebu_pinctrl_find_group_by_pid(pctl, offset); | ||
| 335 | if (!grp) | ||
| 336 | return -EINVAL; | ||
| 337 | |||
| 338 | if (grp->ctrl->mpp_gpio_req) | ||
| 339 | return grp->ctrl->mpp_gpio_req(grp->ctrl, offset); | ||
| 340 | |||
| 341 | setting = mvebu_pinctrl_find_gpio_setting(pctl, grp); | ||
| 342 | if (!setting) | ||
| 343 | return -ENOTSUPP; | ||
| 344 | |||
| 345 | return mvebu_pinconf_group_set(pctldev, grp->gid, setting->val); | ||
| 346 | } | ||
| 347 | |||
| 348 | static int mvebu_pinmux_gpio_set_direction(struct pinctrl_dev *pctldev, | ||
| 349 | struct pinctrl_gpio_range *range, unsigned offset, bool input) | ||
| 350 | { | ||
| 351 | struct mvebu_pinctrl *pctl = pinctrl_dev_get_drvdata(pctldev); | ||
| 352 | struct mvebu_pinctrl_group *grp; | ||
| 353 | struct mvebu_mpp_ctrl_setting *setting; | ||
| 354 | |||
| 355 | grp = mvebu_pinctrl_find_group_by_pid(pctl, offset); | ||
| 356 | if (!grp) | ||
| 357 | return -EINVAL; | ||
| 358 | |||
| 359 | if (grp->ctrl->mpp_gpio_dir) | ||
| 360 | return grp->ctrl->mpp_gpio_dir(grp->ctrl, offset, input); | ||
| 361 | |||
| 362 | setting = mvebu_pinctrl_find_gpio_setting(pctl, grp); | ||
| 363 | if (!setting) | ||
| 364 | return -ENOTSUPP; | ||
| 365 | |||
| 366 | if ((input && (setting->flags & MVEBU_SETTING_GPI)) || | ||
| 367 | (!input && (setting->flags & MVEBU_SETTING_GPO))) | ||
| 368 | return 0; | ||
| 369 | |||
| 370 | return -ENOTSUPP; | ||
| 371 | } | ||
| 372 | |||
| 373 | static struct pinmux_ops mvebu_pinmux_ops = { | ||
| 374 | .get_functions_count = mvebu_pinmux_get_funcs_count, | ||
| 375 | .get_function_name = mvebu_pinmux_get_func_name, | ||
| 376 | .get_function_groups = mvebu_pinmux_get_groups, | ||
| 377 | .gpio_request_enable = mvebu_pinmux_gpio_request_enable, | ||
| 378 | .gpio_set_direction = mvebu_pinmux_gpio_set_direction, | ||
| 379 | .enable = mvebu_pinmux_enable, | ||
| 380 | }; | ||
| 381 | |||
| 382 | static int mvebu_pinctrl_get_groups_count(struct pinctrl_dev *pctldev) | ||
| 383 | { | ||
| 384 | struct mvebu_pinctrl *pctl = pinctrl_dev_get_drvdata(pctldev); | ||
| 385 | return pctl->num_groups; | ||
| 386 | } | ||
| 387 | |||
| 388 | static const char *mvebu_pinctrl_get_group_name(struct pinctrl_dev *pctldev, | ||
| 389 | unsigned gid) | ||
| 390 | { | ||
| 391 | struct mvebu_pinctrl *pctl = pinctrl_dev_get_drvdata(pctldev); | ||
| 392 | return pctl->groups[gid].name; | ||
| 393 | } | ||
| 394 | |||
| 395 | static int mvebu_pinctrl_get_group_pins(struct pinctrl_dev *pctldev, | ||
| 396 | unsigned gid, const unsigned **pins, | ||
| 397 | unsigned *num_pins) | ||
| 398 | { | ||
| 399 | struct mvebu_pinctrl *pctl = pinctrl_dev_get_drvdata(pctldev); | ||
| 400 | *pins = pctl->groups[gid].pins; | ||
| 401 | *num_pins = pctl->groups[gid].npins; | ||
| 402 | return 0; | ||
| 403 | } | ||
| 404 | |||
| 405 | static int mvebu_pinctrl_dt_node_to_map(struct pinctrl_dev *pctldev, | ||
| 406 | struct device_node *np, | ||
| 407 | struct pinctrl_map **map, | ||
| 408 | unsigned *num_maps) | ||
| 409 | { | ||
| 410 | struct mvebu_pinctrl *pctl = pinctrl_dev_get_drvdata(pctldev); | ||
| 411 | struct property *prop; | ||
| 412 | const char *function; | ||
| 413 | const char *group; | ||
| 414 | int ret, nmaps, n; | ||
| 415 | |||
| 416 | *map = NULL; | ||
| 417 | *num_maps = 0; | ||
| 418 | |||
| 419 | ret = of_property_read_string(np, "marvell,function", &function); | ||
| 420 | if (ret) { | ||
| 421 | dev_err(pctl->dev, | ||
| 422 | "missing marvell,function in node %s\n", np->name); | ||
| 423 | return 0; | ||
| 424 | } | ||
| 425 | |||
| 426 | nmaps = of_property_count_strings(np, "marvell,pins"); | ||
| 427 | if (nmaps < 0) { | ||
| 428 | dev_err(pctl->dev, | ||
| 429 | "missing marvell,pins in node %s\n", np->name); | ||
| 430 | return 0; | ||
| 431 | } | ||
| 432 | |||
| 433 | *map = kmalloc(nmaps * sizeof(struct pinctrl_map), GFP_KERNEL); | ||
| 434 | if (map == NULL) { | ||
| 435 | dev_err(pctl->dev, | ||
| 436 | "cannot allocate pinctrl_map memory for %s\n", | ||
| 437 | np->name); | ||
| 438 | return -ENOMEM; | ||
| 439 | } | ||
| 440 | |||
| 441 | n = 0; | ||
| 442 | of_property_for_each_string(np, "marvell,pins", prop, group) { | ||
| 443 | struct mvebu_pinctrl_group *grp = | ||
| 444 | mvebu_pinctrl_find_group_by_name(pctl, group); | ||
| 445 | |||
| 446 | if (!grp) { | ||
| 447 | dev_err(pctl->dev, "unknown pin %s", group); | ||
| 448 | continue; | ||
| 449 | } | ||
| 450 | |||
| 451 | if (!mvebu_pinctrl_find_setting_by_name(pctl, grp, function)) { | ||
| 452 | dev_err(pctl->dev, "unsupported function %s on pin %s", | ||
| 453 | function, group); | ||
| 454 | continue; | ||
| 455 | } | ||
| 456 | |||
| 457 | (*map)[n].type = PIN_MAP_TYPE_MUX_GROUP; | ||
| 458 | (*map)[n].data.mux.group = group; | ||
| 459 | (*map)[n].data.mux.function = function; | ||
| 460 | n++; | ||
| 461 | } | ||
| 462 | |||
| 463 | *num_maps = nmaps; | ||
| 464 | |||
| 465 | return 0; | ||
| 466 | } | ||
| 467 | |||
| 468 | static void mvebu_pinctrl_dt_free_map(struct pinctrl_dev *pctldev, | ||
| 469 | struct pinctrl_map *map, unsigned num_maps) | ||
| 470 | { | ||
| 471 | kfree(map); | ||
| 472 | } | ||
| 473 | |||
| 474 | static struct pinctrl_ops mvebu_pinctrl_ops = { | ||
| 475 | .get_groups_count = mvebu_pinctrl_get_groups_count, | ||
| 476 | .get_group_name = mvebu_pinctrl_get_group_name, | ||
| 477 | .get_group_pins = mvebu_pinctrl_get_group_pins, | ||
| 478 | .dt_node_to_map = mvebu_pinctrl_dt_node_to_map, | ||
| 479 | .dt_free_map = mvebu_pinctrl_dt_free_map, | ||
| 480 | }; | ||
| 481 | |||
| 482 | static int __devinit _add_function(struct mvebu_pinctrl_function *funcs, | ||
| 483 | const char *name) | ||
| 484 | { | ||
| 485 | while (funcs->num_groups) { | ||
| 486 | /* function already there */ | ||
| 487 | if (strcmp(funcs->name, name) == 0) { | ||
| 488 | funcs->num_groups++; | ||
| 489 | return -EEXIST; | ||
| 490 | } | ||
| 491 | funcs++; | ||
| 492 | } | ||
| 493 | funcs->name = name; | ||
| 494 | funcs->num_groups = 1; | ||
| 495 | return 0; | ||
| 496 | } | ||
| 497 | |||
| 498 | static int __devinit mvebu_pinctrl_build_functions(struct platform_device *pdev, | ||
| 499 | struct mvebu_pinctrl *pctl) | ||
| 500 | { | ||
| 501 | struct mvebu_pinctrl_function *funcs; | ||
| 502 | int num = 0; | ||
| 503 | int n, s; | ||
| 504 | |||
| 505 | /* we allocate functions for number of pins and hope | ||
| 506 | * there are less unique functions than pins available */ | ||
| 507 | funcs = devm_kzalloc(&pdev->dev, pctl->desc.npins * | ||
| 508 | sizeof(struct mvebu_pinctrl_function), GFP_KERNEL); | ||
| 509 | if (!funcs) | ||
| 510 | return -ENOMEM; | ||
| 511 | |||
| 512 | for (n = 0; n < pctl->num_groups; n++) { | ||
| 513 | struct mvebu_pinctrl_group *grp = &pctl->groups[n]; | ||
| 514 | for (s = 0; s < grp->num_settings; s++) { | ||
| 515 | /* skip unsupported settings on this variant */ | ||
| 516 | if (pctl->variant && | ||
| 517 | !(pctl->variant & grp->settings[s].variant)) | ||
| 518 | continue; | ||
| 519 | |||
| 520 | /* check for unique functions and count groups */ | ||
| 521 | if (_add_function(funcs, grp->settings[s].name)) | ||
| 522 | continue; | ||
| 523 | |||
| 524 | num++; | ||
| 525 | } | ||
| 526 | } | ||
| 527 | |||
| 528 | /* with the number of unique functions and it's groups known, | ||
| 529 | reallocate functions and assign group names */ | ||
| 530 | funcs = krealloc(funcs, num * sizeof(struct mvebu_pinctrl_function), | ||
| 531 | GFP_KERNEL); | ||
| 532 | if (!funcs) | ||
| 533 | return -ENOMEM; | ||
| 534 | |||
| 535 | pctl->num_functions = num; | ||
| 536 | pctl->functions = funcs; | ||
| 537 | |||
| 538 | for (n = 0; n < pctl->num_groups; n++) { | ||
| 539 | struct mvebu_pinctrl_group *grp = &pctl->groups[n]; | ||
| 540 | for (s = 0; s < grp->num_settings; s++) { | ||
| 541 | struct mvebu_pinctrl_function *f; | ||
| 542 | const char **groups; | ||
| 543 | |||
| 544 | /* skip unsupported settings on this variant */ | ||
| 545 | if (pctl->variant && | ||
| 546 | !(pctl->variant & grp->settings[s].variant)) | ||
| 547 | continue; | ||
| 548 | |||
| 549 | f = mvebu_pinctrl_find_function_by_name(pctl, | ||
| 550 | grp->settings[s].name); | ||
| 551 | |||
| 552 | /* allocate group name array if not done already */ | ||
| 553 | if (!f->groups) { | ||
| 554 | f->groups = devm_kzalloc(&pdev->dev, | ||
| 555 | f->num_groups * sizeof(char *), | ||
| 556 | GFP_KERNEL); | ||
| 557 | if (!f->groups) | ||
| 558 | return -ENOMEM; | ||
| 559 | } | ||
| 560 | |||
| 561 | /* find next free group name and assign current name */ | ||
| 562 | groups = f->groups; | ||
| 563 | while (*groups) | ||
| 564 | groups++; | ||
| 565 | *groups = grp->name; | ||
| 566 | } | ||
| 567 | } | ||
| 568 | |||
| 569 | return 0; | ||
| 570 | } | ||
| 571 | |||
| 572 | int __devinit mvebu_pinctrl_probe(struct platform_device *pdev) | ||
| 573 | { | ||
| 574 | struct mvebu_pinctrl_soc_info *soc = dev_get_platdata(&pdev->dev); | ||
| 575 | struct device_node *np = pdev->dev.of_node; | ||
| 576 | struct mvebu_pinctrl *pctl; | ||
| 577 | void __iomem *base; | ||
| 578 | struct pinctrl_pin_desc *pdesc; | ||
| 579 | unsigned gid, n, k; | ||
| 580 | int ret; | ||
| 581 | |||
| 582 | if (!soc || !soc->controls || !soc->modes) { | ||
| 583 | dev_err(&pdev->dev, "wrong pinctrl soc info\n"); | ||
| 584 | return -EINVAL; | ||
| 585 | } | ||
| 586 | |||
| 587 | base = of_iomap(np, 0); | ||
| 588 | if (!base) { | ||
| 589 | dev_err(&pdev->dev, "unable to get base address\n"); | ||
| 590 | return -ENODEV; | ||
| 591 | } | ||
| 592 | |||
| 593 | pctl = devm_kzalloc(&pdev->dev, sizeof(struct mvebu_pinctrl), | ||
| 594 | GFP_KERNEL); | ||
| 595 | if (!pctl) { | ||
| 596 | dev_err(&pdev->dev, "unable to alloc driver\n"); | ||
| 597 | return -ENOMEM; | ||
| 598 | } | ||
| 599 | |||
| 600 | pctl->desc.name = dev_name(&pdev->dev); | ||
| 601 | pctl->desc.owner = THIS_MODULE; | ||
| 602 | pctl->desc.pctlops = &mvebu_pinctrl_ops; | ||
| 603 | pctl->desc.pmxops = &mvebu_pinmux_ops; | ||
| 604 | pctl->desc.confops = &mvebu_pinconf_ops; | ||
| 605 | pctl->variant = soc->variant; | ||
| 606 | pctl->base = base; | ||
| 607 | pctl->dev = &pdev->dev; | ||
| 608 | platform_set_drvdata(pdev, pctl); | ||
| 609 | |||
| 610 | /* count controls and create names for mvebu generic | ||
| 611 | register controls; also does sanity checks */ | ||
| 612 | pctl->num_groups = 0; | ||
| 613 | pctl->desc.npins = 0; | ||
| 614 | for (n = 0; n < soc->ncontrols; n++) { | ||
| 615 | struct mvebu_mpp_ctrl *ctrl = &soc->controls[n]; | ||
| 616 | char *names; | ||
| 617 | |||
| 618 | pctl->desc.npins += ctrl->npins; | ||
| 619 | /* initial control pins */ | ||
| 620 | for (k = 0; k < ctrl->npins; k++) | ||
| 621 | ctrl->pins[k] = ctrl->pid + k; | ||
| 622 | |||
| 623 | /* special soc specific control */ | ||
| 624 | if (ctrl->mpp_get || ctrl->mpp_set) { | ||
| 625 | if (!ctrl->name || !ctrl->mpp_set || !ctrl->mpp_set) { | ||
| 626 | dev_err(&pdev->dev, "wrong soc control info\n"); | ||
| 627 | return -EINVAL; | ||
| 628 | } | ||
| 629 | pctl->num_groups += 1; | ||
| 630 | continue; | ||
| 631 | } | ||
| 632 | |||
| 633 | /* generic mvebu register control */ | ||
| 634 | names = devm_kzalloc(&pdev->dev, ctrl->npins * 8, GFP_KERNEL); | ||
| 635 | if (!names) { | ||
| 636 | dev_err(&pdev->dev, "failed to alloc mpp names\n"); | ||
| 637 | return -ENOMEM; | ||
| 638 | } | ||
| 639 | for (k = 0; k < ctrl->npins; k++) | ||
| 640 | sprintf(names + 8*k, "mpp%d", ctrl->pid+k); | ||
| 641 | ctrl->name = names; | ||
| 642 | pctl->num_groups += ctrl->npins; | ||
| 643 | } | ||
| 644 | |||
| 645 | pdesc = devm_kzalloc(&pdev->dev, pctl->desc.npins * | ||
| 646 | sizeof(struct pinctrl_pin_desc), GFP_KERNEL); | ||
| 647 | if (!pdesc) { | ||
| 648 | dev_err(&pdev->dev, "failed to alloc pinctrl pins\n"); | ||
| 649 | return -ENOMEM; | ||
| 650 | } | ||
| 651 | |||
| 652 | for (n = 0; n < pctl->desc.npins; n++) | ||
| 653 | pdesc[n].number = n; | ||
| 654 | pctl->desc.pins = pdesc; | ||
| 655 | |||
| 656 | pctl->groups = devm_kzalloc(&pdev->dev, pctl->num_groups * | ||
| 657 | sizeof(struct mvebu_pinctrl_group), GFP_KERNEL); | ||
| 658 | if (!pctl->groups) { | ||
| 659 | dev_err(&pdev->dev, "failed to alloc pinctrl groups\n"); | ||
| 660 | return -ENOMEM; | ||
| 661 | } | ||
| 662 | |||
| 663 | /* assign mpp controls to groups */ | ||
| 664 | gid = 0; | ||
| 665 | for (n = 0; n < soc->ncontrols; n++) { | ||
| 666 | struct mvebu_mpp_ctrl *ctrl = &soc->controls[n]; | ||
| 667 | pctl->groups[gid].gid = gid; | ||
| 668 | pctl->groups[gid].ctrl = ctrl; | ||
| 669 | pctl->groups[gid].name = ctrl->name; | ||
| 670 | pctl->groups[gid].pins = ctrl->pins; | ||
| 671 | pctl->groups[gid].npins = ctrl->npins; | ||
| 672 | |||
| 673 | /* generic mvebu register control maps to a number of groups */ | ||
| 674 | if (!ctrl->mpp_get && !ctrl->mpp_set) { | ||
| 675 | pctl->groups[gid].npins = 1; | ||
| 676 | |||
| 677 | for (k = 1; k < ctrl->npins; k++) { | ||
| 678 | gid++; | ||
| 679 | pctl->groups[gid].gid = gid; | ||
| 680 | pctl->groups[gid].ctrl = ctrl; | ||
| 681 | pctl->groups[gid].name = &ctrl->name[8*k]; | ||
| 682 | pctl->groups[gid].pins = &ctrl->pins[k]; | ||
| 683 | pctl->groups[gid].npins = 1; | ||
| 684 | } | ||
| 685 | } | ||
| 686 | gid++; | ||
| 687 | } | ||
| 688 | |||
| 689 | /* assign mpp modes to groups */ | ||
| 690 | for (n = 0; n < soc->nmodes; n++) { | ||
| 691 | struct mvebu_mpp_mode *mode = &soc->modes[n]; | ||
| 692 | struct mvebu_pinctrl_group *grp = | ||
| 693 | mvebu_pinctrl_find_group_by_pid(pctl, mode->pid); | ||
| 694 | unsigned num_settings; | ||
| 695 | |||
| 696 | if (!grp) { | ||
| 697 | dev_warn(&pdev->dev, "unknown pinctrl group %d\n", | ||
| 698 | mode->pid); | ||
| 699 | continue; | ||
| 700 | } | ||
| 701 | |||
| 702 | for (num_settings = 0; ;) { | ||
| 703 | struct mvebu_mpp_ctrl_setting *set = | ||
| 704 | &mode->settings[num_settings]; | ||
| 705 | |||
| 706 | if (!set->name) | ||
| 707 | break; | ||
| 708 | num_settings++; | ||
| 709 | |||
| 710 | /* skip unsupported settings for this variant */ | ||
| 711 | if (pctl->variant && !(pctl->variant & set->variant)) | ||
| 712 | continue; | ||
| 713 | |||
| 714 | /* find gpio/gpo/gpi settings */ | ||
| 715 | if (strcmp(set->name, "gpio") == 0) | ||
| 716 | set->flags = MVEBU_SETTING_GPI | | ||
| 717 | MVEBU_SETTING_GPO; | ||
| 718 | else if (strcmp(set->name, "gpo") == 0) | ||
| 719 | set->flags = MVEBU_SETTING_GPO; | ||
| 720 | else if (strcmp(set->name, "gpi") == 0) | ||
| 721 | set->flags = MVEBU_SETTING_GPI; | ||
| 722 | } | ||
| 723 | |||
| 724 | grp->settings = mode->settings; | ||
| 725 | grp->num_settings = num_settings; | ||
| 726 | } | ||
| 727 | |||
| 728 | ret = mvebu_pinctrl_build_functions(pdev, pctl); | ||
| 729 | if (ret) { | ||
| 730 | dev_err(&pdev->dev, "unable to build functions\n"); | ||
| 731 | return ret; | ||
| 732 | } | ||
| 733 | |||
| 734 | pctl->pctldev = pinctrl_register(&pctl->desc, &pdev->dev, pctl); | ||
| 735 | if (!pctl->pctldev) { | ||
| 736 | dev_err(&pdev->dev, "unable to register pinctrl driver\n"); | ||
| 737 | return -EINVAL; | ||
| 738 | } | ||
| 739 | |||
| 740 | dev_info(&pdev->dev, "registered pinctrl driver\n"); | ||
| 741 | |||
| 742 | /* register gpio ranges */ | ||
| 743 | for (n = 0; n < soc->ngpioranges; n++) | ||
| 744 | pinctrl_add_gpio_range(pctl->pctldev, &soc->gpioranges[n]); | ||
| 745 | |||
| 746 | return 0; | ||
| 747 | } | ||
| 748 | |||
| 749 | int __devexit mvebu_pinctrl_remove(struct platform_device *pdev) | ||
| 750 | { | ||
| 751 | struct mvebu_pinctrl *pctl = platform_get_drvdata(pdev); | ||
| 752 | pinctrl_unregister(pctl->pctldev); | ||
| 753 | return 0; | ||
| 754 | } | ||
diff --git a/drivers/pinctrl/pinctrl-mvebu.h b/drivers/pinctrl/pinctrl-mvebu.h new file mode 100644 index 000000000000..90bd3beee860 --- /dev/null +++ b/drivers/pinctrl/pinctrl-mvebu.h | |||
| @@ -0,0 +1,192 @@ | |||
| 1 | /* | ||
| 2 | * Marvell MVEBU pinctrl driver | ||
| 3 | * | ||
| 4 | * Authors: Sebastian Hesselbarth <sebastian.hesselbarth@gmail.com> | ||
| 5 | * Thomas Petazzoni <thomas.petazzoni@free-electrons.com> | ||
| 6 | * | ||
| 7 | * This program is free software; you can redistribute it and/or modify | ||
| 8 | * it under the terms of the GNU General Public License as published by | ||
| 9 | * the Free Software Foundation; either version 2 of the License, or | ||
| 10 | * (at your option) any later version. | ||
| 11 | */ | ||
| 12 | |||
| 13 | #ifndef __PINCTRL_MVEBU_H__ | ||
| 14 | #define __PINCTRL_MVEBU_H__ | ||
| 15 | |||
| 16 | /** | ||
| 17 | * struct mvebu_mpp_ctrl - describe a mpp control | ||
| 18 | * @name: name of the control group | ||
| 19 | * @pid: first pin id handled by this control | ||
| 20 | * @npins: number of pins controlled by this control | ||
| 21 | * @mpp_get: (optional) special function to get mpp setting | ||
| 22 | * @mpp_set: (optional) special function to set mpp setting | ||
| 23 | * @mpp_gpio_req: (optional) special function to request gpio | ||
| 24 | * @mpp_gpio_dir: (optional) special function to set gpio direction | ||
| 25 | * | ||
| 26 | * A mpp_ctrl describes a muxable unit, e.g. pin, group of pins, or | ||
| 27 | * internal function, inside the SoC. Each muxable unit can be switched | ||
| 28 | * between two or more different settings, e.g. assign mpp pin 13 to | ||
| 29 | * uart1 or sata. | ||
| 30 | * | ||
| 31 | * If optional mpp_get/_set functions are set these are used to get/set | ||
| 32 | * a specific mode. Otherwise it is assumed that the mpp control is based | ||
| 33 | * on 4-bit groups in subsequent registers. The optional mpp_gpio_req/_dir | ||
| 34 | * functions can be used to allow pin settings with varying gpio pins. | ||
| 35 | */ | ||
| 36 | struct mvebu_mpp_ctrl { | ||
| 37 | const char *name; | ||
| 38 | u8 pid; | ||
| 39 | u8 npins; | ||
| 40 | unsigned *pins; | ||
| 41 | int (*mpp_get)(struct mvebu_mpp_ctrl *ctrl, unsigned long *config); | ||
| 42 | int (*mpp_set)(struct mvebu_mpp_ctrl *ctrl, unsigned long config); | ||
| 43 | int (*mpp_gpio_req)(struct mvebu_mpp_ctrl *ctrl, u8 pid); | ||
| 44 | int (*mpp_gpio_dir)(struct mvebu_mpp_ctrl *ctrl, u8 pid, bool input); | ||
| 45 | }; | ||
| 46 | |||
| 47 | /** | ||
| 48 | * struct mvebu_mpp_ctrl_setting - describe a mpp ctrl setting | ||
| 49 | * @val: ctrl setting value | ||
| 50 | * @name: ctrl setting name, e.g. uart2, spi0 - unique per mpp_mode | ||
| 51 | * @subname: (optional) additional ctrl setting name, e.g. rts, cts | ||
| 52 | * @variant: (optional) variant identifier mask | ||
| 53 | * @flags: (private) flags to store gpi/gpo/gpio capabilities | ||
| 54 | * | ||
| 55 | * A ctrl_setting describes a specific internal mux function that a mpp pin | ||
| 56 | * can be switched to. The value (val) will be written in the corresponding | ||
| 57 | * register for common mpp pin configuration registers on MVEBU. SoC specific | ||
| 58 | * mpp_get/_set function may use val to distinguish between different settings. | ||
| 59 | * | ||
| 60 | * The name will be used to switch to this setting in DT description, e.g. | ||
| 61 | * marvell,function = "uart2". subname is only for debugging purposes. | ||
| 62 | * | ||
| 63 | * If name is one of "gpi", "gpo", "gpio" gpio capabilities are | ||
| 64 | * parsed during initialization and stored in flags. | ||
| 65 | * | ||
| 66 | * The variant can be used to combine different revisions of one SoC to a | ||
| 67 | * common pinctrl driver. It is matched (AND) with variant of soc_info to | ||
| 68 | * determine if a setting is available on the current SoC revision. | ||
| 69 | */ | ||
| 70 | struct mvebu_mpp_ctrl_setting { | ||
| 71 | u8 val; | ||
| 72 | const char *name; | ||
| 73 | const char *subname; | ||
| 74 | u8 variant; | ||
| 75 | u8 flags; | ||
| 76 | #define MVEBU_SETTING_GPO (1 << 0) | ||
| 77 | #define MVEBU_SETTING_GPI (1 << 1) | ||
| 78 | }; | ||
| 79 | |||
| 80 | /** | ||
| 81 | * struct mvebu_mpp_mode - link ctrl and settings | ||
| 82 | * @pid: first pin id handled by this mode | ||
| 83 | * @settings: list of settings available for this mode | ||
| 84 | * | ||
| 85 | * A mode connects all available settings with the corresponding mpp_ctrl | ||
| 86 | * given by pid. | ||
| 87 | */ | ||
| 88 | struct mvebu_mpp_mode { | ||
| 89 | u8 pid; | ||
| 90 | struct mvebu_mpp_ctrl_setting *settings; | ||
| 91 | }; | ||
| 92 | |||
| 93 | /** | ||
| 94 | * struct mvebu_pinctrl_soc_info - SoC specific info passed to pinctrl-mvebu | ||
| 95 | * @variant: variant mask of soc_info | ||
| 96 | * @controls: list of available mvebu_mpp_ctrls | ||
| 97 | * @ncontrols: number of available mvebu_mpp_ctrls | ||
| 98 | * @modes: list of available mvebu_mpp_modes | ||
| 99 | * @nmodes: number of available mvebu_mpp_modes | ||
| 100 | * @gpioranges: list of pinctrl_gpio_ranges | ||
| 101 | * @ngpioranges: number of available pinctrl_gpio_ranges | ||
| 102 | * | ||
| 103 | * This struct describes all pinctrl related information for a specific SoC. | ||
| 104 | * If variant is unequal 0 it will be matched (AND) with variant of each | ||
| 105 | * setting and allows to distinguish between different revisions of one SoC. | ||
| 106 | */ | ||
| 107 | struct mvebu_pinctrl_soc_info { | ||
| 108 | u8 variant; | ||
| 109 | struct mvebu_mpp_ctrl *controls; | ||
| 110 | int ncontrols; | ||
| 111 | struct mvebu_mpp_mode *modes; | ||
| 112 | int nmodes; | ||
| 113 | struct pinctrl_gpio_range *gpioranges; | ||
| 114 | int ngpioranges; | ||
| 115 | }; | ||
| 116 | |||
| 117 | #define MPP_REG_CTRL(_idl, _idh) \ | ||
| 118 | { \ | ||
| 119 | .name = NULL, \ | ||
| 120 | .pid = _idl, \ | ||
| 121 | .npins = _idh - _idl + 1, \ | ||
| 122 | .pins = (unsigned[_idh - _idl + 1]) { }, \ | ||
| 123 | .mpp_get = NULL, \ | ||
| 124 | .mpp_set = NULL, \ | ||
| 125 | .mpp_gpio_req = NULL, \ | ||
| 126 | .mpp_gpio_dir = NULL, \ | ||
| 127 | } | ||
| 128 | |||
| 129 | #define MPP_FUNC_CTRL(_idl, _idh, _name, _func) \ | ||
| 130 | { \ | ||
| 131 | .name = _name, \ | ||
| 132 | .pid = _idl, \ | ||
| 133 | .npins = _idh - _idl + 1, \ | ||
| 134 | .pins = (unsigned[_idh - _idl + 1]) { }, \ | ||
| 135 | .mpp_get = _func ## _get, \ | ||
| 136 | .mpp_set = _func ## _set, \ | ||
| 137 | .mpp_gpio_req = NULL, \ | ||
| 138 | .mpp_gpio_dir = NULL, \ | ||
| 139 | } | ||
| 140 | |||
| 141 | #define MPP_FUNC_GPIO_CTRL(_idl, _idh, _name, _func) \ | ||
| 142 | { \ | ||
| 143 | .name = _name, \ | ||
| 144 | .pid = _idl, \ | ||
| 145 | .npins = _idh - _idl + 1, \ | ||
| 146 | .pins = (unsigned[_idh - _idl + 1]) { }, \ | ||
| 147 | .mpp_get = _func ## _get, \ | ||
| 148 | .mpp_set = _func ## _set, \ | ||
| 149 | .mpp_gpio_req = _func ## _gpio_req, \ | ||
| 150 | .mpp_gpio_dir = _func ## _gpio_dir, \ | ||
| 151 | } | ||
| 152 | |||
| 153 | #define _MPP_VAR_FUNCTION(_val, _name, _subname, _mask) \ | ||
| 154 | { \ | ||
| 155 | .val = _val, \ | ||
| 156 | .name = _name, \ | ||
| 157 | .subname = _subname, \ | ||
| 158 | .variant = _mask, \ | ||
| 159 | .flags = 0, \ | ||
| 160 | } | ||
| 161 | |||
| 162 | #if defined(CONFIG_DEBUG_FS) | ||
| 163 | #define MPP_VAR_FUNCTION(_val, _name, _subname, _mask) \ | ||
| 164 | _MPP_VAR_FUNCTION(_val, _name, _subname, _mask) | ||
| 165 | #else | ||
| 166 | #define MPP_VAR_FUNCTION(_val, _name, _subname, _mask) \ | ||
| 167 | _MPP_VAR_FUNCTION(_val, _name, NULL, _mask) | ||
| 168 | #endif | ||
| 169 | |||
| 170 | #define MPP_FUNCTION(_val, _name, _subname) \ | ||
| 171 | MPP_VAR_FUNCTION(_val, _name, _subname, (u8)-1) | ||
| 172 | |||
| 173 | #define MPP_MODE(_id, ...) \ | ||
| 174 | { \ | ||
| 175 | .pid = _id, \ | ||
| 176 | .settings = (struct mvebu_mpp_ctrl_setting[]){ \ | ||
| 177 | __VA_ARGS__, { } }, \ | ||
| 178 | } | ||
| 179 | |||
| 180 | #define MPP_GPIO_RANGE(_id, _pinbase, _gpiobase, _npins) \ | ||
| 181 | { \ | ||
| 182 | .name = "mvebu-gpio", \ | ||
| 183 | .id = _id, \ | ||
| 184 | .pin_base = _pinbase, \ | ||
| 185 | .base = _gpiobase, \ | ||
| 186 | .npins = _npins, \ | ||
| 187 | } | ||
| 188 | |||
| 189 | int mvebu_pinctrl_probe(struct platform_device *pdev); | ||
| 190 | int mvebu_pinctrl_remove(struct platform_device *pdev); | ||
| 191 | |||
| 192 | #endif | ||
