From bc3a59c1b7b1c367fec615b872bdb89ac232f62e Mon Sep 17 00:00:00 2001 From: Dong Aisheng Date: Sat, 31 Mar 2012 21:26:57 +0800 Subject: ARM: mxs: add initial device tree support for imx28-evk board This patch includes basic dt support which can boot via nfs rootfs. Signed-off-by: Dong Aisheng Signed-off-by: Shawn Guo Acked-by: Marek Vasut --- drivers/clk/mxs/clk-imx28.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/clk/mxs/clk-imx28.c b/drivers/clk/mxs/clk-imx28.c index b2a3257d4f66..5be4636c45a6 100644 --- a/drivers/clk/mxs/clk-imx28.c +++ b/drivers/clk/mxs/clk-imx28.c @@ -142,6 +142,7 @@ static struct clk_lookup hbus_lookups[] __initdata = { static struct clk_lookup xbus_lookups[] __initdata = { { .dev_id = "duart", .con_id = "apb_pclk"}, + { .dev_id = "80074000.serial", .con_id = "apb_pclk"}, { .dev_id = "mxs-dma-apbx", }, { .dev_id = "80024000.dma-apbx", }, }; -- cgit v1.2.3-59-g8ed1b From 2954ff395bcf69cb31dbe500bec20ce0944ea19e Mon Sep 17 00:00:00 2001 From: Shawn Guo Date: Fri, 4 May 2012 21:33:42 +0800 Subject: ARM: mxs: add initial device tree support for imx23-evk board It adds initial device tree support for imx23-evk board, and only serial console is enabled. Signed-off-by: Shawn Guo Acked-by: Marek Vasut --- Documentation/devicetree/bindings/arm/fsl.txt | 4 + arch/arm/boot/dts/imx23-evk.dts | 32 ++++ arch/arm/boot/dts/imx23.dtsi | 243 ++++++++++++++++++++++++++ arch/arm/mach-mxs/Kconfig | 1 + arch/arm/mach-mxs/mach-mxs.c | 24 +++ drivers/clk/mxs/clk-imx23.c | 1 + 6 files changed, 305 insertions(+) create mode 100644 arch/arm/boot/dts/imx23-evk.dts create mode 100644 arch/arm/boot/dts/imx23.dtsi (limited to 'drivers') diff --git a/Documentation/devicetree/bindings/arm/fsl.txt b/Documentation/devicetree/bindings/arm/fsl.txt index fecb580342d4..1708df5a8737 100644 --- a/Documentation/devicetree/bindings/arm/fsl.txt +++ b/Documentation/devicetree/bindings/arm/fsl.txt @@ -1,6 +1,10 @@ Freescale i.MX Platforms Device Tree Bindings ----------------------------------------------- +i.MX23 Evaluation Kit +Required root node properties: + - compatible = "fsl,imx23-evk", "fsl,imx23"; + i.MX28 Evaluation Kit Required root node properties: - compatible = "fsl,imx28-evk", "fsl,imx28"; diff --git a/arch/arm/boot/dts/imx23-evk.dts b/arch/arm/boot/dts/imx23-evk.dts new file mode 100644 index 000000000000..8cad51ee6f89 --- /dev/null +++ b/arch/arm/boot/dts/imx23-evk.dts @@ -0,0 +1,32 @@ +/* + * Copyright 2012 Freescale Semiconductor, Inc. + * + * The code contained herein is licensed under the GNU General Public + * License. You may obtain a copy of the GNU General Public License + * Version 2 or later at the following locations: + * + * http://www.opensource.org/licenses/gpl-license.html + * http://www.gnu.org/copyleft/gpl.html + */ + +/dts-v1/; +/include/ "imx23.dtsi" + +/ { + model = "Freescale i.MX23 Evaluation Kit"; + compatible = "fsl,imx23-evk", "fsl,imx23"; + + memory { + reg = <0x40000000 0x08000000>; + }; + + apb@80000000 { + apbx@80040000 { + duart: serial@80070000 { + pinctrl-names = "default"; + pinctrl-0 = <&duart_pins_a>; + status = "okay"; + }; + }; + }; +}; diff --git a/arch/arm/boot/dts/imx23.dtsi b/arch/arm/boot/dts/imx23.dtsi new file mode 100644 index 000000000000..fb09ccd02189 --- /dev/null +++ b/arch/arm/boot/dts/imx23.dtsi @@ -0,0 +1,243 @@ +/* + * Copyright 2012 Freescale Semiconductor, Inc. + * + * The code contained herein is licensed under the GNU General Public + * License. You may obtain a copy of the GNU General Public License + * Version 2 or later at the following locations: + * + * http://www.opensource.org/licenses/gpl-license.html + * http://www.gnu.org/copyleft/gpl.html + */ + +/include/ "skeleton.dtsi" + +/ { + interrupt-parent = <&icoll>; + + cpus { + cpu@0 { + compatible = "arm,arm926ejs"; + }; + }; + + apb@80000000 { + compatible = "simple-bus"; + #address-cells = <1>; + #size-cells = <1>; + reg = <0x80000000 0x80000>; + ranges; + + apbh@80000000 { + compatible = "simple-bus"; + #address-cells = <1>; + #size-cells = <1>; + reg = <0x80000000 0x40000>; + ranges; + + icoll: interrupt-controller@80000000 { + compatible = "fsl,imx23-icoll", "fsl,mxs-icoll"; + interrupt-controller; + #interrupt-cells = <1>; + reg = <0x80000000 0x2000>; + }; + + dma-apbh@80004000 { + reg = <0x80004000 2000>; + status = "disabled"; + }; + + ecc@80008000 { + reg = <0x80008000 2000>; + status = "disabled"; + }; + + bch@8000a000 { + reg = <0x8000a000 2000>; + status = "disabled"; + }; + + gpmi@8000c000 { + reg = <0x8000c000 2000>; + status = "disabled"; + }; + + ssp0: ssp@80010000 { + reg = <0x80010000 2000>; + status = "disabled"; + }; + + etm@80014000 { + reg = <0x80014000 2000>; + status = "disabled"; + }; + + pinctrl@80018000 { + #address-cells = <1>; + #size-cells = <0>; + compatible = "fsl,imx23-pinctrl"; + reg = <0x80018000 2000>; + + duart_pins_a: duart@0 { + reg = <0>; + fsl,pinmux-ids = <0x11a2 0x11b2>; + fsl,drive-strength = <0>; + fsl,voltage = <1>; + fsl,pull-up = <0>; + }; + }; + + digctl@8001c000 { + reg = <0x8001c000 2000>; + status = "disabled"; + }; + + emi@80020000 { + reg = <0x80020000 2000>; + status = "disabled"; + }; + + dma-apbx@80024000 { + reg = <0x80024000 2000>; + status = "disabled"; + }; + + dcp@80028000 { + reg = <0x80028000 2000>; + status = "disabled"; + }; + + pxp@8002a000 { + reg = <0x8002a000 2000>; + status = "disabled"; + }; + + ocotp@8002c000 { + reg = <0x8002c000 2000>; + status = "disabled"; + }; + + axi-ahb@8002e000 { + reg = <0x8002e000 2000>; + status = "disabled"; + }; + + lcdif@80030000 { + reg = <0x80030000 2000>; + status = "disabled"; + }; + + ssp1: ssp@80034000 { + reg = <0x80034000 2000>; + status = "disabled"; + }; + + tvenc@80038000 { + reg = <0x80038000 2000>; + status = "disabled"; + }; + }; + + apbx@80040000 { + compatible = "simple-bus"; + #address-cells = <1>; + #size-cells = <1>; + reg = <0x80040000 0x40000>; + ranges; + + clkctl@80040000 { + reg = <0x80040000 2000>; + status = "disabled"; + }; + + saif0: saif@80042000 { + reg = <0x80042000 2000>; + status = "disabled"; + }; + + power@80044000 { + reg = <0x80044000 2000>; + status = "disabled"; + }; + + saif1: saif@80046000 { + reg = <0x80046000 2000>; + status = "disabled"; + }; + + audio-out@80048000 { + reg = <0x80048000 2000>; + status = "disabled"; + }; + + audio-in@8004c000 { + reg = <0x8004c000 2000>; + status = "disabled"; + }; + + lradc@80050000 { + reg = <0x80050000 2000>; + status = "disabled"; + }; + + spdif@80054000 { + reg = <0x80054000 2000>; + status = "disabled"; + }; + + i2c@80058000 { + reg = <0x80058000 2000>; + status = "disabled"; + }; + + rtc@8005c000 { + reg = <0x8005c000 2000>; + status = "disabled"; + }; + + pwm@80064000 { + reg = <0x80064000 2000>; + status = "disabled"; + }; + + timrot@80068000 { + reg = <0x80068000 2000>; + status = "disabled"; + }; + + auart0: serial@8006c000 { + reg = <0x8006c000 0x2000>; + status = "disabled"; + }; + + auart1: serial@8006e000 { + reg = <0x8006e000 0x2000>; + status = "disabled"; + }; + + duart: serial@80070000 { + compatible = "arm,pl011", "arm,primecell"; + reg = <0x80070000 0x2000>; + interrupts = <0>; + status = "disabled"; + }; + + usbphy@8007c000 { + reg = <0x8007c000 0x2000>; + status = "disabled"; + }; + }; + }; + + ahb@80080000 { + compatible = "simple-bus"; + #address-cells = <1>; + #size-cells = <1>; + reg = <0x80080000 0x80000>; + ranges; + + usbctrl@80080000 { + reg = <0x80080000 0x10000>; + status = "disabled"; + }; + }; +}; diff --git a/arch/arm/mach-mxs/Kconfig b/arch/arm/mach-mxs/Kconfig index 15bb4e211a27..8138a13e23cf 100644 --- a/arch/arm/mach-mxs/Kconfig +++ b/arch/arm/mach-mxs/Kconfig @@ -23,6 +23,7 @@ comment "MXS platforms:" config MACH_MXS_DT bool "Support MXS platforms from device tree" + select SOC_IMX23 select SOC_IMX28 select USE_OF help diff --git a/arch/arm/mach-mxs/mach-mxs.c b/arch/arm/mach-mxs/mach-mxs.c index 5d81a23943c6..182ea7529d28 100644 --- a/arch/arm/mach-mxs/mach-mxs.c +++ b/arch/arm/mach-mxs/mach-mxs.c @@ -41,6 +41,15 @@ static void __init mxs_dt_init_irq(void) of_irq_init(mxs_irq_match); } +static void __init imx23_timer_init(void) +{ + mx23_clocks_init(); +} + +static struct sys_timer imx23_timer = { + .init = imx23_timer_init, +}; + static void __init imx28_timer_init(void) { mx28_clocks_init(); @@ -69,12 +78,27 @@ static void __init mxs_machine_init(void) NULL, NULL); } +static const char *imx23_dt_compat[] __initdata = { + "fsl,imx23-evk", + "fsl,imx23", + NULL, +}; + static const char *imx28_dt_compat[] __initdata = { "fsl,imx28-evk", "fsl,imx28", NULL, }; +DT_MACHINE_START(IMX23, "Freescale i.MX23 (Device Tree)") + .map_io = mx23_map_io, + .init_irq = mxs_dt_init_irq, + .timer = &imx23_timer, + .init_machine = mxs_machine_init, + .dt_compat = imx23_dt_compat, + .restart = mxs_restart, +MACHINE_END + DT_MACHINE_START(IMX28, "Freescale i.MX28 (Device Tree)") .map_io = mx28_map_io, .init_irq = mxs_dt_init_irq, diff --git a/drivers/clk/mxs/clk-imx23.c b/drivers/clk/mxs/clk-imx23.c index dcae11285716..07fe1f1b4b70 100644 --- a/drivers/clk/mxs/clk-imx23.c +++ b/drivers/clk/mxs/clk-imx23.c @@ -87,6 +87,7 @@ static struct clk_lookup hbus_lookups[] __initdata = { static struct clk_lookup xbus_lookups[] __initdata = { { .dev_id = "duart", .con_id = "apb_pclk"}, + { .dev_id = "80070000.serial", .con_id = "apb_pclk"}, { .dev_id = "mxs-dma-apbx", }, { .dev_id = "80024000.dma-apbx", }, }; -- cgit v1.2.3-59-g8ed1b From f5b7efccdb057a2cc8ee32c83d2f034e494a1f4a Mon Sep 17 00:00:00 2001 From: Dong Aisheng Date: Fri, 4 May 2012 20:12:15 +0800 Subject: dma: mxs-dma: use global stmp_device functionality This can get rid of the mach-dependency. Cc: Dan Williams Cc: Sascha Hauer Cc: Huang Shijie Signed-off-by: Dong Aisheng Signed-off-by: Shawn Guo Acked-by: Wolfram Sang Acked-by: Marek Vasut Acked-by: Vinod Koul --- drivers/dma/Kconfig | 1 + drivers/dma/mxs-dma.c | 26 +++++++++++++------------- 2 files changed, 14 insertions(+), 13 deletions(-) (limited to 'drivers') diff --git a/drivers/dma/Kconfig b/drivers/dma/Kconfig index ef378b5b17e4..aadeb5be9dba 100644 --- a/drivers/dma/Kconfig +++ b/drivers/dma/Kconfig @@ -238,6 +238,7 @@ config IMX_DMA config MXS_DMA bool "MXS DMA support" depends on SOC_IMX23 || SOC_IMX28 + select STMP_DEVICE select DMA_ENGINE help Support the MXS DMA engine. This engine including APBH-DMA diff --git a/drivers/dma/mxs-dma.c b/drivers/dma/mxs-dma.c index 655d4ce6ed0d..bd278187fd81 100644 --- a/drivers/dma/mxs-dma.c +++ b/drivers/dma/mxs-dma.c @@ -23,10 +23,10 @@ #include #include #include +#include #include #include -#include #include "dmaengine.h" @@ -138,10 +138,10 @@ static void mxs_dma_reset_chan(struct mxs_dma_chan *mxs_chan) if (dma_is_apbh() && apbh_is_old()) writel(1 << (chan_id + BP_APBH_CTRL0_RESET_CHANNEL), - mxs_dma->base + HW_APBHX_CTRL0 + MXS_SET_ADDR); + mxs_dma->base + HW_APBHX_CTRL0 + STMP_OFFSET_REG_SET); else writel(1 << (chan_id + BP_APBHX_CHANNEL_CTRL_RESET_CHANNEL), - mxs_dma->base + HW_APBHX_CHANNEL_CTRL + MXS_SET_ADDR); + mxs_dma->base + HW_APBHX_CHANNEL_CTRL + STMP_OFFSET_REG_SET); } static void mxs_dma_enable_chan(struct mxs_dma_chan *mxs_chan) @@ -170,10 +170,10 @@ static void mxs_dma_pause_chan(struct mxs_dma_chan *mxs_chan) /* freeze the channel */ if (dma_is_apbh() && apbh_is_old()) writel(1 << chan_id, - mxs_dma->base + HW_APBHX_CTRL0 + MXS_SET_ADDR); + mxs_dma->base + HW_APBHX_CTRL0 + STMP_OFFSET_REG_SET); else writel(1 << chan_id, - mxs_dma->base + HW_APBHX_CHANNEL_CTRL + MXS_SET_ADDR); + mxs_dma->base + HW_APBHX_CHANNEL_CTRL + STMP_OFFSET_REG_SET); mxs_chan->status = DMA_PAUSED; } @@ -186,10 +186,10 @@ static void mxs_dma_resume_chan(struct mxs_dma_chan *mxs_chan) /* unfreeze the channel */ if (dma_is_apbh() && apbh_is_old()) writel(1 << chan_id, - mxs_dma->base + HW_APBHX_CTRL0 + MXS_CLR_ADDR); + mxs_dma->base + HW_APBHX_CTRL0 + STMP_OFFSET_REG_CLR); else writel(1 << chan_id, - mxs_dma->base + HW_APBHX_CHANNEL_CTRL + MXS_CLR_ADDR); + mxs_dma->base + HW_APBHX_CHANNEL_CTRL + STMP_OFFSET_REG_CLR); mxs_chan->status = DMA_IN_PROGRESS; } @@ -220,11 +220,11 @@ static irqreturn_t mxs_dma_int_handler(int irq, void *dev_id) /* completion status */ stat1 = readl(mxs_dma->base + HW_APBHX_CTRL1); stat1 &= MXS_DMA_CHANNELS_MASK; - writel(stat1, mxs_dma->base + HW_APBHX_CTRL1 + MXS_CLR_ADDR); + writel(stat1, mxs_dma->base + HW_APBHX_CTRL1 + STMP_OFFSET_REG_CLR); /* error status */ stat2 = readl(mxs_dma->base + HW_APBHX_CTRL2); - writel(stat2, mxs_dma->base + HW_APBHX_CTRL2 + MXS_CLR_ADDR); + writel(stat2, mxs_dma->base + HW_APBHX_CTRL2 + STMP_OFFSET_REG_CLR); /* * When both completion and error of termination bits set at the @@ -567,7 +567,7 @@ static int __init mxs_dma_init(struct mxs_dma_engine *mxs_dma) if (ret) return ret; - ret = mxs_reset_block(mxs_dma->base); + ret = stmp_reset_block(mxs_dma->base); if (ret) goto err_out; @@ -580,14 +580,14 @@ static int __init mxs_dma_init(struct mxs_dma_engine *mxs_dma) /* enable apbh burst */ if (dma_is_apbh()) { writel(BM_APBH_CTRL0_APB_BURST_EN, - mxs_dma->base + HW_APBHX_CTRL0 + MXS_SET_ADDR); + mxs_dma->base + HW_APBHX_CTRL0 + STMP_OFFSET_REG_SET); writel(BM_APBH_CTRL0_APB_BURST8_EN, - mxs_dma->base + HW_APBHX_CTRL0 + MXS_SET_ADDR); + mxs_dma->base + HW_APBHX_CTRL0 + STMP_OFFSET_REG_SET); } /* enable irq for all the channels */ writel(MXS_DMA_CHANNELS_MASK << MXS_DMA_CHANNELS, - mxs_dma->base + HW_APBHX_CTRL1 + MXS_SET_ADDR); + mxs_dma->base + HW_APBHX_CTRL1 + STMP_OFFSET_REG_SET); err_out: clk_disable_unprepare(mxs_dma->clk); -- cgit v1.2.3-59-g8ed1b From bb11fb63fc2e5d1092f17d91790bb4aede6d3ef2 Mon Sep 17 00:00:00 2001 From: Shawn Guo Date: Mon, 7 May 2012 14:14:08 +0800 Subject: dma: mxs-dma: let dma_is_apbh and apbh_is_old take parameter Let macros dma_is_apbh and apbh_is_old take mxs_dma as parameter to make the code easy to read. Signed-off-by: Shawn Guo --- drivers/dma/mxs-dma.c | 28 ++++++++++++++++------------ 1 file changed, 16 insertions(+), 12 deletions(-) (limited to 'drivers') diff --git a/drivers/dma/mxs-dma.c b/drivers/dma/mxs-dma.c index bd278187fd81..c93f9fa08caf 100644 --- a/drivers/dma/mxs-dma.c +++ b/drivers/dma/mxs-dma.c @@ -38,10 +38,10 @@ #define MXS_DMA_APBH 0 #define MXS_DMA_APBX 1 -#define dma_is_apbh() (mxs_dma->dev_id == MXS_DMA_APBH) +#define dma_is_apbh(mxs_dma) ((mxs_dma)->dev_id == MXS_DMA_APBH) #define APBH_VERSION_LATEST 3 -#define apbh_is_old() (mxs_dma->version < APBH_VERSION_LATEST) +#define apbh_is_old(mxs_dma) ((mxs_dma)->version < APBH_VERSION_LATEST) #define HW_APBHX_CTRL0 0x000 #define BM_APBH_CTRL0_APB_BURST8_EN (1 << 29) @@ -54,10 +54,14 @@ #define HW_APBH_VERSION (cpu_is_mx23() ? 0x3f0 : 0x800) #define HW_APBX_VERSION 0x800 #define BP_APBHX_VERSION_MAJOR 24 -#define HW_APBHX_CHn_NXTCMDAR(n) \ - (((dma_is_apbh() && apbh_is_old()) ? 0x050 : 0x110) + (n) * 0x70) -#define HW_APBHX_CHn_SEMA(n) \ - (((dma_is_apbh() && apbh_is_old()) ? 0x080 : 0x140) + (n) * 0x70) +/* + * The offset of NXTCMDAR register is different per both dma type and version, + * while stride for each channel is all the same 0x70. + */ +#define HW_APBHX_CHn_NXTCMDAR(d, n) \ + (((dma_is_apbh(d) && apbh_is_old(d)) ? 0x050 : 0x110) + (n) * 0x70) +#define HW_APBHX_CHn_SEMA(d, n) \ + (((dma_is_apbh(d) && apbh_is_old(d)) ? 0x080 : 0x140) + (n) * 0x70) /* * ccw bits definitions @@ -136,7 +140,7 @@ static void mxs_dma_reset_chan(struct mxs_dma_chan *mxs_chan) struct mxs_dma_engine *mxs_dma = mxs_chan->mxs_dma; int chan_id = mxs_chan->chan.chan_id; - if (dma_is_apbh() && apbh_is_old()) + if (dma_is_apbh(mxs_dma) && apbh_is_old(mxs_dma)) writel(1 << (chan_id + BP_APBH_CTRL0_RESET_CHANNEL), mxs_dma->base + HW_APBHX_CTRL0 + STMP_OFFSET_REG_SET); else @@ -151,10 +155,10 @@ static void mxs_dma_enable_chan(struct mxs_dma_chan *mxs_chan) /* set cmd_addr up */ writel(mxs_chan->ccw_phys, - mxs_dma->base + HW_APBHX_CHn_NXTCMDAR(chan_id)); + mxs_dma->base + HW_APBHX_CHn_NXTCMDAR(mxs_dma, chan_id)); /* write 1 to SEMA to kick off the channel */ - writel(1, mxs_dma->base + HW_APBHX_CHn_SEMA(chan_id)); + writel(1, mxs_dma->base + HW_APBHX_CHn_SEMA(mxs_dma, chan_id)); } static void mxs_dma_disable_chan(struct mxs_dma_chan *mxs_chan) @@ -168,7 +172,7 @@ static void mxs_dma_pause_chan(struct mxs_dma_chan *mxs_chan) int chan_id = mxs_chan->chan.chan_id; /* freeze the channel */ - if (dma_is_apbh() && apbh_is_old()) + if (dma_is_apbh(mxs_dma) && apbh_is_old(mxs_dma)) writel(1 << chan_id, mxs_dma->base + HW_APBHX_CTRL0 + STMP_OFFSET_REG_SET); else @@ -184,7 +188,7 @@ static void mxs_dma_resume_chan(struct mxs_dma_chan *mxs_chan) int chan_id = mxs_chan->chan.chan_id; /* unfreeze the channel */ - if (dma_is_apbh() && apbh_is_old()) + if (dma_is_apbh(mxs_dma) && apbh_is_old(mxs_dma)) writel(1 << chan_id, mxs_dma->base + HW_APBHX_CTRL0 + STMP_OFFSET_REG_CLR); else @@ -578,7 +582,7 @@ static int __init mxs_dma_init(struct mxs_dma_engine *mxs_dma) BP_APBHX_VERSION_MAJOR; /* enable apbh burst */ - if (dma_is_apbh()) { + if (dma_is_apbh(mxs_dma)) { writel(BM_APBH_CTRL0_APB_BURST_EN, mxs_dma->base + HW_APBHX_CTRL0 + STMP_OFFSET_REG_SET); writel(BM_APBH_CTRL0_APB_BURST8_EN, -- cgit v1.2.3-59-g8ed1b From 8c92013643f5c40633d61ae331cef49c1069af10 Mon Sep 17 00:00:00 2001 From: Shawn Guo Date: Thu, 10 May 2012 06:23:26 +0800 Subject: dma: mxs-dma: make platform_device_id more generic Rewrite mxs_dma_is_apbh and mxs_dma_is_apbx in order to support other SoCs like imx6q and reform the platform_device_id for the better further dt support. Cc: Dan Williams Cc: Sascha Hauer Cc: Huang Shijie Signed-off-by: Dong Aisheng Signed-off-by: Shawn Guo Acked-by: Marek Vasut Acked-by: Vinod Koul --- arch/arm/mach-mxs/devices/platform-dma.c | 14 ++-- drivers/clk/mxs/clk-imx23.c | 4 +- drivers/clk/mxs/clk-imx28.c | 4 +- drivers/dma/mxs-dma.c | 115 +++++++++++++++++++++---------- include/linux/fsl/mxs-dma.h | 12 +--- 5 files changed, 93 insertions(+), 56 deletions(-) (limited to 'drivers') diff --git a/arch/arm/mach-mxs/devices/platform-dma.c b/arch/arm/mach-mxs/devices/platform-dma.c index 6a0202b1016c..aff481360212 100644 --- a/arch/arm/mach-mxs/devices/platform-dma.c +++ b/arch/arm/mach-mxs/devices/platform-dma.c @@ -32,17 +32,19 @@ static struct platform_device *__init mxs_add_dma(const char *devid, static int __init mxs_add_mxs_dma(void) { - char *apbh = "mxs-dma-apbh"; - char *apbx = "mxs-dma-apbx"; + char *mx23_apbh = "imx23-dma-apbh"; + char *mx23_apbx = "imx23-dma-apbx"; + char *mx28_apbh = "imx28-dma-apbh"; + char *mx28_apbx = "imx28-dma-apbx"; if (cpu_is_mx23()) { - mxs_add_dma(apbh, MX23_APBH_DMA_BASE_ADDR); - mxs_add_dma(apbx, MX23_APBX_DMA_BASE_ADDR); + mxs_add_dma(mx23_apbh, MX23_APBH_DMA_BASE_ADDR); + mxs_add_dma(mx23_apbx, MX23_APBX_DMA_BASE_ADDR); } if (cpu_is_mx28()) { - mxs_add_dma(apbh, MX28_APBH_DMA_BASE_ADDR); - mxs_add_dma(apbx, MX28_APBX_DMA_BASE_ADDR); + mxs_add_dma(mx28_apbh, MX28_APBH_DMA_BASE_ADDR); + mxs_add_dma(mx28_apbx, MX28_APBX_DMA_BASE_ADDR); } return 0; diff --git a/drivers/clk/mxs/clk-imx23.c b/drivers/clk/mxs/clk-imx23.c index 07fe1f1b4b70..96562f5f92f7 100644 --- a/drivers/clk/mxs/clk-imx23.c +++ b/drivers/clk/mxs/clk-imx23.c @@ -81,14 +81,14 @@ static struct clk_lookup uart_lookups[] __initdata = { }; static struct clk_lookup hbus_lookups[] __initdata = { - { .dev_id = "mxs-dma-apbh", }, + { .dev_id = "imx23-dma-apbh", }, { .dev_id = "80004000.dma-apbh", }, }; static struct clk_lookup xbus_lookups[] __initdata = { { .dev_id = "duart", .con_id = "apb_pclk"}, { .dev_id = "80070000.serial", .con_id = "apb_pclk"}, - { .dev_id = "mxs-dma-apbx", }, + { .dev_id = "imx23-dma-apbx", }, { .dev_id = "80024000.dma-apbx", }, }; diff --git a/drivers/clk/mxs/clk-imx28.c b/drivers/clk/mxs/clk-imx28.c index 5be4636c45a6..a7ff4f106ce2 100644 --- a/drivers/clk/mxs/clk-imx28.c +++ b/drivers/clk/mxs/clk-imx28.c @@ -136,14 +136,14 @@ static struct clk_lookup uart_lookups[] __initdata = { }; static struct clk_lookup hbus_lookups[] __initdata = { - { .dev_id = "mxs-dma-apbh", }, + { .dev_id = "imx28-dma-apbh", }, { .dev_id = "80004000.dma-apbh", }, }; static struct clk_lookup xbus_lookups[] __initdata = { { .dev_id = "duart", .con_id = "apb_pclk"}, { .dev_id = "80074000.serial", .con_id = "apb_pclk"}, - { .dev_id = "mxs-dma-apbx", }, + { .dev_id = "imx28-dma-apbx", }, { .dev_id = "80024000.dma-apbx", }, }; diff --git a/drivers/dma/mxs-dma.c b/drivers/dma/mxs-dma.c index c93f9fa08caf..b1cab087cd04 100644 --- a/drivers/dma/mxs-dma.c +++ b/drivers/dma/mxs-dma.c @@ -36,12 +36,8 @@ * dma can program the controller registers of peripheral devices. */ -#define MXS_DMA_APBH 0 -#define MXS_DMA_APBX 1 -#define dma_is_apbh(mxs_dma) ((mxs_dma)->dev_id == MXS_DMA_APBH) - -#define APBH_VERSION_LATEST 3 -#define apbh_is_old(mxs_dma) ((mxs_dma)->version < APBH_VERSION_LATEST) +#define dma_is_apbh(mxs_dma) ((mxs_dma)->type == MXS_DMA_APBH) +#define apbh_is_old(mxs_dma) ((mxs_dma)->dev_id == IMX23_DMA) #define HW_APBHX_CTRL0 0x000 #define BM_APBH_CTRL0_APB_BURST8_EN (1 << 29) @@ -51,9 +47,6 @@ #define HW_APBHX_CTRL2 0x020 #define HW_APBHX_CHANNEL_CTRL 0x030 #define BP_APBHX_CHANNEL_CTRL_RESET_CHANNEL 16 -#define HW_APBH_VERSION (cpu_is_mx23() ? 0x3f0 : 0x800) -#define HW_APBX_VERSION 0x800 -#define BP_APBHX_VERSION_MAJOR 24 /* * The offset of NXTCMDAR register is different per both dma type and version, * while stride for each channel is all the same 0x70. @@ -125,9 +118,19 @@ struct mxs_dma_chan { #define MXS_DMA_CHANNELS 16 #define MXS_DMA_CHANNELS_MASK 0xffff +enum mxs_dma_devtype { + MXS_DMA_APBH, + MXS_DMA_APBX, +}; + +enum mxs_dma_id { + IMX23_DMA, + IMX28_DMA, +}; + struct mxs_dma_engine { - int dev_id; - unsigned int version; + enum mxs_dma_id dev_id; + enum mxs_dma_devtype type; void __iomem *base; struct clk *clk; struct dma_device dma_device; @@ -135,6 +138,66 @@ struct mxs_dma_engine { struct mxs_dma_chan mxs_chans[MXS_DMA_CHANNELS]; }; +struct mxs_dma_type { + enum mxs_dma_id id; + enum mxs_dma_devtype type; +}; + +static struct mxs_dma_type mxs_dma_types[] = { + { + .id = IMX23_DMA, + .type = MXS_DMA_APBH, + }, { + .id = IMX23_DMA, + .type = MXS_DMA_APBX, + }, { + .id = IMX28_DMA, + .type = MXS_DMA_APBH, + }, { + .id = IMX28_DMA, + .type = MXS_DMA_APBX, + } +}; + +static struct platform_device_id mxs_dma_ids[] = { + { + .name = "imx23-dma-apbh", + .driver_data = (kernel_ulong_t) &mxs_dma_types[0], + }, { + .name = "imx23-dma-apbx", + .driver_data = (kernel_ulong_t) &mxs_dma_types[1], + }, { + .name = "imx28-dma-apbh", + .driver_data = (kernel_ulong_t) &mxs_dma_types[2], + }, { + .name = "imx28-dma-apbx", + .driver_data = (kernel_ulong_t) &mxs_dma_types[3], + }, { + /* end of list */ + } +}; + +static struct mxs_dma_chan *to_mxs_dma_chan(struct dma_chan *chan) +{ + return container_of(chan, struct mxs_dma_chan, chan); +} + +int mxs_dma_is_apbh(struct dma_chan *chan) +{ + struct mxs_dma_chan *mxs_chan = to_mxs_dma_chan(chan); + struct mxs_dma_engine *mxs_dma = mxs_chan->mxs_dma; + + return dma_is_apbh(mxs_dma); +} + +int mxs_dma_is_apbx(struct dma_chan *chan) +{ + struct mxs_dma_chan *mxs_chan = to_mxs_dma_chan(chan); + struct mxs_dma_engine *mxs_dma = mxs_chan->mxs_dma; + + return !dma_is_apbh(mxs_dma); +} + static void mxs_dma_reset_chan(struct mxs_dma_chan *mxs_chan) { struct mxs_dma_engine *mxs_dma = mxs_chan->mxs_dma; @@ -198,11 +261,6 @@ static void mxs_dma_resume_chan(struct mxs_dma_chan *mxs_chan) mxs_chan->status = DMA_IN_PROGRESS; } -static struct mxs_dma_chan *to_mxs_dma_chan(struct dma_chan *chan) -{ - return container_of(chan, struct mxs_dma_chan, chan); -} - static dma_cookie_t mxs_dma_tx_submit(struct dma_async_tx_descriptor *tx) { return dma_cookie_assign(tx); @@ -575,12 +633,6 @@ static int __init mxs_dma_init(struct mxs_dma_engine *mxs_dma) if (ret) goto err_out; - /* only major version matters */ - mxs_dma->version = readl(mxs_dma->base + - ((mxs_dma->dev_id == MXS_DMA_APBX) ? - HW_APBX_VERSION : HW_APBH_VERSION)) >> - BP_APBHX_VERSION_MAJOR; - /* enable apbh burst */ if (dma_is_apbh(mxs_dma)) { writel(BM_APBH_CTRL0_APB_BURST_EN, @@ -602,6 +654,8 @@ static int __init mxs_dma_probe(struct platform_device *pdev) { const struct platform_device_id *id_entry = platform_get_device_id(pdev); + const struct mxs_dma_type *dma_type = + (struct mxs_dma_type *)id_entry->driver_data; struct mxs_dma_engine *mxs_dma; struct resource *iores; int ret, i; @@ -610,7 +664,8 @@ static int __init mxs_dma_probe(struct platform_device *pdev) if (!mxs_dma) return -ENOMEM; - mxs_dma->dev_id = id_entry->driver_data; + mxs_dma->dev_id = dma_type->id; + mxs_dma->type = dma_type->type; iores = platform_get_resource(pdev, IORESOURCE_MEM, 0); @@ -693,23 +748,11 @@ err_request_region: return ret; } -static struct platform_device_id mxs_dma_type[] = { - { - .name = "mxs-dma-apbh", - .driver_data = MXS_DMA_APBH, - }, { - .name = "mxs-dma-apbx", - .driver_data = MXS_DMA_APBX, - }, { - /* end of list */ - } -}; - static struct platform_driver mxs_dma_driver = { .driver = { .name = "mxs-dma", }, - .id_table = mxs_dma_type, + .id_table = mxs_dma_ids, }; static int __init mxs_dma_module_init(void) diff --git a/include/linux/fsl/mxs-dma.h b/include/linux/fsl/mxs-dma.h index 203d7c4a3e11..55d870238399 100644 --- a/include/linux/fsl/mxs-dma.h +++ b/include/linux/fsl/mxs-dma.h @@ -15,14 +15,6 @@ struct mxs_dma_data { int chan_irq; }; -static inline int mxs_dma_is_apbh(struct dma_chan *chan) -{ - return !strcmp(dev_name(chan->device->dev), "mxs-dma-apbh"); -} - -static inline int mxs_dma_is_apbx(struct dma_chan *chan) -{ - return !strcmp(dev_name(chan->device->dev), "mxs-dma-apbx"); -} - +extern int mxs_dma_is_apbh(struct dma_chan *chan); +extern int mxs_dma_is_apbx(struct dma_chan *chan); #endif /* __MACH_MXS_DMA_H__ */ -- cgit v1.2.3-59-g8ed1b From 90c9abc5b74d7f7d8226b5dd0d8b6da3a03fe860 Mon Sep 17 00:00:00 2001 From: Dong Aisheng Date: Fri, 4 May 2012 20:12:17 +0800 Subject: dma: mxs-dma: add device tree probe support Cc: Grant Likely Cc: Rob Herring Cc: Rob Landley Cc: Dan Williams Cc: Sascha Hauer Cc: Huang Shijie Signed-off-by: Dong Aisheng Signed-off-by: Shawn Guo Acked-by: Marek Vasut Acked-by: Vinod Koul --- .../devicetree/bindings/dma/fsl-mxs-dma.txt | 19 ++++++++++++++ drivers/dma/mxs-dma.c | 29 ++++++++++++++++++---- 2 files changed, 43 insertions(+), 5 deletions(-) create mode 100644 Documentation/devicetree/bindings/dma/fsl-mxs-dma.txt (limited to 'drivers') diff --git a/Documentation/devicetree/bindings/dma/fsl-mxs-dma.txt b/Documentation/devicetree/bindings/dma/fsl-mxs-dma.txt new file mode 100644 index 000000000000..ded0398d3bdc --- /dev/null +++ b/Documentation/devicetree/bindings/dma/fsl-mxs-dma.txt @@ -0,0 +1,19 @@ +* Freescale MXS DMA + +Required properties: +- compatible : Should be "fsl,-dma-apbh" or "fsl,-dma-apbx" +- reg : Should contain registers location and length + +Supported chips: +imx23, imx28. + +Examples: +dma-apbh@80004000 { + compatible = "fsl,imx28-dma-apbh"; + reg = <0x80004000 2000>; +}; + +dma-apbx@80024000 { + compatible = "fsl,imx28-dma-apbx"; + reg = <0x80024000 2000>; +}; diff --git a/drivers/dma/mxs-dma.c b/drivers/dma/mxs-dma.c index b1cab087cd04..1cb9b974493f 100644 --- a/drivers/dma/mxs-dma.c +++ b/drivers/dma/mxs-dma.c @@ -22,8 +22,11 @@ #include #include #include +#include #include #include +#include +#include #include #include @@ -177,6 +180,15 @@ static struct platform_device_id mxs_dma_ids[] = { } }; +static const struct of_device_id mxs_dma_dt_ids[] = { + { .compatible = "fsl,imx23-dma-apbh", .data = &mxs_dma_ids[0], }, + { .compatible = "fsl,imx23-dma-apbx", .data = &mxs_dma_ids[1], }, + { .compatible = "fsl,imx28-dma-apbh", .data = &mxs_dma_ids[2], }, + { .compatible = "fsl,imx28-dma-apbx", .data = &mxs_dma_ids[3], }, + { /* sentinel */ } +}; +MODULE_DEVICE_TABLE(of, mxs_dma_dt_ids); + static struct mxs_dma_chan *to_mxs_dma_chan(struct dma_chan *chan) { return container_of(chan, struct mxs_dma_chan, chan); @@ -652,10 +664,9 @@ err_out: static int __init mxs_dma_probe(struct platform_device *pdev) { - const struct platform_device_id *id_entry = - platform_get_device_id(pdev); - const struct mxs_dma_type *dma_type = - (struct mxs_dma_type *)id_entry->driver_data; + const struct platform_device_id *id_entry; + const struct of_device_id *of_id; + const struct mxs_dma_type *dma_type; struct mxs_dma_engine *mxs_dma; struct resource *iores; int ret, i; @@ -664,8 +675,15 @@ static int __init mxs_dma_probe(struct platform_device *pdev) if (!mxs_dma) return -ENOMEM; - mxs_dma->dev_id = dma_type->id; + of_id = of_match_device(mxs_dma_dt_ids, &pdev->dev); + if (of_id) + id_entry = of_id->data; + else + id_entry = platform_get_device_id(pdev); + + dma_type = (struct mxs_dma_type *)id_entry->driver_data; mxs_dma->type = dma_type->type; + mxs_dma->dev_id = dma_type->id; iores = platform_get_resource(pdev, IORESOURCE_MEM, 0); @@ -751,6 +769,7 @@ err_request_region: static struct platform_driver mxs_dma_driver = { .driver = { .name = "mxs-dma", + .of_match_table = mxs_dma_dt_ids, }, .id_table = mxs_dma_ids, }; -- cgit v1.2.3-59-g8ed1b From 940a4f7b51f7ad600821e389e80d216baf9e1df8 Mon Sep 17 00:00:00 2001 From: Shawn Guo Date: Fri, 4 May 2012 10:30:14 +0800 Subject: gpio/mxs: use devm_* helpers to make error handling simple It uses devm_* helpers to make the error handling of probe clean and simple. Signed-off-by: Shawn Guo Acked-by: Linus Walleij --- drivers/gpio/gpio-mxs.c | 52 +++++++++++++------------------------------------ 1 file changed, 13 insertions(+), 39 deletions(-) (limited to 'drivers') diff --git a/drivers/gpio/gpio-mxs.c b/drivers/gpio/gpio-mxs.c index 385c58e8405b..95a11dba285c 100644 --- a/drivers/gpio/gpio-mxs.c +++ b/drivers/gpio/gpio-mxs.c @@ -186,44 +186,29 @@ static int __devinit mxs_gpio_probe(struct platform_device *pdev) struct resource *iores = NULL; int err; - port = kzalloc(sizeof(struct mxs_gpio_port), GFP_KERNEL); + port = devm_kzalloc(&pdev->dev, sizeof(*port), GFP_KERNEL); if (!port) return -ENOMEM; port->id = pdev->id; port->virtual_irq_start = MXS_GPIO_IRQ_START + port->id * 32; + port->irq = platform_get_irq(pdev, 0); + if (port->irq < 0) + return port->irq; + /* * map memory region only once, as all the gpio ports * share the same one */ if (!base) { iores = platform_get_resource(pdev, IORESOURCE_MEM, 0); - if (!iores) { - err = -ENODEV; - goto out_kfree; - } - - if (!request_mem_region(iores->start, resource_size(iores), - pdev->name)) { - err = -EBUSY; - goto out_kfree; - } - - base = ioremap(iores->start, resource_size(iores)); - if (!base) { - err = -ENOMEM; - goto out_release_mem; - } + base = devm_request_and_ioremap(&pdev->dev, iores); + if (!base) + return -EADDRNOTAVAIL; } port->base = base; - port->irq = platform_get_irq(pdev, 0); - if (port->irq < 0) { - err = -EINVAL; - goto out_iounmap; - } - /* * select the pin interrupt functionality but initially * disable the interrupts @@ -246,29 +231,18 @@ static int __devinit mxs_gpio_probe(struct platform_device *pdev) port->base + PINCTRL_DOUT(port->id), NULL, port->base + PINCTRL_DOE(port->id), NULL, false); if (err) - goto out_iounmap; + return err; port->bgc.gc.to_irq = mxs_gpio_to_irq; port->bgc.gc.base = port->id * 32; err = gpiochip_add(&port->bgc.gc); - if (err) - goto out_bgpio_remove; + if (err) { + bgpio_remove(&port->bgc); + return err; + } return 0; - -out_bgpio_remove: - bgpio_remove(&port->bgc); -out_iounmap: - if (iores) - iounmap(port->base); -out_release_mem: - if (iores) - release_mem_region(iores->start, resource_size(iores)); -out_kfree: - kfree(port); - dev_info(&pdev->dev, "%s failed with errno %d\n", __func__, err); - return err; } static struct platform_driver mxs_gpio_driver = { -- cgit v1.2.3-59-g8ed1b From 164387d2b4ae206f6275f5f6857aee74654918c4 Mon Sep 17 00:00:00 2001 From: Shawn Guo Date: Thu, 3 May 2012 23:32:52 +0800 Subject: gpio/mxs: get rid of the use of cpu_is_xxx It removes the use of cpu_is_xxx from gpio-mxs driver and instead use platform_device_id to identify the device. Accordingly, mxs platform code is changed to register gpio device with different names, and the registeration are done in soc specific initialization functions now, so postcore_initcall(mxs_add_mxs_gpio) gets removed. Signed-off-by: Shawn Guo Acked-by: Linus Walleij --- arch/arm/mach-mxs/devices/platform-gpio-mxs.c | 24 +-------- arch/arm/mach-mxs/include/mach/common.h | 4 +- arch/arm/mach-mxs/mm.c | 10 ++++ drivers/gpio/gpio-mxs.c | 74 +++++++++++++++++++-------- 4 files changed, 66 insertions(+), 46 deletions(-) (limited to 'drivers') diff --git a/arch/arm/mach-mxs/devices/platform-gpio-mxs.c b/arch/arm/mach-mxs/devices/platform-gpio-mxs.c index ed0885e414e0..cd99f19ec637 100644 --- a/arch/arm/mach-mxs/devices/platform-gpio-mxs.c +++ b/arch/arm/mach-mxs/devices/platform-gpio-mxs.c @@ -14,7 +14,7 @@ #include struct platform_device *__init mxs_add_gpio( - int id, resource_size_t iobase, int irq) + char *name, int id, resource_size_t iobase, int irq) { struct resource res[] = { { @@ -29,25 +29,5 @@ struct platform_device *__init mxs_add_gpio( }; return platform_device_register_resndata(&mxs_apbh_bus, - "gpio-mxs", id, res, ARRAY_SIZE(res), NULL, 0); + name, id, res, ARRAY_SIZE(res), NULL, 0); } - -static int __init mxs_add_mxs_gpio(void) -{ - if (cpu_is_mx23()) { - mxs_add_gpio(0, MX23_PINCTRL_BASE_ADDR, MX23_INT_GPIO0); - mxs_add_gpio(1, MX23_PINCTRL_BASE_ADDR, MX23_INT_GPIO1); - mxs_add_gpio(2, MX23_PINCTRL_BASE_ADDR, MX23_INT_GPIO2); - } - - if (cpu_is_mx28()) { - mxs_add_gpio(0, MX28_PINCTRL_BASE_ADDR, MX28_INT_GPIO0); - mxs_add_gpio(1, MX28_PINCTRL_BASE_ADDR, MX28_INT_GPIO1); - mxs_add_gpio(2, MX28_PINCTRL_BASE_ADDR, MX28_INT_GPIO2); - mxs_add_gpio(3, MX28_PINCTRL_BASE_ADDR, MX28_INT_GPIO3); - mxs_add_gpio(4, MX28_PINCTRL_BASE_ADDR, MX28_INT_GPIO4); - } - - return 0; -} -postcore_initcall(mxs_add_mxs_gpio); diff --git a/arch/arm/mach-mxs/include/mach/common.h b/arch/arm/mach-mxs/include/mach/common.h index 5f9a3583266c..de6c7ba42544 100644 --- a/arch/arm/mach-mxs/include/mach/common.h +++ b/arch/arm/mach-mxs/include/mach/common.h @@ -18,13 +18,11 @@ extern void mxs_restart(char, const char *); extern int mxs_saif_clkmux_select(unsigned int clkmux); extern void mx23_soc_init(void); -extern int mx23_register_gpios(void); extern int mx23_clocks_init(void); extern void mx23_map_io(void); extern void mx23_init_irq(void); extern void mx28_soc_init(void); -extern int mx28_register_gpios(void); extern int mx28_clocks_init(void); extern void mx28_map_io(void); extern void mx28_init_irq(void); @@ -33,5 +31,7 @@ extern void icoll_init_irq(void); extern struct platform_device *mxs_add_dma(const char *devid, resource_size_t base); +extern struct platform_device *mxs_add_gpio(char *name, int id, + resource_size_t iobase, int irq); #endif /* __MACH_MXS_COMMON_H__ */ diff --git a/arch/arm/mach-mxs/mm.c b/arch/arm/mach-mxs/mm.c index 6af4371ec829..dccb67a9e7c4 100644 --- a/arch/arm/mach-mxs/mm.c +++ b/arch/arm/mach-mxs/mm.c @@ -69,6 +69,10 @@ void __init mx23_soc_init(void) mxs_add_dma("imx23-dma-apbh", MX23_APBH_DMA_BASE_ADDR); mxs_add_dma("imx23-dma-apbx", MX23_APBX_DMA_BASE_ADDR); + + mxs_add_gpio("imx23-gpio", 0, MX23_PINCTRL_BASE_ADDR, MX23_INT_GPIO0); + mxs_add_gpio("imx23-gpio", 1, MX23_PINCTRL_BASE_ADDR, MX23_INT_GPIO1); + mxs_add_gpio("imx23-gpio", 2, MX23_PINCTRL_BASE_ADDR, MX23_INT_GPIO2); } void __init mx28_soc_init(void) @@ -77,4 +81,10 @@ void __init mx28_soc_init(void) mxs_add_dma("imx28-dma-apbh", MX23_APBH_DMA_BASE_ADDR); mxs_add_dma("imx28-dma-apbx", MX23_APBX_DMA_BASE_ADDR); + + mxs_add_gpio("imx28-gpio", 0, MX28_PINCTRL_BASE_ADDR, MX28_INT_GPIO0); + mxs_add_gpio("imx28-gpio", 1, MX28_PINCTRL_BASE_ADDR, MX28_INT_GPIO1); + mxs_add_gpio("imx28-gpio", 2, MX28_PINCTRL_BASE_ADDR, MX28_INT_GPIO2); + mxs_add_gpio("imx28-gpio", 3, MX28_PINCTRL_BASE_ADDR, MX28_INT_GPIO3); + mxs_add_gpio("imx28-gpio", 4, MX28_PINCTRL_BASE_ADDR, MX28_INT_GPIO4); } diff --git a/drivers/gpio/gpio-mxs.c b/drivers/gpio/gpio-mxs.c index 95a11dba285c..38ae56f17916 100644 --- a/drivers/gpio/gpio-mxs.c +++ b/drivers/gpio/gpio-mxs.c @@ -29,19 +29,18 @@ #include #include #include -#include #define MXS_SET 0x4 #define MXS_CLR 0x8 -#define PINCTRL_DOUT(n) ((cpu_is_mx23() ? 0x0500 : 0x0700) + (n) * 0x10) -#define PINCTRL_DIN(n) ((cpu_is_mx23() ? 0x0600 : 0x0900) + (n) * 0x10) -#define PINCTRL_DOE(n) ((cpu_is_mx23() ? 0x0700 : 0x0b00) + (n) * 0x10) -#define PINCTRL_PIN2IRQ(n) ((cpu_is_mx23() ? 0x0800 : 0x1000) + (n) * 0x10) -#define PINCTRL_IRQEN(n) ((cpu_is_mx23() ? 0x0900 : 0x1100) + (n) * 0x10) -#define PINCTRL_IRQLEV(n) ((cpu_is_mx23() ? 0x0a00 : 0x1200) + (n) * 0x10) -#define PINCTRL_IRQPOL(n) ((cpu_is_mx23() ? 0x0b00 : 0x1300) + (n) * 0x10) -#define PINCTRL_IRQSTAT(n) ((cpu_is_mx23() ? 0x0c00 : 0x1400) + (n) * 0x10) +#define PINCTRL_DOUT(p) ((is_imx23_gpio(p) ? 0x0500 : 0x0700) + (p->id) * 0x10) +#define PINCTRL_DIN(p) ((is_imx23_gpio(p) ? 0x0600 : 0x0900) + (p->id) * 0x10) +#define PINCTRL_DOE(p) ((is_imx23_gpio(p) ? 0x0700 : 0x0b00) + (p->id) * 0x10) +#define PINCTRL_PIN2IRQ(p) ((is_imx23_gpio(p) ? 0x0800 : 0x1000) + (p->id) * 0x10) +#define PINCTRL_IRQEN(p) ((is_imx23_gpio(p) ? 0x0900 : 0x1100) + (p->id) * 0x10) +#define PINCTRL_IRQLEV(p) ((is_imx23_gpio(p) ? 0x0a00 : 0x1200) + (p->id) * 0x10) +#define PINCTRL_IRQPOL(p) ((is_imx23_gpio(p) ? 0x0b00 : 0x1300) + (p->id) * 0x10) +#define PINCTRL_IRQSTAT(p) ((is_imx23_gpio(p) ? 0x0c00 : 0x1400) + (p->id) * 0x10) #define GPIO_INT_FALL_EDGE 0x0 #define GPIO_INT_LOW_LEV 0x1 @@ -52,14 +51,30 @@ #define irq_to_gpio(irq) ((irq) - MXS_GPIO_IRQ_START) +enum mxs_gpio_id { + IMX23_GPIO, + IMX28_GPIO, +}; + struct mxs_gpio_port { void __iomem *base; int id; int irq; int virtual_irq_start; struct bgpio_chip bgc; + enum mxs_gpio_id devid; }; +static inline int is_imx23_gpio(struct mxs_gpio_port *port) +{ + return port->devid == IMX23_GPIO; +} + +static inline int is_imx28_gpio(struct mxs_gpio_port *port) +{ + return port->devid == IMX28_GPIO; +} + /* Note: This driver assumes 32 GPIOs are handled in one register */ static int mxs_gpio_set_irq_type(struct irq_data *d, unsigned int type) @@ -89,21 +104,21 @@ static int mxs_gpio_set_irq_type(struct irq_data *d, unsigned int type) } /* set level or edge */ - pin_addr = port->base + PINCTRL_IRQLEV(port->id); + pin_addr = port->base + PINCTRL_IRQLEV(port); if (edge & GPIO_INT_LEV_MASK) writel(pin_mask, pin_addr + MXS_SET); else writel(pin_mask, pin_addr + MXS_CLR); /* set polarity */ - pin_addr = port->base + PINCTRL_IRQPOL(port->id); + pin_addr = port->base + PINCTRL_IRQPOL(port); if (edge & GPIO_INT_POL_MASK) writel(pin_mask, pin_addr + MXS_SET); else writel(pin_mask, pin_addr + MXS_CLR); writel(1 << (gpio & 0x1f), - port->base + PINCTRL_IRQSTAT(port->id) + MXS_CLR); + port->base + PINCTRL_IRQSTAT(port) + MXS_CLR); return 0; } @@ -117,8 +132,8 @@ static void mxs_gpio_irq_handler(u32 irq, struct irq_desc *desc) desc->irq_data.chip->irq_ack(&desc->irq_data); - irq_stat = readl(port->base + PINCTRL_IRQSTAT(port->id)) & - readl(port->base + PINCTRL_IRQEN(port->id)); + irq_stat = readl(port->base + PINCTRL_IRQSTAT(port)) & + readl(port->base + PINCTRL_IRQEN(port)); while (irq_stat != 0) { int irqoffset = fls(irq_stat) - 1; @@ -164,8 +179,8 @@ static void __init mxs_gpio_init_gc(struct mxs_gpio_port *port) ct->chip.irq_unmask = irq_gc_mask_set_bit; ct->chip.irq_set_type = mxs_gpio_set_irq_type; ct->chip.irq_set_wake = mxs_gpio_set_wake_irq; - ct->regs.ack = PINCTRL_IRQSTAT(port->id) + MXS_CLR; - ct->regs.mask = PINCTRL_IRQEN(port->id); + ct->regs.ack = PINCTRL_IRQSTAT(port) + MXS_CLR; + ct->regs.mask = PINCTRL_IRQEN(port); irq_setup_generic_chip(gc, IRQ_MSK(32), 0, IRQ_NOREQUEST, 0); } @@ -179,6 +194,19 @@ static int mxs_gpio_to_irq(struct gpio_chip *gc, unsigned offset) return port->virtual_irq_start + offset; } +static struct platform_device_id mxs_gpio_ids[] = { + { + .name = "imx23-gpio", + .driver_data = IMX23_GPIO, + }, { + .name = "imx28-gpio", + .driver_data = IMX28_GPIO, + }, { + /* sentinel */ + } +}; +MODULE_DEVICE_TABLE(platform, mxs_gpio_ids); + static int __devinit mxs_gpio_probe(struct platform_device *pdev) { static void __iomem *base; @@ -191,6 +219,7 @@ static int __devinit mxs_gpio_probe(struct platform_device *pdev) return -ENOMEM; port->id = pdev->id; + port->devid = pdev->id_entry->driver_data; port->virtual_irq_start = MXS_GPIO_IRQ_START + port->id * 32; port->irq = platform_get_irq(pdev, 0); @@ -213,11 +242,11 @@ static int __devinit mxs_gpio_probe(struct platform_device *pdev) * select the pin interrupt functionality but initially * disable the interrupts */ - writel(~0U, port->base + PINCTRL_PIN2IRQ(port->id)); - writel(0, port->base + PINCTRL_IRQEN(port->id)); + writel(~0U, port->base + PINCTRL_PIN2IRQ(port)); + writel(0, port->base + PINCTRL_IRQEN(port)); /* clear address has to be used to clear IRQSTAT bits */ - writel(~0U, port->base + PINCTRL_IRQSTAT(port->id) + MXS_CLR); + writel(~0U, port->base + PINCTRL_IRQSTAT(port) + MXS_CLR); /* gpio-mxs can be a generic irq chip */ mxs_gpio_init_gc(port); @@ -227,9 +256,9 @@ static int __devinit mxs_gpio_probe(struct platform_device *pdev) irq_set_handler_data(port->irq, port); err = bgpio_init(&port->bgc, &pdev->dev, 4, - port->base + PINCTRL_DIN(port->id), - port->base + PINCTRL_DOUT(port->id), NULL, - port->base + PINCTRL_DOE(port->id), NULL, false); + port->base + PINCTRL_DIN(port), + port->base + PINCTRL_DOUT(port), NULL, + port->base + PINCTRL_DOE(port), NULL, false); if (err) return err; @@ -251,6 +280,7 @@ static struct platform_driver mxs_gpio_driver = { .owner = THIS_MODULE, }, .probe = mxs_gpio_probe, + .id_table = mxs_gpio_ids, }; static int __init mxs_gpio_init(void) -- cgit v1.2.3-59-g8ed1b From 4052d45e800ce33e1993fb70604941547ed73d26 Mon Sep 17 00:00:00 2001 From: Shawn Guo Date: Fri, 4 May 2012 14:29:22 +0800 Subject: gpio/mxs: add device tree probe It adds device tree probe for gpio-mxs driver. Signed-off-by: Shawn Guo Acked-by: Linus Walleij --- .../devicetree/bindings/gpio/gpio-mxs.txt | 87 ++++++++++++++++++++++ drivers/gpio/gpio-mxs.c | 36 ++++++++- 2 files changed, 119 insertions(+), 4 deletions(-) create mode 100644 Documentation/devicetree/bindings/gpio/gpio-mxs.txt (limited to 'drivers') diff --git a/Documentation/devicetree/bindings/gpio/gpio-mxs.txt b/Documentation/devicetree/bindings/gpio/gpio-mxs.txt new file mode 100644 index 000000000000..0c35673f7a3e --- /dev/null +++ b/Documentation/devicetree/bindings/gpio/gpio-mxs.txt @@ -0,0 +1,87 @@ +* Freescale MXS GPIO controller + +The Freescale MXS GPIO controller is part of MXS PIN controller. The +GPIOs are organized in port/bank. Each port consists of 32 GPIOs. + +As the GPIO controller is embedded in the PIN controller and all the +GPIO ports share the same IO space with PIN controller, the GPIO node +will be represented as sub-nodes of MXS pinctrl node. + +Required properties for GPIO node: +- compatible : Should be "fsl,-gpio". The supported SoCs include + imx23 and imx28. +- interrupts : Should be the port interrupt shared by all 32 pins. +- gpio-controller : Marks the device node as a gpio controller. +- #gpio-cells : Should be two. The first cell is the pin number and + the second cell is used to specify optional parameters (currently + unused). +- interrupt-controller: Marks the device node as an interrupt controller. +- #interrupt-cells : Should be 2. The first cell is the GPIO number. + The second cell bits[3:0] is used to specify trigger type and level flags: + 1 = low-to-high edge triggered. + 2 = high-to-low edge triggered. + 4 = active high level-sensitive. + 8 = active low level-sensitive. + +Note: Each GPIO port should have an alias correctly numbered in "aliases" +node. + +Examples: + +aliases { + gpio0 = &gpio0; + gpio1 = &gpio1; + gpio2 = &gpio2; + gpio3 = &gpio3; + gpio4 = &gpio4; +}; + +pinctrl@80018000 { + compatible = "fsl,imx28-pinctrl", "simple-bus"; + reg = <0x80018000 2000>; + + gpio0: gpio@0 { + compatible = "fsl,imx28-gpio"; + interrupts = <127>; + gpio-controller; + #gpio-cells = <2>; + interrupt-controller; + #interrupt-cells = <2>; + }; + + gpio1: gpio@1 { + compatible = "fsl,imx28-gpio"; + interrupts = <126>; + gpio-controller; + #gpio-cells = <2>; + interrupt-controller; + #interrupt-cells = <2>; + }; + + gpio2: gpio@2 { + compatible = "fsl,imx28-gpio"; + interrupts = <125>; + gpio-controller; + #gpio-cells = <2>; + interrupt-controller; + #interrupt-cells = <2>; + }; + + gpio3: gpio@3 { + compatible = "fsl,imx28-gpio"; + interrupts = <124>; + gpio-controller; + #gpio-cells = <2>; + interrupt-controller; + #interrupt-cells = <2>; + }; + + gpio4: gpio@4 { + compatible = "fsl,imx28-gpio"; + interrupts = <123>; + gpio-controller; + #gpio-cells = <2>; + interrupt-controller; + #interrupt-cells = <2>; + }; +}; diff --git a/drivers/gpio/gpio-mxs.c b/drivers/gpio/gpio-mxs.c index 38ae56f17916..429228b52acd 100644 --- a/drivers/gpio/gpio-mxs.c +++ b/drivers/gpio/gpio-mxs.c @@ -25,6 +25,9 @@ #include #include #include +#include +#include +#include #include #include #include @@ -207,8 +210,19 @@ static struct platform_device_id mxs_gpio_ids[] = { }; MODULE_DEVICE_TABLE(platform, mxs_gpio_ids); +static const struct of_device_id mxs_gpio_dt_ids[] = { + { .compatible = "fsl,imx23-gpio", .data = (void *) IMX23_GPIO, }, + { .compatible = "fsl,imx28-gpio", .data = (void *) IMX28_GPIO, }, + { /* sentinel */ } +}; +MODULE_DEVICE_TABLE(of, mxs_gpio_dt_ids); + static int __devinit mxs_gpio_probe(struct platform_device *pdev) { + const struct of_device_id *of_id = + of_match_device(mxs_gpio_dt_ids, &pdev->dev); + struct device_node *np = pdev->dev.of_node; + struct device_node *parent; static void __iomem *base; struct mxs_gpio_port *port; struct resource *iores = NULL; @@ -218,8 +232,15 @@ static int __devinit mxs_gpio_probe(struct platform_device *pdev) if (!port) return -ENOMEM; - port->id = pdev->id; - port->devid = pdev->id_entry->driver_data; + if (np) { + port->id = of_alias_get_id(np, "gpio"); + if (port->id < 0) + return port->id; + port->devid = (enum mxs_gpio_id) of_id->data; + } else { + port->id = pdev->id; + port->devid = pdev->id_entry->driver_data; + } port->virtual_irq_start = MXS_GPIO_IRQ_START + port->id * 32; port->irq = platform_get_irq(pdev, 0); @@ -231,8 +252,14 @@ static int __devinit mxs_gpio_probe(struct platform_device *pdev) * share the same one */ if (!base) { - iores = platform_get_resource(pdev, IORESOURCE_MEM, 0); - base = devm_request_and_ioremap(&pdev->dev, iores); + if (np) { + parent = of_get_parent(np); + base = of_iomap(parent, 0); + of_node_put(parent); + } else { + iores = platform_get_resource(pdev, IORESOURCE_MEM, 0); + base = devm_request_and_ioremap(&pdev->dev, iores); + } if (!base) return -EADDRNOTAVAIL; } @@ -278,6 +305,7 @@ static struct platform_driver mxs_gpio_driver = { .driver = { .name = "gpio-mxs", .owner = THIS_MODULE, + .of_match_table = mxs_gpio_dt_ids, }, .probe = mxs_gpio_probe, .id_table = mxs_gpio_ids, -- cgit v1.2.3-59-g8ed1b From 70e60206885b227ff17a88e83145efe33917db24 Mon Sep 17 00:00:00 2001 From: Shawn Guo Date: Sat, 5 May 2012 19:40:09 +0800 Subject: mmc: mxs-mmc: use global stmp_device functionality Use global stmp_device functionality to reduce mach-dependency. Signed-off-by: Shawn Guo Acked-by: Marek Vasut Acked-by: Chris Ball --- drivers/mmc/host/mxs-mmc.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) (limited to 'drivers') diff --git a/drivers/mmc/host/mxs-mmc.c b/drivers/mmc/host/mxs-mmc.c index bb03ddda481d..2ea53613c794 100644 --- a/drivers/mmc/host/mxs-mmc.c +++ b/drivers/mmc/host/mxs-mmc.c @@ -40,9 +40,9 @@ #include #include #include +#include #include -#include #include #define DRIVER_NAME "mxs-mmc" @@ -191,7 +191,7 @@ static void mxs_mmc_reset(struct mxs_mmc_host *host) { u32 ctrl0, ctrl1; - mxs_reset_block(host->base); + stmp_reset_block(host->base); ctrl0 = BM_SSP_CTRL0_IGNORE_CRC; ctrl1 = BF_SSP(0x3, CTRL1_SSP_MODE) | @@ -279,7 +279,7 @@ static irqreturn_t mxs_mmc_irq_handler(int irq, void *dev_id) stat = readl(host->base + HW_SSP_CTRL1); writel(stat & MXS_MMC_IRQ_BITS, - host->base + HW_SSP_CTRL1 + MXS_CLR_ADDR); + host->base + HW_SSP_CTRL1 + STMP_OFFSET_REG_CLR); if ((stat & BM_SSP_CTRL1_SDIO_IRQ) && (stat & BM_SSP_CTRL1_SDIO_IRQ_EN)) mmc_signal_sdio_irq(host->mmc); @@ -637,18 +637,18 @@ static void mxs_mmc_enable_sdio_irq(struct mmc_host *mmc, int enable) if (enable) { writel(BM_SSP_CTRL0_SDIO_IRQ_CHECK, - host->base + HW_SSP_CTRL0 + MXS_SET_ADDR); + host->base + HW_SSP_CTRL0 + STMP_OFFSET_REG_SET); writel(BM_SSP_CTRL1_SDIO_IRQ_EN, - host->base + HW_SSP_CTRL1 + MXS_SET_ADDR); + host->base + HW_SSP_CTRL1 + STMP_OFFSET_REG_SET); if (readl(host->base + HW_SSP_STATUS) & BM_SSP_STATUS_SDIO_IRQ) mmc_signal_sdio_irq(host->mmc); } else { writel(BM_SSP_CTRL0_SDIO_IRQ_CHECK, - host->base + HW_SSP_CTRL0 + MXS_CLR_ADDR); + host->base + HW_SSP_CTRL0 + STMP_OFFSET_REG_CLR); writel(BM_SSP_CTRL1_SDIO_IRQ_EN, - host->base + HW_SSP_CTRL1 + MXS_CLR_ADDR); + host->base + HW_SSP_CTRL1 + STMP_OFFSET_REG_CLR); } spin_unlock_irqrestore(&host->lock, flags); -- cgit v1.2.3-59-g8ed1b From e0bf141db2e649830a1851f7c5c01f3b9b410778 Mon Sep 17 00:00:00 2001 From: Shawn Guo Date: Sun, 6 May 2012 09:36:39 +0800 Subject: mmc: mxs-mmc: let ssp_is_old take host as parameter Let macro ssp_is_old take host as parameter to make the code easy to read. Signed-off-by: Shawn Guo Acked-by: Chris Ball --- drivers/mmc/host/mxs-mmc.c | 57 +++++++++++++++++++++++----------------------- 1 file changed, 29 insertions(+), 28 deletions(-) (limited to 'drivers') diff --git a/drivers/mmc/host/mxs-mmc.c b/drivers/mmc/host/mxs-mmc.c index 2ea53613c794..a699a8673766 100644 --- a/drivers/mmc/host/mxs-mmc.c +++ b/drivers/mmc/host/mxs-mmc.c @@ -51,7 +51,7 @@ #define MXS_MMC_DETECT_TIMEOUT (HZ/2) #define SSP_VERSION_LATEST 4 -#define ssp_is_old() (host->version < SSP_VERSION_LATEST) +#define ssp_is_old(host) ((host)->version < SSP_VERSION_LATEST) /* SSP registers */ #define HW_SSP_CTRL0 0x000 @@ -86,14 +86,14 @@ #define BM_SSP_BLOCK_SIZE_BLOCK_COUNT (0xffffff << 4) #define BP_SSP_BLOCK_SIZE_BLOCK_SIZE (0) #define BM_SSP_BLOCK_SIZE_BLOCK_SIZE (0xf) -#define HW_SSP_TIMING (ssp_is_old() ? 0x050 : 0x070) +#define HW_SSP_TIMING(h) (ssp_is_old(h) ? 0x050 : 0x070) #define BP_SSP_TIMING_TIMEOUT (16) #define BM_SSP_TIMING_TIMEOUT (0xffff << 16) #define BP_SSP_TIMING_CLOCK_DIVIDE (8) #define BM_SSP_TIMING_CLOCK_DIVIDE (0xff << 8) #define BP_SSP_TIMING_CLOCK_RATE (0) #define BM_SSP_TIMING_CLOCK_RATE (0xff) -#define HW_SSP_CTRL1 (ssp_is_old() ? 0x060 : 0x080) +#define HW_SSP_CTRL1(h) (ssp_is_old(h) ? 0x060 : 0x080) #define BM_SSP_CTRL1_SDIO_IRQ (1 << 31) #define BM_SSP_CTRL1_SDIO_IRQ_EN (1 << 30) #define BM_SSP_CTRL1_RESP_ERR_IRQ (1 << 29) @@ -116,11 +116,11 @@ #define BM_SSP_CTRL1_WORD_LENGTH (0xf << 4) #define BP_SSP_CTRL1_SSP_MODE (0) #define BM_SSP_CTRL1_SSP_MODE (0xf) -#define HW_SSP_SDRESP0 (ssp_is_old() ? 0x080 : 0x0a0) -#define HW_SSP_SDRESP1 (ssp_is_old() ? 0x090 : 0x0b0) -#define HW_SSP_SDRESP2 (ssp_is_old() ? 0x0a0 : 0x0c0) -#define HW_SSP_SDRESP3 (ssp_is_old() ? 0x0b0 : 0x0d0) -#define HW_SSP_STATUS (ssp_is_old() ? 0x0c0 : 0x100) +#define HW_SSP_SDRESP0(h) (ssp_is_old(h) ? 0x080 : 0x0a0) +#define HW_SSP_SDRESP1(h) (ssp_is_old(h) ? 0x090 : 0x0b0) +#define HW_SSP_SDRESP2(h) (ssp_is_old(h) ? 0x0a0 : 0x0c0) +#define HW_SSP_SDRESP3(h) (ssp_is_old(h) ? 0x0b0 : 0x0d0) +#define HW_SSP_STATUS(h) (ssp_is_old(h) ? 0x0c0 : 0x100) #define BM_SSP_STATUS_CARD_DETECT (1 << 28) #define BM_SSP_STATUS_SDIO_IRQ (1 << 17) #define HW_SSP_VERSION (cpu_is_mx23() ? 0x110 : 0x130) @@ -183,7 +183,7 @@ static int mxs_mmc_get_cd(struct mmc_host *mmc) { struct mxs_mmc_host *host = mmc_priv(mmc); - return !(readl(host->base + HW_SSP_STATUS) & + return !(readl(host->base + HW_SSP_STATUS(host)) & BM_SSP_STATUS_CARD_DETECT); } @@ -207,7 +207,7 @@ static void mxs_mmc_reset(struct mxs_mmc_host *host) writel(BF_SSP(0xffff, TIMING_TIMEOUT) | BF_SSP(2, TIMING_CLOCK_DIVIDE) | BF_SSP(0, TIMING_CLOCK_RATE), - host->base + HW_SSP_TIMING); + host->base + HW_SSP_TIMING(host)); if (host->sdio_irq_en) { ctrl0 |= BM_SSP_CTRL0_SDIO_IRQ_CHECK; @@ -215,7 +215,7 @@ static void mxs_mmc_reset(struct mxs_mmc_host *host) } writel(ctrl0, host->base + HW_SSP_CTRL0); - writel(ctrl1, host->base + HW_SSP_CTRL1); + writel(ctrl1, host->base + HW_SSP_CTRL1(host)); } static void mxs_mmc_start_cmd(struct mxs_mmc_host *host, @@ -229,12 +229,12 @@ static void mxs_mmc_request_done(struct mxs_mmc_host *host) if (mmc_resp_type(cmd) & MMC_RSP_PRESENT) { if (mmc_resp_type(cmd) & MMC_RSP_136) { - cmd->resp[3] = readl(host->base + HW_SSP_SDRESP0); - cmd->resp[2] = readl(host->base + HW_SSP_SDRESP1); - cmd->resp[1] = readl(host->base + HW_SSP_SDRESP2); - cmd->resp[0] = readl(host->base + HW_SSP_SDRESP3); + cmd->resp[3] = readl(host->base + HW_SSP_SDRESP0(host)); + cmd->resp[2] = readl(host->base + HW_SSP_SDRESP1(host)); + cmd->resp[1] = readl(host->base + HW_SSP_SDRESP2(host)); + cmd->resp[0] = readl(host->base + HW_SSP_SDRESP3(host)); } else { - cmd->resp[0] = readl(host->base + HW_SSP_SDRESP0); + cmd->resp[0] = readl(host->base + HW_SSP_SDRESP0(host)); } } @@ -277,9 +277,9 @@ static irqreturn_t mxs_mmc_irq_handler(int irq, void *dev_id) spin_lock(&host->lock); - stat = readl(host->base + HW_SSP_CTRL1); + stat = readl(host->base + HW_SSP_CTRL1(host)); writel(stat & MXS_MMC_IRQ_BITS, - host->base + HW_SSP_CTRL1 + STMP_OFFSET_REG_CLR); + host->base + HW_SSP_CTRL1(host) + STMP_OFFSET_REG_CLR); if ((stat & BM_SSP_CTRL1_SDIO_IRQ) && (stat & BM_SSP_CTRL1_SDIO_IRQ_EN)) mmc_signal_sdio_irq(host->mmc); @@ -485,7 +485,7 @@ static void mxs_mmc_adtc(struct mxs_mmc_host *host) blocks = 1; /* xfer count, block size and count need to be set differently */ - if (ssp_is_old()) { + if (ssp_is_old(host)) { ctrl0 |= BF_SSP(data_size, CTRL0_XFER_COUNT); cmd0 |= BF_SSP(log2_blksz, CMD0_BLOCK_SIZE) | BF_SSP(blocks - 1, CMD0_BLOCK_COUNT); @@ -509,10 +509,10 @@ static void mxs_mmc_adtc(struct mxs_mmc_host *host) /* set the timeout count */ timeout = mxs_ns_to_ssp_ticks(host->clk_rate, data->timeout_ns); - val = readl(host->base + HW_SSP_TIMING); + val = readl(host->base + HW_SSP_TIMING(host)); val &= ~(BM_SSP_TIMING_TIMEOUT); val |= BF_SSP(timeout, TIMING_TIMEOUT); - writel(val, host->base + HW_SSP_TIMING); + writel(val, host->base + HW_SSP_TIMING(host)); /* pio */ host->ssp_pio_words[0] = ctrl0; @@ -598,11 +598,11 @@ static void mxs_mmc_set_clk_rate(struct mxs_mmc_host *host, unsigned int rate) ssp_sck = ssp_clk / clock_divide / (1 + clock_rate); - val = readl(host->base + HW_SSP_TIMING); + val = readl(host->base + HW_SSP_TIMING(host)); val &= ~(BM_SSP_TIMING_CLOCK_DIVIDE | BM_SSP_TIMING_CLOCK_RATE); val |= BF_SSP(clock_divide, TIMING_CLOCK_DIVIDE); val |= BF_SSP(clock_rate, TIMING_CLOCK_RATE); - writel(val, host->base + HW_SSP_TIMING); + writel(val, host->base + HW_SSP_TIMING(host)); host->clk_rate = ssp_sck; @@ -639,16 +639,17 @@ static void mxs_mmc_enable_sdio_irq(struct mmc_host *mmc, int enable) writel(BM_SSP_CTRL0_SDIO_IRQ_CHECK, host->base + HW_SSP_CTRL0 + STMP_OFFSET_REG_SET); writel(BM_SSP_CTRL1_SDIO_IRQ_EN, - host->base + HW_SSP_CTRL1 + STMP_OFFSET_REG_SET); + host->base + HW_SSP_CTRL1(host) + STMP_OFFSET_REG_SET); - if (readl(host->base + HW_SSP_STATUS) & BM_SSP_STATUS_SDIO_IRQ) + if (readl(host->base + HW_SSP_STATUS(host)) & + BM_SSP_STATUS_SDIO_IRQ) mmc_signal_sdio_irq(host->mmc); } else { writel(BM_SSP_CTRL0_SDIO_IRQ_CHECK, host->base + HW_SSP_CTRL0 + STMP_OFFSET_REG_CLR); writel(BM_SSP_CTRL1_SDIO_IRQ_EN, - host->base + HW_SSP_CTRL1 + STMP_OFFSET_REG_CLR); + host->base + HW_SSP_CTRL1(host) + STMP_OFFSET_REG_CLR); } spin_unlock_irqrestore(&host->lock, flags); @@ -765,8 +766,8 @@ static int mxs_mmc_probe(struct platform_device *pdev) mmc->max_segs = 52; mmc->max_blk_size = 1 << 0xf; - mmc->max_blk_count = (ssp_is_old()) ? 0xff : 0xffffff; - mmc->max_req_size = (ssp_is_old()) ? 0xffff : 0xffffffff; + mmc->max_blk_count = (ssp_is_old(host)) ? 0xff : 0xffffff; + mmc->max_req_size = (ssp_is_old(host)) ? 0xffff : 0xffffffff; mmc->max_seg_size = dma_get_max_seg_size(host->dmach->device->dev); platform_set_drvdata(pdev, mmc); -- cgit v1.2.3-59-g8ed1b From ef9b4d3996624f65ffa928bd7767f0e186687c15 Mon Sep 17 00:00:00 2001 From: Shawn Guo Date: Sat, 5 May 2012 20:24:01 +0800 Subject: mmc: mxs-mmc: get rid of the use of cpu_is_xxx The register HW_SSP_VERSION is broken for ssp version detection, as the address of the register is different between imx23 and imx28. Let's use platform_device_id to detect the device, so that the use of cpu_is_xxx can be removed. Signed-off-by: Shawn Guo Acked-by: Chris Ball --- arch/arm/mach-mxs/devices/platform-mxs-mmc.c | 21 ++++++++-------- arch/arm/mach-mxs/include/mach/devices-common.h | 1 + drivers/clk/mxs/clk-imx23.c | 4 ++-- drivers/clk/mxs/clk-imx28.c | 8 +++---- drivers/mmc/host/mxs-mmc.c | 32 +++++++++++++++++-------- 5 files changed, 40 insertions(+), 26 deletions(-) (limited to 'drivers') diff --git a/arch/arm/mach-mxs/devices/platform-mxs-mmc.c b/arch/arm/mach-mxs/devices/platform-mxs-mmc.c index bef9d923f54e..b33c9d05c552 100644 --- a/arch/arm/mach-mxs/devices/platform-mxs-mmc.c +++ b/arch/arm/mach-mxs/devices/platform-mxs-mmc.c @@ -17,8 +17,9 @@ #include #include -#define mxs_mxs_mmc_data_entry_single(soc, _id, hwid) \ +#define mxs_mxs_mmc_data_entry_single(soc, _devid, _id, hwid) \ { \ + .devid = _devid, \ .id = _id, \ .iobase = soc ## _SSP ## hwid ## _BASE_ADDR, \ .dma = soc ## _DMA_SSP ## hwid, \ @@ -26,23 +27,23 @@ .irq_dma = soc ## _INT_SSP ## hwid ## _DMA, \ } -#define mxs_mxs_mmc_data_entry(soc, _id, hwid) \ - [_id] = mxs_mxs_mmc_data_entry_single(soc, _id, hwid) +#define mxs_mxs_mmc_data_entry(soc, _devid, _id, hwid) \ + [_id] = mxs_mxs_mmc_data_entry_single(soc, _devid, _id, hwid) #ifdef CONFIG_SOC_IMX23 const struct mxs_mxs_mmc_data mx23_mxs_mmc_data[] __initconst = { - mxs_mxs_mmc_data_entry(MX23, 0, 1), - mxs_mxs_mmc_data_entry(MX23, 1, 2), + mxs_mxs_mmc_data_entry(MX23, "imx23-mmc", 0, 1), + mxs_mxs_mmc_data_entry(MX23, "imx23-mmc", 1, 2), }; #endif #ifdef CONFIG_SOC_IMX28 const struct mxs_mxs_mmc_data mx28_mxs_mmc_data[] __initconst = { - mxs_mxs_mmc_data_entry(MX28, 0, 0), - mxs_mxs_mmc_data_entry(MX28, 1, 1), - mxs_mxs_mmc_data_entry(MX28, 2, 2), - mxs_mxs_mmc_data_entry(MX28, 3, 3), + mxs_mxs_mmc_data_entry(MX28, "imx28-mmc", 0, 0), + mxs_mxs_mmc_data_entry(MX28, "imx28-mmc", 1, 1), + mxs_mxs_mmc_data_entry(MX28, "imx28-mmc", 2, 2), + mxs_mxs_mmc_data_entry(MX28, "imx28-mmc", 3, 3), }; #endif @@ -70,6 +71,6 @@ struct platform_device *__init mxs_add_mxs_mmc( }, }; - return mxs_add_platform_device("mxs-mmc", data->id, + return mxs_add_platform_device(data->devid, data->id, res, ARRAY_SIZE(res), pdata, sizeof(*pdata)); } diff --git a/arch/arm/mach-mxs/include/mach/devices-common.h b/arch/arm/mach-mxs/include/mach/devices-common.h index f2e383955d88..2b37689c74ee 100644 --- a/arch/arm/mach-mxs/include/mach/devices-common.h +++ b/arch/arm/mach-mxs/include/mach/devices-common.h @@ -89,6 +89,7 @@ struct platform_device * __init mxs_add_mxs_i2c( /* mmc */ #include struct mxs_mxs_mmc_data { + const char *devid; int id; resource_size_t iobase; resource_size_t dma; diff --git a/drivers/clk/mxs/clk-imx23.c b/drivers/clk/mxs/clk-imx23.c index 96562f5f92f7..f7be225f544c 100644 --- a/drivers/clk/mxs/clk-imx23.c +++ b/drivers/clk/mxs/clk-imx23.c @@ -93,8 +93,8 @@ static struct clk_lookup xbus_lookups[] __initdata = { }; static struct clk_lookup ssp_lookups[] __initdata = { - { .dev_id = "mxs-mmc.0", }, - { .dev_id = "mxs-mmc.1", }, + { .dev_id = "imx23-mmc.0", }, + { .dev_id = "imx23-mmc.1", }, { .dev_id = "80010000.ssp", }, { .dev_id = "80034000.ssp", }, }; diff --git a/drivers/clk/mxs/clk-imx28.c b/drivers/clk/mxs/clk-imx28.c index a7ff4f106ce2..2826a2606a29 100644 --- a/drivers/clk/mxs/clk-imx28.c +++ b/drivers/clk/mxs/clk-imx28.c @@ -148,22 +148,22 @@ static struct clk_lookup xbus_lookups[] __initdata = { }; static struct clk_lookup ssp0_lookups[] __initdata = { - { .dev_id = "mxs-mmc.0", }, + { .dev_id = "imx28-mmc.0", }, { .dev_id = "80010000.ssp", }, }; static struct clk_lookup ssp1_lookups[] __initdata = { - { .dev_id = "mxs-mmc.1", }, + { .dev_id = "imx28-mmc.1", }, { .dev_id = "80012000.ssp", }, }; static struct clk_lookup ssp2_lookups[] __initdata = { - { .dev_id = "mxs-mmc.2", }, + { .dev_id = "imx28-mmc.2", }, { .dev_id = "80014000.ssp", }, }; static struct clk_lookup ssp3_lookups[] __initdata = { - { .dev_id = "mxs-mmc.3", }, + { .dev_id = "imx28-mmc.3", }, { .dev_id = "80016000.ssp", }, }; diff --git a/drivers/mmc/host/mxs-mmc.c b/drivers/mmc/host/mxs-mmc.c index a699a8673766..92395563cd82 100644 --- a/drivers/mmc/host/mxs-mmc.c +++ b/drivers/mmc/host/mxs-mmc.c @@ -42,7 +42,6 @@ #include #include -#include #include #define DRIVER_NAME "mxs-mmc" @@ -50,8 +49,7 @@ /* card detect polling timeout */ #define MXS_MMC_DETECT_TIMEOUT (HZ/2) -#define SSP_VERSION_LATEST 4 -#define ssp_is_old(host) ((host)->version < SSP_VERSION_LATEST) +#define ssp_is_old(host) ((host)->devid == IMX23_MMC) /* SSP registers */ #define HW_SSP_CTRL0 0x000 @@ -123,8 +121,6 @@ #define HW_SSP_STATUS(h) (ssp_is_old(h) ? 0x0c0 : 0x100) #define BM_SSP_STATUS_CARD_DETECT (1 << 28) #define BM_SSP_STATUS_SDIO_IRQ (1 << 17) -#define HW_SSP_VERSION (cpu_is_mx23() ? 0x110 : 0x130) -#define BP_SSP_VERSION_MAJOR (24) #define BF_SSP(value, field) (((value) << BP_SSP_##field) & BM_SSP_##field) @@ -139,6 +135,11 @@ #define SSP_PIO_NUM 3 +enum mxs_mmc_id { + IMX23_MMC, + IMX28_MMC, +}; + struct mxs_mmc_host { struct mmc_host *mmc; struct mmc_request *mrq; @@ -158,7 +159,7 @@ struct mxs_mmc_host { enum dma_transfer_direction slave_dirn; u32 ssp_pio_words[SSP_PIO_NUM]; - unsigned int version; + enum mxs_mmc_id devid; unsigned char bus_width; spinlock_t lock; int sdio_irq_en; @@ -678,6 +679,19 @@ static bool mxs_mmc_dma_filter(struct dma_chan *chan, void *param) return true; } +static struct platform_device_id mxs_mmc_ids[] = { + { + .name = "imx23-mmc", + .driver_data = IMX23_MMC, + }, { + .name = "imx28-mmc", + .driver_data = IMX28_MMC, + }, { + /* sentinel */ + } +}; +MODULE_DEVICE_TABLE(platform, mxs_mmc_ids); + static int mxs_mmc_probe(struct platform_device *pdev) { struct mxs_mmc_host *host; @@ -712,10 +726,7 @@ static int mxs_mmc_probe(struct platform_device *pdev) goto out_mmc_free; } - /* only major verion does matter */ - host->version = readl(host->base + HW_SSP_VERSION) >> - BP_SSP_VERSION_MAJOR; - + host->devid = pdev->id_entry->driver_data; host->mmc = mmc; host->res = r; host->dma_res = dmares; @@ -866,6 +877,7 @@ static const struct dev_pm_ops mxs_mmc_pm_ops = { static struct platform_driver mxs_mmc_driver = { .probe = mxs_mmc_probe, .remove = mxs_mmc_remove, + .id_table = mxs_mmc_ids, .driver = { .name = DRIVER_NAME, .owner = THIS_MODULE, -- cgit v1.2.3-59-g8ed1b From 81f38ee8e6a9472193337da248c30963a9741a30 Mon Sep 17 00:00:00 2001 From: Shawn Guo Date: Sun, 6 May 2012 10:04:23 +0800 Subject: mmc: mxs-mmc: move header from mach into linux folder Rename arch/arm/mach-mxs/include/mach/mmc.h to include/linux/mmc/mxs-mmc.h, so that mxs-mmc driver becomes inclusion free. Signed-off-by: Shawn Guo Acked-by: Marek Vasut Acked-by: Chris Ball --- arch/arm/mach-mxs/include/mach/devices-common.h | 2 +- arch/arm/mach-mxs/include/mach/mmc.h | 18 ------------------ drivers/mmc/host/mxs-mmc.c | 3 +-- include/linux/mmc/mxs-mmc.h | 19 +++++++++++++++++++ 4 files changed, 21 insertions(+), 21 deletions(-) delete mode 100644 arch/arm/mach-mxs/include/mach/mmc.h create mode 100644 include/linux/mmc/mxs-mmc.h (limited to 'drivers') diff --git a/arch/arm/mach-mxs/include/mach/devices-common.h b/arch/arm/mach-mxs/include/mach/devices-common.h index 2b37689c74ee..6fc060151979 100644 --- a/arch/arm/mach-mxs/include/mach/devices-common.h +++ b/arch/arm/mach-mxs/include/mach/devices-common.h @@ -87,7 +87,7 @@ struct platform_device * __init mxs_add_mxs_i2c( const struct mxs_mxs_i2c_data *data); /* mmc */ -#include +#include struct mxs_mxs_mmc_data { const char *devid; int id; diff --git a/arch/arm/mach-mxs/include/mach/mmc.h b/arch/arm/mach-mxs/include/mach/mmc.h deleted file mode 100644 index 211547a05564..000000000000 --- a/arch/arm/mach-mxs/include/mach/mmc.h +++ /dev/null @@ -1,18 +0,0 @@ -/* - * Copyright 2011 Freescale Semiconductor, Inc. All Rights Reserved. - * - * 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 __MACH_MXS_MMC_H__ -#define __MACH_MXS_MMC_H__ - -struct mxs_mmc_platform_data { - int wp_gpio; /* write protect pin */ - unsigned int flags; -#define SLOTF_4_BIT_CAPABLE (1 << 0) -#define SLOTF_8_BIT_CAPABLE (1 << 1) -}; -#endif /* __MACH_MXS_MMC_H__ */ diff --git a/drivers/mmc/host/mxs-mmc.c b/drivers/mmc/host/mxs-mmc.c index 92395563cd82..5343190bb9d9 100644 --- a/drivers/mmc/host/mxs-mmc.c +++ b/drivers/mmc/host/mxs-mmc.c @@ -41,8 +41,7 @@ #include #include #include - -#include +#include #define DRIVER_NAME "mxs-mmc" diff --git a/include/linux/mmc/mxs-mmc.h b/include/linux/mmc/mxs-mmc.h new file mode 100644 index 000000000000..7c2ad3a7f2f3 --- /dev/null +++ b/include/linux/mmc/mxs-mmc.h @@ -0,0 +1,19 @@ +/* + * Copyright 2011 Freescale Semiconductor, Inc. All Rights Reserved. + * + * 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 __LINUX_MMC_MXS_MMC_H__ +#define __LINUX_MMC_MXS_MMC_H__ + +struct mxs_mmc_platform_data { + int wp_gpio; /* write protect pin */ + unsigned int flags; +#define SLOTF_4_BIT_CAPABLE (1 << 0) +#define SLOTF_8_BIT_CAPABLE (1 << 1) +}; + +#endif /* __LINUX_MMC_MXS_MMC_H__ */ -- cgit v1.2.3-59-g8ed1b From df06bfc724b58d649eef4bf51a953c7aeed9635f Mon Sep 17 00:00:00 2001 From: Shawn Guo Date: Sun, 6 May 2012 11:20:40 +0800 Subject: mmc: mxs-mmc: use devm_* helper to make cleanup simpler Use devm_request_and_ioremap and devm_request_irq helpers to clean up the code a little bit. Signed-off-by: Shawn Guo Acked-by: Marek Vasut Acked-by: Chris Ball --- drivers/mmc/host/mxs-mmc.c | 40 +++++++++------------------------------- 1 file changed, 9 insertions(+), 31 deletions(-) (limited to 'drivers') diff --git a/drivers/mmc/host/mxs-mmc.c b/drivers/mmc/host/mxs-mmc.c index 5343190bb9d9..d2729e117ae1 100644 --- a/drivers/mmc/host/mxs-mmc.c +++ b/drivers/mmc/host/mxs-mmc.c @@ -146,8 +146,6 @@ struct mxs_mmc_host { struct mmc_data *data; void __iomem *base; - int irq; - struct resource *res; struct resource *dma_res; struct clk *clk; unsigned int clk_rate; @@ -695,7 +693,7 @@ static int mxs_mmc_probe(struct platform_device *pdev) { struct mxs_mmc_host *host; struct mmc_host *mmc; - struct resource *iores, *dmares, *r; + struct resource *iores, *dmares; struct mxs_mmc_platform_data *pdata; struct pinctrl *pinctrl; int ret = 0, irq_err, irq_dma; @@ -708,28 +706,20 @@ static int mxs_mmc_probe(struct platform_device *pdev) if (!iores || !dmares || irq_err < 0 || irq_dma < 0) return -EINVAL; - r = request_mem_region(iores->start, resource_size(iores), pdev->name); - if (!r) - return -EBUSY; - mmc = mmc_alloc_host(sizeof(struct mxs_mmc_host), &pdev->dev); - if (!mmc) { - ret = -ENOMEM; - goto out_release_mem; - } + if (!mmc) + return -ENOMEM; host = mmc_priv(mmc); - host->base = ioremap(r->start, resource_size(r)); + host->base = devm_request_and_ioremap(&pdev->dev, iores); if (!host->base) { - ret = -ENOMEM; + ret = -EADDRNOTAVAIL; goto out_mmc_free; } host->devid = pdev->id_entry->driver_data; host->mmc = mmc; - host->res = r; host->dma_res = dmares; - host->irq = irq_err; host->sdio_irq_en = 0; pinctrl = devm_pinctrl_get_select_default(&pdev->dev); @@ -741,7 +731,7 @@ static int mxs_mmc_probe(struct platform_device *pdev) host->clk = clk_get(&pdev->dev, NULL); if (IS_ERR(host->clk)) { ret = PTR_ERR(host->clk); - goto out_iounmap; + goto out_mmc_free; } clk_prepare_enable(host->clk); @@ -782,7 +772,8 @@ static int mxs_mmc_probe(struct platform_device *pdev) platform_set_drvdata(pdev, mmc); - ret = request_irq(host->irq, mxs_mmc_irq_handler, 0, DRIVER_NAME, host); + ret = devm_request_irq(&pdev->dev, irq_err, mxs_mmc_irq_handler, 0, + DRIVER_NAME, host); if (ret) goto out_free_dma; @@ -790,26 +781,20 @@ static int mxs_mmc_probe(struct platform_device *pdev) ret = mmc_add_host(mmc); if (ret) - goto out_free_irq; + goto out_free_dma; dev_info(mmc_dev(host->mmc), "initialized\n"); return 0; -out_free_irq: - free_irq(host->irq, host); out_free_dma: if (host->dmach) dma_release_channel(host->dmach); out_clk_put: clk_disable_unprepare(host->clk); clk_put(host->clk); -out_iounmap: - iounmap(host->base); out_mmc_free: mmc_free_host(mmc); -out_release_mem: - release_mem_region(iores->start, resource_size(iores)); return ret; } @@ -817,12 +802,9 @@ static int mxs_mmc_remove(struct platform_device *pdev) { struct mmc_host *mmc = platform_get_drvdata(pdev); struct mxs_mmc_host *host = mmc_priv(mmc); - struct resource *res = host->res; mmc_remove_host(mmc); - free_irq(host->irq, host); - platform_set_drvdata(pdev, NULL); if (host->dmach) @@ -831,12 +813,8 @@ static int mxs_mmc_remove(struct platform_device *pdev) clk_disable_unprepare(host->clk); clk_put(host->clk); - iounmap(host->base); - mmc_free_host(mmc); - release_mem_region(res->start, resource_size(res)); - return 0; } -- cgit v1.2.3-59-g8ed1b From b60188c820347040087bfe329f77b286dfd50a7e Mon Sep 17 00:00:00 2001 From: Shawn Guo Date: Sun, 6 May 2012 11:25:35 +0800 Subject: mmc: mxs-mmc: have dma_channel than dma_res in mxs_mmc_host It replaces dma_res with dma_channel in struct mxs_mmc_host, so that the device tree support will be a little easier, since dma channel can not be retrieved from "struct resource *dma_res". Signed-off-by: Shawn Guo Acked-by: Marek Vasut Acked-by: Chris Ball --- drivers/mmc/host/mxs-mmc.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/mmc/host/mxs-mmc.c b/drivers/mmc/host/mxs-mmc.c index d2729e117ae1..202d0966b673 100644 --- a/drivers/mmc/host/mxs-mmc.c +++ b/drivers/mmc/host/mxs-mmc.c @@ -146,7 +146,7 @@ struct mxs_mmc_host { struct mmc_data *data; void __iomem *base; - struct resource *dma_res; + int dma_channel; struct clk *clk; unsigned int clk_rate; @@ -668,7 +668,7 @@ static bool mxs_mmc_dma_filter(struct dma_chan *chan, void *param) if (!mxs_dma_is_apbh(chan)) return false; - if (chan->chan_id != host->dma_res->start) + if (chan->chan_id != host->dma_channel) return false; chan->private = &host->dma_data; @@ -719,7 +719,7 @@ static int mxs_mmc_probe(struct platform_device *pdev) host->devid = pdev->id_entry->driver_data; host->mmc = mmc; - host->dma_res = dmares; + host->dma_channel = dmares->start; host->sdio_irq_en = 0; pinctrl = devm_pinctrl_get_select_default(&pdev->dev); -- cgit v1.2.3-59-g8ed1b From 31b0ff5e7390a955f0d7279ab922e4b41469729d Mon Sep 17 00:00:00 2001 From: Shawn Guo Date: Sun, 6 May 2012 13:33:40 +0800 Subject: mmc: mxs-mmc: copy wp_gpio in struct mxs_mmc_host Copy wp_gpio from platform_data into struct mxs_mmc_host, so that the use of platform_data can be limited in probe function, which will ease the device tree probe. Signed-off-by: Shawn Guo Acked-by: Marek Vasut Acked-by: Chris Ball --- drivers/mmc/host/mxs-mmc.c | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) (limited to 'drivers') diff --git a/drivers/mmc/host/mxs-mmc.c b/drivers/mmc/host/mxs-mmc.c index 202d0966b673..76232dd277c9 100644 --- a/drivers/mmc/host/mxs-mmc.c +++ b/drivers/mmc/host/mxs-mmc.c @@ -160,21 +160,17 @@ struct mxs_mmc_host { unsigned char bus_width; spinlock_t lock; int sdio_irq_en; + int wp_gpio; }; static int mxs_mmc_get_ro(struct mmc_host *mmc) { struct mxs_mmc_host *host = mmc_priv(mmc); - struct mxs_mmc_platform_data *pdata = - mmc_dev(host->mmc)->platform_data; - if (!pdata) - return -EFAULT; - - if (!gpio_is_valid(pdata->wp_gpio)) + if (!gpio_is_valid(host->wp_gpio)) return -EINVAL; - return gpio_get_value(pdata->wp_gpio); + return gpio_get_value(host->wp_gpio); } static int mxs_mmc_get_cd(struct mmc_host *mmc) @@ -758,6 +754,7 @@ static int mxs_mmc_probe(struct platform_device *pdev) mmc->caps |= MMC_CAP_4_BIT_DATA | MMC_CAP_8_BIT_DATA; if (pdata->flags & SLOTF_4_BIT_CAPABLE) mmc->caps |= MMC_CAP_4_BIT_DATA; + host->wp_gpio = pdata->wp_gpio; } mmc->f_min = 400000; -- cgit v1.2.3-59-g8ed1b From 6de4d817aa38ea74dd446d015c8ed62a3ebaeafb Mon Sep 17 00:00:00 2001 From: Shawn Guo Date: Sun, 6 May 2012 13:30:44 +0800 Subject: mmc: mxs-mmc: add device tree support It adds device tree probe support for mxs-mmc driver. Signed-off-by: Shawn Guo Acked-by: Chris Ball --- Documentation/devicetree/bindings/mmc/mxs-mmc.txt | 25 ++++++++++++ drivers/mmc/host/mxs-mmc.c | 48 ++++++++++++++++++++--- 2 files changed, 68 insertions(+), 5 deletions(-) create mode 100644 Documentation/devicetree/bindings/mmc/mxs-mmc.txt (limited to 'drivers') diff --git a/Documentation/devicetree/bindings/mmc/mxs-mmc.txt b/Documentation/devicetree/bindings/mmc/mxs-mmc.txt new file mode 100644 index 000000000000..14d870a9e3db --- /dev/null +++ b/Documentation/devicetree/bindings/mmc/mxs-mmc.txt @@ -0,0 +1,25 @@ +* Freescale MXS MMC controller + +The Freescale MXS Synchronous Serial Ports (SSP) can act as a MMC controller +to support MMC, SD, and SDIO types of memory cards. + +Required properties: +- compatible: Should be "fsl,-mmc". The supported chips include + imx23 and imx28. +- reg: Should contain registers location and length +- interrupts: Should contain ERROR and DMA interrupts +- fsl,ssp-dma-channel: APBH DMA channel for the SSP +- bus-width: Number of data lines, can be <1>, <4>, or <8> + +Optional properties: +- wp-gpios: Specify GPIOs for write protection + +Examples: + +ssp0: ssp@80010000 { + compatible = "fsl,imx28-mmc"; + reg = <0x80010000 2000>; + interrupts = <96 82>; + fsl,ssp-dma-channel = <0>; + bus-width = <8>; +}; diff --git a/drivers/mmc/host/mxs-mmc.c b/drivers/mmc/host/mxs-mmc.c index 76232dd277c9..34a90266ab11 100644 --- a/drivers/mmc/host/mxs-mmc.c +++ b/drivers/mmc/host/mxs-mmc.c @@ -23,6 +23,9 @@ #include #include #include +#include +#include +#include #include #include #include @@ -685,8 +688,18 @@ static struct platform_device_id mxs_mmc_ids[] = { }; MODULE_DEVICE_TABLE(platform, mxs_mmc_ids); +static const struct of_device_id mxs_mmc_dt_ids[] = { + { .compatible = "fsl,imx23-mmc", .data = (void *) IMX23_MMC, }, + { .compatible = "fsl,imx28-mmc", .data = (void *) IMX28_MMC, }, + { /* sentinel */ } +}; +MODULE_DEVICE_TABLE(of, mxs_mmc_dt_ids); + static int mxs_mmc_probe(struct platform_device *pdev) { + const struct of_device_id *of_id = + of_match_device(mxs_mmc_dt_ids, &pdev->dev); + struct device_node *np = pdev->dev.of_node; struct mxs_mmc_host *host; struct mmc_host *mmc; struct resource *iores, *dmares; @@ -699,7 +712,7 @@ static int mxs_mmc_probe(struct platform_device *pdev) dmares = platform_get_resource(pdev, IORESOURCE_DMA, 0); irq_err = platform_get_irq(pdev, 0); irq_dma = platform_get_irq(pdev, 1); - if (!iores || !dmares || irq_err < 0 || irq_dma < 0) + if (!iores || irq_err < 0 || irq_dma < 0) return -EINVAL; mmc = mmc_alloc_host(sizeof(struct mxs_mmc_host), &pdev->dev); @@ -713,15 +726,31 @@ static int mxs_mmc_probe(struct platform_device *pdev) goto out_mmc_free; } - host->devid = pdev->id_entry->driver_data; + if (np) { + host->devid = (enum mxs_mmc_id) of_id->data; + /* + * TODO: This is a temporary solution and should be changed + * to use generic DMA binding later when the helpers get in. + */ + ret = of_property_read_u32(np, "fsl,ssp-dma-channel", + &host->dma_channel); + if (ret) { + dev_err(mmc_dev(host->mmc), + "failed to get dma channel\n"); + goto out_mmc_free; + } + } else { + host->devid = pdev->id_entry->driver_data; + host->dma_channel = dmares->start; + } + host->mmc = mmc; - host->dma_channel = dmares->start; host->sdio_irq_en = 0; pinctrl = devm_pinctrl_get_select_default(&pdev->dev); if (IS_ERR(pinctrl)) { ret = PTR_ERR(pinctrl); - goto out_iounmap; + goto out_mmc_free; } host->clk = clk_get(&pdev->dev, NULL); @@ -749,7 +778,15 @@ static int mxs_mmc_probe(struct platform_device *pdev) MMC_CAP_SDIO_IRQ | MMC_CAP_NEEDS_POLL; pdata = mmc_dev(host->mmc)->platform_data; - if (pdata) { + if (!pdata) { + u32 bus_width = 0; + of_property_read_u32(np, "bus-width", &bus_width); + if (bus_width == 4) + mmc->caps |= MMC_CAP_4_BIT_DATA; + else if (bus_width == 8) + mmc->caps |= MMC_CAP_4_BIT_DATA | MMC_CAP_8_BIT_DATA; + host->wp_gpio = of_get_named_gpio(np, "wp-gpios", 0); + } else { if (pdata->flags & SLOTF_8_BIT_CAPABLE) mmc->caps |= MMC_CAP_4_BIT_DATA | MMC_CAP_8_BIT_DATA; if (pdata->flags & SLOTF_4_BIT_CAPABLE) @@ -857,6 +894,7 @@ static struct platform_driver mxs_mmc_driver = { .owner = THIS_MODULE, #ifdef CONFIG_PM .pm = &mxs_mmc_pm_ops, + .of_match_table = mxs_mmc_dt_ids, #endif }, }; -- cgit v1.2.3-59-g8ed1b From b2378668489d16eb1a1ac722e84cc6a9a1513ba0 Mon Sep 17 00:00:00 2001 From: Shawn Guo Date: Sat, 12 May 2012 13:43:32 +0800 Subject: i2c: mxs: add device tree probe support Add device tree probe support for i2c-mxs driver. So far, it's only been tested on imx28. Signed-off-by: Shawn Guo Acked-by: Wolfram Sang --- Documentation/devicetree/bindings/i2c/i2c-mxs.txt | 16 ++++++++++++++++ drivers/i2c/busses/i2c-mxs.c | 13 +++++++++++++ 2 files changed, 29 insertions(+) create mode 100644 Documentation/devicetree/bindings/i2c/i2c-mxs.txt (limited to 'drivers') diff --git a/Documentation/devicetree/bindings/i2c/i2c-mxs.txt b/Documentation/devicetree/bindings/i2c/i2c-mxs.txt new file mode 100644 index 000000000000..1bfc02de1b0c --- /dev/null +++ b/Documentation/devicetree/bindings/i2c/i2c-mxs.txt @@ -0,0 +1,16 @@ +* Freescale MXS Inter IC (I2C) Controller + +Required properties: +- compatible: Should be "fsl,-i2c" +- reg: Should contain registers location and length +- interrupts: Should contain ERROR and DMA interrupts + +Examples: + +i2c0: i2c@80058000 { + #address-cells = <1>; + #size-cells = <0>; + compatible = "fsl,imx28-i2c"; + reg = <0x80058000 2000>; + interrupts = <111 68>; +}; diff --git a/drivers/i2c/busses/i2c-mxs.c b/drivers/i2c/busses/i2c-mxs.c index 7fa73eed84a7..7dca58b0e746 100644 --- a/drivers/i2c/busses/i2c-mxs.c +++ b/drivers/i2c/busses/i2c-mxs.c @@ -27,6 +27,9 @@ #include #include #include +#include +#include +#include #include @@ -371,6 +374,7 @@ static int __devinit mxs_i2c_probe(struct platform_device *pdev) adap->algo = &mxs_i2c_algo; adap->dev.parent = dev; adap->nr = pdev->id; + adap->dev.of_node = pdev->dev.of_node; i2c_set_adapdata(adap, i2c); err = i2c_add_numbered_adapter(adap); if (err) { @@ -380,6 +384,8 @@ static int __devinit mxs_i2c_probe(struct platform_device *pdev) return err; } + of_i2c_register_devices(adap); + return 0; } @@ -399,10 +405,17 @@ static int __devexit mxs_i2c_remove(struct platform_device *pdev) return 0; } +static const struct of_device_id mxs_i2c_dt_ids[] = { + { .compatible = "fsl,imx28-i2c", }, + { /* sentinel */ } +}; +MODULE_DEVICE_TABLE(of, mxs_i2c_dt_ids); + static struct platform_driver mxs_i2c_driver = { .driver = { .name = DRIVER_NAME, .owner = THIS_MODULE, + .of_match_table = mxs_i2c_dt_ids, }, .remove = __devexit_p(mxs_i2c_remove), }; -- cgit v1.2.3-59-g8ed1b