* [PATCH 1/3] dma: mv_xor: do not sync the DMA buffer after being deallocated
From: Lubomir Rintel @ 2013-01-18 7:46 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1358495154.28503.5.camel@unicorn>
DMA_CHECK was unhappy:
mv_xor mv_xor.0: DMA-API: device driver tries to sync DMA memory it has not allocated [device address=0x000000001f3a1a40] [size=2000 bytes]
Deallocation, which involves a sync, happens automatically by
mv_xor_slot_cleanup() once the transfer is finished.
Signed-off-by: Lubomir Rintel <lkundrak@v3.sk>
---
drivers/dma/mv_xor.c | 4 ----
1 files changed, 0 insertions(+), 4 deletions(-)
diff --git a/drivers/dma/mv_xor.c b/drivers/dma/mv_xor.c
index e666983..8b81a04 100644
--- a/drivers/dma/mv_xor.c
+++ b/drivers/dma/mv_xor.c
@@ -960,8 +960,6 @@ static int mv_xor_memcpy_self_test(struct mv_xor_chan *mv_chan)
goto free_resources;
}
- dma_sync_single_for_cpu(dma_chan->device->dev, dest_dma,
- MV_XOR_TEST_SIZE, DMA_FROM_DEVICE);
if (memcmp(src, dest, MV_XOR_TEST_SIZE)) {
dev_err(dma_chan->device->dev,
"Self-test copy failed compare, disabling\n");
@@ -1054,8 +1052,6 @@ mv_xor_xor_self_test(struct mv_xor_chan *mv_chan)
goto free_resources;
}
- dma_sync_single_for_cpu(dma_chan->device->dev, dest_dma,
- PAGE_SIZE, DMA_FROM_DEVICE);
for (i = 0; i < (PAGE_SIZE / sizeof(u32)); i++) {
u32 *ptr = page_address(dest);
if (ptr[i] != cmp_word) {
--
1.7.1
^ permalink raw reply related
* [PATCH 2/2] dma: mv_xor: do not sync the DMA buffer after being deallocated
From: Lubomir Rintel @ 2013-01-18 7:45 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1358083137.13136.1.camel@hobbes>
On Sun, 2013-01-13 at 14:18 +0100, Lubomir Rintel wrote:
> On Fri, 2013-01-04 at 17:10 +0100, Thomas Petazzoni wrote:
> > Dear Lubomir Rintel,
> >
> > On Thu, 27 Dec 2012 20:23:48 +0100, Lubomir Rintel wrote:
> >
> > > dma_sync_single_for_cpu(dma_chan->device->dev, dest_dma,
> > > MV_XOR_TEST_SIZE, DMA_FROM_DEVICE);
> > > + dma_unmap_single(dma_chan->device->dev, dest_dma, MV_XOR_TEST_SIZE,
> > > + DMA_FROM_DEVICE);
> >
> > I would assume that dma_unmap_single() implies a
> > dma_sync_single_for_cpu() since you're unmapping the DMA buffer. So if
> > you use dma_unmap_single(), I think you can remove the call to
> > dma_sync_single_for_cpu().
>
> Yes, it indeed seems to be the case (comment for arm_dma_unmap_page():
> "After this call, reads by the CPU to the buffer are guaranteed to see
> whatever the device wrote there.".
>
> > > dma_sync_single_for_cpu(dma_chan->device->dev, dest_dma,
> > > PAGE_SIZE, DMA_FROM_DEVICE);
> > > + dma_unmap_page(dma_chan->device->dev, dest_dma, PAGE_SIZE,
> > > + DMA_FROM_DEVICE);
> >
> > Ditto.
> >
> > Also, the mv_xor_memcpy_self_test() function not only dma_map_single()
> > the destination buffer, but also the source buffer. So presumably, the
> > source buffer should also be dma_unmap_single()'d.
> >
> > And for the mv_xor_xor_self_test() function, multiple source buffers
> > are dma_map_page()'d, so they should all be dma_unmap_page()'d I guess,
> > not only the destination buffer.
>
> Those get released by the mv_xor_run_tx_complete_actions() callback.
>
> I will follow up with an updated patch.
Actually, after cleaning up the sync a couple more selfcheck warnings
popped up. I'd be very thankful if you could take a look (patches
chained to this message).
^ permalink raw reply
* [PATCH] ARM: remove unnecessary 'select GENERIC_GPIO'
From: Shawn Guo @ 2013-01-18 7:33 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20130117141810.GC29285@S2101-09.ap.freescale.net>
On Thu, Jan 17, 2013 at 10:18:13PM +0800, Shawn Guo wrote:
> On Thu, Jan 17, 2013 at 02:36:00PM +0100, Linus Walleij wrote:
> > On Tue, Jan 15, 2013 at 2:13 PM, Shawn Guo <shawn.guo@linaro.org> wrote:
> >
> > > The only use of GENERIC_GPIO (defined by architecture) in GPIO subsystem
> > > is being selected by GPIOLIB. Also there are no any use of the option
> > > at architecture level. Only two sub-architectures shmobile and orion
> > > really use the option as below.
> > >
> > > arch/arm/mach-shmobile/Makefile:obj-$(CONFIG_GENERIC_GPIO) += $(pfc-y)
> > > arch/arm/plat-orion/Makefile:orion-gpio-$(CONFIG_GENERIC_GPIO) += gpio.o
> > >
> > > Remove all those unnecessary sub-architecture level selection of
> > > GENERIC_GPIO, which are there only for confusing people.
> > >
> > > Signed-off-by: Shawn Guo <shawn.guo@linaro.org>
> >
> > Acked-by: Linus Walleij <linus.walleij@linaro.org>
> >
> Thanks, Linus.
>
> Arnd, Olof,
>
> Can you please take a look at the patch, and apply it as a cleanup
> if it looks good to you?
>
The commit log does not look quite good. Will resend the patch with
a better commit log.
Shawn
^ permalink raw reply
* [PATCH v7 15/15] ARM: hs: enable hi4511 with device tree
From: Haojian Zhuang @ 2013-01-18 7:31 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1358494279-16503-1-git-send-email-haojian.zhuang@linaro.org>
Enable Hisilicon Hi4511 development platform with device tree support.
Signed-off-by: Haojian Zhuang <haojian.zhuang@linaro.org>
---
arch/arm/boot/dts/Makefile | 1 +
arch/arm/boot/dts/hi3620.dtsi | 556 +++++++++++++++++++++++++++++
arch/arm/boot/dts/hi4511.dts | 772 +++++++++++++++++++++++++++++++++++++++++
3 files changed, 1329 insertions(+)
create mode 100644 arch/arm/boot/dts/hi3620.dtsi
create mode 100644 arch/arm/boot/dts/hi4511.dts
diff --git a/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile
index e44da40..12626e4 100644
--- a/arch/arm/boot/dts/Makefile
+++ b/arch/arm/boot/dts/Makefile
@@ -48,6 +48,7 @@ dtb-$(CONFIG_ARCH_EXYNOS) += exynos4210-origen.dtb \
exynos5440-ssdk5440.dtb
dtb-$(CONFIG_ARCH_HIGHBANK) += highbank.dtb \
ecx-2000.dtb
+dtb-$(CONFIG_ARCH_HS) += hi4511.dtb
dtb-$(CONFIG_ARCH_INTEGRATOR) += integratorap.dtb \
integratorcp.dtb
dtb-$(CONFIG_ARCH_LPC32XX) += ea3250.dtb phy3250.dtb
diff --git a/arch/arm/boot/dts/hi3620.dtsi b/arch/arm/boot/dts/hi3620.dtsi
new file mode 100644
index 0000000..547a93b
--- /dev/null
+++ b/arch/arm/boot/dts/hi3620.dtsi
@@ -0,0 +1,556 @@
+/*
+ * Hisilicon Ltd. Hi3620 SoC
+ *
+ * Copyright (C) 2012-2013 Linaro Ltd.
+ * Author: Haojian Zhuang <haojian.zhuang@linaro.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * publishhed by the Free Software Foundation.
+ */
+
+/include/ "skeleton.dtsi"
+
+/ {
+ aliases {
+ serial0 = &uart0;
+ serial1 = &uart1;
+ };
+
+ amba {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ compatible = "arm,amba-bus";
+ interrupt-parent = <&intc>;
+ ranges;
+
+ osc32k: osc at 0 {
+ compatible = "fixed-clock";
+ #clock-cells = <0>;
+ clock-frequency = <32768>;
+ clock-output-names = "osc32khz";
+ };
+
+ osc26m: osc at 1 {
+ compatible = "fixed-clock";
+ #clock-cells = <0>;
+ clock-frequency = <26000000>;
+ clock-output-names = "osc26mhz";
+ };
+
+ pclk: clk at 0 {
+ compatible = "fixed-clock";
+ #clock-cells = <0>;
+ clock-frequency = <26000000>;
+ clock-output-names = "apb_pclk";
+ };
+
+ timclk0: clk at 1 {
+ compatible = "fixed-clock";
+ #clock-cells = <0>;
+ clock-frequency = <60000000>;
+ clock-output-names = "timer0";
+ };
+
+ timclk1: clk at 2 {
+ compatible = "fixed-clock";
+ #clock-cells = <0>;
+ clock-frequency = <60000000>;
+ clock-output-names = "timer1";
+ };
+
+ l2: l2-cache {
+ compatible = "arm,pl310-cache";
+ reg = <0xfc10000 0x100000>;
+ interrupts = <0 15 4>;
+ cache-unified;
+ cache-level = <2>;
+ };
+
+ intc: interrupt-controller at fc001000 {
+ compatible = "arm,cortex-a9-gic";
+ #interrupt-cells = <3>;
+ #address-cells = <0>;
+ interrupt-controller;
+ /* gic dist base, gic cpu base */
+ reg = <0xfc001000 0x1000>, <0xfc000100 0x100>;
+ };
+
+ timer0: timer at fc800000 {
+ compatible = "arm,sp804", "arm,primecell";
+ reg = <0xfc800000 0x1000>;
+ /* timer00 & timer01 */
+ interrupts = <0 0 4>, <0 1 4>;
+ clocks = <&timclk0 &timclk1 &pclk>;
+ clock-names = "timer0", "timer1", "apb_pclk";
+ status = "disabled";
+ };
+
+ timer1: timer at fc801000 {
+ /*
+ * Only used in NORMAL state, not available ins
+ * SLOW or DOZE state.
+ * The rate is fixed in 24MHz.
+ */
+ compatible = "arm,sp804", "arm,primecell";
+ reg = <0xfc801000 0x1000>;
+ /* timer10 & timer11 */
+ interrupts = <0 2 4>, <0 3 4>;
+ clocks = <&timclk0 &timclk1 &pclk>;
+ clock-names = "timer0", "timer1", "apb_pclk";
+ status = "disabled";
+ };
+
+ timer2: timer at fca01000 {
+ compatible = "arm,sp804", "arm,primecell";
+ reg = <0xfca01000 0x1000>;
+ /* timer20 & timer21 */
+ interrupts = <0 4 4>, <0 5 4>;
+ clocks = <&timclk0 &timclk1 &pclk>;
+ clock-names = "timer0", "timer1", "apb_pclk";
+ status = "disabled";
+ };
+
+ timer3: timer at fca02000 {
+ compatible = "arm,sp804", "arm,primecell";
+ reg = <0xfca02000 0x1000>;
+ /* timer30 & timer31 */
+ interrupts = <0 6 4>, <0 7 4>;
+ clocks = <&timclk0 &timclk1 &pclk>;
+ clock-names = "timer0", "timer1", "apb_pclk";
+ status = "disabled";
+ };
+
+ timer4: timer at fca03000 {
+ compatible = "arm,sp804", "arm,primecell";
+ reg = <0xfca03000 0x1000>;
+ /* timer40 & timer41 */
+ interrupts = <0 96 4>, <0 97 4>;
+ clocks = <&timclk0 &timclk1 &pclk>;
+ clock-names = "timer0", "timer1", "apb_pclk";
+ status = "disabled";
+ };
+
+ uart0: uart at fcb00000 {
+ compatible = "arm,pl011", "arm,primecell";
+ reg = <0xfcb00000 0x1000>;
+ interrupts = <0 20 4>;
+ clocks = <&pclk>;
+ clock-names = "apb_pclk";
+ status = "disabled";
+ };
+
+ uart1: uart at fcb01000 {
+ compatible = "arm,pl011", "arm,primecell";
+ reg = <0xfcb01000 0x1000>;
+ interrupts = <0 21 4>;
+ clocks = <&pclk>;
+ clock-names = "apb_pclk";
+ status = "disabled";
+ };
+
+ uart2: uart at fcb02000 {
+ compatible = "arm,pl011", "arm,primecell";
+ reg = <0xfcb02000 0x1000>;
+ interrupts = <0 22 4>;
+ clocks = <&pclk>;
+ clock-names = "apb_pclk";
+ status = "disabled";
+ };
+
+ uart3: uart at fcb03000 {
+ compatible = "arm,pl011", "arm,primecell";
+ reg = <0xfcb03000 0x1000>;
+ interrupts = <0 23 4>;
+ clocks = <&pclk>;
+ clock-names = "apb_pclk";
+ status = "disabled";
+ };
+
+ uart4: uart at fcb04000 {
+ compatible = "arm,pl011", "arm,primecell";
+ reg = <0xfcb04000 0x1000>;
+ interrupts = <0 24 4>;
+ clocks = <&pclk>;
+ clock-names = "apb_pclk";
+ status = "disabled";
+ };
+
+ gpio0: gpio at fc806000 {
+ compatible = "arm,pl061", "arm,primecell";
+ reg = <0xfc806000 0x1000>;
+ interrupts = <0 64 0x4>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ gpio-ranges = < &pmx0 2 0 1 &pmx0 3 0 1 &pmx0 4 0 1
+ &pmx0 5 0 1 &pmx0 6 1 1 &pmx0 7 2 1>;
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ clocks = <&pclk>;
+ clock-names = "apb_pclk";
+ status = "disable";
+ };
+
+ gpio1: gpio at fc807000 {
+ compatible = "arm,pl061", "arm,primecell";
+ reg = <0xfc807000 0x1000>;
+ interrupts = <0 65 0x4>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ gpio-ranges = < &pmx0 0 3 1 &pmx0 1 3 1 &pmx0 2 3 1
+ &pmx0 3 3 1 &pmx0 4 3 1 &pmx0 5 4 1
+ &pmx0 6 5 1 &pmx0 7 6 1>;
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ clocks = <&pclk>;
+ clock-names = "apb_pclk";
+ status = "disable";
+ };
+
+ gpio2: gpio at fc808000 {
+ compatible = "arm,pl061", "arm,primecell";
+ reg = <0xfc808000 0x1000>;
+ interrupts = <0 66 0x4>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ gpio-ranges = < &pmx0 0 7 1 &pmx0 1 8 1 &pmx0 2 9 1
+ &pmx0 3 10 1 &pmx0 4 3 1 &pmx0 5 3 1
+ &pmx0 6 3 1 &pmx0 7 3 1>;
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ clocks = <&pclk>;
+ clock-names = "apb_pclk";
+ status = "disable";
+ };
+
+ gpio3: gpio at fc809000 {
+ compatible = "arm,pl061", "arm,primecell";
+ reg = <0xfc809000 0x1000>;
+ interrupts = <0 67 0x4>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ gpio-ranges = < &pmx0 0 3 1 &pmx0 1 3 1 &pmx0 2 3 1
+ &pmx0 3 3 1 &pmx0 4 11 1 &pmx0 5 11 1
+ &pmx0 6 11 1 &pmx0 7 11 1>;
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ clocks = <&pclk>;
+ clock-names = "apb_pclk";
+ status = "disable";
+ };
+
+ gpio4: gpio at fc80a000 {
+ compatible = "arm,pl061", "arm,primecell";
+ reg = <0xfc80a000 0x1000>;
+ interrupts = <0 68 0x4>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ gpio-ranges = < &pmx0 0 11 1 &pmx0 1 11 1 &pmx0 2 11 1
+ &pmx0 3 11 1 &pmx0 4 12 1 &pmx0 5 12 1
+ &pmx0 6 13 1 &pmx0 7 13 1>;
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ clocks = <&pclk>;
+ clock-names = "apb_pclk";
+ status = "disable";
+ };
+
+ gpio5: gpio at fc80b000 {
+ compatible = "arm,pl061", "arm,primecell";
+ reg = <0xfc80b000 0x1000>;
+ interrupts = <0 69 0x4>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ gpio-ranges = < &pmx0 0 14 1 &pmx0 1 15 1 &pmx0 2 16 1
+ &pmx0 3 16 1 &pmx0 4 16 1 &pmx0 5 16 1
+ &pmx0 6 16 1 &pmx0 7 16 1>;
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ clocks = <&pclk>;
+ clock-names = "apb_pclk";
+ status = "disable";
+ };
+
+ gpio6: gpio at fc80c000 {
+ compatible = "arm,pl061", "arm,primecell";
+ reg = <0xfc80c000 0x1000>;
+ interrupts = <0 70 0x4>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ gpio-ranges = < &pmx0 0 16 1 &pmx0 1 16 1 &pmx0 2 17 1
+ &pmx0 3 17 1 &pmx0 4 18 1 &pmx0 5 18 1
+ &pmx0 6 18 1 &pmx0 7 19 1>;
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ clocks = <&pclk>;
+ clock-names = "apb_pclk";
+ status = "disable";
+ };
+
+ gpio7: gpio at fc80d000 {
+ compatible = "arm,pl061", "arm,primecell";
+ reg = <0xfc80d000 0x1000>;
+ interrupts = <0 71 0x4>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ gpio-ranges = < &pmx0 0 19 1 &pmx0 1 20 1 &pmx0 2 21 1
+ &pmx0 3 22 1 &pmx0 4 23 1 &pmx0 5 24 1
+ &pmx0 6 25 1 &pmx0 7 26 1>;
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ clocks = <&pclk>;
+ clock-names = "apb_pclk";
+ status = "disable";
+ };
+
+ gpio8: gpio at fc80e000 {
+ compatible = "arm,pl061", "arm,primecell";
+ reg = <0xfc80e000 0x1000>;
+ interrupts = <0 72 0x4>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ gpio-ranges = < &pmx0 0 27 1 &pmx0 1 28 1 &pmx0 2 29 1
+ &pmx0 3 30 1 &pmx0 4 31 1 &pmx0 5 32 1
+ &pmx0 6 33 1 &pmx0 7 34 1>;
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ clocks = <&pclk>;
+ clock-names = "apb_pclk";
+ status = "disable";
+ };
+
+ gpio9: gpio at fc80f000 {
+ compatible = "arm,pl061", "arm,primecell";
+ reg = <0xfc80f000 0x1000>;
+ interrupts = <0 73 0x4>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ gpio-ranges = < &pmx0 0 35 1 &pmx0 1 36 1 &pmx0 2 37 1
+ &pmx0 3 38 1 &pmx0 4 39 1 &pmx0 5 40 1
+ &pmx0 6 41 1>;
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ clocks = <&pclk>;
+ clock-names = "apb_pclk";
+ status = "disable";
+ };
+
+ gpio10: gpio at fc810000 {
+ compatible = "arm,pl061", "arm,primecell";
+ reg = <0xfc810000 0x1000>;
+ interrupts = <0 74 0x4>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ gpio-ranges = < &pmx0 2 43 1 &pmx0 3 44 1 &pmx0 4 45 1
+ &pmx0 5 45 1 &pmx0 6 46 1 &pmx0 7 46 1>;
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ clocks = <&pclk>;
+ clock-names = "apb_pclk";
+ status = "disable";
+ };
+
+ gpio11: gpio at fc811000 {
+ compatible = "arm,pl061", "arm,primecell";
+ reg = <0xfc811000 0x1000>;
+ interrupts = <0 75 0x4>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ gpio-ranges = < &pmx0 0 47 1 &pmx0 1 47 1 &pmx0 2 47 1
+ &pmx0 3 47 1 &pmx0 4 47 1 &pmx0 5 48 1
+ &pmx0 6 49 1 &pmx0 7 49 1>;
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ clocks = <&pclk>;
+ clock-names = "apb_pclk";
+ status = "disable";
+ };
+
+ gpio12: gpio at fc812000 {
+ compatible = "arm,pl061", "arm,primecell";
+ reg = <0xfc812000 0x1000>;
+ interrupts = <0 76 0x4>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ gpio-ranges = < &pmx0 0 49 1 &pmx0 1 50 1 &pmx0 2 49 1
+ &pmx0 3 49 1 &pmx0 4 51 1 &pmx0 5 51 1
+ &pmx0 6 51 1 &pmx0 7 52 1>;
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ clocks = <&pclk>;
+ clock-names = "apb_pclk";
+ status = "disable";
+ };
+
+ gpio13: gpio at fc813000 {
+ compatible = "arm,pl061", "arm,primecell";
+ reg = <0xfc813000 0x1000>;
+ interrupts = <0 77 0x4>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ gpio-ranges = < &pmx0 0 51 1 &pmx0 1 51 1 &pmx0 2 53 1
+ &pmx0 3 53 1 &pmx0 4 53 1 &pmx0 5 54 1
+ &pmx0 6 55 1 &pmx0 7 56 1>;
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ clocks = <&pclk>;
+ clock-names = "apb_pclk";
+ status = "disable";
+ };
+
+ gpio14: gpio at fc814000 {
+ compatible = "arm,pl061", "arm,primecell";
+ reg = <0xfc814000 0x1000>;
+ interrupts = <0 78 0x4>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ gpio-ranges = < &pmx0 0 57 1 &pmx0 1 97 1 &pmx0 2 97 1
+ &pmx0 3 58 1 &pmx0 4 59 1 &pmx0 5 60 1
+ &pmx0 6 60 1 &pmx0 7 61 1>;
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ clocks = <&pclk>;
+ clock-names = "apb_pclk";
+ status = "disable";
+ };
+
+ gpio15: gpio at fc815000 {
+ compatible = "arm,pl061", "arm,primecell";
+ reg = <0xfc815000 0x1000>;
+ interrupts = <0 79 0x4>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ gpio-ranges = < &pmx0 0 61 1 &pmx0 1 62 1 &pmx0 2 62 1
+ &pmx0 3 63 1 &pmx0 4 63 1 &pmx0 5 64 1
+ &pmx0 6 64 1 &pmx0 7 65 1>;
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ clocks = <&pclk>;
+ clock-names = "apb_pclk";
+ status = "disable";
+ };
+
+ gpio16: gpio at fc816000 {
+ compatible = "arm,pl061", "arm,primecell";
+ reg = <0xfc816000 0x1000>;
+ interrupts = <0 80 0x4>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ gpio-ranges = < &pmx0 0 66 1 &pmx0 1 67 1 &pmx0 2 68 1
+ &pmx0 3 69 1 &pmx0 4 70 1 &pmx0 5 71 1
+ &pmx0 6 72 1 &pmx0 7 73 1>;
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ clocks = <&pclk>;
+ clock-names = "apb_pclk";
+ status = "disable";
+ };
+
+ gpio17: gpio at fc817000 {
+ compatible = "arm,pl061", "arm,primecell";
+ reg = <0xfc817000 0x1000>;
+ interrupts = <0 81 0x4>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ gpio-ranges = < &pmx0 0 74 1 &pmx0 1 75 1 &pmx0 2 76 1
+ &pmx0 3 77 1 &pmx0 4 78 1 &pmx0 5 79 1
+ &pmx0 6 80 1 &pmx0 7 81 1>;
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ clocks = <&pclk>;
+ clock-names = "apb_pclk";
+ status = "disable";
+ };
+
+ gpio18: gpio at fc818000 {
+ compatible = "arm,pl061", "arm,primecell";
+ reg = <0xfc818000 0x1000>;
+ interrupts = <0 82 0x4>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ gpio-ranges = < &pmx0 0 82 1 &pmx0 1 83 1 &pmx0 2 83 1
+ &pmx0 3 84 1 &pmx0 4 84 1 &pmx0 5 85 1
+ &pmx0 6 86 1 &pmx0 7 87 1>;
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ clocks = <&pclk>;
+ clock-names = "apb_pclk";
+ status = "disable";
+ };
+
+ gpio19: gpio at fc819000 {
+ compatible = "arm,pl061", "arm,primecell";
+ reg = <0xfc819000 0x1000>;
+ interrupts = <0 83 0x4>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ gpio-ranges = < &pmx0 0 87 1 &pmx0 1 87 1 &pmx0 2 88 1
+ &pmx0 3 88 1>;
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ clocks = <&pclk>;
+ clock-names = "apb_pclk";
+ status = "disable";
+ };
+
+ gpio20: gpio at fc81a000 {
+ compatible = "arm,pl061", "arm,primecell";
+ reg = <0xfc81a000 0x1000>;
+ interrupts = <0 84 0x4>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ gpio-ranges = < &pmx0 0 89 1 &pmx0 1 89 1 &pmx0 2 90 1
+ &pmx0 3 90 1 &pmx0 4 91 1 &pmx0 5 92 1>;
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ clocks = <&pclk>;
+ clock-names = "apb_pclk";
+ status = "disable";
+ };
+
+ gpio21: gpio at fc81b000 {
+ compatible = "arm,pl061", "arm,primecell";
+ reg = <0xfc81b000 0x1000>;
+ interrupts = <0 85 0x4>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ gpio-ranges = < &pmx0 3 94 1 &pmx0 7 96 1>;
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ clocks = <&pclk>;
+ clock-names = "apb_pclk";
+ status = "disable";
+ };
+
+ pmx0: pinmux at fc803000 {
+ compatible = "pinctrl-single";
+ reg = <0xfc803000 0x188>;
+ #address-cells = <1>;
+ #size-cells = <1>;
+ #gpio-range-cells = <3>;
+ ranges;
+
+ pinctrl-single,register-width = <32>;
+ pinctrl-single,function-mask = <7>;
+ /* pin base, nr pins & gpio function */
+ pinctrl-single,gpio-range = <&range 0 3 0 &range 3 9 1
+ &range 12 1 0 &range 13 29 1
+ &range 43 1 0 &range 44 49 1
+ &range 94 1 1 &range 96 2 1>;
+
+ range: gpio-range {
+ #pinctrl-single,gpio-range-cells = <3>;
+ };
+ };
+
+ pmx1: pinmux at fc803800 {
+ compatible = "pinconf-single";
+ reg = <0xfc803800 0x2dc>;
+ #address-cells = <1>;
+ #size-cells = <1>;
+ ranges;
+
+ pinctrl-single,register-width = <32>;
+ };
+ };
+};
diff --git a/arch/arm/boot/dts/hi4511.dts b/arch/arm/boot/dts/hi4511.dts
new file mode 100644
index 0000000..27a5039
--- /dev/null
+++ b/arch/arm/boot/dts/hi4511.dts
@@ -0,0 +1,772 @@
+/*
+ * Copyright (C) 2012-2013 Linaro Ltd.
+ * Author: Haojian Zhuang <haojian.zhuang@linaro.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * publishhed by the Free Software Foundation.
+ */
+
+/dts-v1/;
+/include/ "hi3620.dtsi"
+
+/ {
+ model = "Hisilicon Hi4511 Development Board";
+ compatible = "hisilicon,hi3620-hi4511";
+
+ chosen {
+ bootargs = "console=ttyAMA0,115200 root=/dev/nfs nfsroot=192.168.1.100:/nfsroot/ ip=192.168.1.101:192.168.1.100::255.255.255.0::eth0:on mem=512m earlyprintk";
+ };
+
+ memory {
+ reg = <0x00000000 0x20000000>;
+ };
+
+ amba {
+ timer0: timer at fc800000 {
+ status = "ok";
+ };
+
+ uart0: uart at fcb00000 { /* console */
+ pinctrl-names = "default", "idle";
+ pinctrl-0 = <&uart0_pmx_func &uart0_cfg_func>;
+ pinctrl-1 = <&uart0_pmx_idle &uart0_cfg_idle>;
+ status = "ok";
+ };
+
+ uart1: uart at fcb01000 { /* modem */
+ pinctrl-names = "default", "idle";
+ pinctrl-0 = <&uart1_pmx_func &uart1_cfg_func>;
+ pinctrl-1 = <&uart1_pmx_idle &uart1_cfg_idle>;
+ status = "ok";
+ };
+
+ uart2: uart at fcb02000 { /* audience */
+ pinctrl-names = "default", "idle";
+ pinctrl-0 = <&uart2_pmx_func &uart2_cfg_func>;
+ pinctrl-1 = <&uart2_pmx_idle &uart2_cfg_idle>;
+ status = "ok";
+ };
+
+ uart3: uart at fcb03000 {
+ pinctrl-names = "default", "idle";
+ pinctrl-0 = <&uart3_pmx_func &uart3_cfg_func>;
+ pinctrl-1 = <&uart3_pmx_idle &uart3_cfg_idle>;
+ status = "ok";
+ };
+
+ uart4: uart at fcb04000 {
+ pinctrl-names = "default", "idle";
+ pinctrl-0 = <&uart4_pmx_func &uart4_cfg_func>;
+ pinctrl-1 = <&uart4_pmx_idle &uart4_cfg_func>;
+ status = "ok";
+ };
+
+ gpio0: gpio at fc806000 {
+ status = "ok";
+ };
+
+ gpio1: gpio at fc807000 {
+ status = "ok";
+ };
+
+ gpio2: gpio at fc808000 {
+ status = "ok";
+ };
+
+ gpio3: gpio at fc809000 {
+ status = "ok";
+ };
+
+ gpio4: gpio at fc80a000 {
+ status = "ok";
+ };
+
+ gpio5: gpio at fc80b000 {
+ status = "ok";
+ };
+
+ gpio6: gpio at fc80c000 {
+ status = "ok";
+ };
+
+ gpio7: gpio at fc80d000 {
+ status = "ok";
+ };
+
+ gpio8: gpio at fc80e000 {
+ status = "ok";
+ };
+
+ gpio9: gpio at fc80f000 {
+ status = "ok";
+ };
+
+ gpio10: gpio at fc810000 {
+ status = "ok";
+ };
+
+ gpio11: gpio at fc811000 {
+ status = "ok";
+ };
+
+ gpio12: gpio at fc812000 {
+ status = "ok";
+ };
+
+ gpio13: gpio at fc813000 {
+ status = "ok";
+ };
+
+ gpio14: gpio at fc814000 {
+ status = "ok";
+ };
+
+ gpio15: gpio at fc815000 {
+ status = "ok";
+ };
+
+ gpio16: gpio at fc816000 {
+ status = "ok";
+ };
+
+ gpio17: gpio at fc817000 {
+ status = "ok";
+ };
+
+ gpio18: gpio at fc818000 {
+ status = "ok";
+ };
+
+ gpio19: gpio at fc819000 {
+ status = "ok";
+ };
+
+ gpio20: gpio at fc81a000 {
+ status = "ok";
+ };
+
+ gpio21: gpio at fc81b000 {
+ status = "ok";
+ };
+
+ gpio-keys {
+ compatible = "gpio-keys";
+
+ call {
+ label = "call";
+ gpios = <&gpio17 2 0>;
+ linux,code = <169>; /* KEY_PHONE */
+ };
+ };
+
+ pmx0: pinmux at fc803000 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&i2c0_pmx_func>;
+
+ board_pmx_pins: pinmux_board_pmx_pins {
+ pinctrl-single,pins = <
+ 0x008 0x0 /* GPIO -- eFUSE_DOUT */
+ 0x100 0x0 /* USIM_CLK & USIM_DATA (IOMG63) */
+ 0x104 0x0 /* USIM_RST (IOMG96) */
+ >;
+ };
+ sd_pmx_pins: pinmux_sd_pins {
+ pinctrl-single,pins = <
+ 0x0bc 0x0 /* SD_CLK, SD_CMD, SD_DATA[0:2] */
+ >;
+ };
+ uart0_pmx_func: pinmux_uart0_pins at 0 {
+ pinctrl-single,pins = <
+ 0x0f0 0x0
+ 0x0f4 0x0 /* UART0_RX & UART0_TX */
+ >;
+ };
+ uart0_pmx_idle: pinmux_uart0_pins at 1 {
+ pinctrl-single,pins = <
+ /*0x0f0 0x1*/ /* UART0_CTS & UART0_RTS */
+ 0x0f4 0x1 /* UART0_RX & UART0_TX */
+ >;
+ };
+ uart1_pmx_func: pinmux_uart1_pins at 0 {
+ pinctrl-single,pins = <
+ 0x0f8 0x0 /* UART1_CTS & UART1_RTS (IOMG61) */
+ 0x0fc 0x0 /* UART1_RX & UART1_TX (IOMG62) */
+ >;
+ };
+ uart1_pmx_idle: pinmux_uart1_pins at 1 {
+ pinctrl-single,pins = <
+ 0x0f8 0x1 /* GPIO (IOMG61) */
+ 0x0fc 0x1 /* GPIO (IOMG62) */
+ >;
+ };
+ uart2_pmx_func: pinmux_uart2_pins at 0 {
+ pinctrl-single,pins = <
+ 0x104 0x2 /* UART2_RXD (IOMG96) */
+ 0x108 0x2 /* UART2_TXD (IOMG64) */
+ >;
+ };
+ uart2_pmx_idle: pinmux_uart2_pins at 1 {
+ pinctrl-single,pins = <
+ 0x104 0x1 /* GPIO (IOMG96) */
+ 0x108 0x1 /* GPIO (IOMG64) */
+ >;
+ };
+ uart3_pmx_func: pinmux_uart3_pins at 0 {
+ pinctrl-single,pins = <
+ 0x160 0x2 /* UART3_CTS & UART3_RTS (IOMG85) */
+ 0x164 0x2 /* UART3_RXD & UART3_TXD (IOMG86) */
+ >;
+ };
+ uart3_pmx_idle: pinmux_uart3_pins at 1 {
+ pinctrl-single,pins = <
+ 0x160 0x1 /* GPIO (IOMG85) */
+ 0x164 0x1 /* GPIO (IOMG86) */
+ >;
+ };
+ uart4_pmx_func: pinmux_uart4_pins at 0 {
+ pinctrl-single,pins = <
+ 0x168 0x0 /* UART4_CTS & UART4_RTS (IOMG87) */
+ 0x16c 0x0 /* UART4_RXD (IOMG88) */
+ 0x170 0x0 /* UART4_TXD (IOMG93) */
+ >;
+ };
+ uart4_pmx_idle: pinmux_uart4_pins at 1 {
+ pinctrl-single,pins = <
+ 0x168 0x1 /* GPIO (IOMG87) */
+ 0x16c 0x1 /* GPIO (IOMG88) */
+ 0x170 0x1 /* GPIO (IOMG93) */
+ >;
+ };
+ i2c0_pmx_func: pinmux_i2c0_pins at 0 {
+ pinctrl-single,pins = <
+ 0x0b4 0x0 /* I2C0_SCL & I2C0_SDA (IOMG45) */
+ >;
+ };
+ i2c0_pmx_idle: pinmux_i2c0_pins at 1 {
+ pinctrl-single,pins = <
+ 0x0b4 0x1 /* GPIO (IOMG45) */
+ >;
+ };
+ i2c1_pmx_func: pinmux_i2c1_pins at 0 {
+ pinctrl-single,pins = <
+ 0x0b8 0x0 /* I2C1_SCL & I2C1_SDA (IOMG46) */
+ >;
+ };
+ i2c1_pmx_idle: pinmux_i2c1_pins at 1 {
+ pinctrl-single,pins = <
+ 0x0b8 0x1 /* GPIO (IOMG46) */
+ >;
+ };
+ i2c2_pmx_func: pinmux_i2c2_pins at 0 {
+ pinctrl-single,pins = <
+ 0x068 0x0 /* I2C2_SCL (IOMG26) */
+ 0x06c 0x0 /* I2C2_SDA (IOMG27) */
+ >;
+ };
+ i2c2_pmx_idle: pinmux_i2c2_pins at 0 {
+ pinctrl-single,pins = <
+ 0x068 0x1 /* GPIO (IOMG26) */
+ 0x06c 0x1 /* GPIO (IOMG27) */
+ >;
+ };
+ i2c3_pmx_func: pinmux_i2c3_pins at 0 {
+ pinctrl-single,pins = <
+ 0x050 0x2 /* I2C3_SCL (IOMG20) */
+ 0x054 0x2 /* I2C3_SDA (IOMG21) */
+ >;
+ };
+ i2c3_pmx_idle: pinmux_i2c3_pins at 0 {
+ pinctrl-single,pins = <
+ 0x050 0x1 /* GPIO (IOMG20) */
+ 0x054 0x1 /* GPIO (IOMG21) */
+ >;
+ };
+ spi0_pmx_func: pinmux_spi0_pins at 0 {
+ pinctrl-single,pins = <
+ 0x0d4 0x0 /* SPI0_CLK/SPI0_DI/SPI0_DO (IOMG53) */
+ 0x0d8 0x0 /* SPI0_CS0 (IOMG54) */
+ 0x0dc 0x0 /* SPI0_CS1 (IOMG55) */
+ 0x0e0 0x0 /* SPI0_CS2 (IOMG56) */
+ 0x0e4 0x0 /* SPI0_CS3 (IOMG57) */
+ >;
+ };
+ spi0_pmx_idle: pinmux_spi0_pins at 1 {
+ pinctrl-single,pins = <
+ 0x0d4 0x1 /* GPIO (IOMG53) */
+ 0x0d8 0x1 /* GPIO (IOMG54) */
+ 0x0dc 0x1 /* GPIO (IOMG55) */
+ 0x0e0 0x1 /* GPIO (IOMG56) */
+ 0x0e4 0x1 /* GPIO (IOMG57) */
+ >;
+ };
+ spi1_pmx_func: pinmux_spi1_pins at 0 {
+ pinctrl-single,pins = <
+ 0x184 0x0 /* SPI1_CLK/SPI1_DI (IOMG98) */
+ 0x0e8 0x0 /* SPI1_DO (IOMG58) */
+ 0x0ec 0x0 /* SPI1_CS (IOMG95) */
+ >;
+ };
+ spi1_pmx_idle: pinmux_spi1_pins at 1 {
+ pinctrl-single,pins = <
+ 0x184 0x1 /* GPIO (IOMG98) */
+ 0x0e8 0x1 /* GPIO (IOMG58) */
+ 0x0ec 0x1 /* GPIO (IOMG95) */
+ >;
+ };
+ kpc_pmx_func: pinmux_kpc_pins at 0 {
+ pinctrl-single,pins = <
+ 0x12c 0x0 /* KEY_IN0 (IOMG73) */
+ 0x130 0x0 /* KEY_IN1 (IOMG74) */
+ 0x134 0x0 /* KEY_IN2 (IOMG75) */
+ 0x10c 0x0 /* KEY_OUT0 (IOMG65) */
+ 0x110 0x0 /* KEY_OUT1 (IOMG66) */
+ 0x114 0x0 /* KEY_OUT2 (IOMG67) */
+ >;
+ };
+ kpc_pmx_idle: pinmux_kpc_pins at 1 {
+ pinctrl-single,pins = <
+ 0x12c 0x1 /* GPIO (IOMG73) */
+ 0x130 0x1 /* GPIO (IOMG74) */
+ 0x134 0x1 /* GPIO (IOMG75) */
+ 0x10c 0x1 /* GPIO (IOMG65) */
+ 0x110 0x1 /* GPIO (IOMG66) */
+ 0x114 0x1 /* GPIO (IOMG67) */
+ >;
+ };
+ gpio_key_func: pinmux_gpiokey_pins {
+ pinctrl-single,pins = <
+ 0x10c 0x1 /* KEY_OUT0/GPIO (IOMG65) */
+ 0x130 0x1 /* KEY_IN1/GPIO (IOMG74) */
+ >;
+ };
+ emmc_pmx_func: pinmux_emmc_pins at 0 {
+ pinctrl-single,pins = <
+ 0x030 0x2 /* eMMC_CMD/eMMC_CLK (IOMG12) */
+ 0x018 0x0 /* NAND_CS3_N (IOMG6) */
+ 0x024 0x0 /* NAND_BUSY2_N (IOMG8) */
+ 0x028 0x0 /* NAND_BUSY3_N (IOMG9) */
+ 0x02c 0x2 /* eMMC_DATA[0:7] (IOMG10) */
+ >;
+ };
+ emmc_pmx_idle: pinmux_emmc_pins at 1 {
+ pinctrl-single,pins = <
+ 0x030 0x0 /* GPIO (IOMG12) */
+ 0x018 0x1 /* GPIO (IOMG6) */
+ 0x024 0x1 /* GPIO (IOMG8) */
+ 0x028 0x1 /* GPIO (IOMG9) */
+ 0x02c 0x1 /* GPIO (IOMG10) */
+ >;
+ };
+ sd_pmx_func: pinmux_sd_pins at 0 {
+ pinctrl-single,pins = <
+ 0x0bc 0x0 /* SD_CLK/SD_CMD/SD_DATA0/SD_DATA1/SD_DATA2 (IOMG47) */
+ 0x0c0 0x0 /* SD_DATA3 (IOMG48) */
+ >;
+ };
+ sd_pmx_idle: pinmux_sd_pins at 1 {
+ pinctrl-single,pins = <
+ 0x0bc 0x1 /* GPIO (IOMG47) */
+ 0x0c0 0x1 /* GPIO (IOMG48) */
+ >;
+ };
+ nand_pmx_func: pinmux_nand_pins at 0 {
+ pinctrl-single,pins = <
+ 0x00c 0x0 /* NAND_ALE/NAND_CLE/.../NAND_DATA[0:7] (IOMG3) */
+ 0x010 0x0 /* NAND_CS1_N (IOMG4) */
+ 0x014 0x0 /* NAND_CS2_N (IOMG5) */
+ 0x018 0x0 /* NAND_CS3_N (IOMG6) */
+ 0x01c 0x0 /* NAND_BUSY0_N (IOMG94) */
+ 0x020 0x0 /* NAND_BUSY1_N (IOMG7) */
+ 0x024 0x0 /* NAND_BUSY2_N (IOMG8) */
+ 0x028 0x0 /* NAND_BUSY3_N (IOMG9) */
+ 0x02c 0x0 /* NAND_DATA[8:15] (IOMG10) */
+ >;
+ };
+ nand_pmx_idle: pinmux_nand_pins at 1 {
+ pinctrl-single,pins = <
+ 0x00c 0x1 /* GPIO (IOMG3) */
+ 0x010 0x1 /* GPIO (IOMG4) */
+ 0x014 0x1 /* GPIO (IOMG5) */
+ 0x018 0x1 /* GPIO (IOMG6) */
+ 0x01c 0x1 /* GPIO (IOMG94) */
+ 0x020 0x1 /* GPIO (IOMG7) */
+ 0x024 0x1 /* GPIO (IOMG8) */
+ 0x028 0x1 /* GPIO (IOMG9) */
+ 0x02c 0x1 /* GPIO (IOMG10) */
+ >;
+ };
+ sdio_pmx_func: pinmux_sdio_pins at 0 {
+ pinctrl-single,pins = <
+ 0x0c4 0x0 /* SDIO_CLK/SDIO_CMD/SDIO_DATA[0:3] (IOMG49) */
+ >;
+ };
+ sdio_pmx_idle: pinmux_sdio_pins at 1 {
+ pinctrl-single,pins = <
+ 0x0c4 0x1 /* GPIO (IOMG49) */
+ >;
+ };
+ audio_out_pmx_func: pinmux_audio_pins at 0 {
+ pinctrl-single,pins = <
+ 0x0f0 0x1 /* GPIO (IOMG59), audio spk & earphone */
+ >;
+ };
+ };
+
+ pmx1: pinmux at fc803800 {
+ pinctrl-names = "default";
+ pinctrl-0 = < &board_pu_pins &board_pd_pins &board_pd_ps_pins
+ &board_np_pins &board_ps_pins &kpc_cfg_func
+ &audio_out_cfg_func>;
+ board_pu_pins: pinmux_board_pu_pins {
+ pinctrl-single,pins = <
+ 0x014 0 /* GPIO_158 (IOCFG2) */
+ 0x018 0 /* GPIO_159 (IOCFG3) */
+ 0x01c 0 /* BOOT_MODE0 (IOCFG4) */
+ 0x020 0 /* BOOT_MODE1 (IOCFG5) */
+ >;
+ pinctrl-single,bias-pullup = <1 1 1>;
+ pinctrl-single,bias-disable = <1 0 1>;
+ };
+ board_pd_pins: pinmux_board_pd_pins {
+ pinctrl-single,pins = <
+ 0x038 0 /* eFUSE_DOUT (IOCFG11) */
+ 0x150 0 /* ISP_GPIO8 (IOCFG93) */
+ 0x154 0 /* ISP_GPIO9 (IOCFG94) */
+ >;
+ pinctrl-single,bias-pulldown = <2 2 2>;
+ pinctrl-single,bias-pullup = <0 1 1>;
+ pinctrl-single,bias-disable = <2 0 3>;
+ };
+ board_pd_ps_pins: pinmux_board_pd_ps_pins {
+ pinctrl-single,pins = <
+ 0x220 0 /* USIM_CLK (IOCFG144) */
+ 0x224 0 /* USIM_DATA (IOCFG145) */
+ 0x228 0 /* USIM_RST (IOCFG146) */
+ 0x2d8 0 /* CLK_OUT0 (IOCFG190) */
+ 0x004 0 /* PMU_SPI_DATA (IOCFG192) */
+ >;
+ pinctrl-single,bias-pulldown = <2 2 2>;
+ pinctrl-single,bias-pullup = <0 1 1>;
+ pinctrl-single,bias-disable = <2 0 3>;
+ pinctrl-single,power-source = <0x30 0xf0>;
+ };
+ board_np_pins: pinmux_board_np_pins {
+ pinctrl-single,pins = <
+ 0x24c 0 /* KEYPAD_OUT7 (IOCFG155) */
+ >;
+ pinctrl-single,bias-pulldown = <0 2 2>;
+ pinctrl-single,bias-pullup = <0 1 1>;
+ pinctrl-single,bias-disable = <0 0 3>;
+ };
+ board_ps_pins: pinmux_board_ps_pins {
+ pinctrl-single,pins = <
+ 0x000 0 /* PMU_SPI_CLK (IOCFG191) */
+ 0x008 0 /* PMU_SPI_CS_N (IOCFG193) */
+ >;
+ pinctrl-single,power-source = <0x30 0xf0>;
+ };
+ uart0_cfg_func: pinmux_uart0_pins at 2 {
+ pinctrl-single,pins = <
+ 0x208 0 /* UART0_RXD (IOCFG138) */
+ 0x20c 0 /* UART0_TXD (IOCFG139) */
+ >;
+ pinctrl-single,bias-pulldown = <0 2 2>;
+ pinctrl-single,bias-pullup = <0 1 1>;
+ pinctrl-single,bias-disable = <0 0 3>;
+ };
+ uart0_cfg_idle: pinmux_uart0_pins at 3 {
+ pinctrl-single,pins = <
+ 0x208 0 /* UART0_RXD (IOCFG138) */
+ 0x20c 0 /* UART0_TXD (IOCFG139) */
+ >;
+ pinctrl-single,bias-pulldown = <2 2 2>;
+ pinctrl-single,bias-pullup = <0 1 1>;
+ pinctrl-single,bias-disable = <2 0 3>;
+ };
+ uart1_cfg_func: pinmux_uart1_pins at 2 {
+ pinctrl-single,pins = <
+ 0x210 0 /* UART1_CTS (IOCFG140) */
+ 0x214 0 /* UART1_RTS (IOCFG141) */
+ 0x218 0 /* UART1_RXD (IOCFG142) */
+ 0x21c 0 /* UART1_TXD (IOCFG143) */
+ >;
+ pinctrl-single,bias-pulldown = <0 2 2>;
+ pinctrl-single,bias-pullup = <0 1 1>;
+ pinctrl-single,bias-disable = <0 0 3>;
+ };
+ uart1_cfg_idle: pinmux_uart1_pins at 3 {
+ pinctrl-single,pins = <
+ 0x210 0 /* UART1_CTS (IOCFG140) */
+ 0x214 0 /* UART1_RTS (IOCFG141) */
+ 0x218 0 /* UART1_RXD (IOCFG142) */
+ 0x21c 0 /* UART1_TXD (IOCFG143) */
+ >;
+ pinctrl-single,bias-pulldown = <2 2 2>;
+ pinctrl-single,bias-pullup = <0 1 1>;
+ pinctrl-single,bias-disable = <2 0 3>;
+ };
+ uart2_cfg_func: pinmux_uart2_pins at 2 {
+ pinctrl-single,pins = <
+ 0x210 0 /* UART1_CTS (IOCFG140) */
+ 0x214 0 /* UART1_RTS (IOCFG141) */
+ 0x218 0 /* UART1_RXD (IOCFG142) */
+ 0x21c 0 /* UART1_TXD (IOCFG143) */
+ >;
+ pinctrl-single,bias-pulldown = <0 2 2>;
+ pinctrl-single,bias-pullup = <0 1 1>;
+ pinctrl-single,bias-disable = <0 0 3>;
+ };
+ uart2_cfg_idle: pinmux_uart2_pins at 3 {
+ pinctrl-single,pins = <
+ 0x210 0 /* GPIO (IOCFG140) */
+ 0x214 0 /* GPIO (IOCFG141) */
+ 0x218 0 /* GPIO (IOCFG142) */
+ 0x21c 0 /* GPIO (IOCFG143) */
+ >;
+ pinctrl-single,bias-pulldown = <2 2 2>;
+ pinctrl-single,bias-pullup = <0 1 1>;
+ pinctrl-single,bias-disable = <2 0 3>;
+ };
+ uart3_cfg_func: pinmux_uart3_pins at 2 {
+ pinctrl-single,pins = <
+ 0x294 0 /* UART3_CTS (IOCFG173) */
+ 0x298 0 /* UART3_RTS (IOCFG174) */
+ 0x29c 0 /* UART3_RXD (IOCFG175) */
+ 0x2a0 0 /* UART3_TXD (IOCFG176) */
+ >;
+ pinctrl-single,bias-pulldown = <0 2 2>;
+ pinctrl-single,bias-pullup = <0 1 1>;
+ pinctrl-single,bias-disable = <0 0 3>;
+ };
+ uart3_cfg_idle: pinmux_uart3_pins at 3 {
+ pinctrl-single,pins = <
+ 0x294 0 /* UART3_CTS (IOCFG173) */
+ 0x298 0 /* UART3_RTS (IOCFG174) */
+ 0x29c 0 /* UART3_RXD (IOCFG175) */
+ 0x2a0 0 /* UART3_TXD (IOCFG176) */
+ >;
+ pinctrl-single,bias-pulldown = <2 2 2>;
+ pinctrl-single,bias-pullup = <0 1 1>;
+ pinctrl-single,bias-disable = <2 0 3>;
+ };
+ uart4_cfg_func: pinmux_uart4_pins at 2 {
+ pinctrl-single,pins = <
+ 0x2a4 0 /* UART4_CTS (IOCFG177) */
+ 0x2a8 0 /* UART4_RTS (IOCFG178) */
+ 0x2ac 0 /* UART4_RXD (IOCFG179) */
+ 0x2b0 0 /* UART4_TXD (IOCFG180) */
+ >;
+ pinctrl-single,bias-pulldown = <0 2 2>;
+ pinctrl-single,bias-pullup = <0 1 1>;
+ pinctrl-single,bias-disable = <0 0 3>;
+ };
+ i2c0_cfg_func: pinmux_i2c0_pins at 2 {
+ pinctrl-single,pins = <
+ 0x17c 0 /* I2C0_SCL (IOCFG103) */
+ 0x180 0 /* I2C0_SDA (IOCFG104) */
+ >;
+ pinctrl-single,bias-pulldown = <0 2 2>;
+ pinctrl-single,bias-pullup = <0 1 1>;
+ pinctrl-single,bias-disable = <0 0 3>;
+ pinctrl-single,power-source = <0x30 0xf0>;
+ };
+ i2c1_cfg_func: pinmux_i2c1_pins at 2 {
+ pinctrl-single,pins = <
+ 0x184 0 /* I2C1_SCL (IOCFG105) */
+ 0x188 0 /* I2C1_SDA (IOCFG106) */
+ >;
+ pinctrl-single,bias-pulldown = <0 2 2>;
+ pinctrl-single,bias-pullup = <0 1 1>;
+ pinctrl-single,bias-disable = <0 0 3>;
+ pinctrl-single,power-source = <0x30 0xf0>;
+ };
+ i2c2_cfg_func: pinmux_i2c2_pins at 2 {
+ pinctrl-single,pins = <
+ 0x118 0 /* I2C2_SCL (IOCFG79) */
+ 0x11c 0 /* I2C2_SDA (IOCFG80) */
+ >;
+ pinctrl-single,bias-pulldown = <0 2 2>;
+ pinctrl-single,bias-pullup = <0 1 1>;
+ pinctrl-single,bias-disable = <0 0 3>;
+ pinctrl-single,power-source = <0x30 0xf0>;
+ };
+ i2c3_cfg_func: pinmux_i2c3_pins at 2 {
+ pinctrl-single,pins = <
+ 0x100 0 /* I2C3_SCL (IOCFG73) */
+ 0x104 0 /* I2C3_SDA (IOCFG74) */
+ >;
+ pinctrl-single,bias-pulldown = <0 2 2>;
+ pinctrl-single,bias-pullup = <0 1 1>;
+ pinctrl-single,bias-disable = <0 0 3>;
+ pinctrl-single,power-source = <0x30 0xf0>;
+ };
+ spi0_cfg_func1: pinmux_spi0_pins at 2 {
+ pinctrl-single,pins = <
+ 0x1d4 0 /* SPI0_CLK (IOCFG125) */
+ 0x1d8 0 /* SPI0_DI (IOCFG126) */
+ 0x1dc 0 /* SPI0_DO (IOCFG127) */
+ >;
+ pinctrl-single,bias-pulldown = <2 2 2>;
+ pinctrl-single,bias-pullup = <0 1 1>;
+ pinctrl-single,bias-disable = <2 0 3>;
+ pinctrl-single,power-source = <0x30 0xf0>;
+ };
+ spi0_cfg_func2: pinmux_spi0_pins at 3 {
+ pinctrl-single,pins = <
+ 0x1e0 0 /* SPI0_CS0 (IOCFG128) */
+ 0x1e4 0 /* SPI0_CS1 (IOCFG129) */
+ 0x1e8 0 /* SPI0_CS2 (IOCFG130 */
+ 0x1ec 0 /* SPI0_CS3 (IOCFG131) */
+ >;
+ pinctrl-single,bias-pulldown = <0 2 2>;
+ pinctrl-single,bias-pullup = <1 1 1>;
+ pinctrl-single,bias-disable = <1 0 3>;
+ pinctrl-single,power-source = <0x30 0xf0>;
+ };
+ spi1_cfg_func1: pinmux_spi1_pins at 2 {
+ pinctrl-single,pins = <
+ 0x1f0 0 /* SPI1_CLK (IOCFG132) */
+ 0x1f4 0 /* SPI1_DI (IOCFG133) */
+ 0x1f8 0 /* SPI1_DO (IOCFG134) */
+ >;
+ pinctrl-single,bias-pulldown = <2 2 2>;
+ pinctrl-single,bias-pullup = <0 1 1>;
+ pinctrl-single,bias-disable = <2 0 3>;
+ pinctrl-single,power-source = <0x30 0xf0>;
+ };
+ spi1_cfg_func2: pinmux_spi1_pins at 3 {
+ pinctrl-single,pins = <
+ 0x1fc 0 /* SPI1_CS (IOCFG135) */
+ >;
+ pinctrl-single,bias-pulldown = <0 2 2>;
+ pinctrl-single,bias-pullup = <1 1 1>;
+ pinctrl-single,bias-disable = <1 0 3>;
+ pinctrl-single,power-source = <0x30 0xf0>;
+ };
+ kpc_cfg_func: pinmux_kpc_pins at 2 {
+ pinctrl-single,pins = <
+ 0x250 0 /* KEY_IN0 (IOCFG156) */
+ 0x254 0 /* KEY_IN1 (IOCFG157) */
+ 0x258 0 /* KEY_IN2 (IOCFG158) */
+ 0x230 0 /* KEY_OUT0 (IOCFG148) */
+ 0x234 0 /* KEY_OUT1 (IOCFG149) */
+ 0x238 0 /* KEY_OUT2 (IOCFG150) */
+ >;
+ pinctrl-single,bias-pulldown = <2 2 2>;
+ pinctrl-single,bias-pullup = <0 1 1>;
+ pinctrl-single,bias-disable = <2 0 3>;
+ };
+ emmc_cfg_func: pinmux_emmc_pins at 2 {
+ pinctrl-single,pins = <
+ 0x0ac 0 /* eMMC_CMD (IOCFG40) */
+ 0x0b0 0 /* eMMC_CLK (IOCFG41) */
+ 0x058 0 /* NAND_CS3_N (IOCFG19) */
+ 0x064 0 /* NAND_BUSY2_N (IOCFG22) */
+ 0x068 0 /* NAND_BUSY3_N (IOCFG23) */
+ 0x08c 0 /* NAND_DATA8 (IOCFG32) */
+ 0x090 0 /* NAND_DATA9 (IOCFG33) */
+ 0x094 0 /* NAND_DATA10 (IOCFG34) */
+ 0x098 0 /* NAND_DATA11 (IOCFG35) */
+ 0x09c 0 /* NAND_DATA12 (IOCFG36) */
+ 0x0a0 0 /* NAND_DATA13 (IOCFG37) */
+ 0x0a4 0 /* NAND_DATA14 (IOCFG38) */
+ 0x0a8 0 /* NAND_DATA15 (IOCFG39) */
+ >;
+ pinctrl-single,bias-pulldown = <0 2 2>;
+ pinctrl-single,bias-pullup = <1 1 1>;
+ pinctrl-single,bias-disable = <1 0 3>;
+ pinctrl-single,power-source = <0x30 0xf0>;
+ };
+ sd_cfg_func1: pinmux_sd_pins at 2 {
+ pinctrl-single,pins = <
+ 0x18c 0 /* SD_CLK (IOCFG107) */
+ 0x190 0 /* SD_CMD (IOCFG108) */
+ >;
+ pinctrl-single,bias-pulldown = <2 2 2>;
+ pinctrl-single,bias-pullup = <0 1 1>;
+ pinctrl-single,bias-disable = <2 0 3>;
+ pinctrl-single,power-source = <0x30 0xf0>;
+ };
+ sd_cfg_func2: pinmux_sd_pins at 3 {
+ pinctrl-single,pins = <
+ 0x194 0 /* SD_DATA0 (IOCFG109) */
+ 0x198 0 /* SD_DATA1 (IOCFG110) */
+ 0x19c 0 /* SD_DATA2 (IOCFG111) */
+ 0x1a0 0 /* SD_DATA3 (IOCFG112) */
+ >;
+ pinctrl-single,bias-pulldown = <2 2 2>;
+ pinctrl-single,bias-pullup = <0 1 1>;
+ pinctrl-single,bias-disable = <2 0 3>;
+ pinctrl-single,power-source = <0x70 0xf0>;
+ };
+ nand_cfg_func1: pinmux_nand_pins at 2 {
+ pinctrl-single,pins = <
+ 0x03c 0 /* NAND_ALE (IOCFG12) */
+ 0x040 0 /* NAND_CLE (IOCFG13) */
+ 0x06c 0 /* NAND_DATA0 (IOCFG24) */
+ 0x070 0 /* NAND_DATA1 (IOCFG25) */
+ 0x074 0 /* NAND_DATA2 (IOCFG26) */
+ 0x078 0 /* NAND_DATA3 (IOCFG27) */
+ 0x07c 0 /* NAND_DATA4 (IOCFG28) */
+ 0x080 0 /* NAND_DATA5 (IOCFG29) */
+ 0x084 0 /* NAND_DATA6 (IOCFG30) */
+ 0x088 0 /* NAND_DATA7 (IOCFG31) */
+ 0x08c 0 /* NAND_DATA8 (IOCFG32) */
+ 0x090 0 /* NAND_DATA9 (IOCFG33) */
+ 0x094 0 /* NAND_DATA10 (IOCFG34) */
+ 0x098 0 /* NAND_DATA11 (IOCFG35) */
+ 0x09c 0 /* NAND_DATA12 (IOCFG36) */
+ 0x0a0 0 /* NAND_DATA13 (IOCFG37) */
+ 0x0a4 0 /* NAND_DATA14 (IOCFG38) */
+ 0x0a8 0 /* NAND_DATA15 (IOCFG39) */
+ >;
+ pinctrl-single,bias-pulldown = <2 2 2>;
+ pinctrl-single,bias-pullup = <0 1 1>;
+ pinctrl-single,bias-disable = <2 0 3>;
+ pinctrl-single,power-source = <0x30 0xf0>;
+ };
+ nand_cfg_func2: pinmux_nand_pins at 3 {
+ pinctrl-single,pins = <
+ 0x044 0 /* NAND_RE_N (IOCFG14) */
+ 0x048 0 /* NAND_WE_N (IOCFG15) */
+ 0x04c 0 /* NAND_CS0_N (IOCFG16) */
+ 0x050 0 /* NAND_CS1_N (IOCFG17) */
+ 0x054 0 /* NAND_CS2_N (IOCFG18) */
+ 0x058 0 /* NAND_CS3_N (IOCFG19) */
+ 0x05c 0 /* NAND_BUSY0_N (IOCFG20) */
+ 0x060 0 /* NAND_BUSY1_N (IOCFG21) */
+ 0x064 0 /* NAND_BUSY2_N (IOCFG22) */
+ 0x068 0 /* NAND_BUSY3_N (IOCFG23) */
+ >;
+ pinctrl-single,bias-pulldown = <0 2 2>;
+ pinctrl-single,bias-pullup = <1 1 1>;
+ pinctrl-single,bias-disable = <1 0 3>;
+ pinctrl-single,power-source = <0x30 0xf0>;
+ };
+ sdio_cfg_func: pinmux_sdio_pins at 2 {
+ pinctrl-single,pins = <
+ 0x1a4 0 /* SDIO0_CLK (IOCG113) */
+ 0x1a8 0 /* SDIO0_CMD (IOCG114) */
+ 0x1ac 0 /* SDIO0_DATA0 (IOCG115) */
+ 0x1b0 0 /* SDIO0_DATA1 (IOCG116) */
+ 0x1b4 0 /* SDIO0_DATA2 (IOCG117) */
+ 0x1b8 0 /* SDIO0_DATA3 (IOCG118) */
+ >;
+ pinctrl-single,bias-pulldown = <2 2 2>;
+ pinctrl-single,bias-pullup = <0 1 1>;
+ pinctrl-single,bias-disable = <2 0 3>;
+ pinctrl-single,power-source = <0x30 0xf0>;
+ };
+ audio_out_cfg_func: pinmux_audio_pins at 1 {
+ pinctrl-single,pins = <
+ 0x200 0 /* GPIO (IOCFG136) */
+ 0x204 0 /* GPIO (IOCFG137) */
+ >;
+ pinctrl-single,bias-pulldown = <2 2 2>;
+ pinctrl-single,bias-pullup = <0 1 1>;
+ pinctrl-single,bias-disable = <2 0 3>;
+ };
+ };
+ };
+};
--
1.7.10.4
^ permalink raw reply related
* [PATCH v7 14/15] pinctrl: single: support generic pinconf
From: Haojian Zhuang @ 2013-01-18 7:31 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1358494279-16503-1-git-send-email-haojian.zhuang@linaro.org>
Support the operation of generic pinconf. The supported config arguments
are INPUT_SCHMITT, INPUT_SCHMITT_DISABLE, POWER_SOURCE, BIAS_DISABLE,
BIAS_PULLUP, BIAS_PULLDOWN, SLEW_RATE.
Signed-off-by: Haojian Zhuang <haojian.zhuang@linaro.org>
---
drivers/pinctrl/Kconfig | 1 +
drivers/pinctrl/pinctrl-single.c | 339 +++++++++++++++++++++++++++++++++++++-
2 files changed, 333 insertions(+), 7 deletions(-)
diff --git a/drivers/pinctrl/Kconfig b/drivers/pinctrl/Kconfig
index c31aeb0..2434c21 100644
--- a/drivers/pinctrl/Kconfig
+++ b/drivers/pinctrl/Kconfig
@@ -143,6 +143,7 @@ config PINCTRL_SINGLE
depends on OF
select PINMUX
select PINCONF
+ select GENERIC_PINCONF
help
This selects the device tree based generic pinctrl driver.
diff --git a/drivers/pinctrl/pinctrl-single.c b/drivers/pinctrl/pinctrl-single.c
index fe8f321..dcbbd7c 100644
--- a/drivers/pinctrl/pinctrl-single.c
+++ b/drivers/pinctrl/pinctrl-single.c
@@ -22,8 +22,10 @@
#include <linux/pinctrl/pinctrl.h>
#include <linux/pinctrl/pinmux.h>
+#include <linux/pinctrl/pinconf-generic.h>
#include "core.h"
+#include "pinconf.h"
#define DRIVER_NAME "pinctrl-single"
#define PCS_MUX_PINS_NAME "pinctrl-single,pins"
@@ -59,6 +61,31 @@ struct pcs_func_vals {
};
/**
+ * struct pcs_conf_vals - pinconf parameter, pinconf register offset
+ * and value, match, mask
+ * @param: config parameter
+ * @val: register value
+ * @match: register match value
+ * @mask: mask of register value
+ */
+struct pcs_conf_vals {
+ enum pin_config_param param;
+ unsigned val;
+ unsigned match;
+ unsigned mask;
+};
+
+/**
+ * struct pcs_conf_type - pinconf property name, pinconf param pair
+ * @name: property name in DTS file
+ * @param: config parameter
+ */
+struct pcs_conf_type {
+ const char *name;
+ enum pin_config_param param;
+};
+
+/**
* struct pcs_function - pinctrl function
* @name: pinctrl function name
* @vals: register and vals array
@@ -73,6 +100,8 @@ struct pcs_function {
unsigned nvals;
const char **pgnames;
int npgnames;
+ struct pcs_conf_vals *conf;
+ int nconfs;
struct list_head node;
};
@@ -131,6 +160,7 @@ struct pcs_name {
* @fshift: function register shift
* @foff: value to turn mux off
* @fmax: max number of functions in fmask
+ * @is_pinconf: whether supports pinconf
* @names: array of register names for pins
* @pins: physical pins on the SoC
* @pgtree: pingroup index radix tree
@@ -157,6 +187,7 @@ struct pcs_device {
unsigned foff;
unsigned fmax;
bool bits_per_mux;
+ bool is_pinconf;
struct pcs_name *names;
struct pcs_data pins;
struct radix_tree_root pgtree;
@@ -342,6 +373,28 @@ static int pcs_get_function_groups(struct pinctrl_dev *pctldev,
return 0;
}
+static int pcs_get_function(struct pinctrl_dev *pctldev, unsigned pin,
+ struct pcs_function **func)
+{
+ struct pcs_device *pcs = pinctrl_dev_get_drvdata(pctldev);
+ struct pin_desc *pdesc = pin_desc_get(pctldev, pin);
+ const struct pinctrl_setting_mux *setting;
+ unsigned fselector;
+
+ /* If pin is not described in DTS & enabled, mux_setting is NULL. */
+ setting = pdesc->mux_setting;
+ if (!setting)
+ return -ENOTSUPP;
+ fselector = setting->func;
+ *func = radix_tree_lookup(&pcs->ftree, fselector);
+ if (!(*func)) {
+ dev_err(pcs->dev, "%s could not find function%i\n",
+ __func__, fselector);
+ return -ENOTSUPP;
+ }
+ return 0;
+}
+
static int pcs_enable(struct pinctrl_dev *pctldev, unsigned fselector,
unsigned group)
{
@@ -464,29 +517,137 @@ static struct pinmux_ops pcs_pinmux_ops = {
static int pcs_pinconf_get(struct pinctrl_dev *pctldev,
unsigned pin, unsigned long *config)
{
+ struct pcs_device *pcs = pinctrl_dev_get_drvdata(pctldev);
+ struct pcs_function *func;
+ unsigned offset = 0, data = 0, i, j, ret;
+
+ ret = pcs_get_function(pctldev, pin, &func);
+ if (ret)
+ return ret;
+
+ for (i = 0; i < func->nconfs; i++) {
+ if (pinconf_to_config_param(*config) != func->conf[i].param)
+ continue;
+ offset = pin * (pcs->width / BITS_PER_BYTE);
+ data = pcs->read(pcs->base + offset) & func->conf[i].mask;
+ switch (func->conf[i].param) {
+ /* 3 parameters */
+ case PIN_CONFIG_BIAS_DISABLE:
+ case PIN_CONFIG_BIAS_PULL_DOWN:
+ case PIN_CONFIG_BIAS_PULL_UP:
+ case PIN_CONFIG_INPUT_SCHMITT_DISABLE:
+ if (data != func->conf[i].match)
+ return -ENOTSUPP;
+ *config = data;
+ break;
+ case PIN_CONFIG_INPUT_SCHMITT:
+ /* either INPUT_SCHMITT or DISABLE */
+ for (j = 0; j < func->nconfs; j++) {
+ switch (func->conf[j].param) {
+ case PIN_CONFIG_INPUT_SCHMITT_DISABLE:
+ if (data == func->conf[j].match)
+ return -ENOTSUPP;
+ break;
+ default:
+ break;
+ }
+ }
+ *config = data;
+ break;
+ case PIN_CONFIG_POWER_SOURCE:
+ case PIN_CONFIG_SLEW_RATE:
+ default:
+ *config = data;
+ break;
+ }
+ return 0;
+ }
return -ENOTSUPP;
}
static int pcs_pinconf_set(struct pinctrl_dev *pctldev,
unsigned pin, unsigned long config)
{
+ struct pcs_device *pcs = pinctrl_dev_get_drvdata(pctldev);
+ struct pcs_function *func;
+ unsigned offset = 0, shift = 0, arg = 0, i, data, ret;
+
+ ret = pcs_get_function(pctldev, pin, &func);
+ if (ret)
+ return ret;
+
+ for (i = 0; i < func->nconfs; i++) {
+ if (pinconf_to_config_param(config) == func->conf[i].param) {
+ offset = pin * (pcs->width / BITS_PER_BYTE);
+ data = pcs->read(pcs->base + offset);
+ switch (func->conf[i].param) {
+ /* 2 parameters */
+ case PIN_CONFIG_INPUT_SCHMITT:
+ case PIN_CONFIG_POWER_SOURCE:
+ case PIN_CONFIG_SLEW_RATE:
+ shift = ffs(func->conf[i].mask) - 1;
+ arg = pinconf_to_config_argument(config);
+ data &= ~func->conf[i].mask;
+ data |= (arg << shift) & func->conf[i].mask;
+ break;
+ /* 3 parameters */
+ case PIN_CONFIG_BIAS_DISABLE:
+ case PIN_CONFIG_BIAS_PULL_DOWN:
+ case PIN_CONFIG_BIAS_PULL_UP:
+ case PIN_CONFIG_INPUT_SCHMITT_DISABLE:
+ data &= ~func->conf[i].mask;
+ data |= func->conf[i].val;
+ break;
+ default:
+ return -ENOTSUPP;
+ }
+ pcs->write(data, pcs->base + offset);
+ return 0;
+ }
+ }
return -ENOTSUPP;
}
static int pcs_pinconf_group_get(struct pinctrl_dev *pctldev,
unsigned group, unsigned long *config)
{
- return -ENOTSUPP;
+ const unsigned *pins;
+ unsigned npins, old = 0;
+ int i, ret;
+
+ ret = pcs_get_group_pins(pctldev, group, &pins, &npins);
+ if (ret)
+ return ret;
+ for (i = 0; i < npins; i++) {
+ if (pcs_pinconf_get(pctldev, pins[i], config))
+ return -ENOTSUPP;
+ /* configs do not match between two pins */
+ if (i && (old != *config))
+ return -ENOTSUPP;
+ old = *config;
+ }
+ return 0;
}
static int pcs_pinconf_group_set(struct pinctrl_dev *pctldev,
unsigned group, unsigned long config)
{
- return -ENOTSUPP;
+ const unsigned *pins;
+ unsigned npins;
+ int i, ret;
+
+ ret = pcs_get_group_pins(pctldev, group, &pins, &npins);
+ if (ret)
+ return ret;
+ for (i = 0; i < npins; i++) {
+ if (pcs_pinconf_set(pctldev, pins[i], config))
+ return -ENOTSUPP;
+ }
+ return 0;
}
static void pcs_pinconf_dbg_show(struct pinctrl_dev *pctldev,
- struct seq_file *s, unsigned offset)
+ struct seq_file *s, unsigned pin)
{
}
@@ -495,6 +656,13 @@ static void pcs_pinconf_group_dbg_show(struct pinctrl_dev *pctldev,
{
}
+static void pcs_pinconf_config_dbg_show(struct pinctrl_dev *pctldev,
+ struct seq_file *s,
+ unsigned long config)
+{
+ pinconf_generic_dump_config(pctldev, s, config);
+}
+
static struct pinconf_ops pcs_pinconf_ops = {
.pin_config_get = pcs_pinconf_get,
.pin_config_set = pcs_pinconf_set,
@@ -502,6 +670,7 @@ static struct pinconf_ops pcs_pinconf_ops = {
.pin_config_group_set = pcs_pinconf_group_set,
.pin_config_dbg_show = pcs_pinconf_dbg_show,
.pin_config_group_dbg_show = pcs_pinconf_group_dbg_show,
+ .pin_config_config_dbg_show = pcs_pinconf_config_dbg_show,
};
/**
@@ -692,11 +861,151 @@ static int pcs_get_pin_by_offset(struct pcs_device *pcs, unsigned offset)
return index;
}
+static int pcs_config_match(unsigned data, unsigned match)
+{
+ int ret = 0;
+
+ if (!match) {
+ if (!data)
+ ret = 1;
+ } else {
+ if ((data & match) == match)
+ ret = 1;
+ }
+ return ret;
+}
+
+static void add_config(struct pcs_conf_vals **conf, enum pin_config_param param,
+ unsigned value, unsigned match, unsigned mask)
+{
+ (*conf)->param = param;
+ (*conf)->val = value;
+ (*conf)->match = match;
+ (*conf)->mask = mask;
+ (*conf)++;
+}
+
+static void add_setting(unsigned long **setting, enum pin_config_param param,
+ unsigned arg)
+{
+ **setting = pinconf_to_config_packed(param, arg);
+ (*setting)++;
+}
+
+/* add pinconf setting with 2 parameters */
+static void pcs_add_conf2(struct device_node *np, const char *name,
+ enum pin_config_param param,
+ struct pcs_conf_vals **conf,
+ unsigned long **settings)
+{
+ unsigned value[2];
+ int ret;
+
+ ret = of_property_read_u32_array(np, name, value, 2);
+ if (ret)
+ return;
+ /* value to set, mask */
+ value[0] &= value[1];
+ add_config(conf, param, value[0], 0, value[1]);
+ add_setting(settings, param, value[0]);
+}
+
+/* add pinconf setting with 3 parameters */
+static void pcs_add_conf3(struct device_node *np, const char *name,
+ enum pin_config_param param,
+ struct pcs_conf_vals **conf,
+ unsigned long **settings)
+{
+ unsigned value[3];
+ int ret;
+
+ ret = of_property_read_u32_array(np, name, value, 3);
+ if (ret)
+ return;
+ /* value to set, match, mask */
+ value[0] &= value[2];
+ value[1] &= value[2];
+ add_config(conf, param, value[0], value[1], value[2]);
+ if (pcs_config_match(value[0], value[1]))
+ ret = 1;
+ else
+ ret = 0;
+ add_setting(settings, param, ret);
+}
+
+static int pcs_parse_pinconf(struct pcs_device *pcs, struct device_node *np,
+ struct pcs_function *func,
+ struct pinctrl_map **map)
+
+{
+ struct pinctrl_map *m = *map;
+ int i = 0, nconfs = 0;
+ unsigned long *settings = NULL, *s = NULL;
+ struct pcs_conf_vals *conf = NULL;
+ struct pcs_conf_type prop2[] = {
+ { "pinctrl-single,power-source", PIN_CONFIG_POWER_SOURCE, },
+ { "pinctrl-single,slew-rate", PIN_CONFIG_SLEW_RATE, },
+ { "pinctrl-single,input-schmitt", PIN_CONFIG_INPUT_SCHMITT, },
+ };
+ struct pcs_conf_type prop3[] = {
+ { "pinctrl-single,bias-disable", PIN_CONFIG_BIAS_DISABLE, },
+ { "pinctrl-single,bias-pullup", PIN_CONFIG_BIAS_PULL_UP, },
+ { "pinctrl-single,bias-pulldown", PIN_CONFIG_BIAS_PULL_DOWN, },
+ { "pinctrl-single,input-schmitt-disable",
+ PIN_CONFIG_INPUT_SCHMITT_DISABLE, },
+ };
+
+ /* If pinconf isn't supported, don't parse properties in below. */
+ if (!pcs->is_pinconf)
+ return 0;
+
+ /* cacluate how much properties are supported in current node */
+ for (i = 0; i < ARRAY_SIZE(prop2); i++) {
+ if (of_find_property(np, prop2[i].name, NULL))
+ nconfs++;
+ }
+ for (i = 0; i < ARRAY_SIZE(prop3); i++) {
+ if (of_find_property(np, prop3[i].name, NULL))
+ nconfs++;
+ }
+ if (!nconfs)
+ return 0;
+
+ func->conf = devm_kzalloc(pcs->dev,
+ sizeof(struct pcs_conf_vals) * nconfs,
+ GFP_KERNEL);
+ if (!func->conf)
+ return -ENOMEM;
+ func->nconfs = nconfs;
+ conf = &(func->conf[0]);
+ m++;
+ settings = devm_kzalloc(pcs->dev, sizeof(unsigned long) * nconfs,
+ GFP_KERNEL);
+ if (!settings)
+ return -ENOMEM;
+ s = &settings[0];
+
+ for (i = 0; i < ARRAY_SIZE(prop2); i++) {
+ pcs_add_conf2(np, prop2[i].name, prop2[i].param, &conf, &s);
+ }
+ for (i = 0; i < ARRAY_SIZE(prop3); i++) {
+ pcs_add_conf3(np, prop3[i].name, prop3[i].param, &conf, &s);
+ }
+ m->type = PIN_MAP_TYPE_CONFIGS_GROUP;
+ m->data.configs.group_or_pin = np->name;
+ m->data.configs.configs = settings;
+ m->data.configs.num_configs = nconfs;
+ return 0;
+}
+
+static void pcs_free_pingroups(struct pcs_device *pcs);
+
/**
* smux_parse_one_pinctrl_entry() - parses a device tree mux entry
* @pcs: pinctrl driver instance
* @np: device node of the mux entry
* @map: map entry
+ * @num_maps: number of map
* @pgnames: pingroup names
*
* Note that this binding currently supports only sets of one register + value.
@@ -713,6 +1022,7 @@ static int pcs_get_pin_by_offset(struct pcs_device *pcs, unsigned offset)
static int pcs_parse_one_pinctrl_entry(struct pcs_device *pcs,
struct device_node *np,
struct pinctrl_map **map,
+ unsigned *num_maps,
const char **pgnames)
{
struct pcs_func_vals *vals;
@@ -785,8 +1095,18 @@ static int pcs_parse_one_pinctrl_entry(struct pcs_device *pcs,
(*map)->data.mux.group = np->name;
(*map)->data.mux.function = np->name;
+ if (pcs->is_pinconf) {
+ if (pcs_parse_pinconf(pcs, np, function, map))
+ goto free_pingroups;
+ *num_maps = 2;
+ } else {
+ *num_maps = 1;
+ }
return 0;
+free_pingroups:
+ pcs_free_pingroups(pcs);
+ *num_maps = 1;
free_function:
pcs_remove_function(pcs, function);
@@ -815,7 +1135,8 @@ static int pcs_dt_node_to_map(struct pinctrl_dev *pctldev,
pcs = pinctrl_dev_get_drvdata(pctldev);
- *map = devm_kzalloc(pcs->dev, sizeof(**map), GFP_KERNEL);
+ /* create 2 maps. One is for pinmux, and the other is for pinconf. */
+ *map = devm_kzalloc(pcs->dev, sizeof(**map) * 2, GFP_KERNEL);
if (!*map)
return -ENOMEM;
@@ -827,13 +1148,13 @@ static int pcs_dt_node_to_map(struct pinctrl_dev *pctldev,
goto free_map;
}
- ret = pcs_parse_one_pinctrl_entry(pcs, np_config, map, pgnames);
+ ret = pcs_parse_one_pinctrl_entry(pcs, np_config, map, num_maps,
+ pgnames);
if (ret < 0) {
dev_err(pcs->dev, "no pins entries for %s\n",
np_config->name);
goto free_pgnames;
}
- *num_maps = 1;
return 0;
@@ -976,6 +1297,7 @@ static int pcs_probe(struct platform_device *pdev)
INIT_LIST_HEAD(&pcs->pingroups);
INIT_LIST_HEAD(&pcs->functions);
INIT_LIST_HEAD(&pcs->gpiofuncs);
+ pcs->is_pinconf = match->data;
PCS_GET_PROP_U32("pinctrl-single,register-width", &pcs->width,
"register width not specified\n");
@@ -1046,6 +1368,8 @@ static int pcs_probe(struct platform_device *pdev)
pcs->desc.pmxops = &pcs_pinmux_ops;
pcs->desc.confops = &pcs_pinconf_ops;
pcs->desc.owner = THIS_MODULE;
+ if (match->data)
+ pcs_pinconf_ops.is_generic = true;
ret = pcs_allocate_pin_table(pcs);
if (ret < 0)
@@ -1086,7 +1410,8 @@ static int pcs_remove(struct platform_device *pdev)
}
static struct of_device_id pcs_of_match[] = {
- { .compatible = DRIVER_NAME, },
+ { .compatible = "pinctrl-single", .data = (void *)false },
+ { .compatible = "pinconf-single", .data = (void *)true },
{ },
};
MODULE_DEVICE_TABLE(of, pcs_of_match);
--
1.7.10.4
^ permalink raw reply related
* [PATCH v7 13/15] pinctrl: single: set function mask as optional
From: Haojian Zhuang @ 2013-01-18 7:31 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1358494279-16503-1-git-send-email-haojian.zhuang@linaro.org>
Since Hisilicon's pin controller is divided into two parts. One is the
function mux, and the other is pin configuration. These two parts are
in the different memory regions. So make pinctrl-single,function-mask
as optional property. Then we can define pingroups without valid
function mux that is only used for pin configuration.
Signed-off-by: Haojian Zhuang <haojian.zhuang@linaro.org>
---
drivers/pinctrl/pinctrl-single.c | 26 ++++++++++++++++++++++----
1 file changed, 22 insertions(+), 4 deletions(-)
diff --git a/drivers/pinctrl/pinctrl-single.c b/drivers/pinctrl/pinctrl-single.c
index 8b9dd95..fe8f321 100644
--- a/drivers/pinctrl/pinctrl-single.c
+++ b/drivers/pinctrl/pinctrl-single.c
@@ -350,6 +350,9 @@ static int pcs_enable(struct pinctrl_dev *pctldev, unsigned fselector,
int i;
pcs = pinctrl_dev_get_drvdata(pctldev);
+ /* If function mask is null, needn't enable it. */
+ if (!pcs->fmask)
+ return 0;
func = radix_tree_lookup(&pcs->ftree, fselector);
if (!func)
return -EINVAL;
@@ -384,6 +387,10 @@ static void pcs_disable(struct pinctrl_dev *pctldev, unsigned fselector,
int i;
pcs = pinctrl_dev_get_drvdata(pctldev);
+ /* If function mask is null, needn't disable it. */
+ if (!pcs->fmask)
+ return;
+
func = radix_tree_lookup(&pcs->ftree, fselector);
if (!func) {
dev_err(pcs->dev, "%s could not find function%i\n",
@@ -427,6 +434,10 @@ static int pcs_request_gpio(struct pinctrl_dev *pctldev,
int mux_bytes = 0;
unsigned data;
+ /* If function mask is null, return directly. */
+ if (!pcs->fmask)
+ return -ENOTSUPP;
+
list_for_each_safe(pos, tmp, &pcs->gpiofuncs) {
frange = list_entry(pos, struct pcs_gpiofunc_range, node);
if (pin >= frange->offset + frange->npins
@@ -969,10 +980,17 @@ static int pcs_probe(struct platform_device *pdev)
PCS_GET_PROP_U32("pinctrl-single,register-width", &pcs->width,
"register width not specified\n");
- PCS_GET_PROP_U32("pinctrl-single,function-mask", &pcs->fmask,
- "function register mask not specified\n");
- pcs->fshift = ffs(pcs->fmask) - 1;
- pcs->fmax = pcs->fmask >> pcs->fshift;
+ ret = of_property_read_u32(np, "pinctrl-single,function-mask",
+ &pcs->fmask);
+ if (!ret) {
+ pcs->fshift = ffs(pcs->fmask) - 1;
+ pcs->fmax = pcs->fmask >> pcs->fshift;
+ } else {
+ /* If mask property doesn't exist, function mux is invalid. */
+ pcs->fmask = 0;
+ pcs->fshift = 0;
+ pcs->fmax = 0;
+ }
ret = of_property_read_u32(np, "pinctrl-single,function-off",
&pcs->foff);
--
1.7.10.4
^ permalink raw reply related
* [PATCH v7 12/15] pinctrl: generic: dump pin configuration
From: Haojian Zhuang @ 2013-01-18 7:31 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1358494279-16503-1-git-send-email-haojian.zhuang@linaro.org>
Add the support of dumping pin configuration.
Signed-off-by: Haojian Zhuang <haojian.zhuang@linaro.org>
---
drivers/pinctrl/pinconf-generic.c | 12 ++++++++++++
drivers/pinctrl/pinconf.h | 8 ++++++++
2 files changed, 20 insertions(+)
diff --git a/drivers/pinctrl/pinconf-generic.c b/drivers/pinctrl/pinconf-generic.c
index 678db63..9bb6d47 100644
--- a/drivers/pinctrl/pinconf-generic.c
+++ b/drivers/pinctrl/pinconf-generic.c
@@ -119,4 +119,16 @@ void pinconf_generic_dump_group(struct pinctrl_dev *pctldev,
}
}
+void pinconf_generic_dump_config(struct pinctrl_dev *pctldev,
+ struct seq_file *s, unsigned long config)
+{
+ int i;
+
+ for(i = 0; i < ARRAY_SIZE(conf_items); i++) {
+ if (pinconf_to_config_param(config) != conf_items[i].param)
+ continue;
+ seq_printf(s, "%s: 0x%x", conf_items[i].display,
+ pinconf_to_config_argument(config));
+ }
+}
#endif
diff --git a/drivers/pinctrl/pinconf.h b/drivers/pinctrl/pinconf.h
index e3ed8cb..8023421 100644
--- a/drivers/pinctrl/pinconf.h
+++ b/drivers/pinctrl/pinconf.h
@@ -98,6 +98,8 @@ void pinconf_generic_dump_pin(struct pinctrl_dev *pctldev,
void pinconf_generic_dump_group(struct pinctrl_dev *pctldev,
struct seq_file *s, const char *gname);
+void pinconf_generic_dump_config(struct pinctrl_dev *pctldev,
+ struct seq_file *s, unsigned long config);
#else
static inline void pinconf_generic_dump_pin(struct pinctrl_dev *pctldev,
@@ -114,4 +116,10 @@ static inline void pinconf_generic_dump_group(struct pinctrl_dev *pctldev,
return;
}
+static void pinconf_generic_dump_config(struct pinctrl_dev *pctldev,
+ struct seq_file *s,
+ unsigned long config)
+{
+ return;
+}
#endif
--
1.7.10.4
^ permalink raw reply related
* [PATCH v7 11/15] pinctrl: generic: add slew rate config parameter
From: Haojian Zhuang @ 2013-01-18 7:31 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1358494279-16503-1-git-send-email-haojian.zhuang@linaro.org>
Add PIN_CONFIG_SLEW_RATE parameter into pinconf-generic driver.
Signed-off-by: Haojian Zhuang <haojian.zhuang@linaro.org>
---
drivers/pinctrl/pinconf-generic.c | 1 +
include/linux/pinctrl/pinconf-generic.h | 4 ++++
2 files changed, 5 insertions(+)
diff --git a/drivers/pinctrl/pinconf-generic.c b/drivers/pinctrl/pinconf-generic.c
index 833a364..678db63 100644
--- a/drivers/pinctrl/pinconf-generic.c
+++ b/drivers/pinctrl/pinconf-generic.c
@@ -45,6 +45,7 @@ struct pin_config_item conf_items[] = {
PCONFDUMP(PIN_CONFIG_INPUT_SCHMITT, "input schmitt trigger", NULL),
PCONFDUMP(PIN_CONFIG_INPUT_DEBOUNCE, "input debounce", "time units"),
PCONFDUMP(PIN_CONFIG_POWER_SOURCE, "pin power source", "selector"),
+ PCONFDUMP(PIN_CONFIG_SLEW_RATE, "slew rate", NULL),
PCONFDUMP(PIN_CONFIG_LOW_POWER_MODE, "pin low power", "mode"),
};
diff --git a/include/linux/pinctrl/pinconf-generic.h b/include/linux/pinctrl/pinconf-generic.h
index 47a1bdd..e970a12 100644
--- a/include/linux/pinctrl/pinconf-generic.h
+++ b/include/linux/pinctrl/pinconf-generic.h
@@ -58,6 +58,9 @@
* @PIN_CONFIG_POWER_SOURCE: if the pin can select between different power
* supplies, the argument to this parameter (on a custom format) tells
* the driver which alternative power source to use.
+ * @PIN_CONFIG_SLEW_RATE: if the pin can select slew rate, the argument to
+ * this parameter (on a custom format) tells the driver which alternative
+ * slew rate to use.
* @PIN_CONFIG_LOW_POWER_MODE: this will configure the pin for low power
* operation, if several modes of operation are supported these can be
* passed in the argument on a custom form, else just use argument 1
@@ -78,6 +81,7 @@ enum pin_config_param {
PIN_CONFIG_INPUT_SCHMITT,
PIN_CONFIG_INPUT_DEBOUNCE,
PIN_CONFIG_POWER_SOURCE,
+ PIN_CONFIG_SLEW_RATE,
PIN_CONFIG_LOW_POWER_MODE,
PIN_CONFIG_END = 0x7FFF,
};
--
1.7.10.4
^ permalink raw reply related
* [PATCH v7 10/15] pinctrl: single: create new gpio function range
From: Haojian Zhuang @ 2013-01-18 7:31 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1358494279-16503-1-git-send-email-haojian.zhuang@linaro.org>
Since gpio driver could create gpio range in DTS, it could invokes
pinctrl_request_gpio(). In the pinctrl-single driver, it needs to
configure pins with gpio function mode.
A new gpio function range should be created in DTS file in below.
pinctrl-single,gpio-range = <phandle pin_offset nr_pins gpio_func>;
range: gpio-range {
#pinctrl-single,gpio-range-cells = <3>;
};
The difference between gpio-ranges property in gpio driver and
pinctrl-single,gpio-range property in pinctrl-single driver.
1. gpio-ranges = <phandle gpio_offset_in_chip pin_offset nr_pins>
gpio-ranges = < &pmx0 0 89 1 &pmx0 1 89 1 &pmx0 2 90 1
&pmx0 3 90 1 &pmx0 4 91 1 &pmx0 5 92 1>;
2. gpio driver could get pin offset from gpio-ranges property.
pinctrl-single driver could get gpio function mode from gpio_func
that is stored in @gpiofuncs list in struct pcs_device.
This new pinctrl-single,gpio-range is used as complement for
gpio-ranges property in gpio driver.
Signed-off-by: Haojian Zhuang <haojian.zhuang@linaro.org>
---
drivers/pinctrl/pinctrl-single.c | 73 ++++++++++++++++++++++++++++++++++++--
1 file changed, 71 insertions(+), 2 deletions(-)
diff --git a/drivers/pinctrl/pinctrl-single.c b/drivers/pinctrl/pinctrl-single.c
index 5c32e88..8b9dd95 100644
--- a/drivers/pinctrl/pinctrl-single.c
+++ b/drivers/pinctrl/pinctrl-single.c
@@ -77,6 +77,20 @@ struct pcs_function {
};
/**
+ * struct pcs_gpiofunc_range - pin ranges with same mux value of gpio function
+ * @offset: offset base of pins
+ * @npins: number pins with the same mux value of gpio function
+ * @gpiofunc: mux value of gpio function
+ * @node: list node
+ */
+struct pcs_gpiofunc_range {
+ unsigned offset;
+ unsigned npins;
+ unsigned gpiofunc;
+ struct list_head node;
+};
+
+/**
* struct pcs_data - wrapper for data needed by pinctrl framework
* @pa: pindesc array
* @cur: index to current element
@@ -123,6 +137,7 @@ struct pcs_name {
* @ftree: function index radix tree
* @pingroups: list of pingroups
* @functions: list of functions
+ * @gpiofuncs: list of gpio functions
* @ngroups: number of pingroups
* @nfuncs: number of functions
* @desc: pin controller descriptor
@@ -148,6 +163,7 @@ struct pcs_device {
struct radix_tree_root ftree;
struct list_head pingroups;
struct list_head functions;
+ struct list_head gpiofuncs;
unsigned ngroups;
unsigned nfuncs;
struct pinctrl_desc desc;
@@ -403,9 +419,26 @@ static void pcs_disable(struct pinctrl_dev *pctldev, unsigned fselector,
}
static int pcs_request_gpio(struct pinctrl_dev *pctldev,
- struct pinctrl_gpio_range *range, unsigned offset)
+ struct pinctrl_gpio_range *range, unsigned pin)
{
- return -ENOTSUPP;
+ struct pcs_device *pcs = pinctrl_dev_get_drvdata(pctldev);
+ struct pcs_gpiofunc_range *frange = NULL;
+ struct list_head *pos, *tmp;
+ int mux_bytes = 0;
+ unsigned data;
+
+ list_for_each_safe(pos, tmp, &pcs->gpiofuncs) {
+ frange = list_entry(pos, struct pcs_gpiofunc_range, node);
+ if (pin >= frange->offset + frange->npins
+ || pin < frange->offset)
+ continue;
+ mux_bytes = pcs->width / BITS_PER_BYTE;
+ data = pcs->read(pcs->base + pin * mux_bytes) & ~pcs->fmask;
+ data |= frange->gpiofunc;
+ pcs->write(data, pcs->base + pin * mux_bytes);
+ break;
+ }
+ return 0;
}
static struct pinmux_ops pcs_pinmux_ops = {
@@ -879,6 +912,37 @@ static void pcs_free_resources(struct pcs_device *pcs)
static struct of_device_id pcs_of_match[];
+static int pcs_add_gpio_func(struct device_node *node, struct pcs_device *pcs)
+{
+ const char *propname = "pinctrl-single,gpio-range";
+ const char *cellname = "#pinctrl-single,gpio-range-cells";
+ struct of_phandle_args gpiospec;
+ struct pcs_gpiofunc_range *range;
+ int ret, i;
+
+ for (i = 0; ; i++) {
+ ret = of_parse_phandle_with_args(node, propname, cellname,
+ i, &gpiospec);
+ /* Do not treat it as error. Only treat it as end condition. */
+ if (ret) {
+ ret = 0;
+ break;
+ }
+ range = devm_kzalloc(pcs->dev, sizeof(*range), GFP_KERNEL);
+ if (!range) {
+ ret = -ENOMEM;
+ break;
+ }
+ range->offset = gpiospec.args[0];
+ range->npins = gpiospec.args[1];
+ range->gpiofunc = gpiospec.args[2];
+ mutex_lock(&pcs->mutex);
+ list_add_tail(&range->node, &pcs->gpiofuncs);
+ mutex_unlock(&pcs->mutex);
+ }
+ return ret;
+}
+
static int pcs_probe(struct platform_device *pdev)
{
struct device_node *np = pdev->dev.of_node;
@@ -900,6 +964,7 @@ static int pcs_probe(struct platform_device *pdev)
mutex_init(&pcs->mutex);
INIT_LIST_HEAD(&pcs->pingroups);
INIT_LIST_HEAD(&pcs->functions);
+ INIT_LIST_HEAD(&pcs->gpiofuncs);
PCS_GET_PROP_U32("pinctrl-single,register-width", &pcs->width,
"register width not specified\n");
@@ -975,6 +1040,10 @@ static int pcs_probe(struct platform_device *pdev)
goto free;
}
+ ret = pcs_add_gpio_func(np, pcs);
+ if (ret < 0)
+ goto free;
+
dev_info(pcs->dev, "%i pins at pa %p size %u\n",
pcs->desc.npins, pcs->base, pcs->size);
--
1.7.10.4
^ permalink raw reply related
* [PATCH v7 09/15] gpio: pl061: set initcall level to module init
From: Haojian Zhuang @ 2013-01-18 7:31 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1358494279-16503-1-git-send-email-haojian.zhuang@linaro.org>
Replace subsys initcall by module initcall level. Since pinctrl
driver is already launched before gpio driver. It's unnecessary
to set gpio driver in subsys init call level.
Signed-off-by: Haojian Zhuang <haojian.zhuang@linaro.org>
---
drivers/gpio/gpio-pl061.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/gpio/gpio-pl061.c b/drivers/gpio/gpio-pl061.c
index 8cfdf60..76adf33 100644
--- a/drivers/gpio/gpio-pl061.c
+++ b/drivers/gpio/gpio-pl061.c
@@ -393,7 +393,7 @@ static int __init pl061_gpio_init(void)
{
return amba_driver_register(&pl061_gpio_driver);
}
-subsys_initcall(pl061_gpio_init);
+module_init(pl061_gpio_init);
MODULE_AUTHOR("Baruch Siach <baruch@tkos.co.il>");
MODULE_DESCRIPTION("PL061 GPIO driver");
--
1.7.10.4
^ permalink raw reply related
* [PATCH v7 08/15] gpio: pl061: bind pinctrl by gpio request
From: Haojian Zhuang @ 2013-01-18 7:31 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1358494279-16503-1-git-send-email-haojian.zhuang@linaro.org>
Add the pl061_gpio_request() to request pinctrl. Create the logic
between pl061 gpio driver and pinctrl (pinctrl-single) driver.
While a gpio pin is requested, it will request pinctrl driver to
set that pin with gpio function mode. So pinctrl driver should
append .gpio_request_enable() in pinmux_ops.
Signed-off-by: Haojian Zhuang <haojian.zhuang@linaro.org>
---
drivers/gpio/gpio-pl061.c | 19 +++++++++++++++++++
1 file changed, 19 insertions(+)
diff --git a/drivers/gpio/gpio-pl061.c b/drivers/gpio/gpio-pl061.c
index 8336719..8cfdf60 100644
--- a/drivers/gpio/gpio-pl061.c
+++ b/drivers/gpio/gpio-pl061.c
@@ -23,6 +23,7 @@
#include <linux/amba/bus.h>
#include <linux/amba/pl061.h>
#include <linux/slab.h>
+#include <linux/pinctrl/consumer.h>
#include <linux/pm.h>
#include <asm/mach/irq.h>
@@ -61,6 +62,23 @@ struct pl061_gpio {
#endif
};
+static int pl061_gpio_request(struct gpio_chip *chip, unsigned offset)
+{
+ /*
+ * Map back to global GPIO space and request muxing, the direction
+ * parameter does not matter for this controller.
+ */
+ int gpio = chip->base + offset;
+
+ /*
+ * Do NOT check the return value at here. Since sometimes the gpio
+ * pin needn't to be configured in pinmux controller. So it's
+ * impossible to find the matched gpio range.
+ */
+ pinctrl_request_gpio(gpio);
+ return 0;
+}
+
static int pl061_direction_input(struct gpio_chip *gc, unsigned offset)
{
struct pl061_gpio *chip = container_of(gc, struct pl061_gpio, gc);
@@ -251,6 +269,7 @@ static int pl061_probe(struct amba_device *adev, const struct amba_id *id)
spin_lock_init(&chip->lock);
+ chip->gc.request = pl061_gpio_request;
chip->gc.direction_input = pl061_direction_input;
chip->gc.direction_output = pl061_direction_output;
chip->gc.get = pl061_get_value;
--
1.7.10.4
^ permalink raw reply related
* [PATCH v7 07/15] gpio: pl061: allocate irq dynamically
From: Haojian Zhuang @ 2013-01-18 7:31 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1358494279-16503-1-git-send-email-haojian.zhuang@linaro.org>
In original implementation, irq base is always specified in platform
data. If it's not specified, pl061 gpio driver can't pass the probe()
function since irq base is missing. While moving to device tree, everything
should be parsed from DTS file. So allocate irq dynamically for irq
base.
Signed-off-by: Haojian Zhuang <haojian.zhuang@linaro.org>
---
drivers/gpio/gpio-pl061.c | 15 ++++++++++++---
1 file changed, 12 insertions(+), 3 deletions(-)
diff --git a/drivers/gpio/gpio-pl061.c b/drivers/gpio/gpio-pl061.c
index c1720de..8336719 100644
--- a/drivers/gpio/gpio-pl061.c
+++ b/drivers/gpio/gpio-pl061.c
@@ -15,6 +15,7 @@
#include <linux/io.h>
#include <linux/ioport.h>
#include <linux/irq.h>
+#include <linux/irqdomain.h>
#include <linux/bitops.h>
#include <linux/workqueue.h>
#include <linux/gpio.h>
@@ -211,6 +212,10 @@ static void __init pl061_init_gc(struct pl061_gpio *chip, int irq_base)
IRQ_GC_INIT_NESTED_LOCK, IRQ_NOREQUEST, 0);
}
+static const struct irq_domain_ops pl061_domain_ops = {
+ .xlate = irq_domain_xlate_twocell,
+};
+
static int pl061_probe(struct amba_device *adev, const struct amba_id *id)
{
struct device *dev = &adev->dev;
@@ -225,10 +230,14 @@ static int pl061_probe(struct amba_device *adev, const struct amba_id *id)
if (pdata) {
chip->gc.base = pdata->gpio_base;
chip->irq_base = pdata->irq_base;
- } else if (adev->dev.of_node) {
+ } else {
chip->gc.base = -1;
- chip->irq_base = 0;
- } else
+ chip->irq_base = irq_alloc_descs(-1, 0, PL061_GPIO_NR, 0);
+ if (chip->irq_base < 0)
+ return chip->irq_base;
+ }
+ if (!irq_domain_add_legacy(adev->dev.of_node, PL061_GPIO_NR,
+ chip->irq_base, 0, &pl061_domain_ops, chip))
return -ENODEV;
if (!devm_request_mem_region(dev, adev->res.start,
--
1.7.10.4
^ permalink raw reply related
* [PATCH v7 06/15] gpio: find gpio base by ascend order
From: Haojian Zhuang @ 2013-01-18 7:31 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1358494279-16503-1-git-send-email-haojian.zhuang@linaro.org>
gpiochip_find_base() always tries to find valid gpio with descend order.
It's inconvient if gpio information is passing from DTS. Now try to find
valid gpio with ascend order.
Signed-off-by: Haojian Zhuang <haojian.zhuang@linaro.org>
---
drivers/gpio/gpiolib.c | 19 ++++++++++---------
1 file changed, 10 insertions(+), 9 deletions(-)
diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c
index 199fca1..8af57e7 100644
--- a/drivers/gpio/gpiolib.c
+++ b/drivers/gpio/gpiolib.c
@@ -128,20 +128,21 @@ static int gpiochip_find_base(int ngpio)
int spare = 0;
int base = -ENOSPC;
- for (i = ARCH_NR_GPIOS - 1; i >= 0 ; i--) {
+ for (i = 0, base = 0; i < ARCH_NR_GPIOS; i++) {
struct gpio_desc *desc = &gpio_desc[i];
struct gpio_chip *chip = desc->chip;
- if (!chip && !test_bit(FLAG_RESERVED, &desc->flags)) {
+ if (chip) {
+ spare = 0;
+ i += chip->ngpio - 1;
+ base = i + 1;
+ } else if (test_bit(FLAG_RESERVED, &desc->flags)) {
+ spare = 0;
+ base = i + 1;
+ } else {
spare++;
- if (spare == ngpio) {
- base = i;
+ if (spare == ngpio)
break;
- }
- } else {
- spare = 0;
- if (chip)
- i -= chip->ngpio - 1;
}
}
--
1.7.10.4
^ permalink raw reply related
* [PATCH v7 05/15] gpio: fix wrong checking condition for gpio range
From: Haojian Zhuang @ 2013-01-18 7:31 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1358494279-16503-1-git-send-email-haojian.zhuang@linaro.org>
Since index++ calculates from 0, the checking condition of "while
(index++)" is always fake. So replace it by unconditional loop.
Signed-off-by: Haojian Zhuang <haojian.zhuang@linaro.org>
---
drivers/gpio/gpiolib-of.c | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/drivers/gpio/gpiolib-of.c b/drivers/gpio/gpiolib-of.c
index b1f0682..011e1e98 100644
--- a/drivers/gpio/gpiolib-of.c
+++ b/drivers/gpio/gpiolib-of.c
@@ -228,7 +228,7 @@ static void of_gpiochip_add_pin_range(struct gpio_chip *chip)
if (!np)
return;
- do {
+ for (;;) {
ret = of_parse_phandle_with_args(np, "gpio-ranges",
"#gpio-range-cells", index, &pinspec);
if (ret)
@@ -254,8 +254,8 @@ static void of_gpiochip_add_pin_range(struct gpio_chip *chip)
if (ret)
break;
-
- } while (index++);
+ index++;
+ }
}
#else
--
1.7.10.4
^ permalink raw reply related
* [PATCH v7 04/15] gpio: set gpio range cells property as 3
From: Haojian Zhuang @ 2013-01-18 7:31 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1358494279-16503-1-git-send-email-haojian.zhuang@linaro.org>
Add gpio offset into "gpio-range-cells" property. It's used to support
sparse pinctrl range in gpio chip.
Signed-off-by: Haojian Zhuang <haojian.zhuang@linaro.org>
---
Documentation/devicetree/bindings/gpio/gpio.txt | 6 +++---
arch/arm/boot/dts/spear1310.dtsi | 4 ++--
arch/arm/boot/dts/spear1340.dtsi | 4 ++--
arch/arm/boot/dts/spear310.dtsi | 4 ++--
arch/arm/boot/dts/spear320.dtsi | 4 ++--
drivers/gpio/gpiolib-of.c | 7 ++-----
6 files changed, 13 insertions(+), 16 deletions(-)
diff --git a/Documentation/devicetree/bindings/gpio/gpio.txt b/Documentation/devicetree/bindings/gpio/gpio.txt
index a336287..d933af3 100644
--- a/Documentation/devicetree/bindings/gpio/gpio.txt
+++ b/Documentation/devicetree/bindings/gpio/gpio.txt
@@ -98,7 +98,7 @@ announce the pinrange to the pin ctrl subsystem. For example,
compatible = "fsl,qe-pario-bank-e", "fsl,qe-pario-bank";
reg = <0x1460 0x18>;
gpio-controller;
- gpio-ranges = <&pinctrl1 20 10>, <&pinctrl2 50 20>;
+ gpio-ranges = <&pinctrl1 0 20 10>, <&pinctrl2 10 50 20>;
}
@@ -107,8 +107,8 @@ where,
Next values specify the base pin and number of pins for the range
handled by 'qe_pio_e' gpio. In the given example from base pin 20 to
- pin 29 under pinctrl1 and pin 50 to pin 69 under pinctrl2 is handled
- by this gpio controller.
+ pin 29 under pinctrl1 with gpio offset 0 and pin 50 to pin 69 under
+ pinctrl2 with gpio offset 10 is handled by this gpio controller.
The pinctrl node must have "#gpio-range-cells" property to show number of
arguments to pass with phandle from gpio controllers node.
diff --git a/arch/arm/boot/dts/spear1310.dtsi b/arch/arm/boot/dts/spear1310.dtsi
index 1513c19..122ae94 100644
--- a/arch/arm/boot/dts/spear1310.dtsi
+++ b/arch/arm/boot/dts/spear1310.dtsi
@@ -89,7 +89,7 @@
pinmux: pinmux at e0700000 {
compatible = "st,spear1310-pinmux";
reg = <0xe0700000 0x1000>;
- #gpio-range-cells = <2>;
+ #gpio-range-cells = <3>;
};
apb {
@@ -212,7 +212,7 @@
interrupt-controller;
gpio-controller;
#gpio-cells = <2>;
- gpio-ranges = <&pinmux 0 246>;
+ gpio-ranges = <&pinmux 0 0 246>;
status = "disabled";
st-plgpio,ngpio = <246>;
diff --git a/arch/arm/boot/dts/spear1340.dtsi b/arch/arm/boot/dts/spear1340.dtsi
index 34da11a..c511c47 100644
--- a/arch/arm/boot/dts/spear1340.dtsi
+++ b/arch/arm/boot/dts/spear1340.dtsi
@@ -63,7 +63,7 @@
pinmux: pinmux at e0700000 {
compatible = "st,spear1340-pinmux";
reg = <0xe0700000 0x1000>;
- #gpio-range-cells = <2>;
+ #gpio-range-cells = <3>;
};
pwm: pwm at e0180000 {
@@ -127,7 +127,7 @@
interrupt-controller;
gpio-controller;
#gpio-cells = <2>;
- gpio-ranges = <&pinmux 0 252>;
+ gpio-ranges = <&pinmux 0 0 252>;
status = "disabled";
st-plgpio,ngpio = <250>;
diff --git a/arch/arm/boot/dts/spear310.dtsi b/arch/arm/boot/dts/spear310.dtsi
index ab45b8c..9537208 100644
--- a/arch/arm/boot/dts/spear310.dtsi
+++ b/arch/arm/boot/dts/spear310.dtsi
@@ -25,7 +25,7 @@
pinmux: pinmux at b4000000 {
compatible = "st,spear310-pinmux";
reg = <0xb4000000 0x1000>;
- #gpio-range-cells = <2>;
+ #gpio-range-cells = <3>;
};
fsmc: flash at 44000000 {
@@ -102,7 +102,7 @@
interrupt-controller;
gpio-controller;
#gpio-cells = <2>;
- gpio-ranges = <&pinmux 0 102>;
+ gpio-ranges = <&pinmux 0 0 102>;
status = "disabled";
st-plgpio,ngpio = <102>;
diff --git a/arch/arm/boot/dts/spear320.dtsi b/arch/arm/boot/dts/spear320.dtsi
index caa5520..ffea342 100644
--- a/arch/arm/boot/dts/spear320.dtsi
+++ b/arch/arm/boot/dts/spear320.dtsi
@@ -24,7 +24,7 @@
pinmux: pinmux at b3000000 {
compatible = "st,spear320-pinmux";
reg = <0xb3000000 0x1000>;
- #gpio-range-cells = <2>;
+ #gpio-range-cells = <3>;
};
clcd at 90000000 {
@@ -130,7 +130,7 @@
interrupt-controller;
gpio-controller;
#gpio-cells = <2>;
- gpio-ranges = <&pinmux 0 102>;
+ gpio-ranges = <&pinmux 0 0 102>;
status = "disabled";
st-plgpio,ngpio = <102>;
diff --git a/drivers/gpio/gpiolib-of.c b/drivers/gpio/gpiolib-of.c
index 25b1dbe..b1f0682 100644
--- a/drivers/gpio/gpiolib-of.c
+++ b/drivers/gpio/gpiolib-of.c
@@ -245,15 +245,12 @@ static void of_gpiochip_add_pin_range(struct gpio_chip *chip)
* to add different ranges for one and the same GPIO chip,
* as the code assumes that we have one consecutive range
* on both, mapping 1-to-1.
- *
- * TODO: make the OF bindings handle multiple sparse ranges
- * on the same GPIO chip.
*/
ret = gpiochip_add_pin_range(chip,
pinctrl_dev_get_devname(pctldev),
- 0, /* offset in gpiochip */
pinspec.args[0],
- pinspec.args[1]);
+ pinspec.args[1],
+ pinspec.args[2]);
if (ret)
break;
--
1.7.10.4
^ permalink raw reply related
* [PATCH v7 03/15] gpio: use pinctrl device name for add range
From: Haojian Zhuang @ 2013-01-18 7:31 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1358494279-16503-1-git-send-email-haojian.zhuang@linaro.org>
gpiochip_add_pin_range() needs pinctrl device name as parameter.
Currently the parameter is pinctrl description name. So fix it.
Signed-off-by: Haojian Zhuang <haojian.zhuang@linaro.org>
---
drivers/gpio/gpiolib-of.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/gpio/gpiolib-of.c b/drivers/gpio/gpiolib-of.c
index d542a14..25b1dbe 100644
--- a/drivers/gpio/gpiolib-of.c
+++ b/drivers/gpio/gpiolib-of.c
@@ -250,7 +250,7 @@ static void of_gpiochip_add_pin_range(struct gpio_chip *chip)
* on the same GPIO chip.
*/
ret = gpiochip_add_pin_range(chip,
- pinctrl_dev_get_name(pctldev),
+ pinctrl_dev_get_devname(pctldev),
0, /* offset in gpiochip */
pinspec.args[0],
pinspec.args[1]);
--
1.7.10.4
^ permalink raw reply related
* [PATCH v7 02/15] pinctrl: core: get devname from pinctrl_dev
From: Haojian Zhuang @ 2013-01-18 7:31 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1358494279-16503-1-git-send-email-haojian.zhuang@linaro.org>
Add new function to get devname from pinctrl_dev. pinctrl_dev_get_name()
can only get pinctrl description name. If we want to use gpio driver to
find pinctrl device node, we need to fetch the pinctrl device name.
Signed-off-by: Haojian Zhuang <haojian.zhuang@linaro.org>
---
drivers/pinctrl/core.c | 6 ++++++
include/linux/pinctrl/pinctrl.h | 1 +
2 files changed, 7 insertions(+)
diff --git a/drivers/pinctrl/core.c b/drivers/pinctrl/core.c
index 59f5a96..e7378a1 100644
--- a/drivers/pinctrl/core.c
+++ b/drivers/pinctrl/core.c
@@ -83,6 +83,12 @@ const char *pinctrl_dev_get_name(struct pinctrl_dev *pctldev)
}
EXPORT_SYMBOL_GPL(pinctrl_dev_get_name);
+const char *pinctrl_dev_get_devname(struct pinctrl_dev *pctldev)
+{
+ return dev_name(pctldev->dev);
+}
+EXPORT_SYMBOL_GPL(pinctrl_dev_get_devname);
+
void *pinctrl_dev_get_drvdata(struct pinctrl_dev *pctldev)
{
return pctldev->driver_data;
diff --git a/include/linux/pinctrl/pinctrl.h b/include/linux/pinctrl/pinctrl.h
index 04d6700..778804d 100644
--- a/include/linux/pinctrl/pinctrl.h
+++ b/include/linux/pinctrl/pinctrl.h
@@ -154,6 +154,7 @@ struct pinctrl_dev *of_pinctrl_get(struct device_node *np)
#endif /* CONFIG_OF */
extern const char *pinctrl_dev_get_name(struct pinctrl_dev *pctldev);
+extern const char *pinctrl_dev_get_devname(struct pinctrl_dev *pctldev);
extern void *pinctrl_dev_get_drvdata(struct pinctrl_dev *pctldev);
#else
--
1.7.10.4
^ permalink raw reply related
* [PATCH v7 01/15] Revert "pinctrl: single: support gpio request and free"
From: Haojian Zhuang @ 2013-01-18 7:31 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1358494279-16503-1-git-send-email-haojian.zhuang@linaro.org>
This reverts commit 2e8b2eab94c35d83bb7da71c63b4695f32ddca88.
Conflicts:
drivers/pinctrl/pinctrl-single.c
ERROR: "__aeabi_uldivmod" [drivers/pinctrl/pinctrl-single.ko]
undefined!]
On Fri, Jan 11, 2013 at 4:00 PM, Russell King wrote:
> The above error happens in builds including pinctrl-single - the
> reason
> is this, where resource_size_t may be 64-bit.
>
> gpio->range.pin_base = (r.start - pcs->res->start) /
> mux_bytes;
> gpio->range.npins = (r.end - r.start) / mux_bytes + 1;
The reason of not fixing this issue and reverting the patch instead is
this patch can't handle another case. It's not easy to handle multiple
gpios sharing one pin register. So this gpio range feature will be
implemented by other patches.
---
drivers/pinctrl/pinctrl-single.c | 79 +-------------------------------------
1 file changed, 2 insertions(+), 77 deletions(-)
diff --git a/drivers/pinctrl/pinctrl-single.c b/drivers/pinctrl/pinctrl-single.c
index f6a360b..5c32e88 100644
--- a/drivers/pinctrl/pinctrl-single.c
+++ b/drivers/pinctrl/pinctrl-single.c
@@ -30,7 +30,6 @@
#define PCS_MUX_BITS_NAME "pinctrl-single,bits"
#define PCS_REG_NAME_LEN ((sizeof(unsigned long) * 2) + 1)
#define PCS_OFF_DISABLED ~0U
-#define PCS_MAX_GPIO_VALUES 2
/**
* struct pcs_pingroup - pingroups for a function
@@ -78,16 +77,6 @@ struct pcs_function {
};
/**
- * struct pcs_gpio_range - pinctrl gpio range
- * @range: subrange of the GPIO number space
- * @gpio_func: gpio function value in the pinmux register
- */
-struct pcs_gpio_range {
- struct pinctrl_gpio_range range;
- int gpio_func;
-};
-
-/**
* struct pcs_data - wrapper for data needed by pinctrl framework
* @pa: pindesc array
* @cur: index to current element
@@ -414,26 +403,9 @@ static void pcs_disable(struct pinctrl_dev *pctldev, unsigned fselector,
}
static int pcs_request_gpio(struct pinctrl_dev *pctldev,
- struct pinctrl_gpio_range *range, unsigned pin)
+ struct pinctrl_gpio_range *range, unsigned offset)
{
- struct pcs_device *pcs = pinctrl_dev_get_drvdata(pctldev);
- struct pcs_gpio_range *gpio = NULL;
- int end, mux_bytes;
- unsigned data;
-
- gpio = container_of(range, struct pcs_gpio_range, range);
- end = range->pin_base + range->npins - 1;
- if (pin < range->pin_base || pin > end) {
- dev_err(pctldev->dev,
- "pin %d isn't in the range of %d to %d\n",
- pin, range->pin_base, end);
- return -EINVAL;
- }
- mux_bytes = pcs->width / BITS_PER_BYTE;
- data = pcs->read(pcs->base + pin * mux_bytes) & ~pcs->fmask;
- data |= gpio->gpio_func;
- pcs->write(data, pcs->base + pin * mux_bytes);
- return 0;
+ return -ENOTSUPP;
}
static struct pinmux_ops pcs_pinmux_ops = {
@@ -907,49 +879,6 @@ static void pcs_free_resources(struct pcs_device *pcs)
static struct of_device_id pcs_of_match[];
-static int pcs_add_gpio_range(struct device_node *node, struct pcs_device *pcs)
-{
- struct pcs_gpio_range *gpio;
- struct device_node *child;
- struct resource r;
- const char name[] = "pinctrl-single";
- u32 gpiores[PCS_MAX_GPIO_VALUES];
- int ret, i = 0, mux_bytes = 0;
-
- for_each_child_of_node(node, child) {
- ret = of_address_to_resource(child, 0, &r);
- if (ret < 0)
- continue;
- memset(gpiores, 0, sizeof(u32) * PCS_MAX_GPIO_VALUES);
- ret = of_property_read_u32_array(child, "pinctrl-single,gpio",
- gpiores, PCS_MAX_GPIO_VALUES);
- if (ret < 0)
- continue;
- gpio = devm_kzalloc(pcs->dev, sizeof(*gpio), GFP_KERNEL);
- if (!gpio) {
- dev_err(pcs->dev, "failed to allocate pcs gpio\n");
- return -ENOMEM;
- }
- gpio->range.name = devm_kzalloc(pcs->dev, sizeof(name),
- GFP_KERNEL);
- if (!gpio->range.name) {
- dev_err(pcs->dev, "failed to allocate range name\n");
- return -ENOMEM;
- }
- memcpy((char *)gpio->range.name, name, sizeof(name));
-
- gpio->range.id = i++;
- gpio->range.base = gpiores[0];
- gpio->gpio_func = gpiores[1];
- mux_bytes = pcs->width / BITS_PER_BYTE;
- gpio->range.pin_base = (r.start - pcs->res->start) / mux_bytes;
- gpio->range.npins = (r.end - r.start) / mux_bytes + 1;
-
- pinctrl_add_gpio_range(pcs->pctl, &gpio->range);
- }
- return 0;
-}
-
static int pcs_probe(struct platform_device *pdev)
{
struct device_node *np = pdev->dev.of_node;
@@ -1046,10 +975,6 @@ static int pcs_probe(struct platform_device *pdev)
goto free;
}
- ret = pcs_add_gpio_range(np, pcs);
- if (ret < 0)
- goto free;
-
dev_info(pcs->dev, "%i pins at pa %p size %u\n",
pcs->desc.npins, pcs->base, pcs->size);
--
1.7.10.4
^ permalink raw reply related
* [PATCH v7 0/15] support pinconf in pinctrl single driver
From: Haojian Zhuang @ 2013-01-18 7:31 UTC (permalink / raw)
To: linux-arm-kernel
Changelog:
v7:
1. Discard the method of adding gpio range from pinctrl-single driver.
Use gpiolib driver to support gpio range from DTS instead.
2. Add gpio request function to claim pin in gpio pl061 driver.
3. Adjust the initcall level in gpio pl061 driver.
4. Allocate gpio number from lowest gpio number to highest. The original
implementation is inverted. It's hard to use since it inverted the sequence
of gpio number.
5. Remove the support of pxa910 temporarily since gpio pxa driver need to
be updated for supporting this solution.
v6:
1. Two configuration array will be created for each pin group.
This first array is stored in pcs_function structure. The 32-bit
configruation argument is stored in this array. Driver stores
data while parsing DTS file, and loads these config array if
function selector is indicated.
The second array is stored in pinctrl_map structure. Driver won't
use it directly. So we could avoid to append lookup pinctrl map
method that is introduced in v5.
v5:
1. Move the properties of pinconf into pin group. So those mask
properties could be merged with other pinconf properties.
2. Append lookup pinctrl map method.
3. Append input schmitt disable config parameter.
4. Clean code.
v4:
1. Define gpio range as sub-node, not label. And remove
pinctrl-single,gpio-ranges property.
2. Use new two properties in sub-node, reg &
pinctrl-single,gpio. GPIO number & GPIO function are listed in
the pinctrl-single,gpio property.
3. Reference the names like pinctrl-single,bias.
4. Add compatible name "pinconf-single". If the compatible name is
"pinctrl-single", there's no pinconf. If the compatible name is
"pinconf-single", there's the generic pinconf in pinctrl-single.
5. Update documents.
v3:
1. Add more comments in document.
2. Replace pcs_readl() & pcs_writel() by pcs->read() & pcs->write().
3. Clean code.
v2:
1. Remove "pinctrl-single,gpio-mask". Since GPIO function is one of the
mux function in the pinmux register of both OMAP and PXA/MMP silicons.
Use "pinctrl-single,function-mask" instead.
^ permalink raw reply
* [PATCH 3/4] Enable ecc-mode selection in the driver
From: Artem Bityutskiy @ 2013-01-18 7:27 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <50F6927D.3070303@mpl.ch>
On Wed, 2013-01-16 at 12:43 +0100, Stefan Peter wrote:
> Hi Andrew
For some reasons I do not see your patches in the mailing lists which
are in CC.
--
Best Regards,
Artem Bityutskiy
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 836 bytes
Desc: This is a digitally signed message part
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20130118/ca0be53c/attachment.sig>
^ permalink raw reply
* [PATCH 9/9] ARM: OMAP2+: AM33XX: control: Add some control module registers and APIs
From: Vaibhav Bedia @ 2013-01-18 7:19 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1358493569-17142-1-git-send-email-vaibhav.bedia@ti.com>
Add minimal APIs for writing to the IPC and the M3_TXEV registers
in the Control module. These will be used in a subsequent patch which
adds suspend-resume support for AM33XX.
Signed-off-by: Vaibhav Bedia <vaibhav.bedia@ti.com>
Acked-by: Santosh Shilimkar <santosh.shilimkar@ti.com>
---
Change from RFC version:
No change
arch/arm/mach-omap2/control.c | 20 ++++++++++++++++++++
arch/arm/mach-omap2/control.h | 41 +++++++++++++++++++++++++++++++++++++++++
2 files changed, 61 insertions(+), 0 deletions(-)
diff --git a/arch/arm/mach-omap2/control.c b/arch/arm/mach-omap2/control.c
index 2adb268..c5d54ae 100644
--- a/arch/arm/mach-omap2/control.c
+++ b/arch/arm/mach-omap2/control.c
@@ -604,3 +604,23 @@ int omap3_ctrl_save_padconf(void)
}
#endif /* CONFIG_ARCH_OMAP3 && CONFIG_PM */
+
+#if defined(CONFIG_SOC_AM33XX) && defined(CONFIG_PM)
+void am33xx_txev_eoi(void)
+{
+ omap_ctrl_writel(AM33XX_M3_TXEV_ACK, AM33XX_CONTROL_M3_TXEV_EOI);
+}
+
+void am33xx_txev_enable(void)
+{
+ omap_ctrl_writel(AM33XX_M3_TXEV_ENABLE, AM33XX_CONTROL_M3_TXEV_EOI);
+}
+
+void am33xx_wkup_m3_ipc_cmd(struct am33xx_ipc_data *data)
+{
+ omap_ctrl_writel(data->resume_addr, AM33XX_CONTROL_IPC_MSG_REG0);
+ omap_ctrl_writel(data->sleep_mode, AM33XX_CONTROL_IPC_MSG_REG1);
+ omap_ctrl_writel(data->param1, AM33XX_CONTROL_IPC_MSG_REG2);
+ omap_ctrl_writel(data->param2, AM33XX_CONTROL_IPC_MSG_REG3);
+}
+#endif /* CONFIG_SOC_AM33XX && CONFIG_PM */
diff --git a/arch/arm/mach-omap2/control.h b/arch/arm/mach-omap2/control.h
index e6c3281..cb85f0a 100644
--- a/arch/arm/mach-omap2/control.h
+++ b/arch/arm/mach-omap2/control.h
@@ -358,6 +358,37 @@
#define AM33XX_CONTROL_STATUS_SYSBOOT1_WIDTH 0x2
#define AM33XX_CONTROL_STATUS_SYSBOOT1_MASK (0x3 << 22)
+#define AM33XX_DDR_IO_CTRL 0x0E04
+#define AM33XX_VTP0_CTRL_REG 0x0E0C
+
+/* AM33XX VTP0_CTRL_REG bits */
+#define AM33XX_VTP_CTRL_START_EN (1 << 0)
+#define AM33XX_VTP_CTRL_LOCK_EN (1 << 4)
+#define AM33XX_VTP_CTRL_READY (1 << 5)
+#define AM33XX_VTP_CTRL_ENABLE (1 << 6)
+
+/* AM33XX M3_TXEV_EOI register */
+#define AM33XX_CONTROL_M3_TXEV_EOI 0x1324
+
+#define AM33XX_M3_TXEV_ACK (0x1 << 0)
+#define AM33XX_M3_TXEV_ENABLE (0x0 << 0)
+
+/* AM33XX IPC message registers */
+#define AM33XX_CONTROL_IPC_MSG_REG0 0x1328
+#define AM33XX_CONTROL_IPC_MSG_REG1 0x132C
+#define AM33XX_CONTROL_IPC_MSG_REG2 0x1330
+#define AM33XX_CONTROL_IPC_MSG_REG3 0x1334
+#define AM33XX_CONTROL_IPC_MSG_REG4 0x1338
+#define AM33XX_CONTROL_IPC_MSG_REG5 0x133C
+#define AM33XX_CONTROL_IPC_MSG_REG6 0x1340
+#define AM33XX_CONTROL_IPC_MSG_REG7 0x1344
+
+#define AM33XX_DDR_CMD0_IOCTRL 0x1404
+#define AM33XX_DDR_CMD1_IOCTRL 0x1408
+#define AM33XX_DDR_CMD2_IOCTRL 0x140C
+#define AM33XX_DDR_DATA0_IOCTRL 0x1440
+#define AM33XX_DDR_DATA1_IOCTRL 0x1444
+
/* CONTROL OMAP STATUS register to identify OMAP3 features */
#define OMAP3_CONTROL_OMAP_STATUS 0x044c
@@ -417,6 +448,16 @@ extern void omap3630_ctrl_disable_rta(void);
extern int omap3_ctrl_save_padconf(void);
extern void omap2_set_globals_control(void __iomem *ctrl,
void __iomem *ctrl_pad);
+struct am33xx_ipc_data {
+ u32 resume_addr;
+ u32 param1;
+ u32 param2;
+ u32 sleep_mode;
+};
+extern void am33xx_wkup_m3_ipc_cmd(struct am33xx_ipc_data *data);
+extern void am33xx_txev_eoi(void);
+extern void am33xx_txev_enable(void);
+
#else
#define omap_ctrl_base_get() 0
#define omap_ctrl_readb(x) 0
--
1.7.0.4
^ permalink raw reply related
* [PATCH 8/9] ARM: DTS: AM33XX: Add nodes for OCMC RAM and WKUP-M3
From: Vaibhav Bedia @ 2013-01-18 7:19 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1358493569-17142-1-git-send-email-vaibhav.bedia@ti.com>
Since AM33XX supports only DT-boot, this is needed
for the appropriate device nodes to be created.
Note: OCMC RAM is part of the PER power domain and supports
retention. The assembly code for low power entry/exit will
run from OCMC RAM. To ensure that the OMAP PM code does not
attempt to disable the clock to OCMC RAM as part of the
suspend process add the no_idle_on_suspend flag.
Signed-off-by: Vaibhav Bedia <vaibhav.bedia@ti.com>
Acked-by: Santosh Shilimkar <santosh.shilimkar@ti.com>
---
Change from RFC version:
No change
arch/arm/boot/dts/am33xx.dtsi | 11 +++++++++++
1 files changed, 11 insertions(+), 0 deletions(-)
diff --git a/arch/arm/boot/dts/am33xx.dtsi b/arch/arm/boot/dts/am33xx.dtsi
index c2f14e8..4731748 100644
--- a/arch/arm/boot/dts/am33xx.dtsi
+++ b/arch/arm/boot/dts/am33xx.dtsi
@@ -385,5 +385,16 @@
mac-address = [ 00 00 00 00 00 00 ];
};
};
+
+ ocmcram: ocmcram at 40300000 {
+ compatible = "ti,ocmcram";
+ ti,hwmods = "ocmcram";
+ ti,no_idle_on_suspend;
+ };
+
+ wkup_m3: wkup_m3 at 44d00000 {
+ compatible = "ti,wkup_m3";
+ ti,hwmods = "wkup_m3";
+ };
};
};
--
1.7.0.4
^ permalink raw reply related
* [PATCH 7/9] ARM: OMAP2+: AM33XX: Update the hardreset API
From: Vaibhav Bedia @ 2013-01-18 7:19 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1358493569-17142-1-git-send-email-vaibhav.bedia@ti.com>
WKUP-M3 has a reset status bit (RM_WKUP_STST.WKUP_M3_LRST)
Update the hardreset API to ensure that the reset line properly
deasserted.
Signed-off-by: Vaibhav Bedia <vaibhav.bedia@ti.com>
Acked-by: Santosh Shilimkar <santosh.shilimkar@ti.com>
---
Change from RFC version:
No change
arch/arm/mach-omap2/omap_hwmod.c | 5 +----
arch/arm/mach-omap2/prm33xx.c | 11 +++++++----
arch/arm/mach-omap2/prm33xx.h | 2 +-
3 files changed, 9 insertions(+), 9 deletions(-)
diff --git a/arch/arm/mach-omap2/omap_hwmod.c b/arch/arm/mach-omap2/omap_hwmod.c
index 4653efb..6549439 100644
--- a/arch/arm/mach-omap2/omap_hwmod.c
+++ b/arch/arm/mach-omap2/omap_hwmod.c
@@ -3041,11 +3041,8 @@ static int _am33xx_assert_hardreset(struct omap_hwmod *oh,
static int _am33xx_deassert_hardreset(struct omap_hwmod *oh,
struct omap_hwmod_rst_info *ohri)
{
- if (ohri->st_shift)
- pr_err("omap_hwmod: %s: %s: hwmod data error: OMAP4 does not support st_shift\n",
- oh->name, ohri->name);
-
return am33xx_prm_deassert_hardreset(ohri->rst_shift,
+ ohri->st_shift,
oh->clkdm->pwrdm.ptr->prcm_offs,
oh->prcm.omap4.rstctrl_offs,
oh->prcm.omap4.rstst_offs);
diff --git a/arch/arm/mach-omap2/prm33xx.c b/arch/arm/mach-omap2/prm33xx.c
index 1ac7388..44c0d72 100644
--- a/arch/arm/mach-omap2/prm33xx.c
+++ b/arch/arm/mach-omap2/prm33xx.c
@@ -110,11 +110,11 @@ int am33xx_prm_assert_hardreset(u8 shift, s16 inst, u16 rstctrl_offs)
* -EINVAL upon an argument error, -EEXIST if the submodule was already out
* of reset, or -EBUSY if the submodule did not exit reset promptly.
*/
-int am33xx_prm_deassert_hardreset(u8 shift, s16 inst,
+int am33xx_prm_deassert_hardreset(u8 shift, u8 st_shift, s16 inst,
u16 rstctrl_offs, u16 rstst_offs)
{
int c;
- u32 mask = 1 << shift;
+ u32 mask = 1 << st_shift;
/* Check the current status to avoid de-asserting the line twice */
if (am33xx_prm_is_hardreset_asserted(shift, inst, rstctrl_offs) == 0)
@@ -122,11 +122,14 @@ int am33xx_prm_deassert_hardreset(u8 shift, s16 inst,
/* Clear the reset status by writing 1 to the status bit */
am33xx_prm_rmw_reg_bits(0xffffffff, mask, inst, rstst_offs);
+
/* de-assert the reset control line */
+ mask = 1 << shift;
+
am33xx_prm_rmw_reg_bits(mask, 0, inst, rstctrl_offs);
- /* wait the status to be set */
- omap_test_timeout(am33xx_prm_is_hardreset_asserted(shift, inst,
+ /* wait the status to be set */
+ omap_test_timeout(am33xx_prm_is_hardreset_asserted(st_shift, inst,
rstst_offs),
MAX_MODULE_HARDRESET_WAIT, c);
diff --git a/arch/arm/mach-omap2/prm33xx.h b/arch/arm/mach-omap2/prm33xx.h
index 1c40373..9b9918d 100644
--- a/arch/arm/mach-omap2/prm33xx.h
+++ b/arch/arm/mach-omap2/prm33xx.h
@@ -125,7 +125,7 @@ extern void am33xx_prm_global_warm_sw_reset(void);
extern int am33xx_prm_is_hardreset_asserted(u8 shift, s16 inst,
u16 rstctrl_offs);
extern int am33xx_prm_assert_hardreset(u8 shift, s16 inst, u16 rstctrl_offs);
-extern int am33xx_prm_deassert_hardreset(u8 shift, s16 inst,
+extern int am33xx_prm_deassert_hardreset(u8 shift, u8 st_shift, s16 inst,
u16 rstctrl_offs, u16 rstst_offs);
#endif /* ASSEMBLER */
#endif
--
1.7.0.4
^ permalink raw reply related
* [PATCH 6/9] ARM: OMAP2+: AM33XX: hwmod: Update the WKUP-M3 hwmod with reset status bit
From: Vaibhav Bedia @ 2013-01-18 7:19 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1358493569-17142-1-git-send-email-vaibhav.bedia@ti.com>
WKUP-M3 has a reset status bit (RM_WKUP_STST.WKUP_M3_LRST)
Update the WKUP-M3 hwmod data to reflect the same.
Signed-off-by: Vaibhav Bedia <vaibhav.bedia@ti.com>
---
Change from RFC version:
No change
arch/arm/mach-omap2/omap_hwmod_33xx_data.c | 1 +
1 files changed, 1 insertions(+), 0 deletions(-)
diff --git a/arch/arm/mach-omap2/omap_hwmod_33xx_data.c b/arch/arm/mach-omap2/omap_hwmod_33xx_data.c
index 34a67e4..78929a4 100644
--- a/arch/arm/mach-omap2/omap_hwmod_33xx_data.c
+++ b/arch/arm/mach-omap2/omap_hwmod_33xx_data.c
@@ -269,6 +269,7 @@ static struct omap_hwmod am33xx_wkup_m3_hwmod = {
.omap4 = {
.clkctrl_offs = AM33XX_CM_WKUP_WKUP_M3_CLKCTRL_OFFSET,
.rstctrl_offs = AM33XX_RM_WKUP_RSTCTRL_OFFSET,
+ .rstst_offs = AM33XX_RM_WKUP_RSTST_OFFSET,
.modulemode = MODULEMODE_SWCTRL,
},
},
--
1.7.0.4
^ permalink raw reply related
* [PATCH 5/9] ARM: OMAP2+: AM33XX: hwmod: Fixup cpgmac0 hwmod entry
From: Vaibhav Bedia @ 2013-01-18 7:19 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1358493569-17142-1-git-send-email-vaibhav.bedia@ti.com>
The current HWMOD code expects the memory region with
the IP's SYSCONFIG register to be marked with ADDR_TYPE_RT
flag.
CPGMAC0 hwmod entry specifies two memory regions and marks
both with the flag ADDR_TYPE_RT although only the 2nd region
has the SYSCONFIG register. This leads to the HWMOD code
accessing the wrong memory address for idle and standby
operations. Fix this by removing the ADDR_TYPE_RT flag from
the 1st memory region in CPGMAC0 hwmod entry.
Signed-off-by: Vaibhav Bedia <vaibhav.bedia@ti.com>
---
Change from RFC version:
No change
arch/arm/mach-omap2/omap_hwmod_33xx_data.c | 1 -
1 files changed, 0 insertions(+), 1 deletions(-)
diff --git a/arch/arm/mach-omap2/omap_hwmod_33xx_data.c b/arch/arm/mach-omap2/omap_hwmod_33xx_data.c
index f2f408c..34a67e4 100644
--- a/arch/arm/mach-omap2/omap_hwmod_33xx_data.c
+++ b/arch/arm/mach-omap2/omap_hwmod_33xx_data.c
@@ -2496,7 +2496,6 @@ static struct omap_hwmod_addr_space am33xx_cpgmac0_addr_space[] = {
{
.pa_start = 0x4a100000,
.pa_end = 0x4a100000 + SZ_2K - 1,
- .flags = ADDR_TYPE_RT,
},
/* cpsw wr */
{
--
1.7.0.4
^ permalink raw reply related
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox