* [PATCH V3 0/4]: ARM: SAMSUNG: Add SPI clkdev support
From: Padmavathi Venna @ 2011-10-10 8:03 UTC (permalink / raw)
To: linux-arm-kernel
This patchset modifies the existing clkdev to make SPI driver
independent of the clock names send from platform data. This
patches enables the SPI driver to request SPI bus clocks
using generic connection ID.
V1 patch series are:
http://www.spinics.net/lists/arm-kernel/msg141671.html
Changes since V1:
-Add newly introduced CLKDEV_INIT macro for creating clk_lookup
structure as suggested by Russell King
V2 patches series are:
http://www.spinics.net/lists/arm-kernel/msg142733.html
Changes since V2:
-Reworked the patches as per the following link. Patch series in
the following link removed & and , from the macro declaration and added
in the macro defination.
http://www.spinics.net/lists/arm-kernel/msg143663.html
Padmavathi Venna (4):
ARM: S3C64XX: Add SPI clkdev support
ARM: S5PC100: Add SPI clkdev support
ARM: S5P64X0: Add SPI clkdev support
ARM: S5PV210: Add SPI clkdev support
arch/arm/mach-s3c64xx/clock.c | 98 ++++++++++++++++--------
arch/arm/mach-s5p64x0/clock-s5p6440.c | 57 +++++++++-----
arch/arm/mach-s5p64x0/clock-s5p6450.c | 57 +++++++++-----
arch/arm/mach-s5pc100/clock.c | 132 ++++++++++++++++++++-------------
arch/arm/mach-s5pv210/clock.c | 58 ++++++++++-----
5 files changed, 259 insertions(+), 143 deletions(-)
--
1.7.4.4
^ permalink raw reply
* [PATCH V3 1/4] ARM: S3C64XX: Add SPI clkdev support
From: Padmavathi Venna @ 2011-10-10 8:03 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1318233789-19882-1-git-send-email-padma.v@samsung.com>
Registered the SPI bus clocks with clkdev using generic
connection id.
Signed-off-by: Padmavathi Venna <padma.v@samsung.com>
---
arch/arm/mach-s3c64xx/clock.c | 98 +++++++++++++++++++++++++++-------------
1 files changed, 66 insertions(+), 32 deletions(-)
diff --git a/arch/arm/mach-s3c64xx/clock.c b/arch/arm/mach-s3c64xx/clock.c
index 39c238d..3420e5c 100644
--- a/arch/arm/mach-s3c64xx/clock.c
+++ b/arch/arm/mach-s3c64xx/clock.c
@@ -184,18 +184,6 @@ static struct clk init_clocks_off[] = {
.enable = s3c64xx_pclk_ctrl,
.ctrlbit = S3C_CLKCON_PCLK_SPI1,
}, {
- .name = "spi_48m",
- .devname = "s3c64xx-spi.0",
- .parent = &clk_48m,
- .enable = s3c64xx_sclk_ctrl,
- .ctrlbit = S3C_CLKCON_SCLK_SPI0_48,
- }, {
- .name = "spi_48m",
- .devname = "s3c64xx-spi.1",
- .parent = &clk_48m,
- .enable = s3c64xx_sclk_ctrl,
- .ctrlbit = S3C_CLKCON_SCLK_SPI1_48,
- }, {
.name = "48m",
.devname = "s3c-sdhci.0",
.parent = &clk_48m,
@@ -625,26 +613,6 @@ static struct clksrc_clk clksrcs[] = {
.reg_div = { .reg = S3C_CLK_DIV2, .shift = 16, .size = 4 },
.sources = &clkset_uart,
}, {
-/* Where does UCLK0 come from? */
- .clk = {
- .name = "spi-bus",
- .devname = "s3c64xx-spi.0",
- .ctrlbit = S3C_CLKCON_SCLK_SPI0,
- .enable = s3c64xx_sclk_ctrl,
- },
- .reg_src = { .reg = S3C_CLK_SRC, .shift = 14, .size = 2 },
- .reg_div = { .reg = S3C_CLK_DIV2, .shift = 0, .size = 4 },
- .sources = &clkset_spi_mmc,
- }, {
- .clk = {
- .name = "spi-bus",
- .devname = "s3c64xx-spi.1",
- .enable = s3c64xx_sclk_ctrl,
- },
- .reg_src = { .reg = S3C_CLK_SRC, .shift = 16, .size = 2 },
- .reg_div = { .reg = S3C_CLK_DIV2, .shift = 4, .size = 4 },
- .sources = &clkset_spi_mmc,
- }, {
.clk = {
.name = "audio-bus",
.devname = "samsung-i2s.0",
@@ -695,6 +663,60 @@ static struct clksrc_clk clksrcs[] = {
},
};
+static struct clk clk_48m_spi0 = {
+ .name = "spi_48m",
+ .parent = &clk_48m,
+ .enable = s3c64xx_sclk_ctrl,
+ .ctrlbit = S3C_CLKCON_SCLK_SPI0_48,
+};
+
+static struct clk clk_48m_spi1 = {
+ .name = "spi_48m",
+ .parent = &clk_48m,
+ .enable = s3c64xx_sclk_ctrl,
+ .ctrlbit = S3C_CLKCON_SCLK_SPI1_48,
+};
+
+static struct clksrc_clk sclk_spi0 = {
+ .clk = {
+ .name = "spi-bus",
+ .ctrlbit = S3C_CLKCON_SCLK_SPI0,
+ .enable = s3c64xx_sclk_ctrl,
+ },
+ .reg_src = { .reg = S3C_CLK_SRC, .shift = 14, .size = 2 },
+ .reg_div = { .reg = S3C_CLK_DIV2, .shift = 0, .size = 4 },
+ .sources = &clkset_spi_mmc,
+};
+
+static struct clksrc_clk sclk_spi1 = {
+ .clk = {
+ .name = "spi-bus",
+ .ctrlbit = S3C_CLKCON_SCLK_SPI1,
+ .enable = s3c64xx_sclk_ctrl,
+ },
+ .reg_src = { .reg = S3C_CLK_SRC, .shift = 16, .size = 2 },
+ .reg_div = { .reg = S3C_CLK_DIV2, .shift = 4, .size = 4 },
+ .sources = &clkset_spi_mmc,
+};
+
+static struct clk_lookup clk_lookup_table[] = {
+ CLKDEV_INIT(NULL, "spi_busclk0", &clk_p),
+ CLKDEV_INIT("s3c64xx-spi.0", "spi_busclk1", &sclk_spi0.clk),
+ CLKDEV_INIT("s3c64xx-spi.0", "spi_busclk2", &clk_48m_spi0),
+ CLKDEV_INIT("s3c64xx-spi.1", "spi_busclk1", &sclk_spi1.clk),
+ CLKDEV_INIT("s3c64xx-spi.1", "spi_busclk2", &clk_48m_spi1),
+};
+
+static struct clksrc_clk *clksrc_cdev[] = {
+ &sclk_spi0,
+ &sclk_spi1,
+};
+
+static struct clk *clk_cdev[] = {
+ &clk_48m_spi0,
+ &clk_48m_spi1,
+};
+
/* Clock initialisation code */
static struct clksrc_clk *init_parents[] = {
@@ -811,11 +833,16 @@ static struct clk *clks[] __initdata = {
void __init s3c64xx_register_clocks(unsigned long xtal,
unsigned armclk_divlimit)
{
+ int ptr;
+
armclk_mask = armclk_divlimit;
s3c24xx_register_baseclocks(xtal);
s3c24xx_register_clocks(clks, ARRAY_SIZE(clks));
+ for (ptr = 0; ptr < ARRAY_SIZE(clksrc_cdev); ptr++)
+ s3c_register_clksrc(clksrc_cdev[ptr], 1);
+
s3c_register_clocks(init_clocks, ARRAY_SIZE(init_clocks));
s3c_register_clocks(init_clocks_off, ARRAY_SIZE(init_clocks_off));
@@ -823,5 +850,12 @@ void __init s3c64xx_register_clocks(unsigned long xtal,
s3c24xx_register_clocks(clks1, ARRAY_SIZE(clks1));
s3c_register_clksrc(clksrcs, ARRAY_SIZE(clksrcs));
+
+ s3c24xx_register_clocks(clk_cdev, ARRAY_SIZE(clk_cdev));
+ for (ptr = 0; ptr < ARRAY_SIZE(clk_cdev); ptr++)
+ s3c_disable_clocks(clk_cdev[ptr], 1);
+
s3c_pwmclk_init();
+
+ clkdev_add_table(clk_lookup_table, ARRAY_SIZE(clk_lookup_table));
}
--
1.7.4.4
^ permalink raw reply related
* [PATCH V3 2/4] ARM: S5PC100: Add SPI clkdev support
From: Padmavathi Venna @ 2011-10-10 8:03 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1318233789-19882-1-git-send-email-padma.v@samsung.com>
Registered the SPI bus clocks with clkdev using generic
connection id.
Signed-off-by: Padmavathi Venna <padma.v@samsung.com>
---
arch/arm/mach-s5pc100/clock.c | 132 +++++++++++++++++++++++++----------------
1 files changed, 81 insertions(+), 51 deletions(-)
diff --git a/arch/arm/mach-s5pc100/clock.c b/arch/arm/mach-s5pc100/clock.c
index 8d47709..e025be7 100644
--- a/arch/arm/mach-s5pc100/clock.c
+++ b/arch/arm/mach-s5pc100/clock.c
@@ -673,24 +673,6 @@ static struct clk init_clocks_off[] = {
.enable = s5pc100_d1_5_ctrl,
.ctrlbit = (1 << 8),
}, {
- .name = "spi_48m",
- .devname = "s3c64xx-spi.0",
- .parent = &clk_mout_48m.clk,
- .enable = s5pc100_sclk0_ctrl,
- .ctrlbit = (1 << 7),
- }, {
- .name = "spi_48m",
- .devname = "s3c64xx-spi.1",
- .parent = &clk_mout_48m.clk,
- .enable = s5pc100_sclk0_ctrl,
- .ctrlbit = (1 << 8),
- }, {
- .name = "spi_48m",
- .devname = "s3c64xx-spi.2",
- .parent = &clk_mout_48m.clk,
- .enable = s5pc100_sclk0_ctrl,
- .ctrlbit = (1 << 9),
- }, {
.name = "mmc_48m",
.devname = "s3c-sdhci.0",
.parent = &clk_mout_48m.clk,
@@ -929,39 +911,6 @@ static struct clksrc_clk clk_sclk_spdif = {
static struct clksrc_clk clksrcs[] = {
{
.clk = {
- .name = "sclk_spi",
- .devname = "s3c64xx-spi.0",
- .ctrlbit = (1 << 4),
- .enable = s5pc100_sclk0_ctrl,
-
- },
- .sources = &clk_src_group1,
- .reg_src = { .reg = S5P_CLK_SRC1, .shift = 4, .size = 2 },
- .reg_div = { .reg = S5P_CLK_DIV2, .shift = 4, .size = 4 },
- }, {
- .clk = {
- .name = "sclk_spi",
- .devname = "s3c64xx-spi.1",
- .ctrlbit = (1 << 5),
- .enable = s5pc100_sclk0_ctrl,
-
- },
- .sources = &clk_src_group1,
- .reg_src = { .reg = S5P_CLK_SRC1, .shift = 8, .size = 2 },
- .reg_div = { .reg = S5P_CLK_DIV2, .shift = 8, .size = 4 },
- }, {
- .clk = {
- .name = "sclk_spi",
- .devname = "s3c64xx-spi.2",
- .ctrlbit = (1 << 6),
- .enable = s5pc100_sclk0_ctrl,
-
- },
- .sources = &clk_src_group1,
- .reg_src = { .reg = S5P_CLK_SRC1, .shift = 12, .size = 2 },
- .reg_div = { .reg = S5P_CLK_DIV2, .shift = 12, .size = 4 },
- }, {
- .clk = {
.name = "uclk1",
.ctrlbit = (1 << 3),
.enable = s5pc100_sclk0_ctrl,
@@ -1098,6 +1047,78 @@ static struct clksrc_clk clksrcs[] = {
},
};
+static struct clk clk_48m_spi0 = {
+ .name = "spi_48m",
+ .parent = &clk_mout_48m.clk,
+ .enable = s5pc100_sclk0_ctrl,
+ .ctrlbit = (1 << 7),
+};
+
+static struct clk clk_48m_spi1 = {
+ .name = "spi_48m",
+ .parent = &clk_mout_48m.clk,
+ .enable = s5pc100_sclk0_ctrl,
+ .ctrlbit = (1 << 8),
+};
+
+static struct clk clk_48m_spi2 = {
+ .name = "spi_48m",
+ .parent = &clk_mout_48m.clk,
+ .enable = s5pc100_sclk0_ctrl,
+ .ctrlbit = (1 << 9),
+};
+
+static struct clksrc_clk sclk_spi0 = {
+ .clk = {
+ .name = "sclk_spi",
+ .ctrlbit = (1 << 4),
+ .enable = s5pc100_sclk0_ctrl,
+ },
+ .sources = &clk_src_group1,
+ .reg_src = { .reg = S5P_CLK_SRC1, .shift = 4, .size = 2 },
+ .reg_div = { .reg = S5P_CLK_DIV2, .shift = 4, .size = 4 },
+};
+
+static struct clksrc_clk sclk_spi1 = {
+ .clk = {
+ .name = "sclk_spi",
+ .ctrlbit = (1 << 5),
+ .enable = s5pc100_sclk0_ctrl,
+ },
+ .sources = &clk_src_group1,
+ .reg_src = { .reg = S5P_CLK_SRC1, .shift = 8, .size = 2 },
+ .reg_div = { .reg = S5P_CLK_DIV2, .shift = 8, .size = 4 },
+};
+
+static struct clksrc_clk sclk_spi2 = {
+ .clk = {
+ .name = "sclk_spi",
+ .ctrlbit = (1 << 6),
+ .enable = s5pc100_sclk0_ctrl,
+ },
+ .sources = &clk_src_group1,
+ .reg_src = { .reg = S5P_CLK_SRC1, .shift = 12, .size = 2 },
+ .reg_div = { .reg = S5P_CLK_DIV2, .shift = 12, .size = 4 },
+};
+
+static struct clk_lookup clk_lookup_table[] = {
+ CLKDEV_INIT(NULL, "spi_busclk0", &clk_p),
+ CLKDEV_INIT("s3c64xx-spi.0", "spi_busclk1", &clk_48m_spi0),
+ CLKDEV_INIT("s3c64xx-spi.0", "spi_busclk2", &sclk_spi0.clk),
+ CLKDEV_INIT("s3c64xx-spi.1", "spi_busclk1", &clk_48m_spi1),
+ CLKDEV_INIT("s3c64xx-spi.1", "spi_busclk2", &sclk_spi1.clk),
+};
+
+static struct clksrc_clk *clksrc_cdev[] = {
+ &sclk_spi0,
+ &sclk_spi1,
+};
+
+static struct clk *clk_cdev[] = {
+ &clk_48m_spi0,
+ &clk_48m_spi1,
+};
+
/* Clock initialisation code */
static struct clksrc_clk *sysclks[] = {
&clk_mout_apll,
@@ -1276,12 +1297,21 @@ void __init s5pc100_register_clocks(void)
s3c_register_clksrc(sysclks[ptr], 1);
s3c_register_clksrc(clksrcs, ARRAY_SIZE(clksrcs));
+
+ for (ptr = 0; ptr < ARRAY_SIZE(clksrc_cdev); ptr++)
+ s3c_register_clksrc(clksrc_cdev[ptr], 1);
+
s3c_register_clocks(init_clocks, ARRAY_SIZE(init_clocks));
s3c_register_clocks(init_clocks_off, ARRAY_SIZE(init_clocks_off));
s3c_disable_clocks(init_clocks_off, ARRAY_SIZE(init_clocks_off));
+ s3c24xx_register_clocks(clk_cdev, ARRAY_SIZE(clk_cdev));
+ for (ptr = 0; ptr < ARRAY_SIZE(clk_cdev); ptr++)
+ s3c_disable_clocks(clk_cdev[ptr], 1);
+
s3c24xx_register_clock(&dummy_apb_pclk);
s3c_pwmclk_init();
+ clkdev_add_table(clk_lookup_table, ARRAY_SIZE(clk_lookup_table));
}
--
1.7.4.4
^ permalink raw reply related
* [PATCH V3 3/4] ARM: S5P64X0: Add SPI clkdev support
From: Padmavathi Venna @ 2011-10-10 8:03 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1318233789-19882-1-git-send-email-padma.v@samsung.com>
Registered the SPI bus clocks with clkdev using generic
connection id.
Signed-off-by: Padmavathi Venna <padma.v@samsung.com>
---
arch/arm/mach-s5p64x0/clock-s5p6440.c | 57 +++++++++++++++++++++-----------
arch/arm/mach-s5p64x0/clock-s5p6450.c | 57 +++++++++++++++++++++-----------
2 files changed, 74 insertions(+), 40 deletions(-)
diff --git a/arch/arm/mach-s5p64x0/clock-s5p6440.c b/arch/arm/mach-s5p64x0/clock-s5p6440.c
index c54c65d..9e4f517 100644
--- a/arch/arm/mach-s5p64x0/clock-s5p6440.c
+++ b/arch/arm/mach-s5p64x0/clock-s5p6440.c
@@ -430,26 +430,6 @@ static struct clksrc_clk clksrcs[] = {
.reg_div = { .reg = S5P64X0_CLK_DIV2, .shift = 16, .size = 4 },
}, {
.clk = {
- .name = "sclk_spi",
- .devname = "s3c64xx-spi.0",
- .ctrlbit = (1 << 20),
- .enable = s5p64x0_sclk_ctrl,
- },
- .sources = &clkset_group1,
- .reg_src = { .reg = S5P64X0_CLK_SRC0, .shift = 14, .size = 2 },
- .reg_div = { .reg = S5P64X0_CLK_DIV2, .shift = 0, .size = 4 },
- }, {
- .clk = {
- .name = "sclk_spi",
- .devname = "s3c64xx-spi.1",
- .ctrlbit = (1 << 21),
- .enable = s5p64x0_sclk_ctrl,
- },
- .sources = &clkset_group1,
- .reg_src = { .reg = S5P64X0_CLK_SRC0, .shift = 16, .size = 2 },
- .reg_div = { .reg = S5P64X0_CLK_DIV2, .shift = 4, .size = 4 },
- }, {
- .clk = {
.name = "sclk_post",
.ctrlbit = (1 << 10),
.enable = s5p64x0_sclk_ctrl,
@@ -487,6 +467,39 @@ static struct clksrc_clk clksrcs[] = {
},
};
+static struct clksrc_clk sclk_spi0 = {
+ .clk = {
+ .name = "sclk_spi",
+ .ctrlbit = (1 << 20),
+ .enable = s5p64x0_sclk_ctrl,
+ },
+ .sources = &clkset_group1,
+ .reg_src = { .reg = S5P64X0_CLK_SRC0, .shift = 14, .size = 2 },
+ .reg_div = { .reg = S5P64X0_CLK_DIV2, .shift = 0, .size = 4 },
+};
+
+static struct clksrc_clk sclk_spi1 = {
+ .clk = {
+ .name = "sclk_spi",
+ .ctrlbit = (1 << 21),
+ .enable = s5p64x0_sclk_ctrl,
+ },
+ .sources = &clkset_group1,
+ .reg_src = { .reg = S5P64X0_CLK_SRC0, .shift = 16, .size = 2 },
+ .reg_div = { .reg = S5P64X0_CLK_DIV2, .shift = 4, .size = 4 },
+};
+
+static struct clk_lookup clk_lookup_table[] = {
+ CLKDEV_INIT(NULL, "spi_busclk0", &clk_p),
+ CLKDEV_INIT("s3c64xx-spi.0", "spi_busclk1", &sclk_spi0.clk),
+ CLKDEV_INIT("s3c64xx-spi.1", "spi_busclk1", &sclk_spi1.clk),
+};
+
+static struct clksrc_clk *clksrc_cdev[] = {
+ &sclk_spi0,
+ &sclk_spi1,
+};
+
/* Clock initialization code */
static struct clksrc_clk *sysclks[] = {
&clk_mout_apll,
@@ -581,6 +594,9 @@ void __init s5p6440_register_clocks(void)
for (ptr = 0; ptr < ARRAY_SIZE(sysclks); ptr++)
s3c_register_clksrc(sysclks[ptr], 1);
+ for (ptr = 0; ptr < ARRAY_SIZE(clksrc_cdev); ptr++)
+ s3c_register_clksrc(clksrc_cdev[ptr], 1);
+
s3c_register_clksrc(clksrcs, ARRAY_SIZE(clksrcs));
s3c_register_clocks(init_clocks, ARRAY_SIZE(init_clocks));
@@ -590,4 +606,5 @@ void __init s5p6440_register_clocks(void)
s3c24xx_register_clock(&dummy_apb_pclk);
s3c_pwmclk_init();
+ clkdev_add_table(clk_lookup_table, ARRAY_SIZE(clk_lookup_table));
}
diff --git a/arch/arm/mach-s5p64x0/clock-s5p6450.c b/arch/arm/mach-s5p64x0/clock-s5p6450.c
index 2d04abf..323c30c 100644
--- a/arch/arm/mach-s5p64x0/clock-s5p6450.c
+++ b/arch/arm/mach-s5p64x0/clock-s5p6450.c
@@ -452,26 +452,6 @@ static struct clksrc_clk clksrcs[] = {
.reg_div = { .reg = S5P64X0_CLK_DIV2, .shift = 16, .size = 4 },
}, {
.clk = {
- .name = "sclk_spi",
- .devname = "s3c64xx-spi.0",
- .ctrlbit = (1 << 20),
- .enable = s5p64x0_sclk_ctrl,
- },
- .sources = &clkset_group2,
- .reg_src = { .reg = S5P64X0_CLK_SRC0, .shift = 14, .size = 2 },
- .reg_div = { .reg = S5P64X0_CLK_DIV2, .shift = 0, .size = 4 },
- }, {
- .clk = {
- .name = "sclk_spi",
- .devname = "s3c64xx-spi.1",
- .ctrlbit = (1 << 21),
- .enable = s5p64x0_sclk_ctrl,
- },
- .sources = &clkset_group2,
- .reg_src = { .reg = S5P64X0_CLK_SRC0, .shift = 16, .size = 2 },
- .reg_div = { .reg = S5P64X0_CLK_DIV2, .shift = 4, .size = 4 },
- }, {
- .clk = {
.name = "sclk_fimc",
.ctrlbit = (1 << 10),
.enable = s5p64x0_sclk_ctrl,
@@ -536,6 +516,39 @@ static struct clksrc_clk clksrcs[] = {
},
};
+static struct clksrc_clk sclk_spi0 = {
+ .clk = {
+ .name = "sclk_spi",
+ .ctrlbit = (1 << 20),
+ .enable = s5p64x0_sclk_ctrl,
+ },
+ .sources = &clkset_group2,
+ .reg_src = { .reg = S5P64X0_CLK_SRC0, .shift = 14, .size = 2 },
+ .reg_div = { .reg = S5P64X0_CLK_DIV2, .shift = 0, .size = 4 },
+};
+
+static struct clksrc_clk sclk_spi1 = {
+ .clk = {
+ .name = "sclk_spi",
+ .ctrlbit = (1 << 21),
+ .enable = s5p64x0_sclk_ctrl,
+ },
+ .sources = &clkset_group2,
+ .reg_src = { .reg = S5P64X0_CLK_SRC0, .shift = 16, .size = 2 },
+ .reg_div = { .reg = S5P64X0_CLK_DIV2, .shift = 4, .size = 4 },
+};
+
+static struct clk_lookup clk_lookup_table[] = {
+ CLKDEV_INIT(NULL, "spi_busclk0", &clk_p),
+ CLKDEV_INIT("s3c64xx-spi.0", "spi_busclk1", &sclk_spi0.clk),
+ CLKDEV_INIT("s3c64xx-spi.1", "spi_busclk1", &sclk_spi1.clk),
+};
+
+static struct clksrc_clk *clksrc_cdev[] = {
+ &sclk_spi0,
+ &sclk_spi1,
+};
+
/* Clock initialization code */
static struct clksrc_clk *sysclks[] = {
&clk_mout_apll,
@@ -632,6 +645,9 @@ void __init s5p6450_register_clocks(void)
for (ptr = 0; ptr < ARRAY_SIZE(sysclks); ptr++)
s3c_register_clksrc(sysclks[ptr], 1);
+ for (ptr = 0; ptr < ARRAY_SIZE(clksrc_cdev); ptr++)
+ s3c_register_clksrc(clksrc_cdev[ptr], 1);
+
s3c_register_clksrc(clksrcs, ARRAY_SIZE(clksrcs));
s3c_register_clocks(init_clocks, ARRAY_SIZE(init_clocks));
@@ -641,4 +657,5 @@ void __init s5p6450_register_clocks(void)
s3c24xx_register_clock(&dummy_apb_pclk);
s3c_pwmclk_init();
+ clkdev_add_table(clk_lookup_table, ARRAY_SIZE(clk_lookup_table));
}
--
1.7.4.4
^ permalink raw reply related
* [PATCH V3 4/4] ARM: S5PV210: Add SPI clkdev support
From: Padmavathi Venna @ 2011-10-10 8:03 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1318233789-19882-1-git-send-email-padma.v@samsung.com>
Registered the SPI bus clocks with clkdev using generic
connection id.
Signed-off-by: Padmavathi Venna <padma.v@samsung.com>
---
arch/arm/mach-s5pv210/clock.c | 58 ++++++++++++++++++++++++++--------------
1 files changed, 38 insertions(+), 20 deletions(-)
diff --git a/arch/arm/mach-s5pv210/clock.c b/arch/arm/mach-s5pv210/clock.c
index 4c5ac7a..3edf034 100644
--- a/arch/arm/mach-s5pv210/clock.c
+++ b/arch/arm/mach-s5pv210/clock.c
@@ -983,26 +983,6 @@ static struct clksrc_clk clksrcs[] = {
.reg_div = { .reg = S5P_CLK_DIV1, .shift = 28, .size = 4 },
}, {
.clk = {
- .name = "sclk_spi",
- .devname = "s3c64xx-spi.0",
- .enable = s5pv210_clk_mask0_ctrl,
- .ctrlbit = (1 << 16),
- },
- .sources = &clkset_group2,
- .reg_src = { .reg = S5P_CLK_SRC5, .shift = 0, .size = 4 },
- .reg_div = { .reg = S5P_CLK_DIV5, .shift = 0, .size = 4 },
- }, {
- .clk = {
- .name = "sclk_spi",
- .devname = "s3c64xx-spi.1",
- .enable = s5pv210_clk_mask0_ctrl,
- .ctrlbit = (1 << 17),
- },
- .sources = &clkset_group2,
- .reg_src = { .reg = S5P_CLK_SRC5, .shift = 4, .size = 4 },
- .reg_div = { .reg = S5P_CLK_DIV5, .shift = 4, .size = 4 },
- }, {
- .clk = {
.name = "sclk_pwi",
.enable = s5pv210_clk_mask0_ctrl,
.ctrlbit = (1 << 29),
@@ -1022,6 +1002,39 @@ static struct clksrc_clk clksrcs[] = {
},
};
+static struct clksrc_clk sclk_spi0 = {
+ .clk = {
+ .name = "sclk_spi",
+ .enable = s5pv210_clk_mask0_ctrl,
+ .ctrlbit = (1 << 16),
+ },
+ .sources = &clkset_group2,
+ .reg_src = { .reg = S5P_CLK_SRC5, .shift = 0, .size = 4 },
+ .reg_div = { .reg = S5P_CLK_DIV5, .shift = 0, .size = 4 },
+};
+
+static struct clksrc_clk sclk_spi1 = {
+ .clk = {
+ .name = "sclk_spi",
+ .enable = s5pv210_clk_mask0_ctrl,
+ .ctrlbit = (1 << 17),
+ },
+ .sources = &clkset_group2,
+ .reg_src = { .reg = S5P_CLK_SRC5, .shift = 4, .size = 4 },
+ .reg_div = { .reg = S5P_CLK_DIV5, .shift = 4, .size = 4 },
+};
+
+static struct clk_lookup clk_lookup_table[] = {
+ CLKDEV_INIT(NULL, "spi_busclk0", &clk_p),
+ CLKDEV_INIT("s3c64xx-spi.0", "spi_busclk1", &sclk_spi0.clk),
+ CLKDEV_INIT("s3c64xx-spi.1", "spi_busclk1", &sclk_spi1.clk),
+};
+
+static struct clksrc_clk *clksrc_cdev[] = {
+ &sclk_spi0,
+ &sclk_spi1,
+};
+
/* Clock initialisation code */
static struct clksrc_clk *sysclks[] = {
&clk_mout_apll,
@@ -1273,6 +1286,9 @@ void __init s5pv210_register_clocks(void)
for (ptr = 0; ptr < ARRAY_SIZE(sclk_tv); ptr++)
s3c_register_clksrc(sclk_tv[ptr], 1);
+ for (ptr = 0; ptr < ARRAY_SIZE(clksrc_cdev); ptr++)
+ s3c_register_clksrc(clksrc_cdev[ptr], 1);
+
s3c_register_clksrc(clksrcs, ARRAY_SIZE(clksrcs));
s3c_register_clocks(init_clocks, ARRAY_SIZE(init_clocks));
@@ -1281,4 +1297,6 @@ void __init s5pv210_register_clocks(void)
s3c24xx_register_clock(&dummy_apb_pclk);
s3c_pwmclk_init();
+
+ clkdev_add_table(clk_lookup_table, ARRAY_SIZE(clk_lookup_table));
}
--
1.7.4.4
^ permalink raw reply related
* [PATCH V2 0/2]: Add SPI Support on Exynos4
From: Padmavathi Venna @ 2011-10-10 8:08 UTC (permalink / raw)
To: linux-arm-kernel
This patchset adds SPI support and register the SPI bus clock
with clkdev using generic connection ID on EXYNOS4. This patch
set is depend on the following patches as it uses a common macro
CLKDEV_INIT to create clk_lookup structure and it also avoids
passing clock names through platform data.
ARM: CLKDEV: Add Common Macro for clk_lookup
ARM: SAMSUNG: Remove SPI bus clocks from platform data
V1 patch series are:
http://www.mail-archive.com/linux-samsung-soc at vger.kernel.org/msg06986.html
ARM: EXYNOS4: Add SPI support to EXYNOS4
SPI: EXYNOS4: Enable the SPI driver for EXYNOS4
Changes Since V1:
Reworked the patches as per the following link. Patch series in
the following link removed & and , from the macro declaration and added
in the macro defination.
http://www.spinics.net/lists/arm-kernel/msg143663.html
arch/arm/mach-exynos4/Kconfig | 1 +
arch/arm/mach-exynos4/Makefile | 1 +
arch/arm/mach-exynos4/clock.c | 82 +++++---
arch/arm/mach-exynos4/dev-spi.c | 225 ++++++++++++++++++++++
arch/arm/mach-exynos4/include/mach/irqs.h | 3 +
arch/arm/mach-exynos4/include/mach/map.h | 3 +
arch/arm/mach-exynos4/include/mach/spi-clocks.h | 16 ++
arch/arm/mach-exynos4/mach-smdkv310.c | 127 ++++++++++++-
arch/arm/plat-samsung/include/plat/devs.h | 3 +
arch/arm/plat-samsung/include/plat/s3c64xx-spi.h | 1 +
drivers/spi/Kconfig | 2 +-
11 files changed, 432 insertions(+), 32 deletions(-)
create mode 100644 arch/arm/mach-exynos4/dev-spi.c
create mode 100644 arch/arm/mach-exynos4/include/mach/spi-clocks.h
--
1.7.4.4
^ permalink raw reply
* [PATCH V2 1/2] ARM: EXYNOS4: Add SPI support
From: Padmavathi Venna @ 2011-10-10 8:08 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1318234084-19960-1-git-send-email-padma.v@samsung.com>
Define SPI platform devices.
Register SPI bus clock with clkdev using generic
connection id.
Signed-off-by: Padmavathi Venna <padma.v@samsung.com>
---
arch/arm/mach-exynos4/Kconfig | 1 +
arch/arm/mach-exynos4/Makefile | 1 +
arch/arm/mach-exynos4/clock.c | 82 +++++---
arch/arm/mach-exynos4/dev-spi.c | 225 ++++++++++++++++++++++
arch/arm/mach-exynos4/include/mach/irqs.h | 3 +
arch/arm/mach-exynos4/include/mach/map.h | 3 +
arch/arm/mach-exynos4/include/mach/spi-clocks.h | 16 ++
arch/arm/plat-samsung/include/plat/devs.h | 3 +
arch/arm/plat-samsung/include/plat/s3c64xx-spi.h | 1 +
9 files changed, 305 insertions(+), 30 deletions(-)
create mode 100644 arch/arm/mach-exynos4/dev-spi.c
create mode 100644 arch/arm/mach-exynos4/include/mach/spi-clocks.h
diff --git a/arch/arm/mach-exynos4/Kconfig b/arch/arm/mach-exynos4/Kconfig
index d0491c2..96b2511 100644
--- a/arch/arm/mach-exynos4/Kconfig
+++ b/arch/arm/mach-exynos4/Kconfig
@@ -154,6 +154,7 @@ config MACH_SMDKV310
select EXYNOS4_SETUP_KEYPAD
select EXYNOS4_SETUP_SDHCI
select EXYNOS4_SETUP_USB_PHY
+ select S3C64XX_DEV_SPI
help
Machine support for Samsung SMDKV310
diff --git a/arch/arm/mach-exynos4/Makefile b/arch/arm/mach-exynos4/Makefile
index e19cd12..7376869 100644
--- a/arch/arm/mach-exynos4/Makefile
+++ b/arch/arm/mach-exynos4/Makefile
@@ -43,6 +43,7 @@ obj-$(CONFIG_EXYNOS4_DEV_AHCI) += dev-ahci.o
obj-$(CONFIG_EXYNOS4_DEV_PD) += dev-pd.o
obj-$(CONFIG_EXYNOS4_DEV_SYSMMU) += dev-sysmmu.o
obj-$(CONFIG_EXYNOS4_DEV_DWMCI) += dev-dwmci.o
+obj-$(CONFIG_S3C64XX_DEV_SPI) += dev-spi.o
obj-$(CONFIG_EXYNOS4_SETUP_FIMC) += setup-fimc.o
obj-$(CONFIG_EXYNOS4_SETUP_FIMD0) += setup-fimd0.o
diff --git a/arch/arm/mach-exynos4/clock.c b/arch/arm/mach-exynos4/clock.c
index a25c818..2497176 100644
--- a/arch/arm/mach-exynos4/clock.c
+++ b/arch/arm/mach-exynos4/clock.c
@@ -1152,36 +1152,6 @@ static struct clksrc_clk clksrcs[] = {
.reg_div = { .reg = S5P_CLKDIV_LCD0, .shift = 0, .size = 4 },
}, {
.clk = {
- .name = "sclk_spi",
- .devname = "s3c64xx-spi.0",
- .enable = exynos4_clksrc_mask_peril1_ctrl,
- .ctrlbit = (1 << 16),
- },
- .sources = &clkset_group,
- .reg_src = { .reg = S5P_CLKSRC_PERIL1, .shift = 16, .size = 4 },
- .reg_div = { .reg = S5P_CLKDIV_PERIL1, .shift = 0, .size = 4 },
- }, {
- .clk = {
- .name = "sclk_spi",
- .devname = "s3c64xx-spi.1",
- .enable = exynos4_clksrc_mask_peril1_ctrl,
- .ctrlbit = (1 << 20),
- },
- .sources = &clkset_group,
- .reg_src = { .reg = S5P_CLKSRC_PERIL1, .shift = 20, .size = 4 },
- .reg_div = { .reg = S5P_CLKDIV_PERIL1, .shift = 16, .size = 4 },
- }, {
- .clk = {
- .name = "sclk_spi",
- .devname = "s3c64xx-spi.2",
- .enable = exynos4_clksrc_mask_peril1_ctrl,
- .ctrlbit = (1 << 24),
- },
- .sources = &clkset_group,
- .reg_src = { .reg = S5P_CLKSRC_PERIL1, .shift = 24, .size = 4 },
- .reg_div = { .reg = S5P_CLKDIV_PERIL2, .shift = 0, .size = 4 },
- }, {
- .clk = {
.name = "sclk_fimg2d",
},
.sources = &clkset_mout_g2d,
@@ -1242,6 +1212,53 @@ static struct clksrc_clk clksrcs[] = {
}
};
+static struct clksrc_clk sclk_spi0 = {
+ .clk = {
+ .name = "sclk_spi",
+ .devname = "s3c64xx-spi.0",
+ .enable = exynos4_clksrc_mask_peril1_ctrl,
+ .ctrlbit = (1 << 16),
+ },
+ .sources = &clkset_group,
+ .reg_src = { .reg = S5P_CLKSRC_PERIL1, .shift = 16, .size = 4 },
+ .reg_div = { .reg = S5P_CLKDIV_PERIL1, .shift = 0, .size = 4 },
+};
+
+static struct clksrc_clk sclk_spi1 = {
+ .clk = {
+ .name = "sclk_spi",
+ .devname = "s3c64xx-spi.1",
+ .enable = exynos4_clksrc_mask_peril1_ctrl,
+ .ctrlbit = (1 << 20),
+ },
+ .sources = &clkset_group,
+ .reg_src = { .reg = S5P_CLKSRC_PERIL1, .shift = 20, .size = 4 },
+ .reg_div = { .reg = S5P_CLKDIV_PERIL1, .shift = 16, .size = 4 },
+};
+static struct clksrc_clk sclk_spi2 = {
+ .clk = {
+ .name = "sclk_spi",
+ .devname = "s3c64xx-spi.2",
+ .enable = exynos4_clksrc_mask_peril1_ctrl,
+ .ctrlbit = (1 << 24),
+ },
+ .sources = &clkset_group,
+ .reg_src = { .reg = S5P_CLKSRC_PERIL1, .shift = 24, .size = 4 },
+ .reg_div = { .reg = S5P_CLKDIV_PERIL2, .shift = 0, .size = 4 },
+};
+
+static struct clk_lookup clk_lookup_table[] = {
+ CLKDEV_INIT("s3c64xx-spi.0", "spi_busclk0", &sclk_spi0.clk),
+ CLKDEV_INIT("s3c64xx-spi.1", "spi_busclk0", &sclk_spi1.clk),
+ CLKDEV_INIT("s3c64xx-spi.2", "spi_busclk0", &sclk_spi2.clk),
+};
+
+static struct clksrc_clk *clksrc_cdev[] = {
+ &sclk_spi0,
+ &sclk_spi1,
+ &sclk_spi2,
+};
+
/* Clock initialization code */
static struct clksrc_clk *sysclks[] = {
&clk_mout_apll,
@@ -1480,6 +1497,9 @@ void __init exynos4_register_clocks(void)
for (ptr = 0; ptr < ARRAY_SIZE(sysclks); ptr++)
s3c_register_clksrc(sysclks[ptr], 1);
+ for (ptr = 0; ptr < ARRAY_SIZE(clksrc_cdev); ptr++)
+ s3c_register_clksrc(clksrc_cdev[ptr], 1);
+
for (ptr = 0; ptr < ARRAY_SIZE(sclk_tv); ptr++)
s3c_register_clksrc(sclk_tv[ptr], 1);
@@ -1493,4 +1513,6 @@ void __init exynos4_register_clocks(void)
s3c24xx_register_clock(&dummy_apb_pclk);
s3c_pwmclk_init();
+
+ clkdev_add_table(clk_lookup_table, ARRAY_SIZE(clk_lookup_table));
}
diff --git a/arch/arm/mach-exynos4/dev-spi.c b/arch/arm/mach-exynos4/dev-spi.c
new file mode 100644
index 0000000..0c9704d
--- /dev/null
+++ b/arch/arm/mach-exynos4/dev-spi.c
@@ -0,0 +1,225 @@
+/* linux/arch/arm/mach-exynos4/dev-spi.c
+ *
+ * Copyright (C) 2011 Samsung Electronics Co. Ltd.
+ *
+ * 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
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/platform_device.h>
+#include <linux/dma-mapping.h>
+#include <linux/gpio.h>
+
+#include <mach/dma.h>
+#include <mach/map.h>
+#include <mach/irqs.h>
+#include <mach/spi-clocks.h>
+
+#include <plat/s3c64xx-spi.h>
+#include <plat/gpio-cfg.h>
+
+/* SPI Controller platform_devices */
+
+/* Since we emulate multi-cs capability, we do not touch the CS.
+ * The emulated CS is toggled by board specific mechanism, as it can
+ * be either some immediate GPIO or some signal out of some other
+ * chip in between ... or some yet another way.
+ * We simply do not assume anything about CS.
+ */
+static int exynos4_spi_cfg_gpio(struct platform_device *pdev)
+{
+ switch (pdev->id) {
+ case 0:
+ s3c_gpio_cfgpin(EXYNOS4_GPB(0), S3C_GPIO_SFN(2));
+ s3c_gpio_setpull(EXYNOS4_GPB(0), S3C_GPIO_PULL_UP);
+ s3c_gpio_cfgall_range(EXYNOS4_GPB(2), 2,
+ S3C_GPIO_SFN(2), S3C_GPIO_PULL_UP);
+ break;
+
+ case 1:
+ s3c_gpio_cfgpin(EXYNOS4_GPB(4), S3C_GPIO_SFN(2));
+ s3c_gpio_setpull(EXYNOS4_GPB(4), S3C_GPIO_PULL_UP);
+ s3c_gpio_cfgall_range(EXYNOS4_GPB(6), 2,
+ S3C_GPIO_SFN(2), S3C_GPIO_PULL_UP);
+ break;
+
+ case 2:
+ s3c_gpio_cfgpin(EXYNOS4_GPC1(1), S3C_GPIO_SFN(5));
+ s3c_gpio_setpull(EXYNOS4_GPC1(1), S3C_GPIO_PULL_UP);
+ s3c_gpio_cfgall_range(EXYNOS4_GPC1(3), 2,
+ S3C_GPIO_SFN(5), S3C_GPIO_PULL_UP);
+ break;
+
+ default:
+ dev_err(&pdev->dev, "Invalid SPI Controller number!");
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static struct resource exynos4_spi0_resource[] = {
+ [0] = {
+ .start = EXYNOS4_PA_SPI0,
+ .end = EXYNOS4_PA_SPI0 + 0x100 - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = DMACH_SPI0_TX,
+ .end = DMACH_SPI0_TX,
+ .flags = IORESOURCE_DMA,
+ },
+ [2] = {
+ .start = DMACH_SPI0_RX,
+ .end = DMACH_SPI0_RX,
+ .flags = IORESOURCE_DMA,
+ },
+ [3] = {
+ .start = IRQ_SPI0,
+ .end = IRQ_SPI0,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct s3c64xx_spi_info exynos4_spi0_pdata = {
+ .cfg_gpio = exynos4_spi_cfg_gpio,
+ .fifo_lvl_mask = 0x1ff,
+ .rx_lvl_offset = 15,
+ .high_speed = 1,
+ .clk_from_cmu = true,
+ .tx_st_done = 25,
+};
+
+static u64 spi_dmamask = DMA_BIT_MASK(32);
+
+struct platform_device exynos4_device_spi0 = {
+ .name = "s3c64xx-spi",
+ .id = 0,
+ .num_resources = ARRAY_SIZE(exynos4_spi0_resource),
+ .resource = exynos4_spi0_resource,
+ .dev = {
+ .dma_mask = &spi_dmamask,
+ .coherent_dma_mask = DMA_BIT_MASK(32),
+ .platform_data = &exynos4_spi0_pdata,
+ },
+};
+
+static struct resource exynos4_spi1_resource[] = {
+ [0] = {
+ .start = EXYNOS4_PA_SPI1,
+ .end = EXYNOS4_PA_SPI1 + 0x100 - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = DMACH_SPI1_TX,
+ .end = DMACH_SPI1_TX,
+ .flags = IORESOURCE_DMA,
+ },
+ [2] = {
+ .start = DMACH_SPI1_RX,
+ .end = DMACH_SPI1_RX,
+ .flags = IORESOURCE_DMA,
+ },
+ [3] = {
+ .start = IRQ_SPI1,
+ .end = IRQ_SPI1,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct s3c64xx_spi_info exynos4_spi1_pdata = {
+ .cfg_gpio = exynos4_spi_cfg_gpio,
+ .fifo_lvl_mask = 0x7f,
+ .rx_lvl_offset = 15,
+ .high_speed = 1,
+ .clk_from_cmu = true,
+ .tx_st_done = 25,
+};
+
+struct platform_device exynos4_device_spi1 = {
+ .name = "s3c64xx-spi",
+ .id = 1,
+ .num_resources = ARRAY_SIZE(exynos4_spi1_resource),
+ .resource = exynos4_spi1_resource,
+ .dev = {
+ .dma_mask = &spi_dmamask,
+ .coherent_dma_mask = DMA_BIT_MASK(32),
+ .platform_data = &exynos4_spi1_pdata,
+ },
+};
+
+static struct resource exynos4_spi2_resource[] = {
+ [0] = {
+ .start = EXYNOS4_PA_SPI2,
+ .end = EXYNOS4_PA_SPI2 + 0x100 - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = DMACH_SPI2_TX,
+ .end = DMACH_SPI2_TX,
+ .flags = IORESOURCE_DMA,
+ },
+ [2] = {
+ .start = DMACH_SPI2_RX,
+ .end = DMACH_SPI2_RX,
+ .flags = IORESOURCE_DMA,
+ },
+ [3] = {
+ .start = IRQ_SPI2,
+ .end = IRQ_SPI2,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct s3c64xx_spi_info exynos4_spi2_pdata = {
+ .cfg_gpio = exynos4_spi_cfg_gpio,
+ .fifo_lvl_mask = 0x7f,
+ .rx_lvl_offset = 15,
+ .high_speed = 1,
+ .clk_from_cmu = true,
+ .tx_st_done = 25,
+};
+
+struct platform_device exynos4_device_spi2 = {
+ .name = "s3c64xx-spi",
+ .id = 2,
+ .num_resources = ARRAY_SIZE(exynos4_spi2_resource),
+ .resource = exynos4_spi2_resource,
+ .dev = {
+ .dma_mask = &spi_dmamask,
+ .coherent_dma_mask = DMA_BIT_MASK(32),
+ .platform_data = &exynos4_spi2_pdata,
+ },
+};
+
+void __init exynos4_spi_set_info(int cntrlr, int src_clk_nr, int num_cs)
+{
+ struct s3c64xx_spi_info *pd;
+
+ /* Reject invalid configuration */
+ if (!num_cs || src_clk_nr < 0
+ || src_clk_nr > EXYNOS4_SPI_SRCCLK_SCLK) {
+ printk(KERN_ERR "%s: Invalid SPI configuration\n", __func__);
+ return;
+ }
+
+ switch (cntrlr) {
+ case 0:
+ pd = &exynos4_spi0_pdata;
+ break;
+ case 1:
+ pd = &exynos4_spi1_pdata;
+ break;
+ case 2:
+ pd = &exynos4_spi2_pdata;
+ break;
+ default:
+ printk(KERN_ERR "%s: Invalid SPI controller(%d)\n",
+ __func__, cntrlr);
+ return;
+ }
+
+ pd->num_cs = num_cs;
+ pd->src_clk_nr = src_clk_nr;
+}
diff --git a/arch/arm/mach-exynos4/include/mach/irqs.h b/arch/arm/mach-exynos4/include/mach/irqs.h
index 62093b9..a9f0341 100644
--- a/arch/arm/mach-exynos4/include/mach/irqs.h
+++ b/arch/arm/mach-exynos4/include/mach/irqs.h
@@ -70,6 +70,9 @@
#define IRQ_IIC5 IRQ_SPI(63)
#define IRQ_IIC6 IRQ_SPI(64)
#define IRQ_IIC7 IRQ_SPI(65)
+#define IRQ_SPI0 IRQ_SPI(66)
+#define IRQ_SPI1 IRQ_SPI(67)
+#define IRQ_SPI2 IRQ_SPI(68)
#define IRQ_USB_HOST IRQ_SPI(70)
#define IRQ_USB_HSOTG IRQ_SPI(71)
diff --git a/arch/arm/mach-exynos4/include/mach/map.h b/arch/arm/mach-exynos4/include/mach/map.h
index 1bea7d1..8dd509e 100644
--- a/arch/arm/mach-exynos4/include/mach/map.h
+++ b/arch/arm/mach-exynos4/include/mach/map.h
@@ -88,6 +88,9 @@
#define EXYNOS4_PA_SYSMMU_TV 0x12E20000
#define EXYNOS4_PA_SYSMMU_MFC_L 0x13620000
#define EXYNOS4_PA_SYSMMU_MFC_R 0x13630000
+#define EXYNOS4_PA_SPI0 0x13920000
+#define EXYNOS4_PA_SPI1 0x13930000
+#define EXYNOS4_PA_SPI2 0x13940000
#define EXYNOS4_PA_GPIO1 0x11400000
#define EXYNOS4_PA_GPIO2 0x11000000
diff --git a/arch/arm/mach-exynos4/include/mach/spi-clocks.h b/arch/arm/mach-exynos4/include/mach/spi-clocks.h
new file mode 100644
index 0000000..576efdf
--- /dev/null
+++ b/arch/arm/mach-exynos4/include/mach/spi-clocks.h
@@ -0,0 +1,16 @@
+/* linux/arch/arm/mach-exynos4/include/mach/spi-clocks.h
+ *
+ * Copyright (C) 2011 Samsung Electronics Co. Ltd.
+ *
+ * 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
+ * published by the Free Software Foundation.
+ */
+
+#ifndef __ASM_ARCH_SPI_CLKS_H
+#define __ASM_ARCH_SPI_CLKS_H __FILE__
+
+/* Must source from SCLK_SPI */
+#define EXYNOS4_SPI_SRCCLK_SCLK 0
+
+#endif /* __ASM_ARCH_SPI_CLKS_H */
diff --git a/arch/arm/plat-samsung/include/plat/devs.h b/arch/arm/plat-samsung/include/plat/devs.h
index ee5014a..7949131 100644
--- a/arch/arm/plat-samsung/include/plat/devs.h
+++ b/arch/arm/plat-samsung/include/plat/devs.h
@@ -84,6 +84,9 @@ extern struct platform_device s5pv210_device_spi0;
extern struct platform_device s5pv210_device_spi1;
extern struct platform_device s5p64x0_device_spi0;
extern struct platform_device s5p64x0_device_spi1;
+extern struct platform_device exynos4_device_spi0;
+extern struct platform_device exynos4_device_spi1;
+extern struct platform_device exynos4_device_spi2;
extern struct platform_device s3c_device_hwmon;
diff --git a/arch/arm/plat-samsung/include/plat/s3c64xx-spi.h b/arch/arm/plat-samsung/include/plat/s3c64xx-spi.h
index c3d82a5..1ec1ea3 100644
--- a/arch/arm/plat-samsung/include/plat/s3c64xx-spi.h
+++ b/arch/arm/plat-samsung/include/plat/s3c64xx-spi.h
@@ -69,5 +69,6 @@ extern void s3c64xx_spi_set_info(int cntrlr, int src_clk_nr, int num_cs);
extern void s5pc100_spi_set_info(int cntrlr, int src_clk_nr, int num_cs);
extern void s5pv210_spi_set_info(int cntrlr, int src_clk_nr, int num_cs);
extern void s5p64x0_spi_set_info(int cntrlr, int src_clk_nr, int num_cs);
+extern void exynos4_spi_set_info(int cntrlr, int src_clk_nr, int num_cs);
#endif /* __S3C64XX_PLAT_SPI_H */
--
1.7.4.4
^ permalink raw reply related
* [PATCH 0/3] ARM: Samsung: Add device tree support for GIC and Interrupt Combiner
From: Thomas Abraham @ 2011-10-10 8:11 UTC (permalink / raw)
To: linux-arm-kernel
This patchset adds device tree support for GIC and Interrupt Combiner modules
in Exynos4 SoC.
Patch 1 moves the statically mapped timer irqs 11 to 15 to the end of the
statically mapped linux irq space for all s5p platforms. This patch is
applicable for s5p64x0, s5pc100, s5pv210 and exynos4.
For all these platforms, the five hardware timer irqs are connected to GIC/VIC
at some hardware irq number (in exynos it is GIC_ID 69 to 73 for five timers).
When any of these hardware interrupt occurs, its interrupt handler calls
generic_handle_irq() with linux irq number 11/12/13/14/15 for timer 0/1/2/3/4
as the parameter. The code that needs to be notified about the timer interrupts
would have already registered its handler for either of the interrupts 11 to 15.
Instead of using linux irq number 11 to 15 to which consumers of timer interrupt
attach their handler, this interrupt range is moved to the end of linux irq
space used. So there will be no interrupts statically mapped between 0 to 31.
The GIC/VIC hardware interrupts, which were previously statically mapped to
start from linux irq 32 are now moved to start from linux irq 0. In case of
exynos, GIC_ID[0] (which is SGI[0]) which was previously at linux irq 32, will
not be at linux irq 0. This was required to use Rob Herring's GIC OF bindings
patches for Exynos4.
Patch 2 adds a interceptor for all ioremap calls targeted towards any of the
statically remapped memory region. This was required because the GIC OF
binding's patchset ioremaps the GIC memory-mapped regions in the gic_of_init()
function. Without this patch, there would be two separate remap for GIC
controller, one statically remapped and the other dynamically remapped by the
gic_of_init() function.
Patch 3 adds device tree support for GIC and Interrupt Combiner controllers on
Exynos4. For GIC controller, this patch is based on Rob Herring's,
"[PATCH 0/3] GIC OF bindings" patchset. The concept of irq domain for interrupt
combiner controller is based on Grant's 'simple' irq converter
This patchset is based on the following tree:
https://github.com/kgene/linux-samsung.git branch: for-next
Patch 1 is tested on smdk6450, smdkc100, smdkv210.
Patch 1 to 3 are tested on smdkv310.
Thomas Abraham (3):
arm: samsung: move timer irq numbers to end of linux irq space
ARM: Exynos4: Add ioremap interceptor for statically remapped regions
ARM: Exynos4: Add support for dt irq specifier to linux virq conversion
.../devicetree/bindings/irq/samsung-combiner.txt | 24 ++++++++++
arch/arm/mach-exynos4/cpu.c | 36 +++++++++++++++-
arch/arm/mach-exynos4/include/mach/entry-macro.S | 1 -
arch/arm/mach-exynos4/include/mach/io.h | 4 ++
arch/arm/mach-exynos4/include/mach/irqs.h | 3 +-
arch/arm/mach-exynos4/irq-combiner.c | 45 ++++++++++++++++++++
arch/arm/mach-s5p64x0/include/mach/irqs.h | 4 +-
arch/arm/mach-s5pc100/include/mach/irqs.h | 3 +-
arch/arm/mach-s5pv210/include/mach/irqs.h | 3 +-
arch/arm/plat-samsung/include/plat/irqs.h | 7 ++-
10 files changed, 117 insertions(+), 13 deletions(-)
create mode 100644 Documentation/devicetree/bindings/irq/samsung-combiner.txt
^ permalink raw reply
* [PATCH 1/3] ARM: Samsung: Move timer irq numbers to end of linux irq space
From: Thomas Abraham @ 2011-10-10 8:11 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1318234289-22041-1-git-send-email-thomas.abraham@linaro.org>
All of Samsung's s5p platforms have timer irqs statically mapped from linux
irq numbers 11 to 15. These timer irqs are moved to end of the statically
mapped linux irq space and the hardware irqs, which were statically mapped
starting from 32 is moved to start from 0. The NR_IRQS macro is consolidated
for all the s5p platforms in this process.
Signed-off-by: Thomas Abraham <thomas.abraham@linaro.org>
---
arch/arm/mach-exynos4/include/mach/entry-macro.S | 1 -
arch/arm/mach-exynos4/include/mach/irqs.h | 3 +--
arch/arm/mach-s5p64x0/include/mach/irqs.h | 4 +---
arch/arm/mach-s5pc100/include/mach/irqs.h | 3 +--
arch/arm/mach-s5pv210/include/mach/irqs.h | 3 +--
arch/arm/plat-samsung/include/plat/irqs.h | 7 +++++--
6 files changed, 9 insertions(+), 12 deletions(-)
diff --git a/arch/arm/mach-exynos4/include/mach/entry-macro.S b/arch/arm/mach-exynos4/include/mach/entry-macro.S
index 4c9adbd..5c4fbcc 100644
--- a/arch/arm/mach-exynos4/include/mach/entry-macro.S
+++ b/arch/arm/mach-exynos4/include/mach/entry-macro.S
@@ -72,7 +72,6 @@
cmpcc \irqnr, \irqnr
cmpne \irqnr, \tmp
cmpcs \irqnr, \irqnr
- addne \irqnr, \irqnr, #32
.endm
diff --git a/arch/arm/mach-exynos4/include/mach/irqs.h b/arch/arm/mach-exynos4/include/mach/irqs.h
index dfd4b7e..43087c3 100644
--- a/arch/arm/mach-exynos4/include/mach/irqs.h
+++ b/arch/arm/mach-exynos4/include/mach/irqs.h
@@ -163,7 +163,6 @@
#define IRQ_GPIO2_NR_GROUPS 9
#define IRQ_GPIO_END (S5P_GPIOINT_BASE + S5P_GPIOINT_COUNT)
-/* Set the default NR_IRQS */
-#define NR_IRQS (IRQ_GPIO_END + 64)
+#define IRQ_TIMER_BASE (IRQ_GPIO_END + 64)
#endif /* __ASM_ARCH_IRQS_H */
diff --git a/arch/arm/mach-s5p64x0/include/mach/irqs.h b/arch/arm/mach-s5p64x0/include/mach/irqs.h
index 53982db..bea73cc 100644
--- a/arch/arm/mach-s5p64x0/include/mach/irqs.h
+++ b/arch/arm/mach-s5p64x0/include/mach/irqs.h
@@ -141,8 +141,6 @@
#define IRQ_EINT_GROUP(grp, x) (IRQ_EINT_GROUP##grp##_BASE + (x))
-/* Set the default NR_IRQS */
-
-#define NR_IRQS (IRQ_EINT_GROUP8_BASE + IRQ_EINT_GROUP8_NR + 1)
+#define IRQ_TIMER_BASE (IRQ_EINT_GROUP8_BASE + IRQ_EINT_GROUP8_NR + 1)
#endif /* __ASM_ARCH_IRQS_H */
diff --git a/arch/arm/mach-s5pc100/include/mach/irqs.h b/arch/arm/mach-s5pc100/include/mach/irqs.h
index d2eb475..3a9d300 100644
--- a/arch/arm/mach-s5pc100/include/mach/irqs.h
+++ b/arch/arm/mach-s5pc100/include/mach/irqs.h
@@ -104,8 +104,7 @@
#define S5P_GPIOINT_BASE (IRQ_EINT(31) + 1)
#define S5P_GPIOINT_GROUP_MAXNR 21
-/* Set the default NR_IRQS */
-#define NR_IRQS (IRQ_EINT(31) + S5P_GPIOINT_COUNT + 1)
+#define IRQ_TIMER_BASE (IRQ_EINT(31) + S5P_GPIOINT_COUNT + 1)
/* Compatibility */
#define IRQ_LCD_FIFO IRQ_LCD0
diff --git a/arch/arm/mach-s5pv210/include/mach/irqs.h b/arch/arm/mach-s5pv210/include/mach/irqs.h
index 5e0de3a..df3173a 100644
--- a/arch/arm/mach-s5pv210/include/mach/irqs.h
+++ b/arch/arm/mach-s5pv210/include/mach/irqs.h
@@ -125,8 +125,7 @@
#define S5P_GPIOINT_BASE (IRQ_EINT(31) + 1)
#define S5P_GPIOINT_GROUP_MAXNR 22
-/* Set the default NR_IRQS */
-#define NR_IRQS (IRQ_EINT(31) + S5P_GPIOINT_COUNT + 1)
+#define IRQ_TIMER_BASE (IRQ_EINT(31) + S5P_GPIOINT_COUNT + 1)
/* Compatibility */
#define IRQ_LCD_FIFO IRQ_LCD0
diff --git a/arch/arm/plat-samsung/include/plat/irqs.h b/arch/arm/plat-samsung/include/plat/irqs.h
index 08d1a7e..b8918b3 100644
--- a/arch/arm/plat-samsung/include/plat/irqs.h
+++ b/arch/arm/plat-samsung/include/plat/irqs.h
@@ -22,7 +22,7 @@
* mulitple of 32 to allow the common code to work
*/
-#define S5P_IRQ_OFFSET (32)
+#define S5P_IRQ_OFFSET (0)
#define S5P_IRQ(x) ((x) + S5P_IRQ_OFFSET)
@@ -44,13 +44,14 @@
#define S5P_IRQ_VIC2(x) (S5P_VIC2_BASE + (x))
#define S5P_IRQ_VIC3(x) (S5P_VIC3_BASE + (x))
-#define S5P_TIMER_IRQ(x) (11 + (x))
+#define S5P_TIMER_IRQ(x) (IRQ_TIMER_BASE + (x))
#define IRQ_TIMER0 S5P_TIMER_IRQ(0)
#define IRQ_TIMER1 S5P_TIMER_IRQ(1)
#define IRQ_TIMER2 S5P_TIMER_IRQ(2)
#define IRQ_TIMER3 S5P_TIMER_IRQ(3)
#define IRQ_TIMER4 S5P_TIMER_IRQ(4)
+#define IRQ_TIMER_COUNT (5)
#define IRQ_EINT(x) ((x) < 16 ? ((x) + S5P_EINT_BASE1) \
: ((x) - 16 + S5P_EINT_BASE2))
@@ -77,4 +78,6 @@
#define S5P_IRQ_TYPE_EDGE_RISING (0x03)
#define S5P_IRQ_TYPE_EDGE_BOTH (0x04)
+#define NR_IRQS (IRQ_TIMER_BASE + IRQ_TIMER_COUNT)
+
#endif /* __PLAT_SAMSUNG_IRQS_H */
--
1.6.6.rc2
^ permalink raw reply related
* [PATCH 2/3] ARM: Exynos4: Add ioremap interceptor for statically remapped regions
From: Thomas Abraham @ 2011-10-10 8:11 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1318234289-22041-1-git-send-email-thomas.abraham@linaro.org>
ioremap() request for statically remapped regions are intercepted and the
statically assigned virtual address is returned. For requests for which
there are no statically remapped regions, the requests are let through.
Cc: Kukjin Kim <kgene.kim@samsung.com>
Signed-off-by: Thomas Abraham <thomas.abraham@linaro.org>
---
arch/arm/mach-exynos4/cpu.c | 16 ++++++++++++++++
arch/arm/mach-exynos4/include/mach/io.h | 4 ++++
2 files changed, 20 insertions(+), 0 deletions(-)
diff --git a/arch/arm/mach-exynos4/cpu.c b/arch/arm/mach-exynos4/cpu.c
index 5b1765b..358624d 100644
--- a/arch/arm/mach-exynos4/cpu.c
+++ b/arch/arm/mach-exynos4/cpu.c
@@ -137,6 +137,22 @@ static struct map_desc exynos4_iodesc1[] __initdata = {
},
};
+/*
+ * For all ioremap requests of statically mapped regions, intercept ioremap and
+ * return virtual address from the iodesc table.
+ */
+void __iomem *exynos4_ioremap(unsigned long phy, size_t size, unsigned int type)
+{
+ struct map_desc *desc = exynos4_iodesc;
+ unsigned int idx;
+
+ for (idx = 0; idx < ARRAY_SIZE(exynos4_iodesc); idx++, desc++)
+ if (desc->pfn == __phys_to_pfn(phy) && desc->type == type)
+ return (void __iomem *)desc->virtual;
+
+ return __arm_ioremap(phy, size, type);
+}
+
static void exynos4_idle(void)
{
if (!need_resched())
diff --git a/arch/arm/mach-exynos4/include/mach/io.h b/arch/arm/mach-exynos4/include/mach/io.h
index d5478d2..33c2890 100644
--- a/arch/arm/mach-exynos4/include/mach/io.h
+++ b/arch/arm/mach-exynos4/include/mach/io.h
@@ -22,5 +22,10 @@
#define __mem_pci(a) (a)
#define IO_SPACE_LIMIT (0xFFFFFFFF)
+#define __arch_ioremap exynos4_ioremap
+#define __arch_iounmap __iounmap
+
+void __iomem *exynos4_ioremap(unsigned long phy, size_t size,
+ unsigned int type);
#endif /* __ASM_ARM_ARCH_IO_H */
--
1.6.6.rc2
^ permalink raw reply related
* [PATCH 3/3] ARM: Exynos4: Add support for dt irq specifier to linux virq conversion
From: Thomas Abraham @ 2011-10-10 8:11 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1318234289-22041-1-git-send-email-thomas.abraham@linaro.org>
Add support for conversion of device tree interrupt specifier to linux
virq domain for GIC and Interrupt combiner controllers.
Signed-off-by: Thomas Abraham <thomas.abraham@linaro.org>
---
.../devicetree/bindings/irq/samsung-combiner.txt | 24 ++++++++++
arch/arm/mach-exynos4/cpu.c | 20 ++++++++-
arch/arm/mach-exynos4/irq-combiner.c | 45 ++++++++++++++++++++
3 files changed, 88 insertions(+), 1 deletions(-)
create mode 100644 Documentation/devicetree/bindings/irq/samsung-combiner.txt
diff --git a/Documentation/devicetree/bindings/irq/samsung-combiner.txt b/Documentation/devicetree/bindings/irq/samsung-combiner.txt
new file mode 100644
index 0000000..b7d5c30
--- /dev/null
+++ b/Documentation/devicetree/bindings/irq/samsung-combiner.txt
@@ -0,0 +1,24 @@
+* Exynos4 Interrupt Combiner Controller
+
+Samsung's Exynos4 architecture includes a interrupt combiner which
+can combine interrupt sources as a group and provide a single
+interrupt request for the group. The interrupt request from each
+group are connected to a parent interrupt controller, which is GIC
+in case of Exynos4.
+
+Required properties:
+- compatible: should be "samsung,exynos4-combiner".
+- interrupt-cells: should be <2>. The meaning of the cells are
+ * First Cell: Combiner Group Number.
+ * Second Cell: Interrupt within the group.
+- reg: Base address and size of interrupt combiner registers.
+- interrupt-controller: Identifies the node as an interrupt controller.
+
+Example:
+
+ combiner: interrupt-controller at 10440000 {
+ compatible = "samsung,exynos4-combiner";
+ #interrupt-cells = <2>;
+ interrupt-controller;
+ reg = <0x10440000 0x200>;
+ };
diff --git a/arch/arm/mach-exynos4/cpu.c b/arch/arm/mach-exynos4/cpu.c
index 358624d..776e8d4 100644
--- a/arch/arm/mach-exynos4/cpu.c
+++ b/arch/arm/mach-exynos4/cpu.c
@@ -10,6 +10,8 @@
#include <linux/sched.h>
#include <linux/sysdev.h>
+#include <linux/of.h>
+#include <linux/of_irq.h>
#include <asm/mach/map.h>
#include <asm/mach/irq.h>
@@ -38,6 +40,8 @@ unsigned int gic_bank_offset __read_mostly;
extern int combiner_init(unsigned int combiner_nr, void __iomem *base,
unsigned int irq_start);
extern void combiner_cascade_irq(unsigned int combiner_nr, unsigned int irq);
+extern void combiner_init_dt(struct device_node *node,
+ struct device_node *parent);
/* Initial IO mappings */
static struct map_desc exynos4_iodesc[] __initdata = {
@@ -229,13 +233,27 @@ static void exynos4_gic_irq_fix_base(struct irq_data *d)
(gic_bank_offset * smp_processor_id());
}
+#ifdef CONFIG_OF
+static const struct of_device_id exynos4_dt_irq_match[] = {
+ { .compatible = "arm,cortex-a9-gic", .data = gic_of_init, },
+ { .compatible = "samsung,exynos4-combiner", .data = combiner_init_dt, },
+ {},
+};
+#endif
+
void __init exynos4_init_irq(void)
{
int irq;
gic_bank_offset = soc_is_exynos4412() ? 0x4000 : 0x8000;
- gic_init(0, IRQ_PPI(0), S5P_VA_GIC_DIST, S5P_VA_GIC_CPU);
+#ifdef CONFIG_OF
+ if (of_have_populated_dt())
+ of_irq_init(exynos4_dt_irq_match);
+ else
+#endif
+ gic_init(0, IRQ_PPI(0), S5P_VA_GIC_DIST, S5P_VA_GIC_CPU);
+
gic_arch_extn.irq_eoi = exynos4_gic_irq_fix_base;
gic_arch_extn.irq_unmask = exynos4_gic_irq_fix_base;
gic_arch_extn.irq_mask = exynos4_gic_irq_fix_base;
diff --git a/arch/arm/mach-exynos4/irq-combiner.c b/arch/arm/mach-exynos4/irq-combiner.c
index 5a2758a..198bd0d 100644
--- a/arch/arm/mach-exynos4/irq-combiner.c
+++ b/arch/arm/mach-exynos4/irq-combiner.c
@@ -12,7 +12,12 @@
* published by the Free Software Foundation.
*/
+#include <linux/errno.h>
#include <linux/io.h>
+#include <linux/of.h>
+#include <linux/of_irq.h>
+#include <linux/irqdomain.h>
+#include <linux/slab.h>
#include <asm/mach/irq.h>
@@ -122,3 +127,43 @@ void __init combiner_init(unsigned int combiner_nr, void __iomem *base,
set_irq_flags(i, IRQF_VALID | IRQF_PROBE);
}
}
+
+#ifdef CONFIG_OF
+/* Translate dt irq specifier to linux virq for interrupt combiner controller */
+static int exynos4_irq_domain_combiner_dt_translate(struct irq_domain *d,
+ struct device_node *controller,
+ const u32 *intspec, unsigned int intsize,
+ unsigned long *out_hwirq, unsigned int *out_type)
+{
+ if (d->of_node != controller)
+ return -EINVAL;
+ if (intsize < 2)
+ return -EINVAL;
+
+ *out_hwirq = COMBINER_IRQ(intspec[0], intspec[1]);
+ *out_type = IRQ_TYPE_NONE;
+ return 0;
+}
+
+static struct irq_domain_ops exynos4_irq_domain_combiner_ops = {
+ .dt_translate = exynos4_irq_domain_combiner_dt_translate,
+};
+
+void __init combiner_init_dt(struct device_node *node,
+ struct device_node *parent)
+{
+ struct irq_domain *domain;
+
+ if (WARN(!node, "combiner_init_dt: invalid node in parameter\n"))
+ return;
+
+ domain = kzalloc(sizeof(*domain), GFP_KERNEL);
+ if (domain) {
+ domain->of_node = node;
+ domain->ops = &exynos4_irq_domain_combiner_ops;
+ irq_domain_add(domain);
+ } else {
+ WARN_ON(1);
+ }
+}
+#endif
--
1.6.6.rc2
^ permalink raw reply related
* [RFC][PATCH] plat-mxc: iomux-v3.h: implicitly enable pull-up/down when that's desired
From: Baruch Siach @ 2011-10-10 8:14 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <201110100758.p9A7wCYT011235@home.pavel.comp>
Hi Paul,
On Mon, Oct 10, 2011 at 11:19:23AM +0400, Paul Fertser wrote:
> To configure pads during the initialisation a set of special constants
> is used, e.g.
> #define MX25_PAD_FEC_MDIO__FEC_MDIO IOMUX_PAD(0x3c4, 0x1cc, 0x10, 0, 0, PAD_CTL_HYS | PAD_CTL_PUS_22K_UP)
>
> The problem is that no pull-up/down is getting activated unless both
> PAD_CTL_PUE (pull-up enable) and PAD_CTL_PKE (pull/keeper module
> enable) set. This is clearly stated in the i.MX25 datasheet and is
> confirmed by the measurements on hardware. This leads to some rather
> hard to understand bugs such as misdetecting an absent ethernet PHY (a
> real bug i had), unstable data transfer etc. This might affect mx25,
> mx35, mx50, mx51 and mx53 SoCs.
>
> It's reasonable to expect that if the pullup value is specified, the
> intention was to have it actually active, so we implicitly add the
> needed bits.
IMO, this patch should include the removal of the now redundant PAD_CTL_PKE
from arch/arm/plat-mxc/include/mach/iomux-mx25.h, and other v3 iomux headers.
baruch
> Cc: stable at kernel.org
> Signed-off-by: Paul Fertser <fercerpav@gmail.com>
> ---
>
> I'm not sure if that's really suitable for -stable so please excuse me
> if it's not. The issue looks real though and if you prefer fixing it
> any other way, please let me know. Sascha, if you think this's appropriate,
> i'll be happy to send the same fix for barebox.
>
> arch/arm/plat-mxc/include/mach/iomux-v3.h | 10 +++++-----
> 1 files changed, 5 insertions(+), 5 deletions(-)
>
> diff --git a/arch/arm/plat-mxc/include/mach/iomux-v3.h b/arch/arm/plat-mxc/include/mach/iomux-v3.h
> index ebbce33..4509956 100644
> --- a/arch/arm/plat-mxc/include/mach/iomux-v3.h
> +++ b/arch/arm/plat-mxc/include/mach/iomux-v3.h
> @@ -89,11 +89,11 @@ typedef u64 iomux_v3_cfg_t;
> #define PAD_CTL_HYS (1 << 8)
>
> #define PAD_CTL_PKE (1 << 7)
> -#define PAD_CTL_PUE (1 << 6)
> -#define PAD_CTL_PUS_100K_DOWN (0 << 4)
> -#define PAD_CTL_PUS_47K_UP (1 << 4)
> -#define PAD_CTL_PUS_100K_UP (2 << 4)
> -#define PAD_CTL_PUS_22K_UP (3 << 4)
> +#define PAD_CTL_PUE (1 << 6 | PAD_CTL_PKE)
> +#define PAD_CTL_PUS_100K_DOWN (0 << 4 | PAD_CTL_PUE)
> +#define PAD_CTL_PUS_47K_UP (1 << 4 | PAD_CTL_PUE)
> +#define PAD_CTL_PUS_100K_UP (2 << 4 | PAD_CTL_PUE)
> +#define PAD_CTL_PUS_22K_UP (3 << 4 | PAD_CTL_PUE)
>
> #define PAD_CTL_ODE (1 << 3)
--
~. .~ Tk Open Systems
=}------------------------------------------------ooO--U--Ooo------------{=
- baruch@tkos.co.il - tel: +972.2.679.5364, http://www.tkos.co.il -
^ permalink raw reply
* [PATCH 2/2] pinmux: add a driver for the U300 pinmux
From: Linus Walleij @ 2011-10-10 8:17 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <CAGsJ_4yKzyFzJwKgA2nkUf6z2fYoQLB48SOJR82DyAvcut7khQ@mail.gmail.com>
On Sat, Oct 8, 2011 at 11:09 AM, Barry Song <21cnbao@gmail.com> wrote:
>> +static void __init u300_pmx_dumpregs(struct u300_pmx *upmx)
>> +{
>> + ? ? ? u16 regval;
>> + ? ? ? int i;
>> +
>> + ? ? ? for (i = 0; i < ARRAY_SIZE(u300_pmx_registers); i++) {
>> + ? ? ? ? ? ? ? regval = readw(upmx->virtbase + u300_pmx_registers[i]);
>> + ? ? ? ? ? ? ? dev_info(upmx->dev, "PMX%u: 0x%04x\n", i, regval);
>> + ? ? ? }
>> +}
>
> is this a debug information or do you want it to be in mainline?
Debug info, I'll delete it. Not that it hurt, but I'll kill it.
>> + /* Create state holders etc for this driver */
>> + upmx = devm_kzalloc(&pdev->dev, sizeof(struct u300_pmx), GFP_KERNEL);
>
> and this would be "devm_kzalloc(&pdev->dev, sizeof(*upmx), GFP_KERNEL); " ?
Same semantic effect, but if you prefer it that way, sure :-)
I've seen both used in the kernel before...
Can I have your Reviewed-by: tag after this?
Linus Walleij
^ permalink raw reply
* [PATCH 2/2] pinmux: add a driver for the U300 pinmux
From: Linus Walleij @ 2011-10-10 8:18 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <15e5a354.4381.132e6876087.Coremail.hongjiujing@126.com>
2011/10/9 tommy.hong <hongjiujing@126.com>:
> [Barry]
>>is?this?a?debug?information?or?do?you?want?it?to?be?in?mainline?
>>
> Hi,Barry,should dumpregs function need "CONFIG_XXX_DEBUG" when probe ?and if
> driver meet some issue or error,we can use dumpregs to trace?
You can add any debug stuff you want if it helps development
and/or transparance of the driver, but this stuff I just deleted, it
is not needed anymore. I just used it to figure out the default
reset-values of the registers.
Yours,
Linus Walleij
^ permalink raw reply
* [PATCH 1/4] mmc: mmci: Bugfix in pio read for small packets
From: Ulf Hansson @ 2011-10-10 8:23 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <CACRpkdY=DFW+J_pQetK38mPqic2iBuDWCx5QZTo-NkL1L37Fuw@mail.gmail.com>
Linus Walleij wrote:
> On Sat, Oct 8, 2011 at 11:10 AM, Russell King - ARM Linux
> <linux@arm.linux.org.uk> wrote:
>> On Fri, Oct 07, 2011 at 03:45:48PM +0200, Ulf Hansson wrote:
>>
>> Well, the patch system says that each one depends on the previous one,
>> and the first one in the series contains the PIO read thing.
>>
>> Do 7108/1 onwards depend on 7106/1 and 7107/1 ?
>
> Probably my fault, since I was helping Ulf out with the patch tracker
> introduction.
>
> The patches should be pretty much semantically orthogonal as
> far as I can tell, the only reason dependency was stated that way
> was that I couldn't tell from head-parsing whether there were
> syntactical dependencies. (And wanted to avoid the annoyance
> of non-applying patches...)
>
> So if they apply, they are independent AFAICT.
7108/1 and 7109/1, have real dependencies. Otherwise there none.
BR
Ulf Hansson
^ permalink raw reply
* [PATCH 1/2] drivers: create a pin control subsystem v9
From: Linus Walleij @ 2011-10-10 8:23 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20111009093651.GC24198@S2100-06.ap.freescale.net>
On Sun, Oct 9, 2011 at 11:36 AM, Shawn Guo <shawn.guo@freescale.com> wrote:
>> + * @hog_on_boot: if this is set to true, the regulator subsystem will itself
> ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?^^^^^^^^^
> s/regulator/pinmux?
Yep!
>> +#endif /* !CONFIG_PINCTRL */
>
> s/!CONFIG_PINCTRL/CONFIG_PINMUX?
Yep!
Foldes into original patch with a fixup comment.
Can I have your Reviewed-by: tag on this subsystem?
Yours,
Linus Walleij
^ permalink raw reply
* [PATCH v10] pinctrl: add a driver for the U300 pinmux
From: Linus Walleij @ 2011-10-10 8:31 UTC (permalink / raw)
To: linux-arm-kernel
From: Linus Walleij <linus.walleij@linaro.org>
This adds a driver for the U300 pinmux portions of the system
controller "SYSCON". It also serves as an example of how to use
the pinmux subsystem. This driver also houses the platform data
for the only supported platform.
This deletes the old U300 driver in arch/arm/mach-u300 and
replace it with a driver using the new subsystem.
The new driver is considerably fatter than the old one, but it
also registers all 467 pins of the system and adds the power
and EMIF pin groups and corresponding functions. The idea
is to use this driver as a a reference for other
implementation so it needs to be as complete and verbose
as possible.
Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
---
ChangeLog v9 -> v10
- Removed debug register dump (review from Barry Song)
- Allocate sizeof(*ptr) instead of sizeof(struct foo)
---
arch/arm/mach-u300/Kconfig | 2 +
arch/arm/mach-u300/Makefile | 2 +-
arch/arm/mach-u300/core.c | 84 +++-
arch/arm/mach-u300/include/mach/syscon.h | 136 ----
arch/arm/mach-u300/mmc.c | 16 -
arch/arm/mach-u300/padmux.c | 367 ----------
arch/arm/mach-u300/padmux.h | 39 -
arch/arm/mach-u300/spi.c | 20 -
drivers/pinctrl/Kconfig | 7 +
drivers/pinctrl/Makefile | 1 +
drivers/pinctrl/pinmux-u300.c | 1135 ++++++++++++++++++++++++++++++
11 files changed, 1228 insertions(+), 581 deletions(-)
delete mode 100644 arch/arm/mach-u300/padmux.c
delete mode 100644 arch/arm/mach-u300/padmux.h
create mode 100644 drivers/pinctrl/pinmux-u300.c
diff --git a/arch/arm/mach-u300/Kconfig b/arch/arm/mach-u300/Kconfig
index 32a7b0f..449fd6a 100644
--- a/arch/arm/mach-u300/Kconfig
+++ b/arch/arm/mach-u300/Kconfig
@@ -6,6 +6,8 @@ comment "ST-Ericsson Mobile Platform Products"
config MACH_U300
bool "U300"
+ select PINCTRL
+ select PINMUX_U300
comment "ST-Ericsson U300/U330/U335/U365 Feature Selections"
diff --git a/arch/arm/mach-u300/Makefile b/arch/arm/mach-u300/Makefile
index 8fd354a..2855381 100644
--- a/arch/arm/mach-u300/Makefile
+++ b/arch/arm/mach-u300/Makefile
@@ -2,7 +2,7 @@
# Makefile for the linux kernel, U300 machine.
#
-obj-y := core.o clock.o timer.o padmux.o
+obj-y := core.o clock.o timer.o
obj-m :=
obj-n :=
obj- :=
diff --git a/arch/arm/mach-u300/core.c b/arch/arm/mach-u300/core.c
index 399c89f..2f5929b 100644
--- a/arch/arm/mach-u300/core.c
+++ b/arch/arm/mach-u300/core.c
@@ -25,6 +25,8 @@
#include <linux/err.h>
#include <linux/mtd/nand.h>
#include <linux/mtd/fsmc.h>
+#include <linux/pinctrl/machine.h>
+#include <linux/pinctrl/pinmux.h>
#include <asm/types.h>
#include <asm/setup.h>
@@ -1535,6 +1537,14 @@ static struct coh901318_platform coh901318_platform = {
.max_channels = U300_DMA_CHANNELS,
};
+static struct resource pinmux_resources[] = {
+ {
+ .start = U300_SYSCON_BASE,
+ .end = U300_SYSCON_BASE + SZ_4K - 1,
+ .flags = IORESOURCE_MEM,
+ },
+};
+
static struct platform_device wdog_device = {
.name = "coh901327_wdog",
.id = -1,
@@ -1630,6 +1640,72 @@ static struct platform_device dma_device = {
},
};
+static struct platform_device pinmux_device = {
+ .name = "pinmux-u300",
+ .id = -1,
+ .num_resources = ARRAY_SIZE(pinmux_resources),
+ .resource = pinmux_resources,
+};
+
+/* Pinmux settings */
+static struct pinmux_map u300_pinmux_map[] = {
+ /* anonymous maps for chip power and EMIFs */
+ PINMUX_MAP_PRIMARY_SYS_HOG("POWER", "power"),
+ PINMUX_MAP_PRIMARY_SYS_HOG("EMIF0", "emif0"),
+ PINMUX_MAP_PRIMARY_SYS_HOG("EMIF1", "emif1"),
+ /* per-device maps for MMC/SD, SPI and UART */
+ PINMUX_MAP_PRIMARY("MMCSD", "mmc0", "mmci"),
+ PINMUX_MAP_PRIMARY("SPI", "spi0", "pl022"),
+ PINMUX_MAP_PRIMARY("UART0", "uart0", "uart0"),
+};
+
+struct u300_mux_hog {
+ const char *name;
+ struct device *dev;
+ struct pinmux *pmx;
+};
+
+static struct u300_mux_hog u300_mux_hogs[] = {
+ {
+ .name = "uart0",
+ .dev = &uart0_device.dev,
+ },
+ {
+ .name = "spi0",
+ .dev = &pl022_device.dev,
+ },
+ {
+ .name = "mmc0",
+ .dev = &mmcsd_device.dev,
+ },
+};
+
+static int __init u300_pinmux_fetch(void)
+{
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(u300_mux_hogs); i++) {
+ struct pinmux *pmx;
+ int ret;
+
+ pmx = pinmux_get(u300_mux_hogs[i].dev, NULL);
+ if (IS_ERR(pmx)) {
+ pr_err("u300: could not get pinmux hog %s\n",
+ u300_mux_hogs[i].name);
+ continue;
+ }
+ ret = pinmux_enable(pmx);
+ if (ret) {
+ pr_err("u300: could enable pinmux hog %s\n",
+ u300_mux_hogs[i].name);
+ continue;
+ }
+ u300_mux_hogs[i].pmx = pmx;
+ }
+ return 0;
+}
+subsys_initcall(u300_pinmux_fetch);
+
/*
* Notice that AMBA devices are initialized before platform devices.
*
@@ -1643,10 +1719,10 @@ static struct platform_device *platform_devs[] __initdata = {
&gpio_device,
&nand_device,
&wdog_device,
- &ave_device
+ &ave_device,
+ &pinmux_device,
};
-
/*
* Interrupts: the U300 platforms have two pl190 ARM PrimeCells connected
* together so some interrupts are connected to the first one and some
@@ -1828,6 +1904,10 @@ void __init u300_init_devices(void)
u300_assign_physmem();
+ /* Initialize pinmuxing */
+ pinmux_register_mappings(u300_pinmux_map,
+ ARRAY_SIZE(u300_pinmux_map));
+
/* Register subdevices on the I2C buses */
u300_i2c_register_board_devices();
diff --git a/arch/arm/mach-u300/include/mach/syscon.h b/arch/arm/mach-u300/include/mach/syscon.h
index 7444f5c..6e84f07 100644
--- a/arch/arm/mach-u300/include/mach/syscon.h
+++ b/arch/arm/mach-u300/include/mach/syscon.h
@@ -234,91 +234,6 @@
#define U300_SYSCON_ECCR_EMIF_1_RET_OUT_CLK_EN_N_DISABLE (0x0004)
#define U300_SYSCON_ECCR_EMIF_MEMCLK_RET_EN_N_DISABLE (0x0002)
#define U300_SYSCON_ECCR_EMIF_SDRCLK_RET_EN_N_DISABLE (0x0001)
-/* PAD MUX Control register 1 (LOW) 16bit (R/W) */
-#define U300_SYSCON_PMC1LR (0x007C)
-#define U300_SYSCON_PMC1LR_MASK (0xFFFF)
-#define U300_SYSCON_PMC1LR_CDI_MASK (0xC000)
-#define U300_SYSCON_PMC1LR_CDI_CDI (0x0000)
-#define U300_SYSCON_PMC1LR_CDI_EMIF (0x4000)
-#ifdef CONFIG_MACH_U300_BS335
-#define U300_SYSCON_PMC1LR_CDI_CDI2 (0x8000)
-#define U300_SYSCON_PMC1LR_CDI_WCDMA_APP_GPIO (0xC000)
-#elif CONFIG_MACH_U300_BS365
-#define U300_SYSCON_PMC1LR_CDI_GPIO (0x8000)
-#define U300_SYSCON_PMC1LR_CDI_WCDMA (0xC000)
-#endif
-#define U300_SYSCON_PMC1LR_PDI_MASK (0x3000)
-#define U300_SYSCON_PMC1LR_PDI_PDI (0x0000)
-#define U300_SYSCON_PMC1LR_PDI_EGG (0x1000)
-#define U300_SYSCON_PMC1LR_PDI_WCDMA (0x3000)
-#define U300_SYSCON_PMC1LR_MMCSD_MASK (0x0C00)
-#define U300_SYSCON_PMC1LR_MMCSD_MMCSD (0x0000)
-#define U300_SYSCON_PMC1LR_MMCSD_MSPRO (0x0400)
-#define U300_SYSCON_PMC1LR_MMCSD_DSP (0x0800)
-#define U300_SYSCON_PMC1LR_MMCSD_WCDMA (0x0C00)
-#define U300_SYSCON_PMC1LR_ETM_MASK (0x0300)
-#define U300_SYSCON_PMC1LR_ETM_ACC (0x0000)
-#define U300_SYSCON_PMC1LR_ETM_APP (0x0100)
-#define U300_SYSCON_PMC1LR_EMIF_1_CS2_MASK (0x00C0)
-#define U300_SYSCON_PMC1LR_EMIF_1_CS2_STATIC (0x0000)
-#define U300_SYSCON_PMC1LR_EMIF_1_CS2_NFIF (0x0040)
-#define U300_SYSCON_PMC1LR_EMIF_1_CS2_SDRAM (0x0080)
-#define U300_SYSCON_PMC1LR_EMIF_1_CS2_STATIC_2GB (0x00C0)
-#define U300_SYSCON_PMC1LR_EMIF_1_CS1_MASK (0x0030)
-#define U300_SYSCON_PMC1LR_EMIF_1_CS1_STATIC (0x0000)
-#define U300_SYSCON_PMC1LR_EMIF_1_CS1_NFIF (0x0010)
-#define U300_SYSCON_PMC1LR_EMIF_1_CS1_SDRAM (0x0020)
-#define U300_SYSCON_PMC1LR_EMIF_1_CS1_SEMI (0x0030)
-#define U300_SYSCON_PMC1LR_EMIF_1_CS0_MASK (0x000C)
-#define U300_SYSCON_PMC1LR_EMIF_1_CS0_STATIC (0x0000)
-#define U300_SYSCON_PMC1LR_EMIF_1_CS0_NFIF (0x0004)
-#define U300_SYSCON_PMC1LR_EMIF_1_CS0_SDRAM (0x0008)
-#define U300_SYSCON_PMC1LR_EMIF_1_CS0_SEMI (0x000C)
-#define U300_SYSCON_PMC1LR_EMIF_1_MASK (0x0003)
-#define U300_SYSCON_PMC1LR_EMIF_1_STATIC (0x0000)
-#define U300_SYSCON_PMC1LR_EMIF_1_SDRAM0 (0x0001)
-#define U300_SYSCON_PMC1LR_EMIF_1_SDRAM1 (0x0002)
-#define U300_SYSCON_PMC1LR_EMIF_1 (0x0003)
-/* PAD MUX Control register 2 (HIGH) 16bit (R/W) */
-#define U300_SYSCON_PMC1HR (0x007E)
-#define U300_SYSCON_PMC1HR_MASK (0xFFFF)
-#define U300_SYSCON_PMC1HR_MISC_2_MASK (0xC000)
-#define U300_SYSCON_PMC1HR_MISC_2_APP_GPIO (0x0000)
-#define U300_SYSCON_PMC1HR_MISC_2_MSPRO (0x4000)
-#define U300_SYSCON_PMC1HR_MISC_2_DSP (0x8000)
-#define U300_SYSCON_PMC1HR_MISC_2_AAIF (0xC000)
-#define U300_SYSCON_PMC1HR_APP_GPIO_2_MASK (0x3000)
-#define U300_SYSCON_PMC1HR_APP_GPIO_2_APP_GPIO (0x0000)
-#define U300_SYSCON_PMC1HR_APP_GPIO_2_NFIF (0x1000)
-#define U300_SYSCON_PMC1HR_APP_GPIO_2_DSP (0x2000)
-#define U300_SYSCON_PMC1HR_APP_GPIO_2_AAIF (0x3000)
-#define U300_SYSCON_PMC1HR_APP_GPIO_1_MASK (0x0C00)
-#define U300_SYSCON_PMC1HR_APP_GPIO_1_APP_GPIO (0x0000)
-#define U300_SYSCON_PMC1HR_APP_GPIO_1_MMC (0x0400)
-#define U300_SYSCON_PMC1HR_APP_GPIO_1_DSP (0x0800)
-#define U300_SYSCON_PMC1HR_APP_GPIO_1_AAIF (0x0C00)
-#define U300_SYSCON_PMC1HR_APP_SPI_CS_2_MASK (0x0300)
-#define U300_SYSCON_PMC1HR_APP_SPI_CS_2_APP_GPIO (0x0000)
-#define U300_SYSCON_PMC1HR_APP_SPI_CS_2_SPI (0x0100)
-#define U300_SYSCON_PMC1HR_APP_SPI_CS_2_AAIF (0x0300)
-#define U300_SYSCON_PMC1HR_APP_SPI_CS_1_MASK (0x00C0)
-#define U300_SYSCON_PMC1HR_APP_SPI_CS_1_APP_GPIO (0x0000)
-#define U300_SYSCON_PMC1HR_APP_SPI_CS_1_SPI (0x0040)
-#define U300_SYSCON_PMC1HR_APP_SPI_CS_1_AAIF (0x00C0)
-#define U300_SYSCON_PMC1HR_APP_SPI_2_MASK (0x0030)
-#define U300_SYSCON_PMC1HR_APP_SPI_2_APP_GPIO (0x0000)
-#define U300_SYSCON_PMC1HR_APP_SPI_2_SPI (0x0010)
-#define U300_SYSCON_PMC1HR_APP_SPI_2_DSP (0x0020)
-#define U300_SYSCON_PMC1HR_APP_SPI_2_AAIF (0x0030)
-#define U300_SYSCON_PMC1HR_APP_UART0_2_MASK (0x000C)
-#define U300_SYSCON_PMC1HR_APP_UART0_2_APP_GPIO (0x0000)
-#define U300_SYSCON_PMC1HR_APP_UART0_2_UART0 (0x0004)
-#define U300_SYSCON_PMC1HR_APP_UART0_2_NFIF_CS (0x0008)
-#define U300_SYSCON_PMC1HR_APP_UART0_2_AAIF (0x000C)
-#define U300_SYSCON_PMC1HR_APP_UART0_1_MASK (0x0003)
-#define U300_SYSCON_PMC1HR_APP_UART0_1_APP_GPIO (0x0000)
-#define U300_SYSCON_PMC1HR_APP_UART0_1_UART0 (0x0001)
-#define U300_SYSCON_PMC1HR_APP_UART0_1_AAIF (0x0003)
/* Step one for killing the applications system 16bit (-/W) */
#define U300_SYSCON_KA1R (0x0080)
#define U300_SYSCON_KA1R_MASK (0xFFFF)
@@ -357,57 +272,6 @@
#define U300_SYSCON_PUCR_EMIF_1_16BIT_PU_ENABLE (0x0080)
#define U300_SYSCON_PUCR_EMIF_1_8BIT_PU_ENABLE (0x0040)
#define U300_SYSCON_PUCR_KEY_IN_PU_EN_MASK (0x003F)
-/* Padmux 2 control */
-#define U300_SYSCON_PMC2R (0x100)
-#define U300_SYSCON_PMC2R_APP_MISC_0_MASK (0x00C0)
-#define U300_SYSCON_PMC2R_APP_MISC_0_APP_GPIO (0x0000)
-#define U300_SYSCON_PMC2R_APP_MISC_0_EMIF_SDRAM (0x0040)
-#define U300_SYSCON_PMC2R_APP_MISC_0_MMC (0x0080)
-#define U300_SYSCON_PMC2R_APP_MISC_0_CDI2 (0x00C0)
-#define U300_SYSCON_PMC2R_APP_MISC_1_MASK (0x0300)
-#define U300_SYSCON_PMC2R_APP_MISC_1_APP_GPIO (0x0000)
-#define U300_SYSCON_PMC2R_APP_MISC_1_EMIF_SDRAM (0x0100)
-#define U300_SYSCON_PMC2R_APP_MISC_1_MMC (0x0200)
-#define U300_SYSCON_PMC2R_APP_MISC_1_CDI2 (0x0300)
-#define U300_SYSCON_PMC2R_APP_MISC_2_MASK (0x0C00)
-#define U300_SYSCON_PMC2R_APP_MISC_2_APP_GPIO (0x0000)
-#define U300_SYSCON_PMC2R_APP_MISC_2_EMIF_SDRAM (0x0400)
-#define U300_SYSCON_PMC2R_APP_MISC_2_MMC (0x0800)
-#define U300_SYSCON_PMC2R_APP_MISC_2_CDI2 (0x0C00)
-#define U300_SYSCON_PMC2R_APP_MISC_3_MASK (0x3000)
-#define U300_SYSCON_PMC2R_APP_MISC_3_APP_GPIO (0x0000)
-#define U300_SYSCON_PMC2R_APP_MISC_3_EMIF_SDRAM (0x1000)
-#define U300_SYSCON_PMC2R_APP_MISC_3_MMC (0x2000)
-#define U300_SYSCON_PMC2R_APP_MISC_3_CDI2 (0x3000)
-#define U300_SYSCON_PMC2R_APP_MISC_4_MASK (0xC000)
-#define U300_SYSCON_PMC2R_APP_MISC_4_APP_GPIO (0x0000)
-#define U300_SYSCON_PMC2R_APP_MISC_4_EMIF_SDRAM (0x4000)
-#define U300_SYSCON_PMC2R_APP_MISC_4_MMC (0x8000)
-#define U300_SYSCON_PMC2R_APP_MISC_4_ACC_GPIO (0xC000)
-/* TODO: More SYSCON registers missing */
-#define U300_SYSCON_PMC3R (0x10c)
-#define U300_SYSCON_PMC3R_APP_MISC_11_MASK (0xc000)
-#define U300_SYSCON_PMC3R_APP_MISC_11_SPI (0x4000)
-#define U300_SYSCON_PMC3R_APP_MISC_10_MASK (0x3000)
-#define U300_SYSCON_PMC3R_APP_MISC_10_SPI (0x1000)
-/* TODO: Missing other configs */
-#define U300_SYSCON_PMC4R (0x168)
-#define U300_SYSCON_PMC4R_APP_MISC_12_MASK (0x0003)
-#define U300_SYSCON_PMC4R_APP_MISC_12_APP_GPIO (0x0000)
-#define U300_SYSCON_PMC4R_APP_MISC_13_MASK (0x000C)
-#define U300_SYSCON_PMC4R_APP_MISC_13_CDI (0x0000)
-#define U300_SYSCON_PMC4R_APP_MISC_13_SMIA (0x0004)
-#define U300_SYSCON_PMC4R_APP_MISC_13_SMIA2 (0x0008)
-#define U300_SYSCON_PMC4R_APP_MISC_13_APP_GPIO (0x000C)
-#define U300_SYSCON_PMC4R_APP_MISC_14_MASK (0x0030)
-#define U300_SYSCON_PMC4R_APP_MISC_14_CDI (0x0000)
-#define U300_SYSCON_PMC4R_APP_MISC_14_SMIA (0x0010)
-#define U300_SYSCON_PMC4R_APP_MISC_14_CDI2 (0x0020)
-#define U300_SYSCON_PMC4R_APP_MISC_14_APP_GPIO (0x0030)
-#define U300_SYSCON_PMC4R_APP_MISC_16_MASK (0x0300)
-#define U300_SYSCON_PMC4R_APP_MISC_16_APP_GPIO_13 (0x0000)
-#define U300_SYSCON_PMC4R_APP_MISC_16_APP_UART1_CTS (0x0100)
-#define U300_SYSCON_PMC4R_APP_MISC_16_EMIF_1_STATIC_CS5_N (0x0200)
/* SYS_0_CLK_CONTROL first clock control 16bit (R/W) */
#define U300_SYSCON_S0CCR (0x120)
#define U300_SYSCON_S0CCR_FIELD_MASK (0x43FF)
diff --git a/arch/arm/mach-u300/mmc.c b/arch/arm/mach-u300/mmc.c
index 677ccef..d5e4a98 100644
--- a/arch/arm/mach-u300/mmc.c
+++ b/arch/arm/mach-u300/mmc.c
@@ -21,7 +21,6 @@
#include <mach/dma_channels.h>
#include "mmc.h"
-#include "padmux.h"
static struct mmci_platform_data mmc0_plat_data = {
/*
@@ -45,24 +44,9 @@ static struct mmci_platform_data mmc0_plat_data = {
int __devinit mmc_init(struct amba_device *adev)
{
struct device *mmcsd_device = &adev->dev;
- struct pmx *pmx;
int ret = 0;
mmcsd_device->platform_data = &mmc0_plat_data;
- /*
- * Setup padmuxing for MMC. Since this must always be
- * compiled into the kernel, pmx is never released.
- */
- pmx = pmx_get(mmcsd_device, U300_APP_PMX_MMC_SETTING);
-
- if (IS_ERR(pmx))
- pr_warning("Could not get padmux handle\n");
- else {
- ret = pmx_activate(mmcsd_device, pmx);
- if (IS_ERR_VALUE(ret))
- pr_warning("Could not activate padmuxing\n");
- }
-
return ret;
}
diff --git a/arch/arm/mach-u300/padmux.c b/arch/arm/mach-u300/padmux.c
deleted file mode 100644
index 4c93c6c..0000000
--- a/arch/arm/mach-u300/padmux.c
+++ /dev/null
@@ -1,367 +0,0 @@
-/*
- *
- * arch/arm/mach-u300/padmux.c
- *
- *
- * Copyright (C) 2009 ST-Ericsson AB
- * License terms: GNU General Public License (GPL) version 2
- * U300 PADMUX functions
- * Author: Martin Persson <martin.persson@stericsson.com>
- */
-
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/device.h>
-#include <linux/err.h>
-#include <linux/errno.h>
-#include <linux/io.h>
-#include <linux/mutex.h>
-#include <linux/string.h>
-#include <linux/bug.h>
-#include <linux/debugfs.h>
-#include <linux/seq_file.h>
-#include <mach/u300-regs.h>
-#include <mach/syscon.h>
-#include "padmux.h"
-
-static DEFINE_MUTEX(pmx_mutex);
-
-const u32 pmx_registers[] = {
- (U300_SYSCON_VBASE + U300_SYSCON_PMC1LR),
- (U300_SYSCON_VBASE + U300_SYSCON_PMC1HR),
- (U300_SYSCON_VBASE + U300_SYSCON_PMC2R),
- (U300_SYSCON_VBASE + U300_SYSCON_PMC3R),
- (U300_SYSCON_VBASE + U300_SYSCON_PMC4R)
-};
-
-/* High level functionality */
-
-/* Lazy dog:
- * onmask = {
- * {"PMC1LR" mask, "PMC1LR" value},
- * {"PMC1HR" mask, "PMC1HR" value},
- * {"PMC2R" mask, "PMC2R" value},
- * {"PMC3R" mask, "PMC3R" value},
- * {"PMC4R" mask, "PMC4R" value}
- * }
- */
-static struct pmx mmc_setting = {
- .setting = U300_APP_PMX_MMC_SETTING,
- .default_on = false,
- .activated = false,
- .name = "MMC",
- .onmask = {
- {U300_SYSCON_PMC1LR_MMCSD_MASK,
- U300_SYSCON_PMC1LR_MMCSD_MMCSD},
- {0, 0},
- {0, 0},
- {0, 0},
- {U300_SYSCON_PMC4R_APP_MISC_12_MASK,
- U300_SYSCON_PMC4R_APP_MISC_12_APP_GPIO}
- },
-};
-
-static struct pmx spi_setting = {
- .setting = U300_APP_PMX_SPI_SETTING,
- .default_on = false,
- .activated = false,
- .name = "SPI",
- .onmask = {{0, 0},
- {U300_SYSCON_PMC1HR_APP_SPI_2_MASK |
- U300_SYSCON_PMC1HR_APP_SPI_CS_1_MASK |
- U300_SYSCON_PMC1HR_APP_SPI_CS_2_MASK,
- U300_SYSCON_PMC1HR_APP_SPI_2_SPI |
- U300_SYSCON_PMC1HR_APP_SPI_CS_1_SPI |
- U300_SYSCON_PMC1HR_APP_SPI_CS_2_SPI},
- {0, 0},
- {0, 0},
- {0, 0}
- },
-};
-
-/* Available padmux settings */
-static struct pmx *pmx_settings[] = {
- &mmc_setting,
- &spi_setting,
-};
-
-static void update_registers(struct pmx *pmx, bool activate)
-{
- u16 regval, val, mask;
- int i;
-
- for (i = 0; i < ARRAY_SIZE(pmx_registers); i++) {
- if (activate)
- val = pmx->onmask[i].val;
- else
- val = 0;
-
- mask = pmx->onmask[i].mask;
- if (mask != 0) {
- regval = readw(pmx_registers[i]);
- regval &= ~mask;
- regval |= val;
- writew(regval, pmx_registers[i]);
- }
- }
-}
-
-struct pmx *pmx_get(struct device *dev, enum pmx_settings setting)
-{
- int i;
- struct pmx *pmx = ERR_PTR(-ENOENT);
-
- if (dev == NULL)
- return ERR_PTR(-EINVAL);
-
- mutex_lock(&pmx_mutex);
- for (i = 0; i < ARRAY_SIZE(pmx_settings); i++) {
-
- if (setting == pmx_settings[i]->setting) {
-
- if (pmx_settings[i]->dev != NULL) {
- WARN(1, "padmux: required setting "
- "in use by another consumer\n");
- } else {
- pmx = pmx_settings[i];
- pmx->dev = dev;
- dev_dbg(dev, "padmux: setting nr %d is now "
- "bound to %s and ready to use\n",
- setting, dev_name(dev));
- break;
- }
- }
- }
- mutex_unlock(&pmx_mutex);
-
- return pmx;
-}
-EXPORT_SYMBOL(pmx_get);
-
-int pmx_put(struct device *dev, struct pmx *pmx)
-{
- int i;
- int ret = -ENOENT;
-
- if (pmx == NULL || dev == NULL)
- return -EINVAL;
-
- mutex_lock(&pmx_mutex);
- for (i = 0; i < ARRAY_SIZE(pmx_settings); i++) {
-
- if (pmx->setting == pmx_settings[i]->setting) {
-
- if (dev != pmx->dev) {
- WARN(1, "padmux: cannot release handle as "
- "it is bound to another consumer\n");
- ret = -EINVAL;
- break;
- } else {
- pmx_settings[i]->dev = NULL;
- ret = 0;
- break;
- }
- }
- }
- mutex_unlock(&pmx_mutex);
-
- return ret;
-}
-EXPORT_SYMBOL(pmx_put);
-
-int pmx_activate(struct device *dev, struct pmx *pmx)
-{
- int i, j, ret;
- ret = 0;
-
- if (pmx == NULL || dev == NULL)
- return -EINVAL;
-
- mutex_lock(&pmx_mutex);
-
- /* Make sure the required bits are not used */
- for (i = 0; i < ARRAY_SIZE(pmx_settings); i++) {
-
- if (pmx_settings[i]->dev == NULL || pmx_settings[i] == pmx)
- continue;
-
- for (j = 0; j < ARRAY_SIZE(pmx_registers); j++) {
-
- if (pmx_settings[i]->onmask[j].mask & pmx->
- onmask[j].mask) {
- /* More than one entry on the same bits */
- WARN(1, "padmux: cannot activate "
- "setting. Bit conflict with "
- "an active setting\n");
-
- ret = -EUSERS;
- goto exit;
- }
- }
- }
- update_registers(pmx, true);
- pmx->activated = true;
- dev_dbg(dev, "padmux: setting nr %d is activated\n",
- pmx->setting);
-
-exit:
- mutex_unlock(&pmx_mutex);
- return ret;
-}
-EXPORT_SYMBOL(pmx_activate);
-
-int pmx_deactivate(struct device *dev, struct pmx *pmx)
-{
- int i;
- int ret = -ENOENT;
-
- if (pmx == NULL || dev == NULL)
- return -EINVAL;
-
- mutex_lock(&pmx_mutex);
- for (i = 0; i < ARRAY_SIZE(pmx_settings); i++) {
-
- if (pmx_settings[i]->dev == NULL)
- continue;
-
- if (pmx->setting == pmx_settings[i]->setting) {
-
- if (dev != pmx->dev) {
- WARN(1, "padmux: cannot deactivate "
- "pmx setting as it was activated "
- "by another consumer\n");
-
- ret = -EBUSY;
- continue;
- } else {
- update_registers(pmx, false);
- pmx_settings[i]->dev = NULL;
- pmx->activated = false;
- ret = 0;
- dev_dbg(dev, "padmux: setting nr %d is deactivated",
- pmx->setting);
- break;
- }
- }
- }
- mutex_unlock(&pmx_mutex);
-
- return ret;
-}
-EXPORT_SYMBOL(pmx_deactivate);
-
-/*
- * For internal use only. If it is to be exported,
- * it should be reentrant. Notice that pmx_activate
- * (i.e. runtime settings) always override default settings.
- */
-static int pmx_set_default(void)
-{
- /* Used to identify several entries on the same bits */
- u16 modbits[ARRAY_SIZE(pmx_registers)];
-
- int i, j;
-
- memset(modbits, 0, ARRAY_SIZE(pmx_registers) * sizeof(u16));
-
- for (i = 0; i < ARRAY_SIZE(pmx_settings); i++) {
-
- if (!pmx_settings[i]->default_on)
- continue;
-
- for (j = 0; j < ARRAY_SIZE(pmx_registers); j++) {
-
- /* Make sure there is only one entry on the same bits */
- if (modbits[j] & pmx_settings[i]->onmask[j].mask) {
- BUG();
- return -EUSERS;
- }
- modbits[j] |= pmx_settings[i]->onmask[j].mask;
- }
- update_registers(pmx_settings[i], true);
- }
- return 0;
-}
-
-#if (defined(CONFIG_DEBUG_FS) && defined(CONFIG_U300_DEBUG))
-static int pmx_show(struct seq_file *s, void *data)
-{
- int i;
- seq_printf(s, "-------------------------------------------------\n");
- seq_printf(s, "SETTING BOUND TO DEVICE STATE\n");
- seq_printf(s, "-------------------------------------------------\n");
- mutex_lock(&pmx_mutex);
- for (i = 0; i < ARRAY_SIZE(pmx_settings); i++) {
- /* Format pmx and device name nicely */
- char cdp[33];
- int chars;
-
- chars = snprintf(&cdp[0], 17, "%s", pmx_settings[i]->name);
- while (chars < 16) {
- cdp[chars] = ' ';
- chars++;
- }
- chars = snprintf(&cdp[16], 17, "%s", pmx_settings[i]->dev ?
- dev_name(pmx_settings[i]->dev) : "N/A");
- while (chars < 16) {
- cdp[chars+16] = ' ';
- chars++;
- }
- cdp[32] = '\0';
-
- seq_printf(s,
- "%s\t%s\n",
- &cdp[0],
- pmx_settings[i]->activated ?
- "ACTIVATED" : "DEACTIVATED"
- );
-
- }
- mutex_unlock(&pmx_mutex);
- return 0;
-}
-
-static int pmx_open(struct inode *inode, struct file *file)
-{
- return single_open(file, pmx_show, NULL);
-}
-
-static const struct file_operations pmx_operations = {
- .owner = THIS_MODULE,
- .open = pmx_open,
- .read = seq_read,
- .llseek = seq_lseek,
- .release = single_release,
-};
-
-static int __init init_pmx_read_debugfs(void)
-{
- /* Expose a simple debugfs interface to view pmx settings */
- (void) debugfs_create_file("padmux", S_IFREG | S_IRUGO,
- NULL, NULL,
- &pmx_operations);
- return 0;
-}
-
-/*
- * This needs to come in after the core_initcall(),
- * because debugfs is not available until
- * the subsystems come up.
- */
-module_init(init_pmx_read_debugfs);
-#endif
-
-static int __init pmx_init(void)
-{
- int ret;
-
- ret = pmx_set_default();
-
- if (IS_ERR_VALUE(ret))
- pr_crit("padmux: default settings could not be set\n");
-
- return 0;
-}
-
-/* Should be initialized before consumers */
-core_initcall(pmx_init);
diff --git a/arch/arm/mach-u300/padmux.h b/arch/arm/mach-u300/padmux.h
deleted file mode 100644
index 6e8b860..0000000
--- a/arch/arm/mach-u300/padmux.h
+++ /dev/null
@@ -1,39 +0,0 @@
-/*
- *
- * arch/arm/mach-u300/padmux.h
- *
- *
- * Copyright (C) 2009 ST-Ericsson AB
- * License terms: GNU General Public License (GPL) version 2
- * U300 PADMUX API
- * Author: Martin Persson <martin.persson@stericsson.com>
- */
-
-#ifndef __MACH_U300_PADMUX_H
-#define __MACH_U300_PADMUX_H
-
-enum pmx_settings {
- U300_APP_PMX_MMC_SETTING,
- U300_APP_PMX_SPI_SETTING
-};
-
-struct pmx_onmask {
- u16 mask; /* Mask bits */
- u16 val; /* Value when active */
-};
-
-struct pmx {
- struct device *dev;
- enum pmx_settings setting;
- char *name;
- bool activated;
- bool default_on;
- struct pmx_onmask onmask[];
-};
-
-struct pmx *pmx_get(struct device *dev, enum pmx_settings setting);
-int pmx_put(struct device *dev, struct pmx *pmx);
-int pmx_activate(struct device *dev, struct pmx *pmx);
-int pmx_deactivate(struct device *dev, struct pmx *pmx);
-
-#endif
diff --git a/arch/arm/mach-u300/spi.c b/arch/arm/mach-u300/spi.c
index 7b597e2..a1affac 100644
--- a/arch/arm/mach-u300/spi.c
+++ b/arch/arm/mach-u300/spi.c
@@ -14,8 +14,6 @@
#include <mach/coh901318.h>
#include <mach/dma_channels.h>
-#include "padmux.h"
-
/*
* The following is for the actual devices on the SSP/SPI bus
*/
@@ -95,25 +93,7 @@ static struct pl022_ssp_controller ssp_platform_data = {
void __init u300_spi_init(struct amba_device *adev)
{
- struct pmx *pmx;
-
adev->dev.platform_data = &ssp_platform_data;
- /*
- * Setup padmuxing for SPI. Since this must always be
- * compiled into the kernel, pmx is never released.
- */
- pmx = pmx_get(&adev->dev, U300_APP_PMX_SPI_SETTING);
-
- if (IS_ERR(pmx))
- dev_warn(&adev->dev, "Could not get padmux handle\n");
- else {
- int ret;
-
- ret = pmx_activate(&adev->dev, pmx);
- if (IS_ERR_VALUE(ret))
- dev_warn(&adev->dev, "Could not activate padmuxing\n");
- }
-
}
void __init u300_spi_register_board_devices(void)
diff --git a/drivers/pinctrl/Kconfig b/drivers/pinctrl/Kconfig
index 02b4d4e..7b175c3 100644
--- a/drivers/pinctrl/Kconfig
+++ b/drivers/pinctrl/Kconfig
@@ -26,4 +26,11 @@ config DEBUG_PINCTRL
help
Say Y here to add some extra checks and diagnostics to PINCTRL calls.
+config PINMUX_U300
+ bool "U300 pinmux driver"
+ depends on ARCH_U300
+ select PINMUX
+ help
+ Say Y here to enable the U300 pinmux driver
+
endif
diff --git a/drivers/pinctrl/Makefile b/drivers/pinctrl/Makefile
index 596ce9f..63d4241 100644
--- a/drivers/pinctrl/Makefile
+++ b/drivers/pinctrl/Makefile
@@ -4,3 +4,4 @@ ccflags-$(CONFIG_DEBUG_PINMUX) += -DDEBUG
obj-$(CONFIG_PINCTRL) += core.o
obj-$(CONFIG_PINMUX) += pinmux.o
+obj-$(CONFIG_PINMUX_U300) += pinmux-u300.o
diff --git a/drivers/pinctrl/pinmux-u300.c b/drivers/pinctrl/pinmux-u300.c
new file mode 100644
index 0000000..23f082f
--- /dev/null
+++ b/drivers/pinctrl/pinmux-u300.c
@@ -0,0 +1,1135 @@
+/*
+ * Driver for the U300 pin controller
+ *
+ * Based on the original U300 padmux functions
+ * Copyright (C) 2009-2011 ST-Ericsson AB
+ * Author: Martin Persson <martin.persson@stericsson.com>
+ * Author: Linus Walleij <linus.walleij@linaro.org>
+ *
+ * The DB3350 design and control registers are oriented around pads rather than
+ * pins, so we enumerate the pads we can mux rather than actual pins. The pads
+ * are connected to different pins in different packaging types, so it would
+ * be confusing.
+ */
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/io.h>
+#include <linux/slab.h>
+#include <linux/err.h>
+#include <linux/pinctrl/pinctrl.h>
+#include <linux/pinctrl/pinmux.h>
+
+/*
+ * Register definitions for the U300 Padmux control registers in the
+ * system controller
+ */
+
+/* PAD MUX Control register 1 (LOW) 16bit (R/W) */
+#define U300_SYSCON_PMC1LR 0x007C
+#define U300_SYSCON_PMC1LR_MASK 0xFFFF
+#define U300_SYSCON_PMC1LR_CDI_MASK 0xC000
+#define U300_SYSCON_PMC1LR_CDI_CDI 0x0000
+#define U300_SYSCON_PMC1LR_CDI_EMIF 0x4000
+/* For BS335 */
+#define U300_SYSCON_PMC1LR_CDI_CDI2 0x8000
+#define U300_SYSCON_PMC1LR_CDI_WCDMA_APP_GPIO 0xC000
+/* For BS365 */
+#define U300_SYSCON_PMC1LR_CDI_GPIO 0x8000
+#define U300_SYSCON_PMC1LR_CDI_WCDMA 0xC000
+/* Common defs */
+#define U300_SYSCON_PMC1LR_PDI_MASK 0x3000
+#define U300_SYSCON_PMC1LR_PDI_PDI 0x0000
+#define U300_SYSCON_PMC1LR_PDI_EGG 0x1000
+#define U300_SYSCON_PMC1LR_PDI_WCDMA 0x3000
+#define U300_SYSCON_PMC1LR_MMCSD_MASK 0x0C00
+#define U300_SYSCON_PMC1LR_MMCSD_MMCSD 0x0000
+#define U300_SYSCON_PMC1LR_MMCSD_MSPRO 0x0400
+#define U300_SYSCON_PMC1LR_MMCSD_DSP 0x0800
+#define U300_SYSCON_PMC1LR_MMCSD_WCDMA 0x0C00
+#define U300_SYSCON_PMC1LR_ETM_MASK 0x0300
+#define U300_SYSCON_PMC1LR_ETM_ACC 0x0000
+#define U300_SYSCON_PMC1LR_ETM_APP 0x0100
+#define U300_SYSCON_PMC1LR_EMIF_1_CS2_MASK 0x00C0
+#define U300_SYSCON_PMC1LR_EMIF_1_CS2_STATIC 0x0000
+#define U300_SYSCON_PMC1LR_EMIF_1_CS2_NFIF 0x0040
+#define U300_SYSCON_PMC1LR_EMIF_1_CS2_SDRAM 0x0080
+#define U300_SYSCON_PMC1LR_EMIF_1_CS2_STATIC_2GB 0x00C0
+#define U300_SYSCON_PMC1LR_EMIF_1_CS1_MASK 0x0030
+#define U300_SYSCON_PMC1LR_EMIF_1_CS1_STATIC 0x0000
+#define U300_SYSCON_PMC1LR_EMIF_1_CS1_NFIF 0x0010
+#define U300_SYSCON_PMC1LR_EMIF_1_CS1_SDRAM 0x0020
+#define U300_SYSCON_PMC1LR_EMIF_1_CS1_SEMI 0x0030
+#define U300_SYSCON_PMC1LR_EMIF_1_CS0_MASK 0x000C
+#define U300_SYSCON_PMC1LR_EMIF_1_CS0_STATIC 0x0000
+#define U300_SYSCON_PMC1LR_EMIF_1_CS0_NFIF 0x0004
+#define U300_SYSCON_PMC1LR_EMIF_1_CS0_SDRAM 0x0008
+#define U300_SYSCON_PMC1LR_EMIF_1_CS0_SEMI 0x000C
+#define U300_SYSCON_PMC1LR_EMIF_1_MASK 0x0003
+#define U300_SYSCON_PMC1LR_EMIF_1_STATIC 0x0000
+#define U300_SYSCON_PMC1LR_EMIF_1_SDRAM0 0x0001
+#define U300_SYSCON_PMC1LR_EMIF_1_SDRAM1 0x0002
+#define U300_SYSCON_PMC1LR_EMIF_1 0x0003
+/* PAD MUX Control register 2 (HIGH) 16bit (R/W) */
+#define U300_SYSCON_PMC1HR 0x007E
+#define U300_SYSCON_PMC1HR_MASK 0xFFFF
+#define U300_SYSCON_PMC1HR_MISC_2_MASK 0xC000
+#define U300_SYSCON_PMC1HR_MISC_2_APP_GPIO 0x0000
+#define U300_SYSCON_PMC1HR_MISC_2_MSPRO 0x4000
+#define U300_SYSCON_PMC1HR_MISC_2_DSP 0x8000
+#define U300_SYSCON_PMC1HR_MISC_2_AAIF 0xC000
+#define U300_SYSCON_PMC1HR_APP_GPIO_2_MASK 0x3000
+#define U300_SYSCON_PMC1HR_APP_GPIO_2_APP_GPIO 0x0000
+#define U300_SYSCON_PMC1HR_APP_GPIO_2_NFIF 0x1000
+#define U300_SYSCON_PMC1HR_APP_GPIO_2_DSP 0x2000
+#define U300_SYSCON_PMC1HR_APP_GPIO_2_AAIF 0x3000
+#define U300_SYSCON_PMC1HR_APP_GPIO_1_MASK 0x0C00
+#define U300_SYSCON_PMC1HR_APP_GPIO_1_APP_GPIO 0x0000
+#define U300_SYSCON_PMC1HR_APP_GPIO_1_MMC 0x0400
+#define U300_SYSCON_PMC1HR_APP_GPIO_1_DSP 0x0800
+#define U300_SYSCON_PMC1HR_APP_GPIO_1_AAIF 0x0C00
+#define U300_SYSCON_PMC1HR_APP_SPI_CS_2_MASK 0x0300
+#define U300_SYSCON_PMC1HR_APP_SPI_CS_2_APP_GPIO 0x0000
+#define U300_SYSCON_PMC1HR_APP_SPI_CS_2_SPI 0x0100
+#define U300_SYSCON_PMC1HR_APP_SPI_CS_2_AAIF 0x0300
+#define U300_SYSCON_PMC1HR_APP_SPI_CS_1_MASK 0x00C0
+#define U300_SYSCON_PMC1HR_APP_SPI_CS_1_APP_GPIO 0x0000
+#define U300_SYSCON_PMC1HR_APP_SPI_CS_1_SPI 0x0040
+#define U300_SYSCON_PMC1HR_APP_SPI_CS_1_AAIF 0x00C0
+#define U300_SYSCON_PMC1HR_APP_SPI_2_MASK 0x0030
+#define U300_SYSCON_PMC1HR_APP_SPI_2_APP_GPIO 0x0000
+#define U300_SYSCON_PMC1HR_APP_SPI_2_SPI 0x0010
+#define U300_SYSCON_PMC1HR_APP_SPI_2_DSP 0x0020
+#define U300_SYSCON_PMC1HR_APP_SPI_2_AAIF 0x0030
+#define U300_SYSCON_PMC1HR_APP_UART0_2_MASK 0x000C
+#define U300_SYSCON_PMC1HR_APP_UART0_2_APP_GPIO 0x0000
+#define U300_SYSCON_PMC1HR_APP_UART0_2_UART0 0x0004
+#define U300_SYSCON_PMC1HR_APP_UART0_2_NFIF_CS 0x0008
+#define U300_SYSCON_PMC1HR_APP_UART0_2_AAIF 0x000C
+#define U300_SYSCON_PMC1HR_APP_UART0_1_MASK 0x0003
+#define U300_SYSCON_PMC1HR_APP_UART0_1_APP_GPIO 0x0000
+#define U300_SYSCON_PMC1HR_APP_UART0_1_UART0 0x0001
+#define U300_SYSCON_PMC1HR_APP_UART0_1_AAIF 0x0003
+/* Padmux 2 control */
+#define U300_SYSCON_PMC2R 0x100
+#define U300_SYSCON_PMC2R_APP_MISC_0_MASK 0x00C0
+#define U300_SYSCON_PMC2R_APP_MISC_0_APP_GPIO 0x0000
+#define U300_SYSCON_PMC2R_APP_MISC_0_EMIF_SDRAM 0x0040
+#define U300_SYSCON_PMC2R_APP_MISC_0_MMC 0x0080
+#define U300_SYSCON_PMC2R_APP_MISC_0_CDI2 0x00C0
+#define U300_SYSCON_PMC2R_APP_MISC_1_MASK 0x0300
+#define U300_SYSCON_PMC2R_APP_MISC_1_APP_GPIO 0x0000
+#define U300_SYSCON_PMC2R_APP_MISC_1_EMIF_SDRAM 0x0100
+#define U300_SYSCON_PMC2R_APP_MISC_1_MMC 0x0200
+#define U300_SYSCON_PMC2R_APP_MISC_1_CDI2 0x0300
+#define U300_SYSCON_PMC2R_APP_MISC_2_MASK 0x0C00
+#define U300_SYSCON_PMC2R_APP_MISC_2_APP_GPIO 0x0000
+#define U300_SYSCON_PMC2R_APP_MISC_2_EMIF_SDRAM 0x0400
+#define U300_SYSCON_PMC2R_APP_MISC_2_MMC 0x0800
+#define U300_SYSCON_PMC2R_APP_MISC_2_CDI2 0x0C00
+#define U300_SYSCON_PMC2R_APP_MISC_3_MASK 0x3000
+#define U300_SYSCON_PMC2R_APP_MISC_3_APP_GPIO 0x0000
+#define U300_SYSCON_PMC2R_APP_MISC_3_EMIF_SDRAM 0x1000
+#define U300_SYSCON_PMC2R_APP_MISC_3_MMC 0x2000
+#define U300_SYSCON_PMC2R_APP_MISC_3_CDI2 0x3000
+#define U300_SYSCON_PMC2R_APP_MISC_4_MASK 0xC000
+#define U300_SYSCON_PMC2R_APP_MISC_4_APP_GPIO 0x0000
+#define U300_SYSCON_PMC2R_APP_MISC_4_EMIF_SDRAM 0x4000
+#define U300_SYSCON_PMC2R_APP_MISC_4_MMC 0x8000
+#define U300_SYSCON_PMC2R_APP_MISC_4_ACC_GPIO 0xC000
+/* TODO: More SYSCON registers missing */
+#define U300_SYSCON_PMC3R 0x10C
+#define U300_SYSCON_PMC3R_APP_MISC_11_MASK 0xC000
+#define U300_SYSCON_PMC3R_APP_MISC_11_SPI 0x4000
+#define U300_SYSCON_PMC3R_APP_MISC_10_MASK 0x3000
+#define U300_SYSCON_PMC3R_APP_MISC_10_SPI 0x1000
+/* TODO: Missing other configs */
+#define U300_SYSCON_PMC4R 0x168
+#define U300_SYSCON_PMC4R_APP_MISC_12_MASK 0x0003
+#define U300_SYSCON_PMC4R_APP_MISC_12_APP_GPIO 0x0000
+#define U300_SYSCON_PMC4R_APP_MISC_13_MASK 0x000C
+#define U300_SYSCON_PMC4R_APP_MISC_13_CDI 0x0000
+#define U300_SYSCON_PMC4R_APP_MISC_13_SMIA 0x0004
+#define U300_SYSCON_PMC4R_APP_MISC_13_SMIA2 0x0008
+#define U300_SYSCON_PMC4R_APP_MISC_13_APP_GPIO 0x000C
+#define U300_SYSCON_PMC4R_APP_MISC_14_MASK 0x0030
+#define U300_SYSCON_PMC4R_APP_MISC_14_CDI 0x0000
+#define U300_SYSCON_PMC4R_APP_MISC_14_SMIA 0x0010
+#define U300_SYSCON_PMC4R_APP_MISC_14_CDI2 0x0020
+#define U300_SYSCON_PMC4R_APP_MISC_14_APP_GPIO 0x0030
+#define U300_SYSCON_PMC4R_APP_MISC_16_MASK 0x0300
+#define U300_SYSCON_PMC4R_APP_MISC_16_APP_GPIO_13 0x0000
+#define U300_SYSCON_PMC4R_APP_MISC_16_APP_UART1_CTS 0x0100
+#define U300_SYSCON_PMC4R_APP_MISC_16_EMIF_1_STATIC_CS5_N 0x0200
+
+#define DRIVER_NAME "pinmux-u300"
+
+/*
+ * The DB3350 has 467 pads, I have enumerated the pads clockwise around the
+ * edges of the silicon, finger by finger. LTCORNER upper left is pad 0.
+ * Data taken from the PadRing chart, arranged like this:
+ *
+ * 0 ..... 104
+ * 466 105
+ * . .
+ * . .
+ * 358 224
+ * 357 .... 225
+ */
+#define U300_NUM_PADS 467
+
+/* Pad names for the pinmux subsystem */
+static const struct pinctrl_pin_desc __refdata u300_pads[] = {
+ /* Pads along the top edge of the chip */
+ PINCTRL_PIN(0, "P PAD VDD 28"),
+ PINCTRL_PIN(1, "P PAD GND 28"),
+ PINCTRL_PIN(2, "PO SIM RST N"),
+ PINCTRL_PIN(3, "VSSIO 25"),
+ PINCTRL_PIN(4, "VSSA ADDA ESDSUB"),
+ PINCTRL_PIN(5, "PWR VSSCOMMON"),
+ PINCTRL_PIN(6, "PI ADC I1 POS"),
+ PINCTRL_PIN(7, "PI ADC I1 NEG"),
+ PINCTRL_PIN(8, "PWR VSSAD0"),
+ PINCTRL_PIN(9, "PWR VCCAD0"),
+ PINCTRL_PIN(10, "PI ADC Q1 NEG"),
+ PINCTRL_PIN(11, "PI ADC Q1 POS"),
+ PINCTRL_PIN(12, "PWR VDDAD"),
+ PINCTRL_PIN(13, "PWR GNDAD"),
+ PINCTRL_PIN(14, "PI ADC I2 POS"),
+ PINCTRL_PIN(15, "PI ADC I2 NEG"),
+ PINCTRL_PIN(16, "PWR VSSAD1"),
+ PINCTRL_PIN(17, "PWR VCCAD1"),
+ PINCTRL_PIN(18, "PI ADC Q2 NEG"),
+ PINCTRL_PIN(19, "PI ADC Q2 POS"),
+ PINCTRL_PIN(20, "VSSA ADDA ESDSUB"),
+ PINCTRL_PIN(21, "PWR VCCGPAD"),
+ PINCTRL_PIN(22, "PI TX POW"),
+ PINCTRL_PIN(23, "PWR VSSGPAD"),
+ PINCTRL_PIN(24, "PO DAC I POS"),
+ PINCTRL_PIN(25, "PO DAC I NEG"),
+ PINCTRL_PIN(26, "PO DAC Q POS"),
+ PINCTRL_PIN(27, "PO DAC Q NEG"),
+ PINCTRL_PIN(28, "PWR VSSDA"),
+ PINCTRL_PIN(29, "PWR VCCDA"),
+ PINCTRL_PIN(30, "VSSA ADDA ESDSUB"),
+ PINCTRL_PIN(31, "P PAD VDDIO 11"),
+ PINCTRL_PIN(32, "PI PLL 26 FILTVDD"),
+ PINCTRL_PIN(33, "PI PLL 26 VCONT"),
+ PINCTRL_PIN(34, "PWR AGNDPLL2V5 32 13"),
+ PINCTRL_PIN(35, "PWR AVDDPLL2V5 32 13"),
+ PINCTRL_PIN(36, "VDDA PLL ESD"),
+ PINCTRL_PIN(37, "VSSA PLL ESD"),
+ PINCTRL_PIN(38, "VSS PLL"),
+ PINCTRL_PIN(39, "VDDC PLL"),
+ PINCTRL_PIN(40, "PWR AGNDPLL2V5 26 60"),
+ PINCTRL_PIN(41, "PWR AVDDPLL2V5 26 60"),
+ PINCTRL_PIN(42, "PWR AVDDPLL2V5 26 208"),
+ PINCTRL_PIN(43, "PWR AGNDPLL2V5 26 208"),
+ PINCTRL_PIN(44, "PWR AVDDPLL2V5 13 208"),
+ PINCTRL_PIN(45, "PWR AGNDPLL2V5 13 208"),
+ PINCTRL_PIN(46, "P PAD VSSIO 11"),
+ PINCTRL_PIN(47, "P PAD VSSIO 12"),
+ PINCTRL_PIN(48, "PI POW RST N"),
+ PINCTRL_PIN(49, "VDDC IO"),
+ PINCTRL_PIN(50, "P PAD VDDIO 16"),
+ PINCTRL_PIN(51, "PO RF WCDMA EN 4"),
+ PINCTRL_PIN(52, "PO RF WCDMA EN 3"),
+ PINCTRL_PIN(53, "PO RF WCDMA EN 2"),
+ PINCTRL_PIN(54, "PO RF WCDMA EN 1"),
+ PINCTRL_PIN(55, "PO RF WCDMA EN 0"),
+ PINCTRL_PIN(56, "PO GSM PA ENABLE"),
+ PINCTRL_PIN(57, "PO RF DATA STRB"),
+ PINCTRL_PIN(58, "PO RF DATA2"),
+ PINCTRL_PIN(59, "PIO RF DATA1"),
+ PINCTRL_PIN(60, "PIO RF DATA0"),
+ PINCTRL_PIN(61, "P PAD VDD 11"),
+ PINCTRL_PIN(62, "P PAD GND 11"),
+ PINCTRL_PIN(63, "P PAD VSSIO 16"),
+ PINCTRL_PIN(64, "P PAD VDDIO 18"),
+ PINCTRL_PIN(65, "PO RF CTRL STRB2"),
+ PINCTRL_PIN(66, "PO RF CTRL STRB1"),
+ PINCTRL_PIN(67, "PO RF CTRL STRB0"),
+ PINCTRL_PIN(68, "PIO RF CTRL DATA"),
+ PINCTRL_PIN(69, "PO RF CTRL CLK"),
+ PINCTRL_PIN(70, "PO TX ADC STRB"),
+ PINCTRL_PIN(71, "PO ANT SW 2"),
+ PINCTRL_PIN(72, "PO ANT SW 3"),
+ PINCTRL_PIN(73, "PO ANT SW 0"),
+ PINCTRL_PIN(74, "PO ANT SW 1"),
+ PINCTRL_PIN(75, "PO M CLKRQ"),
+ PINCTRL_PIN(76, "PI M CLK"),
+ PINCTRL_PIN(77, "PI RTC CLK"),
+ PINCTRL_PIN(78, "P PAD VDD 8"),
+ PINCTRL_PIN(79, "P PAD GND 8"),
+ PINCTRL_PIN(80, "P PAD VSSIO 13"),
+ PINCTRL_PIN(81, "P PAD VDDIO 13"),
+ PINCTRL_PIN(82, "PO SYS 1 CLK"),
+ PINCTRL_PIN(83, "PO SYS 2 CLK"),
+ PINCTRL_PIN(84, "PO SYS 0 CLK"),
+ PINCTRL_PIN(85, "PI SYS 0 CLKRQ"),
+ PINCTRL_PIN(86, "PO PWR MNGT CTRL 1"),
+ PINCTRL_PIN(87, "PO PWR MNGT CTRL 0"),
+ PINCTRL_PIN(88, "PO RESOUT2 RST N"),
+ PINCTRL_PIN(89, "PO RESOUT1 RST N"),
+ PINCTRL_PIN(90, "PO RESOUT0 RST N"),
+ PINCTRL_PIN(91, "PI SERVICE N"),
+ PINCTRL_PIN(92, "P PAD VDD 29"),
+ PINCTRL_PIN(93, "P PAD GND 29"),
+ PINCTRL_PIN(94, "P PAD VSSIO 8"),
+ PINCTRL_PIN(95, "P PAD VDDIO 8"),
+ PINCTRL_PIN(96, "PI EXT IRQ1 N"),
+ PINCTRL_PIN(97, "PI EXT IRQ0 N"),
+ PINCTRL_PIN(98, "PIO DC ON"),
+ PINCTRL_PIN(99, "PIO ACC APP I2C DATA"),
+ PINCTRL_PIN(100, "PIO ACC APP I2C CLK"),
+ PINCTRL_PIN(101, "P PAD VDD 12"),
+ PINCTRL_PIN(102, "P PAD GND 12"),
+ PINCTRL_PIN(103, "P PAD VSSIO 14"),
+ PINCTRL_PIN(104, "P PAD VDDIO 14"),
+ /* Pads along the right edge of the chip */
+ PINCTRL_PIN(105, "PIO APP I2C1 DATA"),
+ PINCTRL_PIN(106, "PIO APP I2C1 CLK"),
+ PINCTRL_PIN(107, "PO KEY OUT0"),
+ PINCTRL_PIN(108, "PO KEY OUT1"),
+ PINCTRL_PIN(109, "PO KEY OUT2"),
+ PINCTRL_PIN(110, "PO KEY OUT3"),
+ PINCTRL_PIN(111, "PO KEY OUT4"),
+ PINCTRL_PIN(112, "PI KEY IN0"),
+ PINCTRL_PIN(113, "PI KEY IN1"),
+ PINCTRL_PIN(114, "PI KEY IN2"),
+ PINCTRL_PIN(115, "P PAD VDDIO 15"),
+ PINCTRL_PIN(116, "P PAD VSSIO 15"),
+ PINCTRL_PIN(117, "P PAD GND 13"),
+ PINCTRL_PIN(118, "P PAD VDD 13"),
+ PINCTRL_PIN(119, "PI KEY IN3"),
+ PINCTRL_PIN(120, "PI KEY IN4"),
+ PINCTRL_PIN(121, "PI KEY IN5"),
+ PINCTRL_PIN(122, "PIO APP PCM I2S1 DATA B"),
+ PINCTRL_PIN(123, "PIO APP PCM I2S1 DATA A"),
+ PINCTRL_PIN(124, "PIO APP PCM I2S1 WS"),
+ PINCTRL_PIN(125, "PIO APP PCM I2S1 CLK"),
+ PINCTRL_PIN(126, "PIO APP PCM I2S0 DATA B"),
+ PINCTRL_PIN(127, "PIO APP PCM I2S0 DATA A"),
+ PINCTRL_PIN(128, "PIO APP PCM I2S0 WS"),
+ PINCTRL_PIN(129, "PIO APP PCM I2S0 CLK"),
+ PINCTRL_PIN(130, "P PAD VDD 17"),
+ PINCTRL_PIN(131, "P PAD GND 17"),
+ PINCTRL_PIN(132, "P PAD VSSIO 19"),
+ PINCTRL_PIN(133, "P PAD VDDIO 19"),
+ PINCTRL_PIN(134, "UART0 RTS"),
+ PINCTRL_PIN(135, "UART0 CTS"),
+ PINCTRL_PIN(136, "UART0 TX"),
+ PINCTRL_PIN(137, "UART0 RX"),
+ PINCTRL_PIN(138, "PIO ACC SPI DO"),
+ PINCTRL_PIN(139, "PIO ACC SPI DI"),
+ PINCTRL_PIN(140, "PIO ACC SPI CS0 N"),
+ PINCTRL_PIN(141, "PIO ACC SPI CS1 N"),
+ PINCTRL_PIN(142, "PIO ACC SPI CS2 N"),
+ PINCTRL_PIN(143, "PIO ACC SPI CLK"),
+ PINCTRL_PIN(144, "PO PDI EXT RST N"),
+ PINCTRL_PIN(145, "P PAD VDDIO 22"),
+ PINCTRL_PIN(146, "P PAD VSSIO 22"),
+ PINCTRL_PIN(147, "P PAD GND 18"),
+ PINCTRL_PIN(148, "P PAD VDD 18"),
+ PINCTRL_PIN(149, "PIO PDI C0"),
+ PINCTRL_PIN(150, "PIO PDI C1"),
+ PINCTRL_PIN(151, "PIO PDI C2"),
+ PINCTRL_PIN(152, "PIO PDI C3"),
+ PINCTRL_PIN(153, "PIO PDI C4"),
+ PINCTRL_PIN(154, "PIO PDI C5"),
+ PINCTRL_PIN(155, "PIO PDI D0"),
+ PINCTRL_PIN(156, "PIO PDI D1"),
+ PINCTRL_PIN(157, "PIO PDI D2"),
+ PINCTRL_PIN(158, "PIO PDI D3"),
+ PINCTRL_PIN(159, "P PAD VDDIO 21"),
+ PINCTRL_PIN(160, "P PAD VSSIO 21"),
+ PINCTRL_PIN(161, "PIO PDI D4"),
+ PINCTRL_PIN(162, "PIO PDI D5"),
+ PINCTRL_PIN(163, "PIO PDI D6"),
+ PINCTRL_PIN(164, "PIO PDI D7"),
+ PINCTRL_PIN(165, "PIO MS INS"),
+ PINCTRL_PIN(166, "MMC DATA DIR LS"),
+ PINCTRL_PIN(167, "MMC DATA 3"),
+ PINCTRL_PIN(168, "MMC DATA 2"),
+ PINCTRL_PIN(169, "MMC DATA 1"),
+ PINCTRL_PIN(170, "MMC DATA 0"),
+ PINCTRL_PIN(171, "MMC CMD DIR LS"),
+ PINCTRL_PIN(172, "P PAD VDD 27"),
+ PINCTRL_PIN(173, "P PAD GND 27"),
+ PINCTRL_PIN(174, "P PAD VSSIO 20"),
+ PINCTRL_PIN(175, "P PAD VDDIO 20"),
+ PINCTRL_PIN(176, "MMC CMD"),
+ PINCTRL_PIN(177, "MMC CLK"),
+ PINCTRL_PIN(178, "PIO APP GPIO 14"),
+ PINCTRL_PIN(179, "PIO APP GPIO 13"),
+ PINCTRL_PIN(180, "PIO APP GPIO 11"),
+ PINCTRL_PIN(181, "PIO APP GPIO 25"),
+ PINCTRL_PIN(182, "PIO APP GPIO 24"),
+ PINCTRL_PIN(183, "PIO APP GPIO 23"),
+ PINCTRL_PIN(184, "PIO APP GPIO 22"),
+ PINCTRL_PIN(185, "PIO APP GPIO 21"),
+ PINCTRL_PIN(186, "PIO APP GPIO 20"),
+ PINCTRL_PIN(187, "P PAD VDD 19"),
+ PINCTRL_PIN(188, "P PAD GND 19"),
+ PINCTRL_PIN(189, "P PAD VSSIO 23"),
+ PINCTRL_PIN(190, "P PAD VDDIO 23"),
+ PINCTRL_PIN(191, "PIO APP GPIO 19"),
+ PINCTRL_PIN(192, "PIO APP GPIO 18"),
+ PINCTRL_PIN(193, "PIO APP GPIO 17"),
+ PINCTRL_PIN(194, "PIO APP GPIO 16"),
+ PINCTRL_PIN(195, "PI CI D1"),
+ PINCTRL_PIN(196, "PI CI D0"),
+ PINCTRL_PIN(197, "PI CI HSYNC"),
+ PINCTRL_PIN(198, "PI CI VSYNC"),
+ PINCTRL_PIN(199, "PI CI EXT CLK"),
+ PINCTRL_PIN(200, "PO CI EXT RST N"),
+ PINCTRL_PIN(201, "P PAD VSSIO 43"),
+ PINCTRL_PIN(202, "P PAD VDDIO 43"),
+ PINCTRL_PIN(203, "PI CI D6"),
+ PINCTRL_PIN(204, "PI CI D7"),
+ PINCTRL_PIN(205, "PI CI D2"),
+ PINCTRL_PIN(206, "PI CI D3"),
+ PINCTRL_PIN(207, "PI CI D4"),
+ PINCTRL_PIN(208, "PI CI D5"),
+ PINCTRL_PIN(209, "PI CI D8"),
+ PINCTRL_PIN(210, "PI CI D9"),
+ PINCTRL_PIN(211, "P PAD VDD 20"),
+ PINCTRL_PIN(212, "P PAD GND 20"),
+ PINCTRL_PIN(213, "P PAD VSSIO 24"),
+ PINCTRL_PIN(214, "P PAD VDDIO 24"),
+ PINCTRL_PIN(215, "P PAD VDDIO 26"),
+ PINCTRL_PIN(216, "PO EMIF 1 A26"),
+ PINCTRL_PIN(217, "PO EMIF 1 A25"),
+ PINCTRL_PIN(218, "P PAD VSSIO 26"),
+ PINCTRL_PIN(219, "PO EMIF 1 A24"),
+ PINCTRL_PIN(220, "PO EMIF 1 A23"),
+ /* Pads along the bottom edge of the chip */
+ PINCTRL_PIN(221, "PO EMIF 1 A22"),
+ PINCTRL_PIN(222, "PO EMIF 1 A21"),
+ PINCTRL_PIN(223, "P PAD VDD 21"),
+ PINCTRL_PIN(224, "P PAD GND 21"),
+ PINCTRL_PIN(225, "P PAD VSSIO 27"),
+ PINCTRL_PIN(226, "P PAD VDDIO 27"),
+ PINCTRL_PIN(227, "PO EMIF 1 A20"),
+ PINCTRL_PIN(228, "PO EMIF 1 A19"),
+ PINCTRL_PIN(229, "PO EMIF 1 A18"),
+ PINCTRL_PIN(230, "PO EMIF 1 A17"),
+ PINCTRL_PIN(231, "P PAD VDDIO 28"),
+ PINCTRL_PIN(232, "P PAD VSSIO 28"),
+ PINCTRL_PIN(233, "PO EMIF 1 A16"),
+ PINCTRL_PIN(234, "PIO EMIF 1 D15"),
+ PINCTRL_PIN(235, "PO EMIF 1 A15"),
+ PINCTRL_PIN(236, "PIO EMIF 1 D14"),
+ PINCTRL_PIN(237, "P PAD VDD 22"),
+ PINCTRL_PIN(238, "P PAD GND 22"),
+ PINCTRL_PIN(239, "P PAD VSSIO 29"),
+ PINCTRL_PIN(240, "P PAD VDDIO 29"),
+ PINCTRL_PIN(241, "PO EMIF 1 A14"),
+ PINCTRL_PIN(242, "PIO EMIF 1 D13"),
+ PINCTRL_PIN(243, "PO EMIF 1 A13"),
+ PINCTRL_PIN(244, "PIO EMIF 1 D12"),
+ PINCTRL_PIN(245, "P PAD VSSIO 30"),
+ PINCTRL_PIN(246, "P PAD VDDIO 30"),
+ PINCTRL_PIN(247, "PO EMIF 1 A12"),
+ PINCTRL_PIN(248, "PIO EMIF 1 D11"),
+ PINCTRL_PIN(249, "PO EMIF 1 A11"),
+ PINCTRL_PIN(250, "PIO EMIF 1 D10"),
+ PINCTRL_PIN(251, "P PAD VSSIO 31"),
+ PINCTRL_PIN(252, "P PAD VDDIO 31"),
+ PINCTRL_PIN(253, "PO EMIF 1 A10"),
+ PINCTRL_PIN(254, "PIO EMIF 1 D09"),
+ PINCTRL_PIN(255, "PO EMIF 1 A09"),
+ PINCTRL_PIN(256, "P PAD VDDIO 32"),
+ PINCTRL_PIN(257, "P PAD VSSIO 32"),
+ PINCTRL_PIN(258, "P PAD GND 24"),
+ PINCTRL_PIN(259, "P PAD VDD 24"),
+ PINCTRL_PIN(260, "PIO EMIF 1 D08"),
+ PINCTRL_PIN(261, "PO EMIF 1 A08"),
+ PINCTRL_PIN(262, "PIO EMIF 1 D07"),
+ PINCTRL_PIN(263, "PO EMIF 1 A07"),
+ PINCTRL_PIN(264, "P PAD VDDIO 33"),
+ PINCTRL_PIN(265, "P PAD VSSIO 33"),
+ PINCTRL_PIN(266, "PIO EMIF 1 D06"),
+ PINCTRL_PIN(267, "PO EMIF 1 A06"),
+ PINCTRL_PIN(268, "PIO EMIF 1 D05"),
+ PINCTRL_PIN(269, "PO EMIF 1 A05"),
+ PINCTRL_PIN(270, "P PAD VDDIO 34"),
+ PINCTRL_PIN(271, "P PAD VSSIO 34"),
+ PINCTRL_PIN(272, "PIO EMIF 1 D04"),
+ PINCTRL_PIN(273, "PO EMIF 1 A04"),
+ PINCTRL_PIN(274, "PIO EMIF 1 D03"),
+ PINCTRL_PIN(275, "PO EMIF 1 A03"),
+ PINCTRL_PIN(276, "P PAD VDDIO 35"),
+ PINCTRL_PIN(277, "P PAD VSSIO 35"),
+ PINCTRL_PIN(278, "P PAD GND 23"),
+ PINCTRL_PIN(279, "P PAD VDD 23"),
+ PINCTRL_PIN(280, "PIO EMIF 1 D02"),
+ PINCTRL_PIN(281, "PO EMIF 1 A02"),
+ PINCTRL_PIN(282, "PIO EMIF 1 D01"),
+ PINCTRL_PIN(283, "PO EMIF 1 A01"),
+ PINCTRL_PIN(284, "P PAD VDDIO 36"),
+ PINCTRL_PIN(285, "P PAD VSSIO 36"),
+ PINCTRL_PIN(286, "PIO EMIF 1 D00"),
+ PINCTRL_PIN(287, "PO EMIF 1 BE1 N"),
+ PINCTRL_PIN(288, "PO EMIF 1 BE0 N"),
+ PINCTRL_PIN(289, "PO EMIF 1 ADV N"),
+ PINCTRL_PIN(290, "P PAD VDDIO 37"),
+ PINCTRL_PIN(291, "P PAD VSSIO 37"),
+ PINCTRL_PIN(292, "PO EMIF 1 SD CKE0"),
+ PINCTRL_PIN(293, "PO EMIF 1 OE N"),
+ PINCTRL_PIN(294, "PO EMIF 1 WE N"),
+ PINCTRL_PIN(295, "P PAD VDDIO 38"),
+ PINCTRL_PIN(296, "P PAD VSSIO 38"),
+ PINCTRL_PIN(297, "PO EMIF 1 CLK"),
+ PINCTRL_PIN(298, "PIO EMIF 1 SD CLK"),
+ PINCTRL_PIN(299, "P PAD VSSIO 45 (not bonded)"),
+ PINCTRL_PIN(300, "P PAD VDDIO 42"),
+ PINCTRL_PIN(301, "P PAD VSSIO 42"),
+ PINCTRL_PIN(302, "P PAD GND 31"),
+ PINCTRL_PIN(303, "P PAD VDD 31"),
+ PINCTRL_PIN(304, "PI EMIF 1 RET CLK"),
+ PINCTRL_PIN(305, "PI EMIF 1 WAIT N"),
+ PINCTRL_PIN(306, "PI EMIF 1 NFIF READY"),
+ PINCTRL_PIN(307, "PO EMIF 1 SD CKE1"),
+ PINCTRL_PIN(308, "PO EMIF 1 CS3 N"),
+ PINCTRL_PIN(309, "P PAD VDD 25"),
+ PINCTRL_PIN(310, "P PAD GND 25"),
+ PINCTRL_PIN(311, "P PAD VSSIO 39"),
+ PINCTRL_PIN(312, "P PAD VDDIO 39"),
+ PINCTRL_PIN(313, "PO EMIF 1 CS2 N"),
+ PINCTRL_PIN(314, "PO EMIF 1 CS1 N"),
+ PINCTRL_PIN(315, "PO EMIF 1 CS0 N"),
+ PINCTRL_PIN(316, "PO ETM TRACE PKT0"),
+ PINCTRL_PIN(317, "PO ETM TRACE PKT1"),
+ PINCTRL_PIN(318, "PO ETM TRACE PKT2"),
+ PINCTRL_PIN(319, "P PAD VDD 30"),
+ PINCTRL_PIN(320, "P PAD GND 30"),
+ PINCTRL_PIN(321, "P PAD VSSIO 44"),
+ PINCTRL_PIN(322, "P PAD VDDIO 44"),
+ PINCTRL_PIN(323, "PO ETM TRACE PKT3"),
+ PINCTRL_PIN(324, "PO ETM TRACE PKT4"),
+ PINCTRL_PIN(325, "PO ETM TRACE PKT5"),
+ PINCTRL_PIN(326, "PO ETM TRACE PKT6"),
+ PINCTRL_PIN(327, "PO ETM TRACE PKT7"),
+ PINCTRL_PIN(328, "PO ETM PIPE STAT0"),
+ PINCTRL_PIN(329, "P PAD VDD 26"),
+ PINCTRL_PIN(330, "P PAD GND 26"),
+ PINCTRL_PIN(331, "P PAD VSSIO 40"),
+ PINCTRL_PIN(332, "P PAD VDDIO 40"),
+ PINCTRL_PIN(333, "PO ETM PIPE STAT1"),
+ PINCTRL_PIN(334, "PO ETM PIPE STAT2"),
+ PINCTRL_PIN(335, "PO ETM TRACE CLK"),
+ PINCTRL_PIN(336, "PO ETM TRACE SYNC"),
+ PINCTRL_PIN(337, "PIO ACC GPIO 33"),
+ PINCTRL_PIN(338, "PIO ACC GPIO 32"),
+ PINCTRL_PIN(339, "PIO ACC GPIO 30"),
+ PINCTRL_PIN(340, "PIO ACC GPIO 29"),
+ PINCTRL_PIN(341, "P PAD VDDIO 17"),
+ PINCTRL_PIN(342, "P PAD VSSIO 17"),
+ PINCTRL_PIN(343, "P PAD GND 15"),
+ PINCTRL_PIN(344, "P PAD VDD 15"),
+ PINCTRL_PIN(345, "PIO ACC GPIO 28"),
+ PINCTRL_PIN(346, "PIO ACC GPIO 27"),
+ PINCTRL_PIN(347, "PIO ACC GPIO 16"),
+ PINCTRL_PIN(348, "PI TAP TMS"),
+ PINCTRL_PIN(349, "PI TAP TDI"),
+ PINCTRL_PIN(350, "PO TAP TDO"),
+ PINCTRL_PIN(351, "PI TAP RST N"),
+ /* Pads along the left edge of the chip */
+ PINCTRL_PIN(352, "PI EMU MODE 0"),
+ PINCTRL_PIN(353, "PO TAP RET CLK"),
+ PINCTRL_PIN(354, "PI TAP CLK"),
+ PINCTRL_PIN(355, "PO EMIF 0 SD CS N"),
+ PINCTRL_PIN(356, "PO EMIF 0 SD CAS N"),
+ PINCTRL_PIN(357, "PO EMIF 0 SD WE N"),
+ PINCTRL_PIN(358, "P PAD VDDIO 1"),
+ PINCTRL_PIN(359, "P PAD VSSIO 1"),
+ PINCTRL_PIN(360, "P PAD GND 1"),
+ PINCTRL_PIN(361, "P PAD VDD 1"),
+ PINCTRL_PIN(362, "PO EMIF 0 SD CKE"),
+ PINCTRL_PIN(363, "PO EMIF 0 SD DQML"),
+ PINCTRL_PIN(364, "PO EMIF 0 SD DQMU"),
+ PINCTRL_PIN(365, "PO EMIF 0 SD RAS N"),
+ PINCTRL_PIN(366, "PIO EMIF 0 D15"),
+ PINCTRL_PIN(367, "PO EMIF 0 A15"),
+ PINCTRL_PIN(368, "PIO EMIF 0 D14"),
+ PINCTRL_PIN(369, "PO EMIF 0 A14"),
+ PINCTRL_PIN(370, "PIO EMIF 0 D13"),
+ PINCTRL_PIN(371, "PO EMIF 0 A13"),
+ PINCTRL_PIN(372, "P PAD VDDIO 2"),
+ PINCTRL_PIN(373, "P PAD VSSIO 2"),
+ PINCTRL_PIN(374, "P PAD GND 2"),
+ PINCTRL_PIN(375, "P PAD VDD 2"),
+ PINCTRL_PIN(376, "PIO EMIF 0 D12"),
+ PINCTRL_PIN(377, "PO EMIF 0 A12"),
+ PINCTRL_PIN(378, "PIO EMIF 0 D11"),
+ PINCTRL_PIN(379, "PO EMIF 0 A11"),
+ PINCTRL_PIN(380, "PIO EMIF 0 D10"),
+ PINCTRL_PIN(381, "PO EMIF 0 A10"),
+ PINCTRL_PIN(382, "PIO EMIF 0 D09"),
+ PINCTRL_PIN(383, "PO EMIF 0 A09"),
+ PINCTRL_PIN(384, "PIO EMIF 0 D08"),
+ PINCTRL_PIN(385, "PO EMIF 0 A08"),
+ PINCTRL_PIN(386, "PIO EMIF 0 D07"),
+ PINCTRL_PIN(387, "PO EMIF 0 A07"),
+ PINCTRL_PIN(388, "P PAD VDDIO 3"),
+ PINCTRL_PIN(389, "P PAD VSSIO 3"),
+ PINCTRL_PIN(390, "P PAD GND 3"),
+ PINCTRL_PIN(391, "P PAD VDD 3"),
+ PINCTRL_PIN(392, "PO EFUSE RDOUT1"),
+ PINCTRL_PIN(393, "PIO EMIF 0 D06"),
+ PINCTRL_PIN(394, "PO EMIF 0 A06"),
+ PINCTRL_PIN(395, "PIO EMIF 0 D05"),
+ PINCTRL_PIN(396, "PO EMIF 0 A05"),
+ PINCTRL_PIN(397, "PIO EMIF 0 D04"),
+ PINCTRL_PIN(398, "PO EMIF 0 A04"),
+ PINCTRL_PIN(399, "A PADS/A VDDCO1v82v5 GND 80U SF LIN VDDCO AF"),
+ PINCTRL_PIN(400, "PWR VDDCO AF"),
+ PINCTRL_PIN(401, "PWR EFUSE HV1"),
+ PINCTRL_PIN(402, "P PAD VSSIO 4"),
+ PINCTRL_PIN(403, "P PAD VDDIO 4"),
+ PINCTRL_PIN(404, "P PAD GND 4"),
+ PINCTRL_PIN(405, "P PAD VDD 4"),
+ PINCTRL_PIN(406, "PIO EMIF 0 D03"),
+ PINCTRL_PIN(407, "PO EMIF 0 A03"),
+ PINCTRL_PIN(408, "PWR EFUSE HV2"),
+ PINCTRL_PIN(409, "PWR EFUSE HV3"),
+ PINCTRL_PIN(410, "PIO EMIF 0 D02"),
+ PINCTRL_PIN(411, "PO EMIF 0 A02"),
+ PINCTRL_PIN(412, "PIO EMIF 0 D01"),
+ PINCTRL_PIN(413, "P PAD VDDIO 5"),
+ PINCTRL_PIN(414, "P PAD VSSIO 5"),
+ PINCTRL_PIN(415, "P PAD GND 5"),
+ PINCTRL_PIN(416, "P PAD VDD 5"),
+ PINCTRL_PIN(417, "PO EMIF 0 A01"),
+ PINCTRL_PIN(418, "PIO EMIF 0 D00"),
+ PINCTRL_PIN(419, "IF 0 SD CLK"),
+ PINCTRL_PIN(420, "APP SPI CLK"),
+ PINCTRL_PIN(421, "APP SPI DO"),
+ PINCTRL_PIN(422, "APP SPI DI"),
+ PINCTRL_PIN(423, "APP SPI CS0"),
+ PINCTRL_PIN(424, "APP SPI CS1"),
+ PINCTRL_PIN(425, "APP SPI CS2"),
+ PINCTRL_PIN(426, "PIO APP GPIO 10"),
+ PINCTRL_PIN(427, "P PAD VDDIO 41"),
+ PINCTRL_PIN(428, "P PAD VSSIO 41"),
+ PINCTRL_PIN(429, "P PAD GND 6"),
+ PINCTRL_PIN(430, "P PAD VDD 6"),
+ PINCTRL_PIN(431, "PIO ACC SDIO0 CMD"),
+ PINCTRL_PIN(432, "PIO ACC SDIO0 CK"),
+ PINCTRL_PIN(433, "PIO ACC SDIO0 D3"),
+ PINCTRL_PIN(434, "PIO ACC SDIO0 D2"),
+ PINCTRL_PIN(435, "PIO ACC SDIO0 D1"),
+ PINCTRL_PIN(436, "PIO ACC SDIO0 D0"),
+ PINCTRL_PIN(437, "PIO USB PU"),
+ PINCTRL_PIN(438, "PIO USB SP"),
+ PINCTRL_PIN(439, "PIO USB DAT VP"),
+ PINCTRL_PIN(440, "PIO USB SE0 VM"),
+ PINCTRL_PIN(441, "PIO USB OE"),
+ PINCTRL_PIN(442, "PIO USB SUSP"),
+ PINCTRL_PIN(443, "P PAD VSSIO 6"),
+ PINCTRL_PIN(444, "P PAD VDDIO 6"),
+ PINCTRL_PIN(445, "PIO USB PUEN"),
+ PINCTRL_PIN(446, "PIO ACC UART0 RX"),
+ PINCTRL_PIN(447, "PIO ACC UART0 TX"),
+ PINCTRL_PIN(448, "PIO ACC UART0 CTS"),
+ PINCTRL_PIN(449, "PIO ACC UART0 RTS"),
+ PINCTRL_PIN(450, "PIO ACC UART3 RX"),
+ PINCTRL_PIN(451, "PIO ACC UART3 TX"),
+ PINCTRL_PIN(452, "PIO ACC UART3 CTS"),
+ PINCTRL_PIN(453, "PIO ACC UART3 RTS"),
+ PINCTRL_PIN(454, "PIO ACC IRDA TX"),
+ PINCTRL_PIN(455, "P PAD VDDIO 7"),
+ PINCTRL_PIN(456, "P PAD VSSIO 7"),
+ PINCTRL_PIN(457, "P PAD GND 7"),
+ PINCTRL_PIN(458, "P PAD VDD 7"),
+ PINCTRL_PIN(459, "PIO ACC IRDA RX"),
+ PINCTRL_PIN(460, "PIO ACC PCM I2S CLK"),
+ PINCTRL_PIN(461, "PIO ACC PCM I2S WS"),
+ PINCTRL_PIN(462, "PIO ACC PCM I2S DATA A"),
+ PINCTRL_PIN(463, "PIO ACC PCM I2S DATA B"),
+ PINCTRL_PIN(464, "PO SIM CLK"),
+ PINCTRL_PIN(465, "PIO ACC IRDA SD"),
+ PINCTRL_PIN(466, "PIO SIM DATA"),
+};
+
+/**
+ * @dev: a pointer back to containing device
+ * @virtbase: the offset to the controller in virtual memory
+ */
+struct u300_pmx {
+ struct device *dev;
+ struct pinctrl_dev *pctl;
+ u32 phybase;
+ u32 physize;
+ void __iomem *virtbase;
+};
+
+/**
+ * u300_pmx_registers - the array of registers read/written for each pinmux
+ * shunt setting
+ */
+const u32 u300_pmx_registers[] = {
+ U300_SYSCON_PMC1LR,
+ U300_SYSCON_PMC1HR,
+ U300_SYSCON_PMC2R,
+ U300_SYSCON_PMC3R,
+ U300_SYSCON_PMC4R,
+};
+
+/**
+ * struct u300_pin_group - describes a U300 pin group
+ * @name: the name of this specific pin group
+ * @pins: an array of discrete physical pins used in this group, taken
+ * from the driver-local pin enumeration space
+ * @num_pins: the number of pins in this group array, i.e. the number of
+ * elements in .pins so we can iterate over that array
+ */
+struct u300_pin_group {
+ const char *name;
+ const unsigned int *pins;
+ const unsigned num_pins;
+};
+
+/**
+ * struct pmx_onmask - mask bits to enable/disable padmux
+ * @mask: mask bits to disable
+ * @val: mask bits to enable
+ *
+ * onmask lazy dog:
+ * onmask = {
+ * {"PMC1LR" mask, "PMC1LR" value},
+ * {"PMC1HR" mask, "PMC1HR" value},
+ * {"PMC2R" mask, "PMC2R" value},
+ * {"PMC3R" mask, "PMC3R" value},
+ * {"PMC4R" mask, "PMC4R" value}
+ * }
+ */
+struct u300_pmx_mask {
+ u16 mask;
+ u16 bits;
+};
+
+/* The chip power pins are VDD, GND, VDDIO and VSSIO */
+static const unsigned power_pins[] = { 0, 1, 3, 31, 46, 47, 49, 50, 61, 62, 63,
+ 64, 78, 79, 80, 81, 92, 93, 94, 95, 101, 102, 103, 104, 115, 116, 117,
+ 118, 130, 131, 132, 133, 145, 146, 147, 148, 159, 160, 172, 173, 174,
+ 175, 187, 188, 189, 190, 201, 202, 211, 212, 213, 214, 215, 218, 223,
+ 224, 225, 226, 231, 232, 237, 238, 239, 240, 245, 246, 251, 252, 256,
+ 257, 258, 259, 264, 265, 270, 271, 276, 277, 278, 279, 284, 285, 290,
+ 291, 295, 296, 299, 300, 301, 302, 303, 309, 310, 311, 312, 319, 320,
+ 321, 322, 329, 330, 331, 332, 341, 342, 343, 344, 358, 359, 360, 361,
+ 372, 373, 374, 375, 388, 389, 390, 391, 402, 403, 404, 405, 413, 414,
+ 415, 416, 427, 428, 429, 430, 443, 444, 455, 456, 457, 458 };
+static const unsigned emif0_pins[] = { 355, 356, 357, 362, 363, 364, 365, 366,
+ 367, 368, 369, 370, 371, 376, 377, 378, 379, 380, 381, 382, 383, 384,
+ 385, 386, 387, 393, 394, 395, 396, 397, 398, 406, 407, 410, 411, 412,
+ 417, 418 };
+static const unsigned emif1_pins[] = { 216, 217, 219, 220, 221, 222, 227, 228,
+ 229, 230, 233, 234, 235, 236, 241, 242, 243, 244, 247, 248, 249, 250,
+ 253, 254, 255, 260, 261, 262, 263, 266, 267, 268, 269, 272, 273, 274,
+ 275, 280, 281, 282, 283, 286, 287, 288, 289, 292, 293, 294, 297, 298,
+ 304, 305, 306, 307, 308, 313, 314, 315 };
+static const unsigned uart0_pins[] = { 134, 135, 136, 137 };
+static const unsigned mmc0_pins[] = { 166, 167, 168, 169, 170, 171, 176, 177 };
+static const unsigned spi0_pins[] = { 420, 421, 422, 423, 424, 425 };
+
+static const struct u300_pmx_mask emif0_mask[] = {
+ {0, 0},
+ {0, 0},
+ {0, 0},
+ {0, 0},
+ {0, 0},
+};
+
+static const struct u300_pmx_mask emif1_mask[] = {
+ /*
+ * This connects the SDRAM to CS2 and a NAND flash to
+ * CS0 on the EMIF.
+ */
+ {
+ U300_SYSCON_PMC1LR_EMIF_1_CS2_MASK |
+ U300_SYSCON_PMC1LR_EMIF_1_CS1_MASK |
+ U300_SYSCON_PMC1LR_EMIF_1_CS0_MASK |
+ U300_SYSCON_PMC1LR_EMIF_1_MASK,
+ U300_SYSCON_PMC1LR_EMIF_1_CS2_SDRAM |
+ U300_SYSCON_PMC1LR_EMIF_1_CS1_STATIC |
+ U300_SYSCON_PMC1LR_EMIF_1_CS0_NFIF |
+ U300_SYSCON_PMC1LR_EMIF_1_SDRAM0
+ },
+ {0, 0},
+ {0, 0},
+ {0, 0},
+ {0, 0},
+};
+
+static const struct u300_pmx_mask uart0_mask[] = {
+ {0, 0},
+ {
+ U300_SYSCON_PMC1HR_APP_UART0_1_MASK |
+ U300_SYSCON_PMC1HR_APP_UART0_2_MASK,
+ U300_SYSCON_PMC1HR_APP_UART0_1_UART0 |
+ U300_SYSCON_PMC1HR_APP_UART0_2_UART0
+ },
+ {0, 0},
+ {0, 0},
+ {0, 0},
+};
+
+static const struct u300_pmx_mask mmc0_mask[] = {
+ { U300_SYSCON_PMC1LR_MMCSD_MASK, U300_SYSCON_PMC1LR_MMCSD_MMCSD},
+ {0, 0},
+ {0, 0},
+ {0, 0},
+ { U300_SYSCON_PMC4R_APP_MISC_12_MASK,
+ U300_SYSCON_PMC4R_APP_MISC_12_APP_GPIO }
+};
+
+static const struct u300_pmx_mask spi0_mask[] = {
+ {0, 0},
+ {
+ U300_SYSCON_PMC1HR_APP_SPI_2_MASK |
+ U300_SYSCON_PMC1HR_APP_SPI_CS_1_MASK |
+ U300_SYSCON_PMC1HR_APP_SPI_CS_2_MASK,
+ U300_SYSCON_PMC1HR_APP_SPI_2_SPI |
+ U300_SYSCON_PMC1HR_APP_SPI_CS_1_SPI |
+ U300_SYSCON_PMC1HR_APP_SPI_CS_2_SPI
+ },
+ {0, 0},
+ {0, 0},
+ {0, 0}
+};
+
+static const struct u300_pin_group u300_pin_groups[] = {
+ {
+ .name = "powergrp",
+ .pins = power_pins,
+ .num_pins = ARRAY_SIZE(power_pins),
+ },
+ {
+ .name = "emif0grp",
+ .pins = emif0_pins,
+ .num_pins = ARRAY_SIZE(emif0_pins),
+ },
+ {
+ .name = "emif1grp",
+ .pins = emif1_pins,
+ .num_pins = ARRAY_SIZE(emif1_pins),
+ },
+ {
+ .name = "uart0grp",
+ .pins = uart0_pins,
+ .num_pins = ARRAY_SIZE(uart0_pins),
+ },
+ {
+ .name = "mmc0grp",
+ .pins = mmc0_pins,
+ .num_pins = ARRAY_SIZE(mmc0_pins),
+ },
+ {
+ .name = "spi0grp",
+ .pins = spi0_pins,
+ .num_pins = ARRAY_SIZE(spi0_pins),
+ },
+};
+
+static int u300_list_groups(struct pinctrl_dev *pctldev, unsigned selector)
+{
+ if (selector >= ARRAY_SIZE(u300_pin_groups))
+ return -EINVAL;
+ return 0;
+}
+
+static const char *u300_get_group_name(struct pinctrl_dev *pctldev,
+ unsigned selector)
+{
+ if (selector >= ARRAY_SIZE(u300_pin_groups))
+ return NULL;
+ return u300_pin_groups[selector].name;
+}
+
+static int u300_get_group_pins(struct pinctrl_dev *pctldev, unsigned selector,
+ unsigned ** const pins,
+ unsigned * const num_pins)
+{
+ if (selector >= ARRAY_SIZE(u300_pin_groups))
+ return -EINVAL;
+ *pins = (unsigned *) u300_pin_groups[selector].pins;
+ *num_pins = u300_pin_groups[selector].num_pins;
+ return 0;
+}
+
+static void u300_pin_dbg_show(struct pinctrl_dev *pctldev, struct seq_file *s,
+ unsigned offset)
+{
+ seq_printf(s, " " DRIVER_NAME);
+}
+
+static struct pinctrl_ops u300_pctrl_ops = {
+ .list_groups = u300_list_groups,
+ .get_group_name = u300_get_group_name,
+ .get_group_pins = u300_get_group_pins,
+ .pin_dbg_show = u300_pin_dbg_show,
+};
+
+/*
+ * Here we define the available functions and their corresponding pin groups
+ */
+
+/**
+ * struct u300_pmx_func - describes U300 pinmux functions
+ * @name: the name of this specific function
+ * @groups: corresponding pin groups
+ * @onmask: bits to set to enable this when doing pin muxing
+ */
+struct u300_pmx_func {
+ const char *name;
+ const char * const *groups;
+ const unsigned num_groups;
+ const struct u300_pmx_mask *mask;
+};
+
+static const char * const powergrps[] = { "powergrp" };
+static const char * const emif0grps[] = { "emif0grp" };
+static const char * const emif1grps[] = { "emif1grp" };
+static const char * const uart0grps[] = { "uart0grp" };
+static const char * const mmc0grps[] = { "mmc0grp" };
+static const char * const spi0grps[] = { "spi0grp" };
+
+static const struct u300_pmx_func u300_pmx_functions[] = {
+ {
+ .name = "power",
+ .groups = powergrps,
+ .num_groups = ARRAY_SIZE(powergrps),
+ /* Mask is N/A */
+ },
+ {
+ .name = "emif0",
+ .groups = emif0grps,
+ .num_groups = ARRAY_SIZE(emif0grps),
+ .mask = emif0_mask,
+ },
+ {
+ .name = "emif1",
+ .groups = emif1grps,
+ .num_groups = ARRAY_SIZE(emif1grps),
+ .mask = emif1_mask,
+ },
+ {
+ .name = "uart0",
+ .groups = uart0grps,
+ .num_groups = ARRAY_SIZE(uart0grps),
+ .mask = uart0_mask,
+ },
+ {
+ .name = "mmc0",
+ .groups = mmc0grps,
+ .num_groups = ARRAY_SIZE(mmc0grps),
+ .mask = mmc0_mask,
+ },
+ {
+ .name = "spi0",
+ .groups = spi0grps,
+ .num_groups = ARRAY_SIZE(spi0grps),
+ .mask = spi0_mask,
+ },
+};
+
+static void u300_pmx_endisable(struct u300_pmx *upmx, unsigned selector,
+ bool enable)
+{
+ u16 regval, val, mask;
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(u300_pmx_registers); i++) {
+ if (enable)
+ val = u300_pmx_functions[selector].mask->bits;
+ else
+ val = 0;
+
+ mask = u300_pmx_functions[selector].mask->mask;
+ if (mask != 0) {
+ regval = readw(upmx->virtbase + u300_pmx_registers[i]);
+ regval &= ~mask;
+ regval |= val;
+ writew(regval, upmx->virtbase + u300_pmx_registers[i]);
+ }
+ }
+}
+
+static int u300_pmx_enable(struct pinctrl_dev *pctldev, unsigned selector,
+ unsigned group)
+{
+ struct u300_pmx *upmx;
+
+ /* There is nothing to do with the power pins */
+ if (selector == 0)
+ return 0;
+
+ upmx = pctldev_get_drvdata(pctldev);
+ u300_pmx_endisable(upmx, selector, true);
+
+ return 0;
+}
+
+static void u300_pmx_disable(struct pinctrl_dev *pctldev, unsigned selector,
+ unsigned group)
+{
+ struct u300_pmx *upmx;
+
+ /* There is nothing to do with the power pins */
+ if (selector == 0)
+ return;
+
+ upmx = pctldev_get_drvdata(pctldev);
+ u300_pmx_endisable(upmx, selector, false);
+}
+
+static int u300_pmx_list_funcs(struct pinctrl_dev *pctldev, unsigned selector)
+{
+ if (selector >= ARRAY_SIZE(u300_pmx_functions))
+ return -EINVAL;
+ return 0;
+}
+
+static const char *u300_pmx_get_func_name(struct pinctrl_dev *pctldev,
+ unsigned selector)
+{
+ return u300_pmx_functions[selector].name;
+}
+
+static int u300_pmx_get_groups(struct pinctrl_dev *pctldev, unsigned selector,
+ const char * const **groups,
+ unsigned * const num_groups)
+{
+ *groups = u300_pmx_functions[selector].groups;
+ *num_groups = u300_pmx_functions[selector].num_groups;
+ return 0;
+}
+
+static struct pinmux_ops u300_pmx_ops = {
+ .list_functions = u300_pmx_list_funcs,
+ .get_function_name = u300_pmx_get_func_name,
+ .get_function_groups = u300_pmx_get_groups,
+ .enable = u300_pmx_enable,
+ .disable = u300_pmx_disable,
+};
+
+/*
+ * FIXME: this will be set to sane values as this driver engulfs
+ * drivers/gpio/gpio-u300.c and we really know this stuff.
+ */
+static struct pinctrl_gpio_range u300_gpio_range = {
+ .name = "COH901*",
+ .id = 0,
+ .base = 0,
+ .npins = 64,
+};
+
+static struct pinctrl_desc u300_pmx_desc = {
+ .name = DRIVER_NAME,
+ .pins = u300_pads,
+ .npins = ARRAY_SIZE(u300_pads),
+ .maxpin = U300_NUM_PADS-1,
+ .pctlops = &u300_pctrl_ops,
+ .pmxops = &u300_pmx_ops,
+ .owner = THIS_MODULE,
+};
+
+static int __init u300_pmx_probe(struct platform_device *pdev)
+{
+ int ret;
+ struct u300_pmx *upmx;
+ struct resource *res;
+
+ /* Create state holders etc for this driver */
+ upmx = devm_kzalloc(&pdev->dev, sizeof(*upmx), GFP_KERNEL);
+ if (!upmx)
+ return -ENOMEM;
+
+ upmx->dev = &pdev->dev;
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ if (!res) {
+ ret = -ENOENT;
+ goto out_no_resource;
+ }
+ upmx->phybase = res->start;
+ upmx->physize = resource_size(res);
+
+ if (request_mem_region(upmx->phybase, upmx->physize,
+ DRIVER_NAME) == NULL) {
+ ret = -EBUSY;
+ goto out_no_memregion;
+ }
+
+ upmx->virtbase = ioremap(upmx->phybase, upmx->physize);
+ if (!upmx->virtbase) {
+ ret = -ENOMEM;
+ goto out_no_remap;
+ }
+
+ upmx->pctl = pinctrl_register(&u300_pmx_desc, &pdev->dev, upmx);
+ if (IS_ERR(upmx->pctl)) {
+ dev_err(&pdev->dev, "could not register U300 pinmux driver\n");
+ ret = PTR_ERR(upmx->pctl);
+ goto out_no_pmx;
+ }
+
+ /* We will handle a range of GPIO pins */
+ pinctrl_add_gpio_range(upmx->pctl, &u300_gpio_range);
+
+ platform_set_drvdata(pdev, upmx);
+
+ dev_info(&pdev->dev, "initialized U300 pinmux driver\n");
+
+ return 0;
+
+out_no_pmx:
+ iounmap(upmx->virtbase);
+out_no_remap:
+ platform_set_drvdata(pdev, NULL);
+out_no_memregion:
+ release_mem_region(upmx->phybase, upmx->physize);
+out_no_resource:
+ devm_kfree(&pdev->dev, upmx);
+ return ret;
+}
+
+static int __exit u300_pmx_remove(struct platform_device *pdev)
+{
+ struct u300_pmx *upmx = platform_get_drvdata(pdev);
+
+ pinctrl_remove_gpio_range(upmx->pctl, &u300_gpio_range);
+ pinctrl_unregister(upmx->pctl);
+ iounmap(upmx->virtbase);
+ release_mem_region(upmx->phybase, upmx->physize);
+ platform_set_drvdata(pdev, NULL);
+ devm_kfree(&pdev->dev, upmx);
+
+ return 0;
+}
+
+static struct platform_driver u300_pmx_driver = {
+ .driver = {
+ .name = DRIVER_NAME,
+ .owner = THIS_MODULE,
+ },
+ .remove = __exit_p(u300_pmx_remove),
+};
+
+static int __init u300_pmx_init(void)
+{
+ return platform_driver_probe(&u300_pmx_driver, u300_pmx_probe);
+}
+arch_initcall(u300_pmx_init);
+
+static void __exit u300_pmx_exit(void)
+{
+ platform_driver_unregister(&u300_pmx_driver);
+}
+module_exit(u300_pmx_exit);
+
+MODULE_AUTHOR("Linus Walleij <linus.walleij@linaro.org>");
+MODULE_DESCRIPTION("U300 pin control driver");
+MODULE_LICENSE("GPL v2");
--
1.7.3.2
^ permalink raw reply related
* [PATCH v3] pinmux: add a driver for the CSR SiRFprimaII pinmux
From: Linus Walleij @ 2011-10-10 8:31 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1318155073-28038-1-git-send-email-Barry.Song@csr.com>
On Sun, Oct 9, 2011 at 12:11 PM, Barry Song <Barry.Song@csr.com> wrote:
> From: Rongjun Ying <Rongjun.Ying@csr.com>
>
> Signed-off-by: Rongjun Ying <Rongjun.Ying@csr.com>
> Signed-off-by: Barry Song <Baohua.Song@csr.com>
> ---
> ?-v3:
> ?rebase to Linux W's v9;
> ?use preprocessor to shorten pin function lists;
This is looking good.
I have signed this off and merged it to my tree.
Yours,
Linus Walleij
^ permalink raw reply
* [PATCH 5/9] ARM: SPMP8000: Add pinmux driver
From: Linus Walleij @ 2011-10-10 8:34 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <CAGsJ_4zaqk_ECjaCXPeYJMRASE1zND+cZ2cwaLYVDhaVjsfSVw@mail.gmail.com>
On Mon, Oct 10, 2011 at 10:01 AM, Barry Song <21cnbao@gmail.com> wrote:
> And Linus, can you help to take care prima2 pinmux driver v3 i sent
> yesterday and make sure it is merged in the window too.
> our lots of device drivers depend on it, so i'd like it is ready
> before we upstream lots of other drivers.
It is taken care of and queued for the merge window :-)
If it gets merged in the end is up to Torvalds.
Yours,
Linus Walleij
^ permalink raw reply
* [PATCH 7/9] ARM: SPMP8000: Add dts file of SPMP8000 SoC and Letcool board
From: Jamie Iles @ 2011-10-10 8:54 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1318178172-7965-8-git-send-email-zoss@devai.org>
Hi Zoltan,
Just minor comments again. Also, if you could cc all device tree stuff
to devicetree-discuss at lists.ozlabs.org then you'll get a wider audience
for these bits.
Jamie
On Sun, Oct 09, 2011 at 06:36:10PM +0200, Zoltan Devai wrote:
> Signed-off-by: Zoltan Devai <zoss@devai.org>
> ---
> arch/arm/boot/dts/spmp8000-letcool.dts | 163 ++++++++++++++++++++++++++++++
> arch/arm/boot/dts/spmp8000.dtsi | 169 ++++++++++++++++++++++++++++++++
> 2 files changed, 332 insertions(+), 0 deletions(-)
> create mode 100644 arch/arm/boot/dts/spmp8000-letcool.dts
> create mode 100644 arch/arm/boot/dts/spmp8000.dtsi
>
> diff --git a/arch/arm/boot/dts/spmp8000-letcool.dts b/arch/arm/boot/dts/spmp8000-letcool.dts
> new file mode 100644
> index 0000000..270f00e
> --- /dev/null
> +++ b/arch/arm/boot/dts/spmp8000-letcool.dts
> @@ -0,0 +1,163 @@
> +/dts-v1/;
> +/include/ "spmp8000.dtsi"
> +/ {
> + model = "Letcool N350JP handheld game console";
> + compatible = "gameware,letcool", "sunplus,spmp8000";
> +
> + memory {
> + reg = <0x00000000 0x02000000>;
> + };
> +
> + chosen {
> + bootargs = "console=tty0 mem=32M root=/dev/mmcblk0p1 console=ttyS0,115200 rootdelay=5 loglevel=8 earlyprintk";
It's preferred to keep bootargs in the bootloader if at all possible.
> + linux,stdout-path = &uart0;
> + };
> +
> + pwm-backlight {
> + compatible = "pwm-backlight";
> + reg = <0 0>; /* Hack to pass platform data as AUXDATA */
> + };
> +
> + plat {
> + plat-apb {
> + mmc at 92B0B000 {
> + cd-gpios = <&gpio0 9 0>;
> + };
> + };
> + };
> +
> + armapb {
> + gpio at 9000A000 {
> + polarity = <0>;
> + sticky = <0>;
> + direction = <0xFFFFFFFF>;
> + debounce-val = <100>;
> + debounce = <0xFFFFFFFF>;
> + };
> +
> + gpio at 9000A004 {
> + polarity = <0>;
> + sticky = <0>;
> + direction = <0xFFFFFFFF>;
> + debounce-val = <100>;
> + debounce = <0xFFFFFFFF>;
> + };
> + };
> +
> + gpio-keys {
> + compatible = "gpio-keys";
> + #address-cells = <1>;
> + #size-cells = <0>;
> + autorepeat;
> +
> + up {
> + label = "D-Pad Up";
> + gpios = <&gpio0 0 0>;
> + linux,code = <103>; /* KEY_UP */
> + gpio-key,wakeup;
> + };
> +
> + right {
> + label = "D-Pad Right";
> + gpios = <&gpio0 1 0>;
> + linux,code = <106>; /* KEY_RIGHT */
> + gpio-key,wakeup;
> + };
> +
> + down {
> + label = "D-Pad Down";
> + gpios = <&gpio0 2 0>;
> + linux,code = <108>; /* KEY_DOWN */
> + gpio-key,wakeup;
> + };
> +
> + left {
> + label = "D-Pad Left";
> + gpios = <&gpio0 3 0>;
> + linux,code = <105>; /* KEY_LEFT */
> + gpio-key,wakeup;
> + };
> +
> + button-x {
> + label = "Button X";
> + gpios = <&gpio0 4 0>;
> + linux,code = <45>; /* KEY_X */
> + gpio-key,wakeup;
> + };
> +
> + button-a {
> + label = "Button A";
> + gpios = <&gpio0 5 0>;
> + linux,code = <30>; /* KEY_A */
> + gpio-key,wakeup;
> + };
> +
> + button-y {
> + label = "Button Y";
> + gpios = <&gpio0 6 0>;
> + linux,code = <21>; /* KEY_Y */
> + gpio-key,wakeup;
> + };
> +
> + button-b {
> + label = "Button B";
> + gpios = <&gpio0 7 0>;
> + linux,code = <48>; /* KEY_B */
> + gpio-key,wakeup;
> + };
> + };
> +
> + analog-keys {
> + compatible = "spmp8000-ak";
> +
> + channel-1 {
> + adc-channel = <1>;
> + idle-value = <0>;
> + tolerance = <10>;
> +
> + button-left {
> + adc-value = <0x00B0>;
> + linux,code = <0x110>; /* BTN_LEFT */
> + };
> +
> + button-right {
> + adc-value = <0xFEAB>;
> + linux,code = <0x111>; /* BTN_RIGHT */
> + };
> +
> + button-volup {
> + adc-value = <0x015E>;
> + linux,code = <115>; /* KEY_VOLUMEUP */
> + };
> +
> + button-voldown {
> + adc-value = <0xFF56>;
> + linux,code = <114>; /* KEY_VOLUMEDOWN */
> + };
> + };
> +
> + channel-3 {
> + adc-channel = <3>;
> + idle-value = <5>;
> + tolerance = <10>;
> +
> + button-select {
> + adc-value = <0x0113>;
> + linux,code = <0x13a>; /* BTN_SELECT */
> + };
> +
> + button-start {
> + adc-value = <0xFEF7>;
> + linux,code = <0x13b>; /* BTN_START */
> + };
> + };
> +
> + };
> +
> + snd-card {
> + compatible = "spmp8000-sndcard";
> + hp-detect-gpios = <&gpio0 8 0>;
> + spk-enable-gpios = <&gpio3 12 0>;
> + };
> +
> +};
> diff --git a/arch/arm/boot/dts/spmp8000.dtsi b/arch/arm/boot/dts/spmp8000.dtsi
> new file mode 100644
> index 0000000..74764b2c6
> --- /dev/null
> +++ b/arch/arm/boot/dts/spmp8000.dtsi
> @@ -0,0 +1,169 @@
> +/ {
> + compatible = "sunplus,spmp8000";
> + #address-cells = <1>;
> + #size-cells = <1>;
> +
> + armapb {
> + compatible = "simple-bus";
> + #address-cells = <1>;
> + #size-cells = <1>;
> + ranges = <0x90000000 0x90000000 0x10000>;
I'm not sure you need a ranges property like this as it isn't doing any
translation. I think it would be nicer to have ranges = <0 0x90000000
0x10000> and use bus local addresses for the child nodes.
> + timer at 90000000 {
> + compatible = "sunplus,spmp8000-timer";
> + reg = <0x90000000 0x1000>;
> + interrupt-parent = <&vic0>;
> + interrupts = <7 8 9>;
> + };
> +
> + pwm at 90000000 {
> + compatible = "sunplus,spmp8000-pwm";
> + reg = <0x90000000 0x1000>;
> + id = <0>;
This is probably a little too generic. sunplus,pwm-id ?
> + };
> +
> + gpio3: gpio at 90005070 {
> + compatible = "basic-mmio-gpio"; /* No DT binding yet */
I did start work on a binding
(http://lists.ozlabs.org/pipermail/devicetree-discuss/2011-August/007137.html)
but it hasn't moved along too far. Thinking about it a little more
though I'm not sure that the generic binding is quite the right approach
if we need to handle gpio's that can generate interrupts too though.
> + reg = <0x90005070 0xC>;
> + gpio-controller;
> + #gpio-cells = <2>;
> + };
> +
> + gpio0: gpio at 9000A000 {
> + compatible = "sunplus,spmp8000-gpio";
> + reg = <0x9000A000 0x1000>;
> + interrupt-parent = <&vic1>;
> + interrupts = <0>;
> + gpio-controller;
> + #gpio-cells = <2>;
> + bits = <16>;
sunplus,nr-gpios?
> + interrupt-controller;
> + #interrupt-cells = <1>;
> + };
> +
> + gpio1: gpio at 9000A004 {
> + compatible = "sunplus,spmp8000-gpio";
> + reg = <0x9000A004 0x1000>;
> + interrupt-parent = <&vic1>;
> + interrupts = <1>;
> + gpio-controller;
> + #gpio-cells = <2>;
> + bits = <32>;
> + interrupt-controller;
> + #interrupt-cells = <1>;
> + };
> + };
> +
> + armahb {
> + compatible = "simple-bus";
> + #address-cells = <1>;
> + #size-cells = <1>;
> + ranges = <0x90010000 0x90010000 0x20000>;
> +
> + vic0: interrupt-controller at 90010000 {
> + compatible = "arm,pl192";
> + interrupt-controller;
> + #interrupt-cells = <1>;
> + reg = <0x90010000 0x1000>;
> + };
> +
> + vic1: interrupt-controller at 900020000 {
> + compatible = "arm,pl192";
> + interrupt-controller;
> + #interrupt-cells = <1>;
> + reg = <0x90020000 0x1000>;
> + };
> + };
> +
> + plat {
> + compatible = "simple-bus";
> + #address-cells = <1>;
> + #size-cells = <1>;
> + ranges = <0x92000000 0x92000000 0x1000000>;
> +
> + plat-apb {
Why are there 2 levels of nesting here? Can't the child nodes of
plat-apb just be under plat?
> + compatible = "simple-bus";
> + #address-cells = <1>;
> + #size-cells = <1>;
> + ranges = <0x92B00000 0x92B00000 0x10000>;
> +
> + dma at 92B00000 {
> + compatible = "sunplus,spmp8000-apbdma-c";
> + reg = <0x92B00000 0x1000>;
> + interrupt-parent = <&vic1>;
> + interrupts = <28 29 30 31>;
> + };
> +
> + uart0: uart-c0 at 92B04000 {
> + compatible = "ns16550a";
> + reg = <0x92B04000 0x1000>;
> + clock-frequency = <2076923>;
> + interrupt-parent = <&vic1>;
> + interrupts = <24>;
> + current-speed = <115200>;
> + reg-shift = <2>;
> + };
> +
> + mmc at 92B0B000 {
> + compatible = "sunplus,mmc";
> + reg = <0x92B0B000 0x1000>;
> + interrupt-parent = <&vic1>;
> + interrupts = <8>;
> + };
> + };
> + };
> +
> + axi {
> + compatible = "simple-bus";
> + #address-cells = <1>;
> + #size-cells = <1>;
> + ranges = <0x93000000 0x93000000 0x800000>;
> +
> + fb at 93000000 {
> + compatible = "sunplus,spmp8000-lcd";
> + reg = <0x93000000 0x1000>;
> + interrupt-parent = <&vic0>;
> + interrupts = <23>;
> + };
> +
> + axi-apb {
> + compatible = "simple-bus";
> + #address-cells = <1>;
> + #size-cells = <1>;
> + ranges = <0x93010000 0x93010000 0x10000>;
> +
> + dma at 93010000 {
> + compatible = "sunplus,spmp8000-apbdma-a";
> + reg = <0x93010000 0x1000>;
> + interrupt-parent = <&vic0>;
> + interrupts = <24 25 26 27>;
> + };
> +
> + i2s at 93012000 {
> + compatible = "sunplus,spmp8000-i2s-tx";
> + reg = <0x93012000 0x1000>;
> + interrupt-parent = <&vic0>;
> + interrupts = <13>;
> + };
> +
> + i2s at 9301D000 {
> + compatible = "sunplus,spmp8000-i2s-rx";
> + reg = <0x9301D000 0x1000>;
> + interrupt-parent = <&vic0>;
> + interrupts = <14>;
> + };
> +
> + adc at 9301F000 {
> + compatible = "sunplus,spmp8000-adc";
> + reg = <0x9301F000 0x20>;
> + interrupt-parent = <&vic1>;
> + interrupts = <27>;
> + };
> +
> + codec at 9301F020 {
> + compatible = "sunplus,spmp8000-codec";
> + reg = <0x9301F020 0x20>;
> + };
> + };
> + };
> +};
> --
> 1.7.4.1
>
>
> _______________________________________________
> linux-arm-kernel mailing list
> linux-arm-kernel at lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply
* Add support for the SPMP8000 SoC and Letcool board
From: Jamie Iles @ 2011-10-10 8:55 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1318178172-7965-1-git-send-email-zoss@devai.org>
On Sun, Oct 09, 2011 at 06:36:03PM +0200, Zoltan Devai wrote:
> Hi,
>
> This series adds support for the Sunplus SPMP8000 SoC, an ARM926EJ-S based
> MCU, which is most commonly found in handheld game consoles and digital cams.
> Most of the work was done during GSoC 2011, with Greg KH as my mentor.
>
> The board I'm using for development is the Letcool N350JP handheld.
>
> The patches are based on Arnds for-next branch with Jamie Iles' vic-dt patches
> on top.
Excellent! Can I take that as a Tested-by from you for that series?
Jamie
^ permalink raw reply
* [PATCH 1/5 v4] ARM Realview PCIX map include file changes
From: Colin Tuckley @ 2011-10-10 9:27 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20111007192224.GB25689@n2100.arm.linux.org.uk>
> -----Original Message-----
> From: Russell King - ARM Linux [mailto:linux at arm.linux.org.uk]
> Subject: Re: [PATCH 1/5 v4] ARM Realview PCIX map include file changes
> > +#define IO_SPACE_LIMIT 0x0000ffff
>
> Does this in asm/io.h:
>
> #ifndef IO_SPACE_LIMIT
> #if defined(CONFIG_PCMCIA_SOC_COMMON) ||
> defined(CONFIG_PCMCIA_SOC_COMMON_MODULE)
> #define IO_SPACE_LIMIT ((resource_size_t)0xffffffff)
> #elif defined(CONFIG_PCI) || defined(CONFIG_ISA) ||
> defined(CONFIG_PCCARD)
> #define IO_SPACE_LIMIT ((resource_size_t)0xffff)
> #else
> #define IO_SPACE_LIMIT ((resource_size_t)0)
> #endif
> #endif
>
> not work here for some reason? I think as PCMCIA_SOC_COMMON would not
> be
> defined, but CONFIG_PCI would be, it'd give the correct answer. Please
> confirm.
Ah, I wasn't aware of that. However when I include asm/io.h and remove the
explicit definition of IO_SPACE_LIMIT I get compilation errors in
arch/arm/kernel/bios32.c and arch/arm/mm/iomap.c for " 'IO_SPACE_LIMIT'
undeclared.
A quick check shows that the piece of code you quote above does not exist in
my (3.1.0-rc9) source tree.
Colin
^ permalink raw reply
* [PATCH v2] ARM: EXYNOS4: Add support for M-5MOLS camera on Nuri board
From: Sylwester Nawrocki @ 2011-10-10 9:29 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <034f01cc8705$199b0dc0$4cd12940$%kim@samsung.com>
Add voltage regulator and platform data definition for M-5MOLS sensor
and MIPI-CSI receiver drivers. Add CAM power domain dependencies for
FIMC device and set up camera port A GPIO. Configure I2C0 bus timings.
Signed-off-by: Sylwester Nawrocki <s.nawrocki@samsung.com>
Signed-off-by: HeungJun Kim <riverful.kim@samsung.com>
Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
---
Hi Kgene,
I have corrected the white space issues as you pointed out and removed
unnecessary gpio_free() in this patch.
Thanks,
Sylwester
---
arch/arm/mach-exynos4/Kconfig | 8 ++
arch/arm/mach-exynos4/mach-nuri.c | 156 +++++++++++++++++++++++++++++++++++++
2 files changed, 164 insertions(+), 0 deletions(-)
diff --git a/arch/arm/mach-exynos4/Kconfig b/arch/arm/mach-exynos4/Kconfig
index dd660eb..4bc4b1f 100644
--- a/arch/arm/mach-exynos4/Kconfig
+++ b/arch/arm/mach-exynos4/Kconfig
@@ -215,6 +215,7 @@ config MACH_UNIVERSAL_C210
config MACH_NURI
bool "Mobile NURI Board"
select CPU_EXYNOS4210
+ select S5P_GPIO_INT
select S3C_DEV_WDT
select S3C_DEV_RTC
select S5P_DEV_FIMD0
@@ -224,9 +225,16 @@ config MACH_NURI
select S3C_DEV_I2C1
select S3C_DEV_I2C3
select S3C_DEV_I2C5
+ select S5P_DEV_CSIS0
+ select S5P_DEV_FIMC0
+ select S5P_DEV_FIMC1
+ select S5P_DEV_FIMC2
+ select S5P_DEV_FIMC3
select S5P_DEV_MFC
select S5P_DEV_USB_EHCI
+ select S5P_SETUP_MIPIPHY
select EXYNOS4_DEV_PD
+ select EXYNOS4_SETUP_FIMC
select EXYNOS4_SETUP_FIMD0
select EXYNOS4_SETUP_I2C1
select EXYNOS4_SETUP_I2C3
diff --git a/arch/arm/mach-exynos4/mach-nuri.c b/arch/arm/mach-exynos4/mach-nuri.c
index bbd13f4..f5cecd8 100644
--- a/arch/arm/mach-exynos4/mach-nuri.c
+++ b/arch/arm/mach-exynos4/mach-nuri.c
@@ -27,6 +27,9 @@
#include <linux/pwm_backlight.h>
#include <video/platform_lcd.h>
+#include <media/m5mols.h>
+#include <media/s5p_fimc.h>
+#include <media/v4l2-mediabus.h>
#include <asm/mach/arch.h>
#include <asm/mach-types.h>
@@ -45,6 +48,9 @@
#include <plat/iic.h>
#include <plat/mfc.h>
#include <plat/pd.h>
+#include <plat/fimc-core.h>
+#include <plat/camport.h>
+#include <plat/mipi_csis.h>
#include <mach/map.h>
@@ -65,6 +71,8 @@
enum fixed_regulator_id {
FIXED_REG_ID_MMC = 0,
FIXED_REG_ID_MAX8903,
+ FIXED_REG_ID_CAM_A28V,
+ FIXED_REG_ID_CAM_12V,
};
static struct s3c2410_uartcfg nuri_uartcfgs[] __initdata = {
@@ -1117,10 +1125,145 @@ static void __init nuri_ehci_init(void)
s5p_ehci_set_platdata(pdata);
}
+/* CAMERA */
+static struct regulator_consumer_supply cam_vdda_supply[] = {
+ REGULATOR_SUPPLY("a_sensor", "0-001f"),
+};
+
+static struct regulator_init_data cam_vdda_reg_init_data = {
+ .constraints = { .valid_ops_mask = REGULATOR_CHANGE_STATUS },
+ .num_consumer_supplies = ARRAY_SIZE(cam_vdda_supply),
+ .consumer_supplies = cam_vdda_supply,
+};
+
+static struct fixed_voltage_config cam_vdda_fixed_voltage_cfg = {
+ .supply_name = "CAM_IO_EN",
+ .microvolts = 2800000,
+ .gpio = EXYNOS4_GPE2(1), /* CAM_IO_EN */
+ .enable_high = 1,
+ .init_data = &cam_vdda_reg_init_data,
+};
+
+static struct platform_device cam_vdda_fixed_rdev = {
+ .name = "reg-fixed-voltage", .id = FIXED_REG_ID_CAM_A28V,
+ .dev = { .platform_data = &cam_vdda_fixed_voltage_cfg },
+};
+
+static struct regulator_consumer_supply camera_8m_12v_supply =
+ REGULATOR_SUPPLY("dig_12", "0-001f");
+
+static struct regulator_init_data cam_8m_12v_reg_init_data = {
+ .num_consumer_supplies = 1,
+ .consumer_supplies = &camera_8m_12v_supply,
+ .constraints = {
+ .valid_ops_mask = REGULATOR_CHANGE_STATUS
+ },
+};
+
+static struct fixed_voltage_config cam_8m_12v_fixed_voltage_cfg = {
+ .supply_name = "8M_1.2V",
+ .microvolts = 1200000,
+ .gpio = EXYNOS4_GPE2(5), /* 8M_1.2V_EN */
+ .enable_high = 1,
+ .init_data = &cam_8m_12v_reg_init_data,
+};
+
+static struct platform_device cam_8m_12v_fixed_rdev = {
+ .name = "reg-fixed-voltage", .id = FIXED_REG_ID_CAM_12V,
+ .dev = { .platform_data = &cam_8m_12v_fixed_voltage_cfg },
+};
+
+static struct s5p_platform_mipi_csis mipi_csis_platdata = {
+ .clk_rate = 166000000UL,
+ .lanes = 2,
+ .alignment = 32,
+ .hs_settle = 12,
+ .phy_enable = s5p_csis_phy_enable,
+};
+
+#define GPIO_CAM_MEGA_RST EXYNOS4_GPY3(7) /* ISP_RESET */
+#define GPIO_CAM_8M_ISP_INT EXYNOS4_GPL2(5)
+
+static struct m5mols_platform_data m5mols_platdata = {
+ .gpio_reset = GPIO_CAM_MEGA_RST,
+};
+
+static struct i2c_board_info m5mols_board_info = {
+ I2C_BOARD_INFO("M5MOLS", 0x1F),
+ .platform_data = &m5mols_platdata,
+};
+
+static struct s5p_fimc_isp_info nuri_camera_sensors[] = {
+ {
+ .flags = V4L2_MBUS_PCLK_SAMPLE_FALLING |
+ V4L2_MBUS_VSYNC_ACTIVE_LOW,
+ .bus_type = FIMC_MIPI_CSI2,
+ .board_info = &m5mols_board_info,
+ .clk_frequency = 24000000UL,
+ .csi_data_align = 32,
+ },
+};
+
+static struct s5p_platform_fimc fimc_md_platdata = {
+ .isp_info = nuri_camera_sensors,
+ .num_clients = ARRAY_SIZE(nuri_camera_sensors),
+};
+
+struct platform_device s5p_device_fimc_md = {
+ .name = "s5p-fimc-md",
+ .id = -1,
+};
+
+static struct gpio nuri_camera_gpios[] = {
+ { GPIO_CAM_8M_ISP_INT, GPIOF_IN, "8M_ISP_INT" },
+ { GPIO_CAM_MEGA_RST, GPIOF_OUT_INIT_LOW, "CAM_8M_NRST" },
+};
+
+static void nuri_camera_init(void)
+{
+ s3c_set_platdata(&mipi_csis_platdata, sizeof(mipi_csis_platdata),
+ &s5p_device_mipi_csis0);
+ s3c_set_platdata(&fimc_md_platdata, sizeof(fimc_md_platdata),
+ &s5p_device_fimc_md);
+
+ if (gpio_request_array(nuri_camera_gpios,
+ ARRAY_SIZE(nuri_camera_gpios))) {
+ pr_err("%s: GPIO request failed\n", __func__);
+ return;
+ }
+
+ m5mols_board_info.irq = s5p_register_gpio_interrupt(GPIO_CAM_8M_ISP_INT);
+ if (!IS_ERR_VALUE(m5mols_board_info.irq))
+ s3c_gpio_cfgpin(GPIO_CAM_8M_ISP_INT, S3C_GPIO_SFN(0xF));
+ else
+ pr_err("%s: Failed to configure 8M_ISP_INT GPIO\n", __func__);
+
+ /* Free GPIOs controlled directly by the sensor drivers. */
+ gpio_free(GPIO_CAM_MEGA_RST);
+
+ if (exynos4_fimc_setup_gpio(S5P_CAMPORT_A)) {
+ pr_err("%s: Camera port A setup failed\n", __func__);
+ return;
+ }
+ /* Increase drive strength of the sensor clock output */
+ s5p_gpio_set_drvstr(EXYNOS4_GPJ1(3), S5P_GPIO_DRVSTR_LV4);
+}
+
+static struct s3c2410_platform_i2c nuri_i2c0_platdata __initdata = {
+ .frequency = 400000U,
+ .sda_delay = 200,
+};
+
static struct platform_device *nuri_devices[] __initdata = {
/* Samsung Platform Devices */
&s3c_device_i2c5, /* PMIC should initialize first */
+ &s3c_device_i2c0,
&emmc_fixed_voltage,
+ &s5p_device_mipi_csis0,
+ &s5p_device_fimc0,
+ &s5p_device_fimc1,
+ &s5p_device_fimc2,
+ &s5p_device_fimc3,
&s5p_device_fimd0,
&s3c_device_hsmmc0,
&s3c_device_hsmmc2,
@@ -1137,6 +1280,8 @@ static struct platform_device *nuri_devices[] __initdata = {
&s5p_device_mfc_r,
&exynos4_device_pd[PD_MFC],
&exynos4_device_pd[PD_LCD0],
+ &exynos4_device_pd[PD_CAM],
+ &s5p_device_fimc_md,
/* NURI Devices */
&nuri_gpio_keys,
@@ -1144,6 +1289,8 @@ static struct platform_device *nuri_devices[] __initdata = {
&nuri_backlight_device,
&max8903_fixed_reg_dev,
&nuri_max8903_device,
+ &cam_vdda_fixed_rdev,
+ &cam_8m_12v_fixed_rdev,
};
static void __init nuri_map_io(void)
@@ -1164,6 +1311,7 @@ static void __init nuri_machine_init(void)
nuri_tsp_init();
nuri_power_init();
+ s3c_i2c0_set_platdata(&nuri_i2c0_platdata);
i2c_register_board_info(1, i2c1_devs, ARRAY_SIZE(i2c1_devs));
s3c_i2c3_set_platdata(&i2c3_data);
i2c_register_board_info(3, i2c3_devs, ARRAY_SIZE(i2c3_devs));
@@ -1175,6 +1323,8 @@ static void __init nuri_machine_init(void)
s5p_fimd0_set_platdata(&nuri_fb_pdata);
+ nuri_camera_init();
+
nuri_ehci_init();
clk_xusbxti.rate = 24000000;
@@ -1182,6 +1332,12 @@ static void __init nuri_machine_init(void)
platform_add_devices(nuri_devices, ARRAY_SIZE(nuri_devices));
s5p_device_mfc.dev.parent = &exynos4_device_pd[PD_MFC].dev;
s5p_device_fimd0.dev.parent = &exynos4_device_pd[PD_LCD0].dev;
+
+ s5p_device_fimc0.dev.parent = &exynos4_device_pd[PD_CAM].dev;
+ s5p_device_fimc1.dev.parent = &exynos4_device_pd[PD_CAM].dev;
+ s5p_device_fimc2.dev.parent = &exynos4_device_pd[PD_CAM].dev;
+ s5p_device_fimc3.dev.parent = &exynos4_device_pd[PD_CAM].dev;
+ s5p_device_mipi_csis0.dev.parent = &exynos4_device_pd[PD_CAM].dev;
}
MACHINE_START(NURI, "NURI")
--
1.7.7
^ permalink raw reply related
* [PATCH 6/9] ARM: SPMP8000: Add pwm driver
From: Sascha Hauer @ 2011-10-10 9:30 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <CAKnu2MocUpNwK5n3sq=5+n0vZEO-JRz+PAJQtE7yX3ZQ8-wq1Q@mail.gmail.com>
On Mon, Oct 10, 2011 at 03:50:51AM +0200, Linus Walleij wrote:
> 2011/10/9 Zoltan Devai <zoss@devai.org>:
>
> > Signed-off-by: Zoltan Devai <zoss@devai.org>
> > ---
> > ?arch/arm/mach-spmp8000/pwm.c | ?246 ++++++++++++++++++++++++++++++++++++++++++
> > ?1 files changed, 246 insertions(+), 0 deletions(-)
> > ?create mode 100644 arch/arm/mach-spmp8000/pwm.c
>
> Also PWM should have its own subsystem, sadly that is an area
> where discussions about the patches for generic PWM in
> drivers/pwm/ by Sascha Hauer seem to have stalled recently. :-(
>
> Those we have tend to live in drivers/misc/ and drivers/mfd/
> which is not good.
>
> Kudos to Sascha for trying to solve the mess, we need more
> subsystems...
Thanks, I'll respin these patches when I find the time. In the mean
time if anyone wants to work on this my latest branch is here:
git://git.pengutronix.de/git/imx/linux-2.6.git pwmlib
It contains the pwm framework and converts most in tree drivers to
the new framework.
Sascha
--
Pengutronix e.K. | |
Industrial Linux Solutions | http://www.pengutronix.de/ |
Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0 |
Amtsgericht Hildesheim, HRA 2686 | Fax: +49-5121-206917-5555 |
^ permalink raw reply
* [PATCH 4/5 v4] Realview PCIX support - add main support module code
From: Colin Tuckley @ 2011-10-10 9:32 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20111007231937.GC25689@n2100.arm.linux.org.uk>
> -----Original Message-----
> From: Russell King - ARM Linux [mailto:linux at arm.linux.org.uk]
> Subject: Re: [PATCH 4/5 v4] Realview PCIX support - add main support
> module code
Russell said:
> I thought one of my previous review points on this was that it was
> completely unsafe to match only on dev->device, rather than on both
> dev->device and dev->vendor. Device IDs are allocated by individual
> vendors and are meaningless without also checking the vendor ID.
And
> And I thought we'd got to the point where we had a swizzle here.
The patch I sent to the list was indeed an old version. However the reason
is that despite the testing we did and your suggested changes the swizzle
based code still does not fully work. So I thought it best to post working
code.
I'm still waiting for a response from you on the last round of test results
I sent.
Regards,
Colin
^ permalink raw reply
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