diff options
author | Olof Johansson <olof@lixom.net> | 2012-05-13 01:33:24 -0400 |
---|---|---|
committer | Olof Johansson <olof@lixom.net> | 2012-05-13 01:33:24 -0400 |
commit | e29402edf848359d619ce06af86d61e62c292c87 (patch) | |
tree | 94451c1d400d478654e0d0e78564e882081b806c /drivers | |
parent | bf98a6eaa9964fef49f186834713bfc57d16ede1 (diff) | |
parent | 530f1d416091212243b341e0022b2967886b30e4 (diff) |
Merge branch 'mxs/dt/for-3.5' of git://git.linaro.org/people/shawnguo/linux-2.6 into next/dt2
* 'mxs/dt/for-3.5' of git://git.linaro.org/people/shawnguo/linux-2.6: (51 commits)
ARM: dts: enable audio support for imx28-evk
ARM: dts: enable i2c device for imx28-evk
i2c: mxs: add device tree probe support
ARM: dts: enable mmc for imx28-evk
ARM: dts: enable mmc for imx23-evk
mmc: mxs-mmc: add device tree support
mmc: mxs-mmc: copy wp_gpio in struct mxs_mmc_host
mmc: mxs-mmc: have dma_channel than dma_res in mxs_mmc_host
mmc: mxs-mmc: use devm_* helper to make cleanup simpler
mmc: mxs-mmc: move header from mach into linux folder
mmc: mxs-mmc: get rid of the use of cpu_is_xxx
mmc: mxs-mmc: let ssp_is_old take host as parameter
mmc: mxs-mmc: use global stmp_device functionality
ARM: mxs: add gpio support for device tree boot
gpio/mxs: add device tree probe
gpio/mxs: get rid of the use of cpu_is_xxx
gpio/mxs: use devm_* helpers to make error handling simple
ARM: mxs: add mxs-dma dt support
ARM: mxs: do not add dma device by default
dma: mxs-dma: add device tree probe support
...
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/clk/Makefile | 2 | ||||
-rw-r--r-- | drivers/clk/mxs/Makefile | 8 | ||||
-rw-r--r-- | drivers/clk/mxs/clk-div.c | 110 | ||||
-rw-r--r-- | drivers/clk/mxs/clk-frac.c | 139 | ||||
-rw-r--r-- | drivers/clk/mxs/clk-imx23.c | 205 | ||||
-rw-r--r-- | drivers/clk/mxs/clk-imx28.c | 338 | ||||
-rw-r--r-- | drivers/clk/mxs/clk-pll.c | 116 | ||||
-rw-r--r-- | drivers/clk/mxs/clk-ref.c | 154 | ||||
-rw-r--r-- | drivers/clk/mxs/clk.c | 28 | ||||
-rw-r--r-- | drivers/clk/mxs/clk.h | 66 | ||||
-rw-r--r-- | drivers/dma/Kconfig | 1 | ||||
-rw-r--r-- | drivers/dma/mxs-dma.c | 188 | ||||
-rw-r--r-- | drivers/gpio/gpio-mxs.c | 156 | ||||
-rw-r--r-- | drivers/i2c/busses/i2c-imx.c | 8 | ||||
-rw-r--r-- | drivers/i2c/busses/i2c-mxs.c | 19 | ||||
-rw-r--r-- | drivers/mmc/host/mxs-mmc.c | 203 | ||||
-rw-r--r-- | drivers/mmc/host/sdhci-esdhc-imx.c | 9 | ||||
-rw-r--r-- | drivers/mtd/nand/gpmi-nand/gpmi-nand.c | 9 | ||||
-rw-r--r-- | drivers/net/can/flexcan.c | 6 | ||||
-rw-r--r-- | drivers/net/ethernet/freescale/fec.c | 9 | ||||
-rw-r--r-- | drivers/spi/spi-imx.c | 8 | ||||
-rw-r--r-- | drivers/tty/serial/amba-pl011.c | 8 | ||||
-rw-r--r-- | drivers/tty/serial/imx.c | 8 | ||||
-rw-r--r-- | drivers/tty/serial/mxs-auart.c | 8 | ||||
-rw-r--r-- | drivers/video/mxsfb.c | 9 |
25 files changed, 1607 insertions, 208 deletions
diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile index 1f736bc11c4b..a576f5447d38 100644 --- a/drivers/clk/Makefile +++ b/drivers/clk/Makefile | |||
@@ -2,3 +2,5 @@ | |||
2 | obj-$(CONFIG_CLKDEV_LOOKUP) += clkdev.o | 2 | obj-$(CONFIG_CLKDEV_LOOKUP) += clkdev.o |
3 | obj-$(CONFIG_COMMON_CLK) += clk.o clk-fixed-rate.o clk-gate.o \ | 3 | obj-$(CONFIG_COMMON_CLK) += clk.o clk-fixed-rate.o clk-gate.o \ |
4 | clk-mux.o clk-divider.o | 4 | clk-mux.o clk-divider.o |
5 | |||
6 | obj-$(CONFIG_ARCH_MXS) += mxs/ | ||
diff --git a/drivers/clk/mxs/Makefile b/drivers/clk/mxs/Makefile new file mode 100644 index 000000000000..7bedeec08524 --- /dev/null +++ b/drivers/clk/mxs/Makefile | |||
@@ -0,0 +1,8 @@ | |||
1 | # | ||
2 | # Makefile for mxs specific clk | ||
3 | # | ||
4 | |||
5 | obj-y += clk.o clk-pll.o clk-ref.o clk-div.o clk-frac.o | ||
6 | |||
7 | obj-$(CONFIG_SOC_IMX23) += clk-imx23.o | ||
8 | obj-$(CONFIG_SOC_IMX28) += clk-imx28.o | ||
diff --git a/drivers/clk/mxs/clk-div.c b/drivers/clk/mxs/clk-div.c new file mode 100644 index 000000000000..90e1da93877e --- /dev/null +++ b/drivers/clk/mxs/clk-div.c | |||
@@ -0,0 +1,110 @@ | |||
1 | /* | ||
2 | * Copyright 2012 Freescale Semiconductor, Inc. | ||
3 | * | ||
4 | * The code contained herein is licensed under the GNU General Public | ||
5 | * License. You may obtain a copy of the GNU General Public License | ||
6 | * Version 2 or later at the following locations: | ||
7 | * | ||
8 | * http://www.opensource.org/licenses/gpl-license.html | ||
9 | * http://www.gnu.org/copyleft/gpl.html | ||
10 | */ | ||
11 | |||
12 | #include <linux/clk.h> | ||
13 | #include <linux/clk-provider.h> | ||
14 | #include <linux/err.h> | ||
15 | #include <linux/slab.h> | ||
16 | #include "clk.h" | ||
17 | |||
18 | /** | ||
19 | * struct clk_div - mxs integer divider clock | ||
20 | * @divider: the parent class | ||
21 | * @ops: pointer to clk_ops of parent class | ||
22 | * @reg: register address | ||
23 | * @busy: busy bit shift | ||
24 | * | ||
25 | * The mxs divider clock is a subclass of basic clk_divider with an | ||
26 | * addtional busy bit. | ||
27 | */ | ||
28 | struct clk_div { | ||
29 | struct clk_divider divider; | ||
30 | const struct clk_ops *ops; | ||
31 | void __iomem *reg; | ||
32 | u8 busy; | ||
33 | }; | ||
34 | |||
35 | static inline struct clk_div *to_clk_div(struct clk_hw *hw) | ||
36 | { | ||
37 | struct clk_divider *divider = container_of(hw, struct clk_divider, hw); | ||
38 | |||
39 | return container_of(divider, struct clk_div, divider); | ||
40 | } | ||
41 | |||
42 | static unsigned long clk_div_recalc_rate(struct clk_hw *hw, | ||
43 | unsigned long parent_rate) | ||
44 | { | ||
45 | struct clk_div *div = to_clk_div(hw); | ||
46 | |||
47 | return div->ops->recalc_rate(&div->divider.hw, parent_rate); | ||
48 | } | ||
49 | |||
50 | static long clk_div_round_rate(struct clk_hw *hw, unsigned long rate, | ||
51 | unsigned long *prate) | ||
52 | { | ||
53 | struct clk_div *div = to_clk_div(hw); | ||
54 | |||
55 | return div->ops->round_rate(&div->divider.hw, rate, prate); | ||
56 | } | ||
57 | |||
58 | static int clk_div_set_rate(struct clk_hw *hw, unsigned long rate, | ||
59 | unsigned long parent_rate) | ||
60 | { | ||
61 | struct clk_div *div = to_clk_div(hw); | ||
62 | int ret; | ||
63 | |||
64 | ret = div->ops->set_rate(&div->divider.hw, rate, parent_rate); | ||
65 | if (!ret) | ||
66 | ret = mxs_clk_wait(div->reg, div->busy); | ||
67 | |||
68 | return ret; | ||
69 | } | ||
70 | |||
71 | static struct clk_ops clk_div_ops = { | ||
72 | .recalc_rate = clk_div_recalc_rate, | ||
73 | .round_rate = clk_div_round_rate, | ||
74 | .set_rate = clk_div_set_rate, | ||
75 | }; | ||
76 | |||
77 | struct clk *mxs_clk_div(const char *name, const char *parent_name, | ||
78 | void __iomem *reg, u8 shift, u8 width, u8 busy) | ||
79 | { | ||
80 | struct clk_div *div; | ||
81 | struct clk *clk; | ||
82 | struct clk_init_data init; | ||
83 | |||
84 | div = kzalloc(sizeof(*div), GFP_KERNEL); | ||
85 | if (!div) | ||
86 | return ERR_PTR(-ENOMEM); | ||
87 | |||
88 | init.name = name; | ||
89 | init.ops = &clk_div_ops; | ||
90 | init.flags = CLK_SET_RATE_PARENT; | ||
91 | init.parent_names = (parent_name ? &parent_name: NULL); | ||
92 | init.num_parents = (parent_name ? 1 : 0); | ||
93 | |||
94 | div->reg = reg; | ||
95 | div->busy = busy; | ||
96 | |||
97 | div->divider.reg = reg; | ||
98 | div->divider.shift = shift; | ||
99 | div->divider.width = width; | ||
100 | div->divider.flags = CLK_DIVIDER_ONE_BASED; | ||
101 | div->divider.lock = &mxs_lock; | ||
102 | div->divider.hw.init = &init; | ||
103 | div->ops = &clk_divider_ops; | ||
104 | |||
105 | clk = clk_register(NULL, &div->divider.hw); | ||
106 | if (IS_ERR(clk)) | ||
107 | kfree(div); | ||
108 | |||
109 | return clk; | ||
110 | } | ||
diff --git a/drivers/clk/mxs/clk-frac.c b/drivers/clk/mxs/clk-frac.c new file mode 100644 index 000000000000..e6aa6b567d68 --- /dev/null +++ b/drivers/clk/mxs/clk-frac.c | |||
@@ -0,0 +1,139 @@ | |||
1 | /* | ||
2 | * Copyright 2012 Freescale Semiconductor, Inc. | ||
3 | * | ||
4 | * The code contained herein is licensed under the GNU General Public | ||
5 | * License. You may obtain a copy of the GNU General Public License | ||
6 | * Version 2 or later at the following locations: | ||
7 | * | ||
8 | * http://www.opensource.org/licenses/gpl-license.html | ||
9 | * http://www.gnu.org/copyleft/gpl.html | ||
10 | */ | ||
11 | |||
12 | #include <linux/clk.h> | ||
13 | #include <linux/clk-provider.h> | ||
14 | #include <linux/err.h> | ||
15 | #include <linux/io.h> | ||
16 | #include <linux/slab.h> | ||
17 | #include "clk.h" | ||
18 | |||
19 | /** | ||
20 | * struct clk_frac - mxs fractional divider clock | ||
21 | * @hw: clk_hw for the fractional divider clock | ||
22 | * @reg: register address | ||
23 | * @shift: the divider bit shift | ||
24 | * @width: the divider bit width | ||
25 | * @busy: busy bit shift | ||
26 | * | ||
27 | * The clock is an adjustable fractional divider with a busy bit to wait | ||
28 | * when the divider is adjusted. | ||
29 | */ | ||
30 | struct clk_frac { | ||
31 | struct clk_hw hw; | ||
32 | void __iomem *reg; | ||
33 | u8 shift; | ||
34 | u8 width; | ||
35 | u8 busy; | ||
36 | }; | ||
37 | |||
38 | #define to_clk_frac(_hw) container_of(_hw, struct clk_frac, hw) | ||
39 | |||
40 | static unsigned long clk_frac_recalc_rate(struct clk_hw *hw, | ||
41 | unsigned long parent_rate) | ||
42 | { | ||
43 | struct clk_frac *frac = to_clk_frac(hw); | ||
44 | u32 div; | ||
45 | |||
46 | div = readl_relaxed(frac->reg) >> frac->shift; | ||
47 | div &= (1 << frac->width) - 1; | ||
48 | |||
49 | return (parent_rate >> frac->width) * div; | ||
50 | } | ||
51 | |||
52 | static long clk_frac_round_rate(struct clk_hw *hw, unsigned long rate, | ||
53 | unsigned long *prate) | ||
54 | { | ||
55 | struct clk_frac *frac = to_clk_frac(hw); | ||
56 | unsigned long parent_rate = *prate; | ||
57 | u32 div; | ||
58 | u64 tmp; | ||
59 | |||
60 | if (rate > parent_rate) | ||
61 | return -EINVAL; | ||
62 | |||
63 | tmp = rate; | ||
64 | tmp <<= frac->width; | ||
65 | do_div(tmp, parent_rate); | ||
66 | div = tmp; | ||
67 | |||
68 | if (!div) | ||
69 | return -EINVAL; | ||
70 | |||
71 | return (parent_rate >> frac->width) * div; | ||
72 | } | ||
73 | |||
74 | static int clk_frac_set_rate(struct clk_hw *hw, unsigned long rate, | ||
75 | unsigned long parent_rate) | ||
76 | { | ||
77 | struct clk_frac *frac = to_clk_frac(hw); | ||
78 | unsigned long flags; | ||
79 | u32 div, val; | ||
80 | u64 tmp; | ||
81 | |||
82 | if (rate > parent_rate) | ||
83 | return -EINVAL; | ||
84 | |||
85 | tmp = rate; | ||
86 | tmp <<= frac->width; | ||
87 | do_div(tmp, parent_rate); | ||
88 | div = tmp; | ||
89 | |||
90 | if (!div) | ||
91 | return -EINVAL; | ||
92 | |||
93 | spin_lock_irqsave(&mxs_lock, flags); | ||
94 | |||
95 | val = readl_relaxed(frac->reg); | ||
96 | val &= ~(((1 << frac->width) - 1) << frac->shift); | ||
97 | val |= div << frac->shift; | ||
98 | writel_relaxed(val, frac->reg); | ||
99 | |||
100 | spin_unlock_irqrestore(&mxs_lock, flags); | ||
101 | |||
102 | return mxs_clk_wait(frac->reg, frac->busy); | ||
103 | } | ||
104 | |||
105 | static struct clk_ops clk_frac_ops = { | ||
106 | .recalc_rate = clk_frac_recalc_rate, | ||
107 | .round_rate = clk_frac_round_rate, | ||
108 | .set_rate = clk_frac_set_rate, | ||
109 | }; | ||
110 | |||
111 | struct clk *mxs_clk_frac(const char *name, const char *parent_name, | ||
112 | void __iomem *reg, u8 shift, u8 width, u8 busy) | ||
113 | { | ||
114 | struct clk_frac *frac; | ||
115 | struct clk *clk; | ||
116 | struct clk_init_data init; | ||
117 | |||
118 | frac = kzalloc(sizeof(*frac), GFP_KERNEL); | ||
119 | if (!frac) | ||
120 | return ERR_PTR(-ENOMEM); | ||
121 | |||
122 | init.name = name; | ||
123 | init.ops = &clk_frac_ops; | ||
124 | init.flags = CLK_SET_RATE_PARENT; | ||
125 | init.parent_names = (parent_name ? &parent_name: NULL); | ||
126 | init.num_parents = (parent_name ? 1 : 0); | ||
127 | |||
128 | frac->reg = reg; | ||
129 | frac->shift = shift; | ||
130 | frac->width = width; | ||
131 | frac->busy = busy; | ||
132 | frac->hw.init = &init; | ||
133 | |||
134 | clk = clk_register(NULL, &frac->hw); | ||
135 | if (IS_ERR(clk)) | ||
136 | kfree(frac); | ||
137 | |||
138 | return clk; | ||
139 | } | ||
diff --git a/drivers/clk/mxs/clk-imx23.c b/drivers/clk/mxs/clk-imx23.c new file mode 100644 index 000000000000..f7be225f544c --- /dev/null +++ b/drivers/clk/mxs/clk-imx23.c | |||
@@ -0,0 +1,205 @@ | |||
1 | /* | ||
2 | * Copyright 2012 Freescale Semiconductor, Inc. | ||
3 | * | ||
4 | * The code contained herein is licensed under the GNU General Public | ||
5 | * License. You may obtain a copy of the GNU General Public License | ||
6 | * Version 2 or later at the following locations: | ||
7 | * | ||
8 | * http://www.opensource.org/licenses/gpl-license.html | ||
9 | * http://www.gnu.org/copyleft/gpl.html | ||
10 | */ | ||
11 | |||
12 | #include <linux/clk.h> | ||
13 | #include <linux/clkdev.h> | ||
14 | #include <linux/err.h> | ||
15 | #include <linux/init.h> | ||
16 | #include <linux/io.h> | ||
17 | #include <mach/common.h> | ||
18 | #include <mach/mx23.h> | ||
19 | #include "clk.h" | ||
20 | |||
21 | #define DIGCTRL MX23_IO_ADDRESS(MX23_DIGCTL_BASE_ADDR) | ||
22 | #define CLKCTRL MX23_IO_ADDRESS(MX23_CLKCTRL_BASE_ADDR) | ||
23 | #define PLLCTRL0 (CLKCTRL + 0x0000) | ||
24 | #define CPU (CLKCTRL + 0x0020) | ||
25 | #define HBUS (CLKCTRL + 0x0030) | ||
26 | #define XBUS (CLKCTRL + 0x0040) | ||
27 | #define XTAL (CLKCTRL + 0x0050) | ||
28 | #define PIX (CLKCTRL + 0x0060) | ||
29 | #define SSP (CLKCTRL + 0x0070) | ||
30 | #define GPMI (CLKCTRL + 0x0080) | ||
31 | #define SPDIF (CLKCTRL + 0x0090) | ||
32 | #define EMI (CLKCTRL + 0x00a0) | ||
33 | #define SAIF (CLKCTRL + 0x00c0) | ||
34 | #define TV (CLKCTRL + 0x00d0) | ||
35 | #define ETM (CLKCTRL + 0x00e0) | ||
36 | #define FRAC (CLKCTRL + 0x00f0) | ||
37 | #define CLKSEQ (CLKCTRL + 0x0110) | ||
38 | |||
39 | #define BP_CPU_INTERRUPT_WAIT 12 | ||
40 | #define BP_CLKSEQ_BYPASS_SAIF 0 | ||
41 | #define BP_CLKSEQ_BYPASS_SSP 5 | ||
42 | #define BP_SAIF_DIV_FRAC_EN 16 | ||
43 | #define BP_FRAC_IOFRAC 24 | ||
44 | |||
45 | static void __init clk_misc_init(void) | ||
46 | { | ||
47 | u32 val; | ||
48 | |||
49 | /* Gate off cpu clock in WFI for power saving */ | ||
50 | __mxs_setl(1 << BP_CPU_INTERRUPT_WAIT, CPU); | ||
51 | |||
52 | /* Clear BYPASS for SAIF */ | ||
53 | __mxs_clrl(1 << BP_CLKSEQ_BYPASS_SAIF, CLKSEQ); | ||
54 | |||
55 | /* SAIF has to use frac div for functional operation */ | ||
56 | val = readl_relaxed(SAIF); | ||
57 | val |= 1 << BP_SAIF_DIV_FRAC_EN; | ||
58 | writel_relaxed(val, SAIF); | ||
59 | |||
60 | /* | ||
61 | * Source ssp clock from ref_io than ref_xtal, | ||
62 | * as ref_xtal only provides 24 MHz as maximum. | ||
63 | */ | ||
64 | __mxs_clrl(1 << BP_CLKSEQ_BYPASS_SSP, CLKSEQ); | ||
65 | |||
66 | /* | ||
67 | * 480 MHz seems too high to be ssp clock source directly, | ||
68 | * so set frac to get a 288 MHz ref_io. | ||
69 | */ | ||
70 | __mxs_clrl(0x3f << BP_FRAC_IOFRAC, FRAC); | ||
71 | __mxs_setl(30 << BP_FRAC_IOFRAC, FRAC); | ||
72 | } | ||
73 | |||
74 | static struct clk_lookup uart_lookups[] __initdata = { | ||
75 | { .dev_id = "duart", }, | ||
76 | { .dev_id = "mxs-auart.0", }, | ||
77 | { .dev_id = "mxs-auart.1", }, | ||
78 | { .dev_id = "8006c000.serial", }, | ||
79 | { .dev_id = "8006e000.serial", }, | ||
80 | { .dev_id = "80070000.serial", }, | ||
81 | }; | ||
82 | |||
83 | static struct clk_lookup hbus_lookups[] __initdata = { | ||
84 | { .dev_id = "imx23-dma-apbh", }, | ||
85 | { .dev_id = "80004000.dma-apbh", }, | ||
86 | }; | ||
87 | |||
88 | static struct clk_lookup xbus_lookups[] __initdata = { | ||
89 | { .dev_id = "duart", .con_id = "apb_pclk"}, | ||
90 | { .dev_id = "80070000.serial", .con_id = "apb_pclk"}, | ||
91 | { .dev_id = "imx23-dma-apbx", }, | ||
92 | { .dev_id = "80024000.dma-apbx", }, | ||
93 | }; | ||
94 | |||
95 | static struct clk_lookup ssp_lookups[] __initdata = { | ||
96 | { .dev_id = "imx23-mmc.0", }, | ||
97 | { .dev_id = "imx23-mmc.1", }, | ||
98 | { .dev_id = "80010000.ssp", }, | ||
99 | { .dev_id = "80034000.ssp", }, | ||
100 | }; | ||
101 | |||
102 | static struct clk_lookup lcdif_lookups[] __initdata = { | ||
103 | { .dev_id = "imx23-fb", }, | ||
104 | { .dev_id = "80030000.lcdif", }, | ||
105 | }; | ||
106 | |||
107 | static struct clk_lookup gpmi_lookups[] __initdata = { | ||
108 | { .dev_id = "imx23-gpmi-nand", }, | ||
109 | { .dev_id = "8000c000.gpmi", }, | ||
110 | }; | ||
111 | |||
112 | static const char *sel_pll[] __initconst = { "pll", "ref_xtal", }; | ||
113 | static const char *sel_cpu[] __initconst = { "ref_cpu", "ref_xtal", }; | ||
114 | static const char *sel_pix[] __initconst = { "ref_pix", "ref_xtal", }; | ||
115 | static const char *sel_io[] __initconst = { "ref_io", "ref_xtal", }; | ||
116 | static const char *cpu_sels[] __initconst = { "cpu_pll", "cpu_xtal", }; | ||
117 | static const char *emi_sels[] __initconst = { "emi_pll", "emi_xtal", }; | ||
118 | |||
119 | enum imx23_clk { | ||
120 | ref_xtal, pll, ref_cpu, ref_emi, ref_pix, ref_io, saif_sel, | ||
121 | lcdif_sel, gpmi_sel, ssp_sel, emi_sel, cpu, etm_sel, cpu_pll, | ||
122 | cpu_xtal, hbus, xbus, lcdif_div, ssp_div, gpmi_div, emi_pll, | ||
123 | emi_xtal, etm_div, saif_div, clk32k_div, rtc, adc, spdif_div, | ||
124 | clk32k, dri, pwm, filt, uart, ssp, gpmi, spdif, emi, saif, | ||
125 | lcdif, etm, usb, usb_pwr, | ||
126 | clk_max | ||
127 | }; | ||
128 | |||
129 | static struct clk *clks[clk_max]; | ||
130 | |||
131 | static enum imx23_clk clks_init_on[] __initdata = { | ||
132 | cpu, hbus, xbus, emi, uart, | ||
133 | }; | ||
134 | |||
135 | int __init mx23_clocks_init(void) | ||
136 | { | ||
137 | int i; | ||
138 | |||
139 | clk_misc_init(); | ||
140 | |||
141 | clks[ref_xtal] = mxs_clk_fixed("ref_xtal", 24000000); | ||
142 | clks[pll] = mxs_clk_pll("pll", "ref_xtal", PLLCTRL0, 16, 480000000); | ||
143 | clks[ref_cpu] = mxs_clk_ref("ref_cpu", "pll", FRAC, 0); | ||
144 | clks[ref_emi] = mxs_clk_ref("ref_emi", "pll", FRAC, 1); | ||
145 | clks[ref_pix] = mxs_clk_ref("ref_pix", "pll", FRAC, 2); | ||
146 | clks[ref_io] = mxs_clk_ref("ref_io", "pll", FRAC, 3); | ||
147 | clks[saif_sel] = mxs_clk_mux("saif_sel", CLKSEQ, 0, 1, sel_pll, ARRAY_SIZE(sel_pll)); | ||
148 | clks[lcdif_sel] = mxs_clk_mux("lcdif_sel", CLKSEQ, 1, 1, sel_pix, ARRAY_SIZE(sel_pix)); | ||
149 | clks[gpmi_sel] = mxs_clk_mux("gpmi_sel", CLKSEQ, 4, 1, sel_io, ARRAY_SIZE(sel_io)); | ||
150 | clks[ssp_sel] = mxs_clk_mux("ssp_sel", CLKSEQ, 5, 1, sel_io, ARRAY_SIZE(sel_io)); | ||
151 | clks[emi_sel] = mxs_clk_mux("emi_sel", CLKSEQ, 6, 1, emi_sels, ARRAY_SIZE(emi_sels)); | ||
152 | clks[cpu] = mxs_clk_mux("cpu", CLKSEQ, 7, 1, cpu_sels, ARRAY_SIZE(cpu_sels)); | ||
153 | clks[etm_sel] = mxs_clk_mux("etm_sel", CLKSEQ, 8, 1, sel_cpu, ARRAY_SIZE(sel_cpu)); | ||
154 | clks[cpu_pll] = mxs_clk_div("cpu_pll", "ref_cpu", CPU, 0, 6, 28); | ||
155 | clks[cpu_xtal] = mxs_clk_div("cpu_xtal", "ref_xtal", CPU, 16, 10, 29); | ||
156 | clks[hbus] = mxs_clk_div("hbus", "cpu", HBUS, 0, 5, 29); | ||
157 | clks[xbus] = mxs_clk_div("xbus", "ref_xtal", XBUS, 0, 10, 31); | ||
158 | clks[lcdif_div] = mxs_clk_div("lcdif_div", "lcdif_sel", PIX, 0, 12, 29); | ||
159 | clks[ssp_div] = mxs_clk_div("ssp_div", "ssp_sel", SSP, 0, 9, 29); | ||
160 | clks[gpmi_div] = mxs_clk_div("gpmi_div", "gpmi_sel", GPMI, 0, 10, 29); | ||
161 | clks[emi_pll] = mxs_clk_div("emi_pll", "ref_emi", EMI, 0, 6, 28); | ||
162 | clks[emi_xtal] = mxs_clk_div("emi_xtal", "ref_xtal", EMI, 8, 4, 29); | ||
163 | clks[etm_div] = mxs_clk_div("etm_div", "etm_sel", ETM, 0, 6, 29); | ||
164 | clks[saif_div] = mxs_clk_frac("saif_div", "saif_sel", SAIF, 0, 16, 29); | ||
165 | clks[clk32k_div] = mxs_clk_fixed_factor("clk32k_div", "ref_xtal", 1, 750); | ||
166 | clks[rtc] = mxs_clk_fixed_factor("rtc", "ref_xtal", 1, 768); | ||
167 | clks[adc] = mxs_clk_fixed_factor("adc", "clk32k", 1, 16); | ||
168 | clks[spdif_div] = mxs_clk_fixed_factor("spdif_div", "pll", 1, 4); | ||
169 | clks[clk32k] = mxs_clk_gate("clk32k", "clk32k_div", XTAL, 26); | ||
170 | clks[dri] = mxs_clk_gate("dri", "ref_xtal", XTAL, 28); | ||
171 | clks[pwm] = mxs_clk_gate("pwm", "ref_xtal", XTAL, 29); | ||
172 | clks[filt] = mxs_clk_gate("filt", "ref_xtal", XTAL, 30); | ||
173 | clks[uart] = mxs_clk_gate("uart", "ref_xtal", XTAL, 31); | ||
174 | clks[ssp] = mxs_clk_gate("ssp", "ssp_div", SSP, 31); | ||
175 | clks[gpmi] = mxs_clk_gate("gpmi", "gpmi_div", GPMI, 31); | ||
176 | clks[spdif] = mxs_clk_gate("spdif", "spdif_div", SPDIF, 31); | ||
177 | clks[emi] = mxs_clk_gate("emi", "emi_sel", EMI, 31); | ||
178 | clks[saif] = mxs_clk_gate("saif", "saif_div", SAIF, 31); | ||
179 | clks[lcdif] = mxs_clk_gate("lcdif", "lcdif_div", PIX, 31); | ||
180 | clks[etm] = mxs_clk_gate("etm", "etm_div", ETM, 31); | ||
181 | clks[usb] = mxs_clk_gate("usb", "usb_pwr", DIGCTRL, 2); | ||
182 | clks[usb_pwr] = clk_register_gate(NULL, "usb_pwr", "pll", 0, PLLCTRL0, 18, 0, &mxs_lock); | ||
183 | |||
184 | for (i = 0; i < ARRAY_SIZE(clks); i++) | ||
185 | if (IS_ERR(clks[i])) { | ||
186 | pr_err("i.MX23 clk %d: register failed with %ld\n", | ||
187 | i, PTR_ERR(clks[i])); | ||
188 | return PTR_ERR(clks[i]); | ||
189 | } | ||
190 | |||
191 | clk_register_clkdev(clks[clk32k], NULL, "timrot"); | ||
192 | clk_register_clkdevs(clks[hbus], hbus_lookups, ARRAY_SIZE(hbus_lookups)); | ||
193 | clk_register_clkdevs(clks[xbus], xbus_lookups, ARRAY_SIZE(xbus_lookups)); | ||
194 | clk_register_clkdevs(clks[uart], uart_lookups, ARRAY_SIZE(uart_lookups)); | ||
195 | clk_register_clkdevs(clks[ssp], ssp_lookups, ARRAY_SIZE(ssp_lookups)); | ||
196 | clk_register_clkdevs(clks[gpmi], gpmi_lookups, ARRAY_SIZE(gpmi_lookups)); | ||
197 | clk_register_clkdevs(clks[lcdif], lcdif_lookups, ARRAY_SIZE(lcdif_lookups)); | ||
198 | |||
199 | for (i = 0; i < ARRAY_SIZE(clks_init_on); i++) | ||
200 | clk_prepare_enable(clks[clks_init_on[i]]); | ||
201 | |||
202 | mxs_timer_init(MX23_INT_TIMER0); | ||
203 | |||
204 | return 0; | ||
205 | } | ||
diff --git a/drivers/clk/mxs/clk-imx28.c b/drivers/clk/mxs/clk-imx28.c new file mode 100644 index 000000000000..2826a2606a29 --- /dev/null +++ b/drivers/clk/mxs/clk-imx28.c | |||
@@ -0,0 +1,338 @@ | |||
1 | /* | ||
2 | * Copyright 2012 Freescale Semiconductor, Inc. | ||
3 | * | ||
4 | * The code contained herein is licensed under the GNU General Public | ||
5 | * License. You may obtain a copy of the GNU General Public License | ||
6 | * Version 2 or later at the following locations: | ||
7 | * | ||
8 | * http://www.opensource.org/licenses/gpl-license.html | ||
9 | * http://www.gnu.org/copyleft/gpl.html | ||
10 | */ | ||
11 | |||
12 | #include <linux/clk.h> | ||
13 | #include <linux/clkdev.h> | ||
14 | #include <linux/err.h> | ||
15 | #include <linux/init.h> | ||
16 | #include <linux/io.h> | ||
17 | #include <mach/common.h> | ||
18 | #include <mach/mx28.h> | ||
19 | #include "clk.h" | ||
20 | |||
21 | #define CLKCTRL MX28_IO_ADDRESS(MX28_CLKCTRL_BASE_ADDR) | ||
22 | #define PLL0CTRL0 (CLKCTRL + 0x0000) | ||
23 | #define PLL1CTRL0 (CLKCTRL + 0x0020) | ||
24 | #define PLL2CTRL0 (CLKCTRL + 0x0040) | ||
25 | #define CPU (CLKCTRL + 0x0050) | ||
26 | #define HBUS (CLKCTRL + 0x0060) | ||
27 | #define XBUS (CLKCTRL + 0x0070) | ||
28 | #define XTAL (CLKCTRL + 0x0080) | ||
29 | #define SSP0 (CLKCTRL + 0x0090) | ||
30 | #define SSP1 (CLKCTRL + 0x00a0) | ||
31 | #define SSP2 (CLKCTRL + 0x00b0) | ||
32 | #define SSP3 (CLKCTRL + 0x00c0) | ||
33 | #define GPMI (CLKCTRL + 0x00d0) | ||
34 | #define SPDIF (CLKCTRL + 0x00e0) | ||
35 | #define EMI (CLKCTRL + 0x00f0) | ||
36 | #define SAIF0 (CLKCTRL + 0x0100) | ||
37 | #define SAIF1 (CLKCTRL + 0x0110) | ||
38 | #define LCDIF (CLKCTRL + 0x0120) | ||
39 | #define ETM (CLKCTRL + 0x0130) | ||
40 | #define ENET (CLKCTRL + 0x0140) | ||
41 | #define FLEXCAN (CLKCTRL + 0x0160) | ||
42 | #define FRAC0 (CLKCTRL + 0x01b0) | ||
43 | #define FRAC1 (CLKCTRL + 0x01c0) | ||
44 | #define CLKSEQ (CLKCTRL + 0x01d0) | ||
45 | |||
46 | #define BP_CPU_INTERRUPT_WAIT 12 | ||
47 | #define BP_SAIF_DIV_FRAC_EN 16 | ||
48 | #define BP_ENET_DIV_TIME 21 | ||
49 | #define BP_ENET_SLEEP 31 | ||
50 | #define BP_CLKSEQ_BYPASS_SAIF0 0 | ||
51 | #define BP_CLKSEQ_BYPASS_SSP0 3 | ||
52 | #define BP_FRAC0_IO1FRAC 16 | ||
53 | #define BP_FRAC0_IO0FRAC 24 | ||
54 | |||
55 | #define DIGCTRL MX28_IO_ADDRESS(MX28_DIGCTL_BASE_ADDR) | ||
56 | #define BP_SAIF_CLKMUX 10 | ||
57 | |||
58 | /* | ||
59 | * HW_SAIF_CLKMUX_SEL: | ||
60 | * DIRECT(0x0): SAIF0 clock pins selected for SAIF0 input clocks, and SAIF1 | ||
61 | * clock pins selected for SAIF1 input clocks. | ||
62 | * CROSSINPUT(0x1): SAIF1 clock inputs selected for SAIF0 input clocks, and | ||
63 | * SAIF0 clock inputs selected for SAIF1 input clocks. | ||
64 | * EXTMSTR0(0x2): SAIF0 clock pin selected for both SAIF0 and SAIF1 input | ||
65 | * clocks. | ||
66 | * EXTMSTR1(0x3): SAIF1 clock pin selected for both SAIF0 and SAIF1 input | ||
67 | * clocks. | ||
68 | */ | ||
69 | int mxs_saif_clkmux_select(unsigned int clkmux) | ||
70 | { | ||
71 | if (clkmux > 0x3) | ||
72 | return -EINVAL; | ||
73 | |||
74 | __mxs_clrl(0x3 << BP_SAIF_CLKMUX, DIGCTRL); | ||
75 | __mxs_setl(clkmux << BP_SAIF_CLKMUX, DIGCTRL); | ||
76 | |||
77 | return 0; | ||
78 | } | ||
79 | |||
80 | static void __init clk_misc_init(void) | ||
81 | { | ||
82 | u32 val; | ||
83 | |||
84 | /* Gate off cpu clock in WFI for power saving */ | ||
85 | __mxs_setl(1 << BP_CPU_INTERRUPT_WAIT, CPU); | ||
86 | |||
87 | /* 0 is a bad default value for a divider */ | ||
88 | __mxs_setl(1 << BP_ENET_DIV_TIME, ENET); | ||
89 | |||
90 | /* Clear BYPASS for SAIF */ | ||
91 | __mxs_clrl(0x3 << BP_CLKSEQ_BYPASS_SAIF0, CLKSEQ); | ||
92 | |||
93 | /* SAIF has to use frac div for functional operation */ | ||
94 | val = readl_relaxed(SAIF0); | ||
95 | val |= 1 << BP_SAIF_DIV_FRAC_EN; | ||
96 | writel_relaxed(val, SAIF0); | ||
97 | |||
98 | val = readl_relaxed(SAIF1); | ||
99 | val |= 1 << BP_SAIF_DIV_FRAC_EN; | ||
100 | writel_relaxed(val, SAIF1); | ||
101 | |||
102 | /* Extra fec clock setting */ | ||
103 | val = readl_relaxed(ENET); | ||
104 | val &= ~(1 << BP_ENET_SLEEP); | ||
105 | writel_relaxed(val, ENET); | ||
106 | |||
107 | /* | ||
108 | * Source ssp clock from ref_io than ref_xtal, | ||
109 | * as ref_xtal only provides 24 MHz as maximum. | ||
110 | */ | ||
111 | __mxs_clrl(0xf << BP_CLKSEQ_BYPASS_SSP0, CLKSEQ); | ||
112 | |||
113 | /* | ||
114 | * 480 MHz seems too high to be ssp clock source directly, | ||
115 | * so set frac0 to get a 288 MHz ref_io0. | ||
116 | */ | ||
117 | val = readl_relaxed(FRAC0); | ||
118 | val &= ~(0x3f << BP_FRAC0_IO0FRAC); | ||
119 | val |= 30 << BP_FRAC0_IO0FRAC; | ||
120 | writel_relaxed(val, FRAC0); | ||
121 | } | ||
122 | |||
123 | static struct clk_lookup uart_lookups[] __initdata = { | ||
124 | { .dev_id = "duart", }, | ||
125 | { .dev_id = "mxs-auart.0", }, | ||
126 | { .dev_id = "mxs-auart.1", }, | ||
127 | { .dev_id = "mxs-auart.2", }, | ||
128 | { .dev_id = "mxs-auart.3", }, | ||
129 | { .dev_id = "mxs-auart.4", }, | ||
130 | { .dev_id = "8006a000.serial", }, | ||
131 | { .dev_id = "8006c000.serial", }, | ||
132 | { .dev_id = "8006e000.serial", }, | ||
133 | { .dev_id = "80070000.serial", }, | ||
134 | { .dev_id = "80072000.serial", }, | ||
135 | { .dev_id = "80074000.serial", }, | ||
136 | }; | ||
137 | |||
138 | static struct clk_lookup hbus_lookups[] __initdata = { | ||
139 | { .dev_id = "imx28-dma-apbh", }, | ||
140 | { .dev_id = "80004000.dma-apbh", }, | ||
141 | }; | ||
142 | |||
143 | static struct clk_lookup xbus_lookups[] __initdata = { | ||
144 | { .dev_id = "duart", .con_id = "apb_pclk"}, | ||
145 | { .dev_id = "80074000.serial", .con_id = "apb_pclk"}, | ||
146 | { .dev_id = "imx28-dma-apbx", }, | ||
147 | { .dev_id = "80024000.dma-apbx", }, | ||
148 | }; | ||
149 | |||
150 | static struct clk_lookup ssp0_lookups[] __initdata = { | ||
151 | { .dev_id = "imx28-mmc.0", }, | ||
152 | { .dev_id = "80010000.ssp", }, | ||
153 | }; | ||
154 | |||
155 | static struct clk_lookup ssp1_lookups[] __initdata = { | ||
156 | { .dev_id = "imx28-mmc.1", }, | ||
157 | { .dev_id = "80012000.ssp", }, | ||
158 | }; | ||
159 | |||
160 | static struct clk_lookup ssp2_lookups[] __initdata = { | ||
161 | { .dev_id = "imx28-mmc.2", }, | ||
162 | { .dev_id = "80014000.ssp", }, | ||
163 | }; | ||
164 | |||
165 | static struct clk_lookup ssp3_lookups[] __initdata = { | ||
166 | { .dev_id = "imx28-mmc.3", }, | ||
167 | { .dev_id = "80016000.ssp", }, | ||
168 | }; | ||
169 | |||
170 | static struct clk_lookup lcdif_lookups[] __initdata = { | ||
171 | { .dev_id = "imx28-fb", }, | ||
172 | { .dev_id = "80030000.lcdif", }, | ||
173 | }; | ||
174 | |||
175 | static struct clk_lookup gpmi_lookups[] __initdata = { | ||
176 | { .dev_id = "imx28-gpmi-nand", }, | ||
177 | { .dev_id = "8000c000.gpmi", }, | ||
178 | }; | ||
179 | |||
180 | static struct clk_lookup fec_lookups[] __initdata = { | ||
181 | { .dev_id = "imx28-fec.0", }, | ||
182 | { .dev_id = "imx28-fec.1", }, | ||
183 | { .dev_id = "800f0000.ethernet", }, | ||
184 | { .dev_id = "800f4000.ethernet", }, | ||
185 | }; | ||
186 | |||
187 | static struct clk_lookup can0_lookups[] __initdata = { | ||
188 | { .dev_id = "flexcan.0", }, | ||
189 | { .dev_id = "80032000.can", }, | ||
190 | }; | ||
191 | |||
192 | static struct clk_lookup can1_lookups[] __initdata = { | ||
193 | { .dev_id = "flexcan.1", }, | ||
194 | { .dev_id = "80034000.can", }, | ||
195 | }; | ||
196 | |||
197 | static struct clk_lookup saif0_lookups[] __initdata = { | ||
198 | { .dev_id = "mxs-saif.0", }, | ||
199 | { .dev_id = "80042000.saif", }, | ||
200 | }; | ||
201 | |||
202 | static struct clk_lookup saif1_lookups[] __initdata = { | ||
203 | { .dev_id = "mxs-saif.1", }, | ||
204 | { .dev_id = "80046000.saif", }, | ||
205 | }; | ||
206 | |||
207 | static const char *sel_cpu[] __initconst = { "ref_cpu", "ref_xtal", }; | ||
208 | static const char *sel_io0[] __initconst = { "ref_io0", "ref_xtal", }; | ||
209 | static const char *sel_io1[] __initconst = { "ref_io1", "ref_xtal", }; | ||
210 | static const char *sel_pix[] __initconst = { "ref_pix", "ref_xtal", }; | ||
211 | static const char *sel_gpmi[] __initconst = { "ref_gpmi", "ref_xtal", }; | ||
212 | static const char *sel_pll0[] __initconst = { "pll0", "ref_xtal", }; | ||
213 | static const char *cpu_sels[] __initconst = { "cpu_pll", "cpu_xtal", }; | ||
214 | static const char *emi_sels[] __initconst = { "emi_pll", "emi_xtal", }; | ||
215 | static const char *ptp_sels[] __initconst = { "ref_xtal", "pll0", }; | ||
216 | |||
217 | enum imx28_clk { | ||
218 | ref_xtal, pll0, pll1, pll2, ref_cpu, ref_emi, ref_io0, ref_io1, | ||
219 | ref_pix, ref_hsadc, ref_gpmi, saif0_sel, saif1_sel, gpmi_sel, | ||
220 | ssp0_sel, ssp1_sel, ssp2_sel, ssp3_sel, emi_sel, etm_sel, | ||
221 | lcdif_sel, cpu, ptp_sel, cpu_pll, cpu_xtal, hbus, xbus, | ||
222 | ssp0_div, ssp1_div, ssp2_div, ssp3_div, gpmi_div, emi_pll, | ||
223 | emi_xtal, lcdif_div, etm_div, ptp, saif0_div, saif1_div, | ||
224 | clk32k_div, rtc, lradc, spdif_div, clk32k, pwm, uart, ssp0, | ||
225 | ssp1, ssp2, ssp3, gpmi, spdif, emi, saif0, saif1, lcdif, etm, | ||
226 | fec, can0, can1, usb0, usb1, usb0_pwr, usb1_pwr, enet_out, | ||
227 | clk_max | ||
228 | }; | ||
229 | |||
230 | static struct clk *clks[clk_max]; | ||
231 | |||
232 | static enum imx28_clk clks_init_on[] __initdata = { | ||
233 | cpu, hbus, xbus, emi, uart, | ||
234 | }; | ||
235 | |||
236 | int __init mx28_clocks_init(void) | ||
237 | { | ||
238 | int i; | ||
239 | |||
240 | clk_misc_init(); | ||
241 | |||
242 | clks[ref_xtal] = mxs_clk_fixed("ref_xtal", 24000000); | ||
243 | clks[pll0] = mxs_clk_pll("pll0", "ref_xtal", PLL0CTRL0, 17, 480000000); | ||
244 | clks[pll1] = mxs_clk_pll("pll1", "ref_xtal", PLL1CTRL0, 17, 480000000); | ||
245 | clks[pll2] = mxs_clk_pll("pll2", "ref_xtal", PLL2CTRL0, 23, 50000000); | ||
246 | clks[ref_cpu] = mxs_clk_ref("ref_cpu", "pll0", FRAC0, 0); | ||
247 | clks[ref_emi] = mxs_clk_ref("ref_emi", "pll0", FRAC0, 1); | ||
248 | clks[ref_io0] = mxs_clk_ref("ref_io0", "pll0", FRAC0, 2); | ||
249 | clks[ref_io1] = mxs_clk_ref("ref_io1", "pll0", FRAC0, 3); | ||
250 | clks[ref_pix] = mxs_clk_ref("ref_pix", "pll0", FRAC1, 0); | ||
251 | clks[ref_hsadc] = mxs_clk_ref("ref_hsadc", "pll0", FRAC1, 1); | ||
252 | clks[ref_gpmi] = mxs_clk_ref("ref_gpmi", "pll0", FRAC1, 2); | ||
253 | clks[saif0_sel] = mxs_clk_mux("saif0_sel", CLKSEQ, 0, 1, sel_pll0, ARRAY_SIZE(sel_pll0)); | ||
254 | clks[saif1_sel] = mxs_clk_mux("saif1_sel", CLKSEQ, 1, 1, sel_pll0, ARRAY_SIZE(sel_pll0)); | ||
255 | clks[gpmi_sel] = mxs_clk_mux("gpmi_sel", CLKSEQ, 2, 1, sel_gpmi, ARRAY_SIZE(sel_gpmi)); | ||
256 | clks[ssp0_sel] = mxs_clk_mux("ssp0_sel", CLKSEQ, 3, 1, sel_io0, ARRAY_SIZE(sel_io0)); | ||
257 | clks[ssp1_sel] = mxs_clk_mux("ssp1_sel", CLKSEQ, 4, 1, sel_io0, ARRAY_SIZE(sel_io0)); | ||
258 | clks[ssp2_sel] = mxs_clk_mux("ssp2_sel", CLKSEQ, 5, 1, sel_io1, ARRAY_SIZE(sel_io1)); | ||
259 | clks[ssp3_sel] = mxs_clk_mux("ssp3_sel", CLKSEQ, 6, 1, sel_io1, ARRAY_SIZE(sel_io1)); | ||
260 | clks[emi_sel] = mxs_clk_mux("emi_sel", CLKSEQ, 7, 1, emi_sels, ARRAY_SIZE(emi_sels)); | ||
261 | clks[etm_sel] = mxs_clk_mux("etm_sel", CLKSEQ, 8, 1, sel_cpu, ARRAY_SIZE(sel_cpu)); | ||
262 | clks[lcdif_sel] = mxs_clk_mux("lcdif_sel", CLKSEQ, 14, 1, sel_pix, ARRAY_SIZE(sel_pix)); | ||
263 | clks[cpu] = mxs_clk_mux("cpu", CLKSEQ, 18, 1, cpu_sels, ARRAY_SIZE(cpu_sels)); | ||
264 | clks[ptp_sel] = mxs_clk_mux("ptp_sel", ENET, 19, 1, ptp_sels, ARRAY_SIZE(ptp_sels)); | ||
265 | clks[cpu_pll] = mxs_clk_div("cpu_pll", "ref_cpu", CPU, 0, 6, 28); | ||
266 | clks[cpu_xtal] = mxs_clk_div("cpu_xtal", "ref_xtal", CPU, 16, 10, 29); | ||
267 | clks[hbus] = mxs_clk_div("hbus", "cpu", HBUS, 0, 5, 31); | ||
268 | clks[xbus] = mxs_clk_div("xbus", "ref_xtal", XBUS, 0, 10, 31); | ||
269 | clks[ssp0_div] = mxs_clk_div("ssp0_div", "ssp0_sel", SSP0, 0, 9, 29); | ||
270 | clks[ssp1_div] = mxs_clk_div("ssp1_div", "ssp1_sel", SSP1, 0, 9, 29); | ||
271 | clks[ssp2_div] = mxs_clk_div("ssp2_div", "ssp2_sel", SSP2, 0, 9, 29); | ||
272 | clks[ssp3_div] = mxs_clk_div("ssp3_div", "ssp3_sel", SSP3, 0, 9, 29); | ||
273 | clks[gpmi_div] = mxs_clk_div("gpmi_div", "gpmi_sel", GPMI, 0, 10, 29); | ||
274 | clks[emi_pll] = mxs_clk_div("emi_pll", "ref_emi", EMI, 0, 6, 28); | ||
275 | clks[emi_xtal] = mxs_clk_div("emi_xtal", "ref_xtal", EMI, 8, 4, 29); | ||
276 | clks[lcdif_div] = mxs_clk_div("lcdif_div", "lcdif_sel", LCDIF, 0, 13, 29); | ||
277 | clks[etm_div] = mxs_clk_div("etm_div", "etm_sel", ETM, 0, 7, 29); | ||
278 | clks[ptp] = mxs_clk_div("ptp", "ptp_sel", ENET, 21, 6, 27); | ||
279 | clks[saif0_div] = mxs_clk_frac("saif0_div", "saif0_sel", SAIF0, 0, 16, 29); | ||
280 | clks[saif1_div] = mxs_clk_frac("saif1_div", "saif1_sel", SAIF1, 0, 16, 29); | ||
281 | clks[clk32k_div] = mxs_clk_fixed_factor("clk32k_div", "ref_xtal", 1, 750); | ||
282 | clks[rtc] = mxs_clk_fixed_factor("rtc", "ref_xtal", 1, 768); | ||
283 | clks[lradc] = mxs_clk_fixed_factor("lradc", "clk32k", 1, 16); | ||
284 | clks[spdif_div] = mxs_clk_fixed_factor("spdif_div", "pll0", 1, 4); | ||
285 | clks[clk32k] = mxs_clk_gate("clk32k", "clk32k_div", XTAL, 26); | ||
286 | clks[pwm] = mxs_clk_gate("pwm", "ref_xtal", XTAL, 29); | ||
287 | clks[uart] = mxs_clk_gate("uart", "ref_xtal", XTAL, 31); | ||
288 | clks[ssp0] = mxs_clk_gate("ssp0", "ssp0_div", SSP0, 31); | ||
289 | clks[ssp1] = mxs_clk_gate("ssp1", "ssp1_div", SSP1, 31); | ||
290 | clks[ssp2] = mxs_clk_gate("ssp2", "ssp2_div", SSP2, 31); | ||
291 | clks[ssp3] = mxs_clk_gate("ssp3", "ssp3_div", SSP3, 31); | ||
292 | clks[gpmi] = mxs_clk_gate("gpmi", "gpmi_div", GPMI, 31); | ||
293 | clks[spdif] = mxs_clk_gate("spdif", "spdif_div", SPDIF, 31); | ||
294 | clks[emi] = mxs_clk_gate("emi", "emi_sel", EMI, 31); | ||
295 | clks[saif0] = mxs_clk_gate("saif0", "saif0_div", SAIF0, 31); | ||
296 | clks[saif1] = mxs_clk_gate("saif1", "saif1_div", SAIF1, 31); | ||
297 | clks[lcdif] = mxs_clk_gate("lcdif", "lcdif_div", LCDIF, 31); | ||
298 | clks[etm] = mxs_clk_gate("etm", "etm_div", ETM, 31); | ||
299 | clks[fec] = mxs_clk_gate("fec", "hbus", ENET, 30); | ||
300 | clks[can0] = mxs_clk_gate("can0", "ref_xtal", FLEXCAN, 30); | ||
301 | clks[can1] = mxs_clk_gate("can1", "ref_xtal", FLEXCAN, 28); | ||
302 | clks[usb0] = mxs_clk_gate("usb0", "usb0_pwr", DIGCTRL, 2); | ||
303 | clks[usb1] = mxs_clk_gate("usb1", "usb1_pwr", DIGCTRL, 16); | ||
304 | clks[usb0_pwr] = clk_register_gate(NULL, "usb0_pwr", "pll0", 0, PLL0CTRL0, 18, 0, &mxs_lock); | ||
305 | clks[usb1_pwr] = clk_register_gate(NULL, "usb1_pwr", "pll1", 0, PLL1CTRL0, 18, 0, &mxs_lock); | ||
306 | clks[enet_out] = clk_register_gate(NULL, "enet_out", "pll2", 0, ENET, 18, 0, &mxs_lock); | ||
307 | |||
308 | for (i = 0; i < ARRAY_SIZE(clks); i++) | ||
309 | if (IS_ERR(clks[i])) { | ||
310 | pr_err("i.MX28 clk %d: register failed with %ld\n", | ||
311 | i, PTR_ERR(clks[i])); | ||
312 | return PTR_ERR(clks[i]); | ||
313 | } | ||
314 | |||
315 | clk_register_clkdev(clks[clk32k], NULL, "timrot"); | ||
316 | clk_register_clkdev(clks[enet_out], NULL, "enet_out"); | ||
317 | clk_register_clkdevs(clks[hbus], hbus_lookups, ARRAY_SIZE(hbus_lookups)); | ||
318 | clk_register_clkdevs(clks[xbus], xbus_lookups, ARRAY_SIZE(xbus_lookups)); | ||
319 | clk_register_clkdevs(clks[uart], uart_lookups, ARRAY_SIZE(uart_lookups)); | ||
320 | clk_register_clkdevs(clks[ssp0], ssp0_lookups, ARRAY_SIZE(ssp0_lookups)); | ||
321 | clk_register_clkdevs(clks[ssp1], ssp1_lookups, ARRAY_SIZE(ssp1_lookups)); | ||
322 | clk_register_clkdevs(clks[ssp2], ssp2_lookups, ARRAY_SIZE(ssp2_lookups)); | ||
323 | clk_register_clkdevs(clks[ssp3], ssp3_lookups, ARRAY_SIZE(ssp3_lookups)); | ||
324 | clk_register_clkdevs(clks[gpmi], gpmi_lookups, ARRAY_SIZE(gpmi_lookups)); | ||
325 | clk_register_clkdevs(clks[saif0], saif0_lookups, ARRAY_SIZE(saif0_lookups)); | ||
326 | clk_register_clkdevs(clks[saif1], saif1_lookups, ARRAY_SIZE(saif1_lookups)); | ||
327 | clk_register_clkdevs(clks[lcdif], lcdif_lookups, ARRAY_SIZE(lcdif_lookups)); | ||
328 | clk_register_clkdevs(clks[fec], fec_lookups, ARRAY_SIZE(fec_lookups)); | ||
329 | clk_register_clkdevs(clks[can0], can0_lookups, ARRAY_SIZE(can0_lookups)); | ||
330 | clk_register_clkdevs(clks[can1], can1_lookups, ARRAY_SIZE(can1_lookups)); | ||
331 | |||
332 | for (i = 0; i < ARRAY_SIZE(clks_init_on); i++) | ||
333 | clk_prepare_enable(clks[clks_init_on[i]]); | ||
334 | |||
335 | mxs_timer_init(MX28_INT_TIMER0); | ||
336 | |||
337 | return 0; | ||
338 | } | ||
diff --git a/drivers/clk/mxs/clk-pll.c b/drivers/clk/mxs/clk-pll.c new file mode 100644 index 000000000000..fadae41833ec --- /dev/null +++ b/drivers/clk/mxs/clk-pll.c | |||
@@ -0,0 +1,116 @@ | |||
1 | /* | ||
2 | * Copyright 2012 Freescale Semiconductor, Inc. | ||
3 | * | ||
4 | * The code contained herein is licensed under the GNU General Public | ||
5 | * License. You may obtain a copy of the GNU General Public License | ||
6 | * Version 2 or later at the following locations: | ||
7 | * | ||
8 | * http://www.opensource.org/licenses/gpl-license.html | ||
9 | * http://www.gnu.org/copyleft/gpl.html | ||
10 | */ | ||
11 | |||
12 | #include <linux/clk.h> | ||
13 | #include <linux/clk-provider.h> | ||
14 | #include <linux/delay.h> | ||
15 | #include <linux/err.h> | ||
16 | #include <linux/io.h> | ||
17 | #include <linux/slab.h> | ||
18 | #include "clk.h" | ||
19 | |||
20 | /** | ||
21 | * struct clk_pll - mxs pll clock | ||
22 | * @hw: clk_hw for the pll | ||
23 | * @base: base address of the pll | ||
24 | * @power: the shift of power bit | ||
25 | * @rate: the clock rate of the pll | ||
26 | * | ||
27 | * The mxs pll is a fixed rate clock with power and gate control, | ||
28 | * and the shift of gate bit is always 31. | ||
29 | */ | ||
30 | struct clk_pll { | ||
31 | struct clk_hw hw; | ||
32 | void __iomem *base; | ||
33 | u8 power; | ||
34 | unsigned long rate; | ||
35 | }; | ||
36 | |||
37 | #define to_clk_pll(_hw) container_of(_hw, struct clk_pll, hw) | ||
38 | |||
39 | static int clk_pll_prepare(struct clk_hw *hw) | ||
40 | { | ||
41 | struct clk_pll *pll = to_clk_pll(hw); | ||
42 | |||
43 | writel_relaxed(1 << pll->power, pll->base + SET); | ||
44 | |||
45 | udelay(10); | ||
46 | |||
47 | return 0; | ||
48 | } | ||
49 | |||
50 | static void clk_pll_unprepare(struct clk_hw *hw) | ||
51 | { | ||
52 | struct clk_pll *pll = to_clk_pll(hw); | ||
53 | |||
54 | writel_relaxed(1 << pll->power, pll->base + CLR); | ||
55 | } | ||
56 | |||
57 | static int clk_pll_enable(struct clk_hw *hw) | ||
58 | { | ||
59 | struct clk_pll *pll = to_clk_pll(hw); | ||
60 | |||
61 | writel_relaxed(1 << 31, pll->base + CLR); | ||
62 | |||
63 | return 0; | ||
64 | } | ||
65 | |||
66 | static void clk_pll_disable(struct clk_hw *hw) | ||
67 | { | ||
68 | struct clk_pll *pll = to_clk_pll(hw); | ||
69 | |||
70 | writel_relaxed(1 << 31, pll->base + SET); | ||
71 | } | ||
72 | |||
73 | static unsigned long clk_pll_recalc_rate(struct clk_hw *hw, | ||
74 | unsigned long parent_rate) | ||
75 | { | ||
76 | struct clk_pll *pll = to_clk_pll(hw); | ||
77 | |||
78 | return pll->rate; | ||
79 | } | ||
80 | |||
81 | static const struct clk_ops clk_pll_ops = { | ||
82 | .prepare = clk_pll_prepare, | ||
83 | .unprepare = clk_pll_unprepare, | ||
84 | .enable = clk_pll_enable, | ||
85 | .disable = clk_pll_disable, | ||
86 | .recalc_rate = clk_pll_recalc_rate, | ||
87 | }; | ||
88 | |||
89 | struct clk *mxs_clk_pll(const char *name, const char *parent_name, | ||
90 | void __iomem *base, u8 power, unsigned long rate) | ||
91 | { | ||
92 | struct clk_pll *pll; | ||
93 | struct clk *clk; | ||
94 | struct clk_init_data init; | ||
95 | |||
96 | pll = kzalloc(sizeof(*pll), GFP_KERNEL); | ||
97 | if (!pll) | ||
98 | return ERR_PTR(-ENOMEM); | ||
99 | |||
100 | init.name = name; | ||
101 | init.ops = &clk_pll_ops; | ||
102 | init.flags = 0; | ||
103 | init.parent_names = (parent_name ? &parent_name: NULL); | ||
104 | init.num_parents = (parent_name ? 1 : 0); | ||
105 | |||
106 | pll->base = base; | ||
107 | pll->rate = rate; | ||
108 | pll->power = power; | ||
109 | pll->hw.init = &init; | ||
110 | |||
111 | clk = clk_register(NULL, &pll->hw); | ||
112 | if (IS_ERR(clk)) | ||
113 | kfree(pll); | ||
114 | |||
115 | return clk; | ||
116 | } | ||
diff --git a/drivers/clk/mxs/clk-ref.c b/drivers/clk/mxs/clk-ref.c new file mode 100644 index 000000000000..4adeed6c2f94 --- /dev/null +++ b/drivers/clk/mxs/clk-ref.c | |||
@@ -0,0 +1,154 @@ | |||
1 | /* | ||
2 | * Copyright 2012 Freescale Semiconductor, Inc. | ||
3 | * | ||
4 | * The code contained herein is licensed under the GNU General Public | ||
5 | * License. You may obtain a copy of the GNU General Public License | ||
6 | * Version 2 or later at the following locations: | ||
7 | * | ||
8 | * http://www.opensource.org/licenses/gpl-license.html | ||
9 | * http://www.gnu.org/copyleft/gpl.html | ||
10 | */ | ||
11 | |||
12 | #include <linux/clk.h> | ||
13 | #include <linux/clk-provider.h> | ||
14 | #include <linux/err.h> | ||
15 | #include <linux/io.h> | ||
16 | #include <linux/slab.h> | ||
17 | #include "clk.h" | ||
18 | |||
19 | /** | ||
20 | * struct clk_ref - mxs reference clock | ||
21 | * @hw: clk_hw for the reference clock | ||
22 | * @reg: register address | ||
23 | * @idx: the index of the reference clock within the same register | ||
24 | * | ||
25 | * The mxs reference clock sources from pll. Every 4 reference clocks share | ||
26 | * one register space, and @idx is used to identify them. Each reference | ||
27 | * clock has a gate control and a fractional * divider. The rate is calculated | ||
28 | * as pll rate * (18 / FRAC), where FRAC = 18 ~ 35. | ||
29 | */ | ||
30 | struct clk_ref { | ||
31 | struct clk_hw hw; | ||
32 | void __iomem *reg; | ||
33 | u8 idx; | ||
34 | }; | ||
35 | |||
36 | #define to_clk_ref(_hw) container_of(_hw, struct clk_ref, hw) | ||
37 | |||
38 | static int clk_ref_enable(struct clk_hw *hw) | ||
39 | { | ||
40 | struct clk_ref *ref = to_clk_ref(hw); | ||
41 | |||
42 | writel_relaxed(1 << ((ref->idx + 1) * 8 - 1), ref->reg + CLR); | ||
43 | |||
44 | return 0; | ||
45 | } | ||
46 | |||
47 | static void clk_ref_disable(struct clk_hw *hw) | ||
48 | { | ||
49 | struct clk_ref *ref = to_clk_ref(hw); | ||
50 | |||
51 | writel_relaxed(1 << ((ref->idx + 1) * 8 - 1), ref->reg + SET); | ||
52 | } | ||
53 | |||
54 | static unsigned long clk_ref_recalc_rate(struct clk_hw *hw, | ||
55 | unsigned long parent_rate) | ||
56 | { | ||
57 | struct clk_ref *ref = to_clk_ref(hw); | ||
58 | u64 tmp = parent_rate; | ||
59 | u8 frac = (readl_relaxed(ref->reg) >> (ref->idx * 8)) & 0x3f; | ||
60 | |||
61 | tmp *= 18; | ||
62 | do_div(tmp, frac); | ||
63 | |||
64 | return tmp; | ||
65 | } | ||
66 | |||
67 | static long clk_ref_round_rate(struct clk_hw *hw, unsigned long rate, | ||
68 | unsigned long *prate) | ||
69 | { | ||
70 | unsigned long parent_rate = *prate; | ||
71 | u64 tmp = parent_rate; | ||
72 | u8 frac; | ||
73 | |||
74 | tmp = tmp * 18 + rate / 2; | ||
75 | do_div(tmp, rate); | ||
76 | frac = tmp; | ||
77 | |||
78 | if (frac < 18) | ||
79 | frac = 18; | ||
80 | else if (frac > 35) | ||
81 | frac = 35; | ||
82 | |||
83 | tmp = parent_rate; | ||
84 | tmp *= 18; | ||
85 | do_div(tmp, frac); | ||
86 | |||
87 | return tmp; | ||
88 | } | ||
89 | |||
90 | static int clk_ref_set_rate(struct clk_hw *hw, unsigned long rate, | ||
91 | unsigned long parent_rate) | ||
92 | { | ||
93 | struct clk_ref *ref = to_clk_ref(hw); | ||
94 | unsigned long flags; | ||
95 | u64 tmp = parent_rate; | ||
96 | u32 val; | ||
97 | u8 frac, shift = ref->idx * 8; | ||
98 | |||
99 | tmp = tmp * 18 + rate / 2; | ||
100 | do_div(tmp, rate); | ||
101 | frac = tmp; | ||
102 | |||
103 | if (frac < 18) | ||
104 | frac = 18; | ||
105 | else if (frac > 35) | ||
106 | frac = 35; | ||
107 | |||
108 | spin_lock_irqsave(&mxs_lock, flags); | ||
109 | |||
110 | val = readl_relaxed(ref->reg); | ||
111 | val &= ~(0x3f << shift); | ||
112 | val |= frac << shift; | ||
113 | writel_relaxed(val, ref->reg); | ||
114 | |||
115 | spin_unlock_irqrestore(&mxs_lock, flags); | ||
116 | |||
117 | return 0; | ||
118 | } | ||
119 | |||
120 | static const struct clk_ops clk_ref_ops = { | ||
121 | .enable = clk_ref_enable, | ||
122 | .disable = clk_ref_disable, | ||
123 | .recalc_rate = clk_ref_recalc_rate, | ||
124 | .round_rate = clk_ref_round_rate, | ||
125 | .set_rate = clk_ref_set_rate, | ||
126 | }; | ||
127 | |||
128 | struct clk *mxs_clk_ref(const char *name, const char *parent_name, | ||
129 | void __iomem *reg, u8 idx) | ||
130 | { | ||
131 | struct clk_ref *ref; | ||
132 | struct clk *clk; | ||
133 | struct clk_init_data init; | ||
134 | |||
135 | ref = kzalloc(sizeof(*ref), GFP_KERNEL); | ||
136 | if (!ref) | ||
137 | return ERR_PTR(-ENOMEM); | ||
138 | |||
139 | init.name = name; | ||
140 | init.ops = &clk_ref_ops; | ||
141 | init.flags = 0; | ||
142 | init.parent_names = (parent_name ? &parent_name: NULL); | ||
143 | init.num_parents = (parent_name ? 1 : 0); | ||
144 | |||
145 | ref->reg = reg; | ||
146 | ref->idx = idx; | ||
147 | ref->hw.init = &init; | ||
148 | |||
149 | clk = clk_register(NULL, &ref->hw); | ||
150 | if (IS_ERR(clk)) | ||
151 | kfree(ref); | ||
152 | |||
153 | return clk; | ||
154 | } | ||
diff --git a/drivers/clk/mxs/clk.c b/drivers/clk/mxs/clk.c new file mode 100644 index 000000000000..b24d56067c80 --- /dev/null +++ b/drivers/clk/mxs/clk.c | |||
@@ -0,0 +1,28 @@ | |||
1 | /* | ||
2 | * Copyright 2012 Freescale Semiconductor, Inc. | ||
3 | * | ||
4 | * The code contained herein is licensed under the GNU General Public | ||
5 | * License. You may obtain a copy of the GNU General Public License | ||
6 | * Version 2 or later at the following locations: | ||
7 | * | ||
8 | * http://www.opensource.org/licenses/gpl-license.html | ||
9 | * http://www.gnu.org/copyleft/gpl.html | ||
10 | */ | ||
11 | |||
12 | #include <linux/err.h> | ||
13 | #include <linux/io.h> | ||
14 | #include <linux/jiffies.h> | ||
15 | #include <linux/spinlock.h> | ||
16 | |||
17 | DEFINE_SPINLOCK(mxs_lock); | ||
18 | |||
19 | int mxs_clk_wait(void __iomem *reg, u8 shift) | ||
20 | { | ||
21 | unsigned long timeout = jiffies + msecs_to_jiffies(10); | ||
22 | |||
23 | while (readl_relaxed(reg) & (1 << shift)) | ||
24 | if (time_after(jiffies, timeout)) | ||
25 | return -ETIMEDOUT; | ||
26 | |||
27 | return 0; | ||
28 | } | ||
diff --git a/drivers/clk/mxs/clk.h b/drivers/clk/mxs/clk.h new file mode 100644 index 000000000000..81421e28e69c --- /dev/null +++ b/drivers/clk/mxs/clk.h | |||
@@ -0,0 +1,66 @@ | |||
1 | /* | ||
2 | * Copyright 2012 Freescale Semiconductor, Inc. | ||
3 | * | ||
4 | * The code contained herein is licensed under the GNU General Public | ||
5 | * License. You may obtain a copy of the GNU General Public License | ||
6 | * Version 2 or later at the following locations: | ||
7 | * | ||
8 | * http://www.opensource.org/licenses/gpl-license.html | ||
9 | * http://www.gnu.org/copyleft/gpl.html | ||
10 | */ | ||
11 | |||
12 | #ifndef __MXS_CLK_H | ||
13 | #define __MXS_CLK_H | ||
14 | |||
15 | #include <linux/clk.h> | ||
16 | #include <linux/clk-provider.h> | ||
17 | #include <linux/spinlock.h> | ||
18 | |||
19 | #define SET 0x4 | ||
20 | #define CLR 0x8 | ||
21 | |||
22 | extern spinlock_t mxs_lock; | ||
23 | |||
24 | int mxs_clk_wait(void __iomem *reg, u8 shift); | ||
25 | |||
26 | struct clk *mxs_clk_pll(const char *name, const char *parent_name, | ||
27 | void __iomem *base, u8 power, unsigned long rate); | ||
28 | |||
29 | struct clk *mxs_clk_ref(const char *name, const char *parent_name, | ||
30 | void __iomem *reg, u8 idx); | ||
31 | |||
32 | struct clk *mxs_clk_div(const char *name, const char *parent_name, | ||
33 | void __iomem *reg, u8 shift, u8 width, u8 busy); | ||
34 | |||
35 | struct clk *mxs_clk_frac(const char *name, const char *parent_name, | ||
36 | void __iomem *reg, u8 shift, u8 width, u8 busy); | ||
37 | |||
38 | static inline struct clk *mxs_clk_fixed(const char *name, int rate) | ||
39 | { | ||
40 | return clk_register_fixed_rate(NULL, name, NULL, CLK_IS_ROOT, rate); | ||
41 | } | ||
42 | |||
43 | static inline struct clk *mxs_clk_gate(const char *name, | ||
44 | const char *parent_name, void __iomem *reg, u8 shift) | ||
45 | { | ||
46 | return clk_register_gate(NULL, name, parent_name, CLK_SET_RATE_PARENT, | ||
47 | reg, shift, CLK_GATE_SET_TO_DISABLE, | ||
48 | &mxs_lock); | ||
49 | } | ||
50 | |||
51 | static inline struct clk *mxs_clk_mux(const char *name, void __iomem *reg, | ||
52 | u8 shift, u8 width, const char **parent_names, int num_parents) | ||
53 | { | ||
54 | return clk_register_mux(NULL, name, parent_names, num_parents, | ||
55 | CLK_SET_RATE_PARENT, reg, shift, width, | ||
56 | 0, &mxs_lock); | ||
57 | } | ||
58 | |||
59 | static inline struct clk *mxs_clk_fixed_factor(const char *name, | ||
60 | const char *parent_name, unsigned int mult, unsigned int div) | ||
61 | { | ||
62 | return clk_register_fixed_factor(NULL, name, parent_name, | ||
63 | CLK_SET_RATE_PARENT, mult, div); | ||
64 | } | ||
65 | |||
66 | #endif /* __MXS_CLK_H */ | ||
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 | |||
238 | config MXS_DMA | 238 | config MXS_DMA |
239 | bool "MXS DMA support" | 239 | bool "MXS DMA support" |
240 | depends on SOC_IMX23 || SOC_IMX28 | 240 | depends on SOC_IMX23 || SOC_IMX28 |
241 | select STMP_DEVICE | ||
241 | select DMA_ENGINE | 242 | select DMA_ENGINE |
242 | help | 243 | help |
243 | Support the MXS DMA engine. This engine including APBH-DMA | 244 | 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..1cb9b974493f 100644 --- a/drivers/dma/mxs-dma.c +++ b/drivers/dma/mxs-dma.c | |||
@@ -22,11 +22,14 @@ | |||
22 | #include <linux/platform_device.h> | 22 | #include <linux/platform_device.h> |
23 | #include <linux/dmaengine.h> | 23 | #include <linux/dmaengine.h> |
24 | #include <linux/delay.h> | 24 | #include <linux/delay.h> |
25 | #include <linux/module.h> | ||
25 | #include <linux/fsl/mxs-dma.h> | 26 | #include <linux/fsl/mxs-dma.h> |
27 | #include <linux/stmp_device.h> | ||
28 | #include <linux/of.h> | ||
29 | #include <linux/of_device.h> | ||
26 | 30 | ||
27 | #include <asm/irq.h> | 31 | #include <asm/irq.h> |
28 | #include <mach/mxs.h> | 32 | #include <mach/mxs.h> |
29 | #include <mach/common.h> | ||
30 | 33 | ||
31 | #include "dmaengine.h" | 34 | #include "dmaengine.h" |
32 | 35 | ||
@@ -36,12 +39,8 @@ | |||
36 | * dma can program the controller registers of peripheral devices. | 39 | * dma can program the controller registers of peripheral devices. |
37 | */ | 40 | */ |
38 | 41 | ||
39 | #define MXS_DMA_APBH 0 | 42 | #define dma_is_apbh(mxs_dma) ((mxs_dma)->type == MXS_DMA_APBH) |
40 | #define MXS_DMA_APBX 1 | 43 | #define apbh_is_old(mxs_dma) ((mxs_dma)->dev_id == IMX23_DMA) |
41 | #define dma_is_apbh() (mxs_dma->dev_id == MXS_DMA_APBH) | ||
42 | |||
43 | #define APBH_VERSION_LATEST 3 | ||
44 | #define apbh_is_old() (mxs_dma->version < APBH_VERSION_LATEST) | ||
45 | 44 | ||
46 | #define HW_APBHX_CTRL0 0x000 | 45 | #define HW_APBHX_CTRL0 0x000 |
47 | #define BM_APBH_CTRL0_APB_BURST8_EN (1 << 29) | 46 | #define BM_APBH_CTRL0_APB_BURST8_EN (1 << 29) |
@@ -51,13 +50,14 @@ | |||
51 | #define HW_APBHX_CTRL2 0x020 | 50 | #define HW_APBHX_CTRL2 0x020 |
52 | #define HW_APBHX_CHANNEL_CTRL 0x030 | 51 | #define HW_APBHX_CHANNEL_CTRL 0x030 |
53 | #define BP_APBHX_CHANNEL_CTRL_RESET_CHANNEL 16 | 52 | #define BP_APBHX_CHANNEL_CTRL_RESET_CHANNEL 16 |
54 | #define HW_APBH_VERSION (cpu_is_mx23() ? 0x3f0 : 0x800) | 53 | /* |
55 | #define HW_APBX_VERSION 0x800 | 54 | * The offset of NXTCMDAR register is different per both dma type and version, |
56 | #define BP_APBHX_VERSION_MAJOR 24 | 55 | * while stride for each channel is all the same 0x70. |
57 | #define HW_APBHX_CHn_NXTCMDAR(n) \ | 56 | */ |
58 | (((dma_is_apbh() && apbh_is_old()) ? 0x050 : 0x110) + (n) * 0x70) | 57 | #define HW_APBHX_CHn_NXTCMDAR(d, n) \ |
59 | #define HW_APBHX_CHn_SEMA(n) \ | 58 | (((dma_is_apbh(d) && apbh_is_old(d)) ? 0x050 : 0x110) + (n) * 0x70) |
60 | (((dma_is_apbh() && apbh_is_old()) ? 0x080 : 0x140) + (n) * 0x70) | 59 | #define HW_APBHX_CHn_SEMA(d, n) \ |
60 | (((dma_is_apbh(d) && apbh_is_old(d)) ? 0x080 : 0x140) + (n) * 0x70) | ||
61 | 61 | ||
62 | /* | 62 | /* |
63 | * ccw bits definitions | 63 | * ccw bits definitions |
@@ -121,9 +121,19 @@ struct mxs_dma_chan { | |||
121 | #define MXS_DMA_CHANNELS 16 | 121 | #define MXS_DMA_CHANNELS 16 |
122 | #define MXS_DMA_CHANNELS_MASK 0xffff | 122 | #define MXS_DMA_CHANNELS_MASK 0xffff |
123 | 123 | ||
124 | enum mxs_dma_devtype { | ||
125 | MXS_DMA_APBH, | ||
126 | MXS_DMA_APBX, | ||
127 | }; | ||
128 | |||
129 | enum mxs_dma_id { | ||
130 | IMX23_DMA, | ||
131 | IMX28_DMA, | ||
132 | }; | ||
133 | |||
124 | struct mxs_dma_engine { | 134 | struct mxs_dma_engine { |
125 | int dev_id; | 135 | enum mxs_dma_id dev_id; |
126 | unsigned int version; | 136 | enum mxs_dma_devtype type; |
127 | void __iomem *base; | 137 | void __iomem *base; |
128 | struct clk *clk; | 138 | struct clk *clk; |
129 | struct dma_device dma_device; | 139 | struct dma_device dma_device; |
@@ -131,17 +141,86 @@ struct mxs_dma_engine { | |||
131 | struct mxs_dma_chan mxs_chans[MXS_DMA_CHANNELS]; | 141 | struct mxs_dma_chan mxs_chans[MXS_DMA_CHANNELS]; |
132 | }; | 142 | }; |
133 | 143 | ||
144 | struct mxs_dma_type { | ||
145 | enum mxs_dma_id id; | ||
146 | enum mxs_dma_devtype type; | ||
147 | }; | ||
148 | |||
149 | static struct mxs_dma_type mxs_dma_types[] = { | ||
150 | { | ||
151 | .id = IMX23_DMA, | ||
152 | .type = MXS_DMA_APBH, | ||
153 | }, { | ||
154 | .id = IMX23_DMA, | ||
155 | .type = MXS_DMA_APBX, | ||
156 | }, { | ||
157 | .id = IMX28_DMA, | ||
158 | .type = MXS_DMA_APBH, | ||
159 | }, { | ||
160 | .id = IMX28_DMA, | ||
161 | .type = MXS_DMA_APBX, | ||
162 | } | ||
163 | }; | ||
164 | |||
165 | static struct platform_device_id mxs_dma_ids[] = { | ||
166 | { | ||
167 | .name = "imx23-dma-apbh", | ||
168 | .driver_data = (kernel_ulong_t) &mxs_dma_types[0], | ||
169 | }, { | ||
170 | .name = "imx23-dma-apbx", | ||
171 | .driver_data = (kernel_ulong_t) &mxs_dma_types[1], | ||
172 | }, { | ||
173 | .name = "imx28-dma-apbh", | ||
174 | .driver_data = (kernel_ulong_t) &mxs_dma_types[2], | ||
175 | }, { | ||
176 | .name = "imx28-dma-apbx", | ||
177 | .driver_data = (kernel_ulong_t) &mxs_dma_types[3], | ||
178 | }, { | ||
179 | /* end of list */ | ||
180 | } | ||
181 | }; | ||
182 | |||
183 | static const struct of_device_id mxs_dma_dt_ids[] = { | ||
184 | { .compatible = "fsl,imx23-dma-apbh", .data = &mxs_dma_ids[0], }, | ||
185 | { .compatible = "fsl,imx23-dma-apbx", .data = &mxs_dma_ids[1], }, | ||
186 | { .compatible = "fsl,imx28-dma-apbh", .data = &mxs_dma_ids[2], }, | ||
187 | { .compatible = "fsl,imx28-dma-apbx", .data = &mxs_dma_ids[3], }, | ||
188 | { /* sentinel */ } | ||
189 | }; | ||
190 | MODULE_DEVICE_TABLE(of, mxs_dma_dt_ids); | ||
191 | |||
192 | static struct mxs_dma_chan *to_mxs_dma_chan(struct dma_chan *chan) | ||
193 | { | ||
194 | return container_of(chan, struct mxs_dma_chan, chan); | ||
195 | } | ||
196 | |||
197 | int mxs_dma_is_apbh(struct dma_chan *chan) | ||
198 | { | ||
199 | struct mxs_dma_chan *mxs_chan = to_mxs_dma_chan(chan); | ||
200 | struct mxs_dma_engine *mxs_dma = mxs_chan->mxs_dma; | ||
201 | |||
202 | return dma_is_apbh(mxs_dma); | ||
203 | } | ||
204 | |||
205 | int mxs_dma_is_apbx(struct dma_chan *chan) | ||
206 | { | ||
207 | struct mxs_dma_chan *mxs_chan = to_mxs_dma_chan(chan); | ||
208 | struct mxs_dma_engine *mxs_dma = mxs_chan->mxs_dma; | ||
209 | |||
210 | return !dma_is_apbh(mxs_dma); | ||
211 | } | ||
212 | |||
134 | static void mxs_dma_reset_chan(struct mxs_dma_chan *mxs_chan) | 213 | static void mxs_dma_reset_chan(struct mxs_dma_chan *mxs_chan) |
135 | { | 214 | { |
136 | struct mxs_dma_engine *mxs_dma = mxs_chan->mxs_dma; | 215 | struct mxs_dma_engine *mxs_dma = mxs_chan->mxs_dma; |
137 | int chan_id = mxs_chan->chan.chan_id; | 216 | int chan_id = mxs_chan->chan.chan_id; |
138 | 217 | ||
139 | if (dma_is_apbh() && apbh_is_old()) | 218 | if (dma_is_apbh(mxs_dma) && apbh_is_old(mxs_dma)) |
140 | writel(1 << (chan_id + BP_APBH_CTRL0_RESET_CHANNEL), | 219 | writel(1 << (chan_id + BP_APBH_CTRL0_RESET_CHANNEL), |
141 | mxs_dma->base + HW_APBHX_CTRL0 + MXS_SET_ADDR); | 220 | mxs_dma->base + HW_APBHX_CTRL0 + STMP_OFFSET_REG_SET); |
142 | else | 221 | else |
143 | writel(1 << (chan_id + BP_APBHX_CHANNEL_CTRL_RESET_CHANNEL), | 222 | writel(1 << (chan_id + BP_APBHX_CHANNEL_CTRL_RESET_CHANNEL), |
144 | mxs_dma->base + HW_APBHX_CHANNEL_CTRL + MXS_SET_ADDR); | 223 | mxs_dma->base + HW_APBHX_CHANNEL_CTRL + STMP_OFFSET_REG_SET); |
145 | } | 224 | } |
146 | 225 | ||
147 | static void mxs_dma_enable_chan(struct mxs_dma_chan *mxs_chan) | 226 | static void mxs_dma_enable_chan(struct mxs_dma_chan *mxs_chan) |
@@ -151,10 +230,10 @@ static void mxs_dma_enable_chan(struct mxs_dma_chan *mxs_chan) | |||
151 | 230 | ||
152 | /* set cmd_addr up */ | 231 | /* set cmd_addr up */ |
153 | writel(mxs_chan->ccw_phys, | 232 | writel(mxs_chan->ccw_phys, |
154 | mxs_dma->base + HW_APBHX_CHn_NXTCMDAR(chan_id)); | 233 | mxs_dma->base + HW_APBHX_CHn_NXTCMDAR(mxs_dma, chan_id)); |
155 | 234 | ||
156 | /* write 1 to SEMA to kick off the channel */ | 235 | /* write 1 to SEMA to kick off the channel */ |
157 | writel(1, mxs_dma->base + HW_APBHX_CHn_SEMA(chan_id)); | 236 | writel(1, mxs_dma->base + HW_APBHX_CHn_SEMA(mxs_dma, chan_id)); |
158 | } | 237 | } |
159 | 238 | ||
160 | static void mxs_dma_disable_chan(struct mxs_dma_chan *mxs_chan) | 239 | static void mxs_dma_disable_chan(struct mxs_dma_chan *mxs_chan) |
@@ -168,12 +247,12 @@ static void mxs_dma_pause_chan(struct mxs_dma_chan *mxs_chan) | |||
168 | int chan_id = mxs_chan->chan.chan_id; | 247 | int chan_id = mxs_chan->chan.chan_id; |
169 | 248 | ||
170 | /* freeze the channel */ | 249 | /* freeze the channel */ |
171 | if (dma_is_apbh() && apbh_is_old()) | 250 | if (dma_is_apbh(mxs_dma) && apbh_is_old(mxs_dma)) |
172 | writel(1 << chan_id, | 251 | writel(1 << chan_id, |
173 | mxs_dma->base + HW_APBHX_CTRL0 + MXS_SET_ADDR); | 252 | mxs_dma->base + HW_APBHX_CTRL0 + STMP_OFFSET_REG_SET); |
174 | else | 253 | else |
175 | writel(1 << chan_id, | 254 | writel(1 << chan_id, |
176 | mxs_dma->base + HW_APBHX_CHANNEL_CTRL + MXS_SET_ADDR); | 255 | mxs_dma->base + HW_APBHX_CHANNEL_CTRL + STMP_OFFSET_REG_SET); |
177 | 256 | ||
178 | mxs_chan->status = DMA_PAUSED; | 257 | mxs_chan->status = DMA_PAUSED; |
179 | } | 258 | } |
@@ -184,21 +263,16 @@ static void mxs_dma_resume_chan(struct mxs_dma_chan *mxs_chan) | |||
184 | int chan_id = mxs_chan->chan.chan_id; | 263 | int chan_id = mxs_chan->chan.chan_id; |
185 | 264 | ||
186 | /* unfreeze the channel */ | 265 | /* unfreeze the channel */ |
187 | if (dma_is_apbh() && apbh_is_old()) | 266 | if (dma_is_apbh(mxs_dma) && apbh_is_old(mxs_dma)) |
188 | writel(1 << chan_id, | 267 | writel(1 << chan_id, |
189 | mxs_dma->base + HW_APBHX_CTRL0 + MXS_CLR_ADDR); | 268 | mxs_dma->base + HW_APBHX_CTRL0 + STMP_OFFSET_REG_CLR); |
190 | else | 269 | else |
191 | writel(1 << chan_id, | 270 | writel(1 << chan_id, |
192 | mxs_dma->base + HW_APBHX_CHANNEL_CTRL + MXS_CLR_ADDR); | 271 | mxs_dma->base + HW_APBHX_CHANNEL_CTRL + STMP_OFFSET_REG_CLR); |
193 | 272 | ||
194 | mxs_chan->status = DMA_IN_PROGRESS; | 273 | mxs_chan->status = DMA_IN_PROGRESS; |
195 | } | 274 | } |
196 | 275 | ||
197 | static struct mxs_dma_chan *to_mxs_dma_chan(struct dma_chan *chan) | ||
198 | { | ||
199 | return container_of(chan, struct mxs_dma_chan, chan); | ||
200 | } | ||
201 | |||
202 | static dma_cookie_t mxs_dma_tx_submit(struct dma_async_tx_descriptor *tx) | 276 | static dma_cookie_t mxs_dma_tx_submit(struct dma_async_tx_descriptor *tx) |
203 | { | 277 | { |
204 | return dma_cookie_assign(tx); | 278 | return dma_cookie_assign(tx); |
@@ -220,11 +294,11 @@ static irqreturn_t mxs_dma_int_handler(int irq, void *dev_id) | |||
220 | /* completion status */ | 294 | /* completion status */ |
221 | stat1 = readl(mxs_dma->base + HW_APBHX_CTRL1); | 295 | stat1 = readl(mxs_dma->base + HW_APBHX_CTRL1); |
222 | stat1 &= MXS_DMA_CHANNELS_MASK; | 296 | stat1 &= MXS_DMA_CHANNELS_MASK; |
223 | writel(stat1, mxs_dma->base + HW_APBHX_CTRL1 + MXS_CLR_ADDR); | 297 | writel(stat1, mxs_dma->base + HW_APBHX_CTRL1 + STMP_OFFSET_REG_CLR); |
224 | 298 | ||
225 | /* error status */ | 299 | /* error status */ |
226 | stat2 = readl(mxs_dma->base + HW_APBHX_CTRL2); | 300 | stat2 = readl(mxs_dma->base + HW_APBHX_CTRL2); |
227 | writel(stat2, mxs_dma->base + HW_APBHX_CTRL2 + MXS_CLR_ADDR); | 301 | writel(stat2, mxs_dma->base + HW_APBHX_CTRL2 + STMP_OFFSET_REG_CLR); |
228 | 302 | ||
229 | /* | 303 | /* |
230 | * When both completion and error of termination bits set at the | 304 | * When both completion and error of termination bits set at the |
@@ -567,27 +641,21 @@ static int __init mxs_dma_init(struct mxs_dma_engine *mxs_dma) | |||
567 | if (ret) | 641 | if (ret) |
568 | return ret; | 642 | return ret; |
569 | 643 | ||
570 | ret = mxs_reset_block(mxs_dma->base); | 644 | ret = stmp_reset_block(mxs_dma->base); |
571 | if (ret) | 645 | if (ret) |
572 | goto err_out; | 646 | goto err_out; |
573 | 647 | ||
574 | /* only major version matters */ | ||
575 | mxs_dma->version = readl(mxs_dma->base + | ||
576 | ((mxs_dma->dev_id == MXS_DMA_APBX) ? | ||
577 | HW_APBX_VERSION : HW_APBH_VERSION)) >> | ||
578 | BP_APBHX_VERSION_MAJOR; | ||
579 | |||
580 | /* enable apbh burst */ | 648 | /* enable apbh burst */ |
581 | if (dma_is_apbh()) { | 649 | if (dma_is_apbh(mxs_dma)) { |
582 | writel(BM_APBH_CTRL0_APB_BURST_EN, | 650 | writel(BM_APBH_CTRL0_APB_BURST_EN, |
583 | mxs_dma->base + HW_APBHX_CTRL0 + MXS_SET_ADDR); | 651 | mxs_dma->base + HW_APBHX_CTRL0 + STMP_OFFSET_REG_SET); |
584 | writel(BM_APBH_CTRL0_APB_BURST8_EN, | 652 | writel(BM_APBH_CTRL0_APB_BURST8_EN, |
585 | mxs_dma->base + HW_APBHX_CTRL0 + MXS_SET_ADDR); | 653 | mxs_dma->base + HW_APBHX_CTRL0 + STMP_OFFSET_REG_SET); |
586 | } | 654 | } |
587 | 655 | ||
588 | /* enable irq for all the channels */ | 656 | /* enable irq for all the channels */ |
589 | writel(MXS_DMA_CHANNELS_MASK << MXS_DMA_CHANNELS, | 657 | writel(MXS_DMA_CHANNELS_MASK << MXS_DMA_CHANNELS, |
590 | mxs_dma->base + HW_APBHX_CTRL1 + MXS_SET_ADDR); | 658 | mxs_dma->base + HW_APBHX_CTRL1 + STMP_OFFSET_REG_SET); |
591 | 659 | ||
592 | err_out: | 660 | err_out: |
593 | clk_disable_unprepare(mxs_dma->clk); | 661 | clk_disable_unprepare(mxs_dma->clk); |
@@ -596,8 +664,9 @@ err_out: | |||
596 | 664 | ||
597 | static int __init mxs_dma_probe(struct platform_device *pdev) | 665 | static int __init mxs_dma_probe(struct platform_device *pdev) |
598 | { | 666 | { |
599 | const struct platform_device_id *id_entry = | 667 | const struct platform_device_id *id_entry; |
600 | platform_get_device_id(pdev); | 668 | const struct of_device_id *of_id; |
669 | const struct mxs_dma_type *dma_type; | ||
601 | struct mxs_dma_engine *mxs_dma; | 670 | struct mxs_dma_engine *mxs_dma; |
602 | struct resource *iores; | 671 | struct resource *iores; |
603 | int ret, i; | 672 | int ret, i; |
@@ -606,7 +675,15 @@ static int __init mxs_dma_probe(struct platform_device *pdev) | |||
606 | if (!mxs_dma) | 675 | if (!mxs_dma) |
607 | return -ENOMEM; | 676 | return -ENOMEM; |
608 | 677 | ||
609 | mxs_dma->dev_id = id_entry->driver_data; | 678 | of_id = of_match_device(mxs_dma_dt_ids, &pdev->dev); |
679 | if (of_id) | ||
680 | id_entry = of_id->data; | ||
681 | else | ||
682 | id_entry = platform_get_device_id(pdev); | ||
683 | |||
684 | dma_type = (struct mxs_dma_type *)id_entry->driver_data; | ||
685 | mxs_dma->type = dma_type->type; | ||
686 | mxs_dma->dev_id = dma_type->id; | ||
610 | 687 | ||
611 | iores = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 688 | iores = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
612 | 689 | ||
@@ -689,23 +766,12 @@ err_request_region: | |||
689 | return ret; | 766 | return ret; |
690 | } | 767 | } |
691 | 768 | ||
692 | static struct platform_device_id mxs_dma_type[] = { | ||
693 | { | ||
694 | .name = "mxs-dma-apbh", | ||
695 | .driver_data = MXS_DMA_APBH, | ||
696 | }, { | ||
697 | .name = "mxs-dma-apbx", | ||
698 | .driver_data = MXS_DMA_APBX, | ||
699 | }, { | ||
700 | /* end of list */ | ||
701 | } | ||
702 | }; | ||
703 | |||
704 | static struct platform_driver mxs_dma_driver = { | 769 | static struct platform_driver mxs_dma_driver = { |
705 | .driver = { | 770 | .driver = { |
706 | .name = "mxs-dma", | 771 | .name = "mxs-dma", |
772 | .of_match_table = mxs_dma_dt_ids, | ||
707 | }, | 773 | }, |
708 | .id_table = mxs_dma_type, | 774 | .id_table = mxs_dma_ids, |
709 | }; | 775 | }; |
710 | 776 | ||
711 | static int __init mxs_dma_module_init(void) | 777 | static int __init mxs_dma_module_init(void) |
diff --git a/drivers/gpio/gpio-mxs.c b/drivers/gpio/gpio-mxs.c index 385c58e8405b..429228b52acd 100644 --- a/drivers/gpio/gpio-mxs.c +++ b/drivers/gpio/gpio-mxs.c | |||
@@ -25,23 +25,25 @@ | |||
25 | #include <linux/io.h> | 25 | #include <linux/io.h> |
26 | #include <linux/irq.h> | 26 | #include <linux/irq.h> |
27 | #include <linux/gpio.h> | 27 | #include <linux/gpio.h> |
28 | #include <linux/of.h> | ||
29 | #include <linux/of_address.h> | ||
30 | #include <linux/of_device.h> | ||
28 | #include <linux/platform_device.h> | 31 | #include <linux/platform_device.h> |
29 | #include <linux/slab.h> | 32 | #include <linux/slab.h> |
30 | #include <linux/basic_mmio_gpio.h> | 33 | #include <linux/basic_mmio_gpio.h> |
31 | #include <linux/module.h> | 34 | #include <linux/module.h> |
32 | #include <mach/mxs.h> | ||
33 | 35 | ||
34 | #define MXS_SET 0x4 | 36 | #define MXS_SET 0x4 |
35 | #define MXS_CLR 0x8 | 37 | #define MXS_CLR 0x8 |
36 | 38 | ||
37 | #define PINCTRL_DOUT(n) ((cpu_is_mx23() ? 0x0500 : 0x0700) + (n) * 0x10) | 39 | #define PINCTRL_DOUT(p) ((is_imx23_gpio(p) ? 0x0500 : 0x0700) + (p->id) * 0x10) |
38 | #define PINCTRL_DIN(n) ((cpu_is_mx23() ? 0x0600 : 0x0900) + (n) * 0x10) | 40 | #define PINCTRL_DIN(p) ((is_imx23_gpio(p) ? 0x0600 : 0x0900) + (p->id) * 0x10) |
39 | #define PINCTRL_DOE(n) ((cpu_is_mx23() ? 0x0700 : 0x0b00) + (n) * 0x10) | 41 | #define PINCTRL_DOE(p) ((is_imx23_gpio(p) ? 0x0700 : 0x0b00) + (p->id) * 0x10) |
40 | #define PINCTRL_PIN2IRQ(n) ((cpu_is_mx23() ? 0x0800 : 0x1000) + (n) * 0x10) | 42 | #define PINCTRL_PIN2IRQ(p) ((is_imx23_gpio(p) ? 0x0800 : 0x1000) + (p->id) * 0x10) |
41 | #define PINCTRL_IRQEN(n) ((cpu_is_mx23() ? 0x0900 : 0x1100) + (n) * 0x10) | 43 | #define PINCTRL_IRQEN(p) ((is_imx23_gpio(p) ? 0x0900 : 0x1100) + (p->id) * 0x10) |
42 | #define PINCTRL_IRQLEV(n) ((cpu_is_mx23() ? 0x0a00 : 0x1200) + (n) * 0x10) | 44 | #define PINCTRL_IRQLEV(p) ((is_imx23_gpio(p) ? 0x0a00 : 0x1200) + (p->id) * 0x10) |
43 | #define PINCTRL_IRQPOL(n) ((cpu_is_mx23() ? 0x0b00 : 0x1300) + (n) * 0x10) | 45 | #define PINCTRL_IRQPOL(p) ((is_imx23_gpio(p) ? 0x0b00 : 0x1300) + (p->id) * 0x10) |
44 | #define PINCTRL_IRQSTAT(n) ((cpu_is_mx23() ? 0x0c00 : 0x1400) + (n) * 0x10) | 46 | #define PINCTRL_IRQSTAT(p) ((is_imx23_gpio(p) ? 0x0c00 : 0x1400) + (p->id) * 0x10) |
45 | 47 | ||
46 | #define GPIO_INT_FALL_EDGE 0x0 | 48 | #define GPIO_INT_FALL_EDGE 0x0 |
47 | #define GPIO_INT_LOW_LEV 0x1 | 49 | #define GPIO_INT_LOW_LEV 0x1 |
@@ -52,14 +54,30 @@ | |||
52 | 54 | ||
53 | #define irq_to_gpio(irq) ((irq) - MXS_GPIO_IRQ_START) | 55 | #define irq_to_gpio(irq) ((irq) - MXS_GPIO_IRQ_START) |
54 | 56 | ||
57 | enum mxs_gpio_id { | ||
58 | IMX23_GPIO, | ||
59 | IMX28_GPIO, | ||
60 | }; | ||
61 | |||
55 | struct mxs_gpio_port { | 62 | struct mxs_gpio_port { |
56 | void __iomem *base; | 63 | void __iomem *base; |
57 | int id; | 64 | int id; |
58 | int irq; | 65 | int irq; |
59 | int virtual_irq_start; | 66 | int virtual_irq_start; |
60 | struct bgpio_chip bgc; | 67 | struct bgpio_chip bgc; |
68 | enum mxs_gpio_id devid; | ||
61 | }; | 69 | }; |
62 | 70 | ||
71 | static inline int is_imx23_gpio(struct mxs_gpio_port *port) | ||
72 | { | ||
73 | return port->devid == IMX23_GPIO; | ||
74 | } | ||
75 | |||
76 | static inline int is_imx28_gpio(struct mxs_gpio_port *port) | ||
77 | { | ||
78 | return port->devid == IMX28_GPIO; | ||
79 | } | ||
80 | |||
63 | /* Note: This driver assumes 32 GPIOs are handled in one register */ | 81 | /* Note: This driver assumes 32 GPIOs are handled in one register */ |
64 | 82 | ||
65 | static int mxs_gpio_set_irq_type(struct irq_data *d, unsigned int type) | 83 | static int mxs_gpio_set_irq_type(struct irq_data *d, unsigned int type) |
@@ -89,21 +107,21 @@ static int mxs_gpio_set_irq_type(struct irq_data *d, unsigned int type) | |||
89 | } | 107 | } |
90 | 108 | ||
91 | /* set level or edge */ | 109 | /* set level or edge */ |
92 | pin_addr = port->base + PINCTRL_IRQLEV(port->id); | 110 | pin_addr = port->base + PINCTRL_IRQLEV(port); |
93 | if (edge & GPIO_INT_LEV_MASK) | 111 | if (edge & GPIO_INT_LEV_MASK) |
94 | writel(pin_mask, pin_addr + MXS_SET); | 112 | writel(pin_mask, pin_addr + MXS_SET); |
95 | else | 113 | else |
96 | writel(pin_mask, pin_addr + MXS_CLR); | 114 | writel(pin_mask, pin_addr + MXS_CLR); |
97 | 115 | ||
98 | /* set polarity */ | 116 | /* set polarity */ |
99 | pin_addr = port->base + PINCTRL_IRQPOL(port->id); | 117 | pin_addr = port->base + PINCTRL_IRQPOL(port); |
100 | if (edge & GPIO_INT_POL_MASK) | 118 | if (edge & GPIO_INT_POL_MASK) |
101 | writel(pin_mask, pin_addr + MXS_SET); | 119 | writel(pin_mask, pin_addr + MXS_SET); |
102 | else | 120 | else |
103 | writel(pin_mask, pin_addr + MXS_CLR); | 121 | writel(pin_mask, pin_addr + MXS_CLR); |
104 | 122 | ||
105 | writel(1 << (gpio & 0x1f), | 123 | writel(1 << (gpio & 0x1f), |
106 | port->base + PINCTRL_IRQSTAT(port->id) + MXS_CLR); | 124 | port->base + PINCTRL_IRQSTAT(port) + MXS_CLR); |
107 | 125 | ||
108 | return 0; | 126 | return 0; |
109 | } | 127 | } |
@@ -117,8 +135,8 @@ static void mxs_gpio_irq_handler(u32 irq, struct irq_desc *desc) | |||
117 | 135 | ||
118 | desc->irq_data.chip->irq_ack(&desc->irq_data); | 136 | desc->irq_data.chip->irq_ack(&desc->irq_data); |
119 | 137 | ||
120 | irq_stat = readl(port->base + PINCTRL_IRQSTAT(port->id)) & | 138 | irq_stat = readl(port->base + PINCTRL_IRQSTAT(port)) & |
121 | readl(port->base + PINCTRL_IRQEN(port->id)); | 139 | readl(port->base + PINCTRL_IRQEN(port)); |
122 | 140 | ||
123 | while (irq_stat != 0) { | 141 | while (irq_stat != 0) { |
124 | int irqoffset = fls(irq_stat) - 1; | 142 | int irqoffset = fls(irq_stat) - 1; |
@@ -164,8 +182,8 @@ static void __init mxs_gpio_init_gc(struct mxs_gpio_port *port) | |||
164 | ct->chip.irq_unmask = irq_gc_mask_set_bit; | 182 | ct->chip.irq_unmask = irq_gc_mask_set_bit; |
165 | ct->chip.irq_set_type = mxs_gpio_set_irq_type; | 183 | ct->chip.irq_set_type = mxs_gpio_set_irq_type; |
166 | ct->chip.irq_set_wake = mxs_gpio_set_wake_irq; | 184 | ct->chip.irq_set_wake = mxs_gpio_set_wake_irq; |
167 | ct->regs.ack = PINCTRL_IRQSTAT(port->id) + MXS_CLR; | 185 | ct->regs.ack = PINCTRL_IRQSTAT(port) + MXS_CLR; |
168 | ct->regs.mask = PINCTRL_IRQEN(port->id); | 186 | ct->regs.mask = PINCTRL_IRQEN(port); |
169 | 187 | ||
170 | irq_setup_generic_chip(gc, IRQ_MSK(32), 0, IRQ_NOREQUEST, 0); | 188 | irq_setup_generic_chip(gc, IRQ_MSK(32), 0, IRQ_NOREQUEST, 0); |
171 | } | 189 | } |
@@ -179,60 +197,83 @@ static int mxs_gpio_to_irq(struct gpio_chip *gc, unsigned offset) | |||
179 | return port->virtual_irq_start + offset; | 197 | return port->virtual_irq_start + offset; |
180 | } | 198 | } |
181 | 199 | ||
200 | static struct platform_device_id mxs_gpio_ids[] = { | ||
201 | { | ||
202 | .name = "imx23-gpio", | ||
203 | .driver_data = IMX23_GPIO, | ||
204 | }, { | ||
205 | .name = "imx28-gpio", | ||
206 | .driver_data = IMX28_GPIO, | ||
207 | }, { | ||
208 | /* sentinel */ | ||
209 | } | ||
210 | }; | ||
211 | MODULE_DEVICE_TABLE(platform, mxs_gpio_ids); | ||
212 | |||
213 | static const struct of_device_id mxs_gpio_dt_ids[] = { | ||
214 | { .compatible = "fsl,imx23-gpio", .data = (void *) IMX23_GPIO, }, | ||
215 | { .compatible = "fsl,imx28-gpio", .data = (void *) IMX28_GPIO, }, | ||
216 | { /* sentinel */ } | ||
217 | }; | ||
218 | MODULE_DEVICE_TABLE(of, mxs_gpio_dt_ids); | ||
219 | |||
182 | static int __devinit mxs_gpio_probe(struct platform_device *pdev) | 220 | static int __devinit mxs_gpio_probe(struct platform_device *pdev) |
183 | { | 221 | { |
222 | const struct of_device_id *of_id = | ||
223 | of_match_device(mxs_gpio_dt_ids, &pdev->dev); | ||
224 | struct device_node *np = pdev->dev.of_node; | ||
225 | struct device_node *parent; | ||
184 | static void __iomem *base; | 226 | static void __iomem *base; |
185 | struct mxs_gpio_port *port; | 227 | struct mxs_gpio_port *port; |
186 | struct resource *iores = NULL; | 228 | struct resource *iores = NULL; |
187 | int err; | 229 | int err; |
188 | 230 | ||
189 | port = kzalloc(sizeof(struct mxs_gpio_port), GFP_KERNEL); | 231 | port = devm_kzalloc(&pdev->dev, sizeof(*port), GFP_KERNEL); |
190 | if (!port) | 232 | if (!port) |
191 | return -ENOMEM; | 233 | return -ENOMEM; |
192 | 234 | ||
193 | port->id = pdev->id; | 235 | if (np) { |
236 | port->id = of_alias_get_id(np, "gpio"); | ||
237 | if (port->id < 0) | ||
238 | return port->id; | ||
239 | port->devid = (enum mxs_gpio_id) of_id->data; | ||
240 | } else { | ||
241 | port->id = pdev->id; | ||
242 | port->devid = pdev->id_entry->driver_data; | ||
243 | } | ||
194 | port->virtual_irq_start = MXS_GPIO_IRQ_START + port->id * 32; | 244 | port->virtual_irq_start = MXS_GPIO_IRQ_START + port->id * 32; |
195 | 245 | ||
246 | port->irq = platform_get_irq(pdev, 0); | ||
247 | if (port->irq < 0) | ||
248 | return port->irq; | ||
249 | |||
196 | /* | 250 | /* |
197 | * map memory region only once, as all the gpio ports | 251 | * map memory region only once, as all the gpio ports |
198 | * share the same one | 252 | * share the same one |
199 | */ | 253 | */ |
200 | if (!base) { | 254 | if (!base) { |
201 | iores = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 255 | if (np) { |
202 | if (!iores) { | 256 | parent = of_get_parent(np); |
203 | err = -ENODEV; | 257 | base = of_iomap(parent, 0); |
204 | goto out_kfree; | 258 | of_node_put(parent); |
205 | } | 259 | } else { |
206 | 260 | iores = platform_get_resource(pdev, IORESOURCE_MEM, 0); | |
207 | if (!request_mem_region(iores->start, resource_size(iores), | 261 | base = devm_request_and_ioremap(&pdev->dev, iores); |
208 | pdev->name)) { | ||
209 | err = -EBUSY; | ||
210 | goto out_kfree; | ||
211 | } | ||
212 | |||
213 | base = ioremap(iores->start, resource_size(iores)); | ||
214 | if (!base) { | ||
215 | err = -ENOMEM; | ||
216 | goto out_release_mem; | ||
217 | } | 262 | } |
263 | if (!base) | ||
264 | return -EADDRNOTAVAIL; | ||
218 | } | 265 | } |
219 | port->base = base; | 266 | port->base = base; |
220 | 267 | ||
221 | port->irq = platform_get_irq(pdev, 0); | ||
222 | if (port->irq < 0) { | ||
223 | err = -EINVAL; | ||
224 | goto out_iounmap; | ||
225 | } | ||
226 | |||
227 | /* | 268 | /* |
228 | * select the pin interrupt functionality but initially | 269 | * select the pin interrupt functionality but initially |
229 | * disable the interrupts | 270 | * disable the interrupts |
230 | */ | 271 | */ |
231 | writel(~0U, port->base + PINCTRL_PIN2IRQ(port->id)); | 272 | writel(~0U, port->base + PINCTRL_PIN2IRQ(port)); |
232 | writel(0, port->base + PINCTRL_IRQEN(port->id)); | 273 | writel(0, port->base + PINCTRL_IRQEN(port)); |
233 | 274 | ||
234 | /* clear address has to be used to clear IRQSTAT bits */ | 275 | /* clear address has to be used to clear IRQSTAT bits */ |
235 | writel(~0U, port->base + PINCTRL_IRQSTAT(port->id) + MXS_CLR); | 276 | writel(~0U, port->base + PINCTRL_IRQSTAT(port) + MXS_CLR); |
236 | 277 | ||
237 | /* gpio-mxs can be a generic irq chip */ | 278 | /* gpio-mxs can be a generic irq chip */ |
238 | mxs_gpio_init_gc(port); | 279 | mxs_gpio_init_gc(port); |
@@ -242,41 +283,32 @@ static int __devinit mxs_gpio_probe(struct platform_device *pdev) | |||
242 | irq_set_handler_data(port->irq, port); | 283 | irq_set_handler_data(port->irq, port); |
243 | 284 | ||
244 | err = bgpio_init(&port->bgc, &pdev->dev, 4, | 285 | err = bgpio_init(&port->bgc, &pdev->dev, 4, |
245 | port->base + PINCTRL_DIN(port->id), | 286 | port->base + PINCTRL_DIN(port), |
246 | port->base + PINCTRL_DOUT(port->id), NULL, | 287 | port->base + PINCTRL_DOUT(port), NULL, |
247 | port->base + PINCTRL_DOE(port->id), NULL, false); | 288 | port->base + PINCTRL_DOE(port), NULL, false); |
248 | if (err) | 289 | if (err) |
249 | goto out_iounmap; | 290 | return err; |
250 | 291 | ||
251 | port->bgc.gc.to_irq = mxs_gpio_to_irq; | 292 | port->bgc.gc.to_irq = mxs_gpio_to_irq; |
252 | port->bgc.gc.base = port->id * 32; | 293 | port->bgc.gc.base = port->id * 32; |
253 | 294 | ||
254 | err = gpiochip_add(&port->bgc.gc); | 295 | err = gpiochip_add(&port->bgc.gc); |
255 | if (err) | 296 | if (err) { |
256 | goto out_bgpio_remove; | 297 | bgpio_remove(&port->bgc); |
298 | return err; | ||
299 | } | ||
257 | 300 | ||
258 | return 0; | 301 | return 0; |
259 | |||
260 | out_bgpio_remove: | ||
261 | bgpio_remove(&port->bgc); | ||
262 | out_iounmap: | ||
263 | if (iores) | ||
264 | iounmap(port->base); | ||
265 | out_release_mem: | ||
266 | if (iores) | ||
267 | release_mem_region(iores->start, resource_size(iores)); | ||
268 | out_kfree: | ||
269 | kfree(port); | ||
270 | dev_info(&pdev->dev, "%s failed with errno %d\n", __func__, err); | ||
271 | return err; | ||
272 | } | 302 | } |
273 | 303 | ||
274 | static struct platform_driver mxs_gpio_driver = { | 304 | static struct platform_driver mxs_gpio_driver = { |
275 | .driver = { | 305 | .driver = { |
276 | .name = "gpio-mxs", | 306 | .name = "gpio-mxs", |
277 | .owner = THIS_MODULE, | 307 | .owner = THIS_MODULE, |
308 | .of_match_table = mxs_gpio_dt_ids, | ||
278 | }, | 309 | }, |
279 | .probe = mxs_gpio_probe, | 310 | .probe = mxs_gpio_probe, |
311 | .id_table = mxs_gpio_ids, | ||
280 | }; | 312 | }; |
281 | 313 | ||
282 | static int __init mxs_gpio_init(void) | 314 | static int __init mxs_gpio_init(void) |
diff --git a/drivers/i2c/busses/i2c-imx.c b/drivers/i2c/busses/i2c-imx.c index dfb84b7ee550..56bce9a8bcbb 100644 --- a/drivers/i2c/busses/i2c-imx.c +++ b/drivers/i2c/busses/i2c-imx.c | |||
@@ -51,6 +51,7 @@ | |||
51 | #include <linux/of.h> | 51 | #include <linux/of.h> |
52 | #include <linux/of_device.h> | 52 | #include <linux/of_device.h> |
53 | #include <linux/of_i2c.h> | 53 | #include <linux/of_i2c.h> |
54 | #include <linux/pinctrl/consumer.h> | ||
54 | 55 | ||
55 | #include <mach/irqs.h> | 56 | #include <mach/irqs.h> |
56 | #include <mach/hardware.h> | 57 | #include <mach/hardware.h> |
@@ -470,6 +471,7 @@ static int __init i2c_imx_probe(struct platform_device *pdev) | |||
470 | struct imx_i2c_struct *i2c_imx; | 471 | struct imx_i2c_struct *i2c_imx; |
471 | struct resource *res; | 472 | struct resource *res; |
472 | struct imxi2c_platform_data *pdata = pdev->dev.platform_data; | 473 | struct imxi2c_platform_data *pdata = pdev->dev.platform_data; |
474 | struct pinctrl *pinctrl; | ||
473 | void __iomem *base; | 475 | void __iomem *base; |
474 | resource_size_t res_size; | 476 | resource_size_t res_size; |
475 | int irq, bitrate; | 477 | int irq, bitrate; |
@@ -520,6 +522,12 @@ static int __init i2c_imx_probe(struct platform_device *pdev) | |||
520 | i2c_imx->base = base; | 522 | i2c_imx->base = base; |
521 | i2c_imx->res = res; | 523 | i2c_imx->res = res; |
522 | 524 | ||
525 | pinctrl = devm_pinctrl_get_select_default(&pdev->dev); | ||
526 | if (IS_ERR(pinctrl)) { | ||
527 | ret = PTR_ERR(pinctrl); | ||
528 | goto fail3; | ||
529 | } | ||
530 | |||
523 | /* Get I2C clock */ | 531 | /* Get I2C clock */ |
524 | i2c_imx->clk = clk_get(&pdev->dev, "i2c_clk"); | 532 | i2c_imx->clk = clk_get(&pdev->dev, "i2c_clk"); |
525 | if (IS_ERR(i2c_imx->clk)) { | 533 | if (IS_ERR(i2c_imx->clk)) { |
diff --git a/drivers/i2c/busses/i2c-mxs.c b/drivers/i2c/busses/i2c-mxs.c index 76b8af44f634..7dca58b0e746 100644 --- a/drivers/i2c/busses/i2c-mxs.c +++ b/drivers/i2c/busses/i2c-mxs.c | |||
@@ -26,6 +26,10 @@ | |||
26 | #include <linux/platform_device.h> | 26 | #include <linux/platform_device.h> |
27 | #include <linux/jiffies.h> | 27 | #include <linux/jiffies.h> |
28 | #include <linux/io.h> | 28 | #include <linux/io.h> |
29 | #include <linux/pinctrl/consumer.h> | ||
30 | #include <linux/of.h> | ||
31 | #include <linux/of_device.h> | ||
32 | #include <linux/of_i2c.h> | ||
29 | 33 | ||
30 | #include <mach/common.h> | 34 | #include <mach/common.h> |
31 | 35 | ||
@@ -325,10 +329,15 @@ static int __devinit mxs_i2c_probe(struct platform_device *pdev) | |||
325 | struct device *dev = &pdev->dev; | 329 | struct device *dev = &pdev->dev; |
326 | struct mxs_i2c_dev *i2c; | 330 | struct mxs_i2c_dev *i2c; |
327 | struct i2c_adapter *adap; | 331 | struct i2c_adapter *adap; |
332 | struct pinctrl *pinctrl; | ||
328 | struct resource *res; | 333 | struct resource *res; |
329 | resource_size_t res_size; | 334 | resource_size_t res_size; |
330 | int err, irq; | 335 | int err, irq; |
331 | 336 | ||
337 | pinctrl = devm_pinctrl_get_select_default(dev); | ||
338 | if (IS_ERR(pinctrl)) | ||
339 | return PTR_ERR(pinctrl); | ||
340 | |||
332 | i2c = devm_kzalloc(dev, sizeof(struct mxs_i2c_dev), GFP_KERNEL); | 341 | i2c = devm_kzalloc(dev, sizeof(struct mxs_i2c_dev), GFP_KERNEL); |
333 | if (!i2c) | 342 | if (!i2c) |
334 | return -ENOMEM; | 343 | return -ENOMEM; |
@@ -365,6 +374,7 @@ static int __devinit mxs_i2c_probe(struct platform_device *pdev) | |||
365 | adap->algo = &mxs_i2c_algo; | 374 | adap->algo = &mxs_i2c_algo; |
366 | adap->dev.parent = dev; | 375 | adap->dev.parent = dev; |
367 | adap->nr = pdev->id; | 376 | adap->nr = pdev->id; |
377 | adap->dev.of_node = pdev->dev.of_node; | ||
368 | i2c_set_adapdata(adap, i2c); | 378 | i2c_set_adapdata(adap, i2c); |
369 | err = i2c_add_numbered_adapter(adap); | 379 | err = i2c_add_numbered_adapter(adap); |
370 | if (err) { | 380 | if (err) { |
@@ -374,6 +384,8 @@ static int __devinit mxs_i2c_probe(struct platform_device *pdev) | |||
374 | return err; | 384 | return err; |
375 | } | 385 | } |
376 | 386 | ||
387 | of_i2c_register_devices(adap); | ||
388 | |||
377 | return 0; | 389 | return 0; |
378 | } | 390 | } |
379 | 391 | ||
@@ -393,10 +405,17 @@ static int __devexit mxs_i2c_remove(struct platform_device *pdev) | |||
393 | return 0; | 405 | return 0; |
394 | } | 406 | } |
395 | 407 | ||
408 | static const struct of_device_id mxs_i2c_dt_ids[] = { | ||
409 | { .compatible = "fsl,imx28-i2c", }, | ||
410 | { /* sentinel */ } | ||
411 | }; | ||
412 | MODULE_DEVICE_TABLE(of, mxs_i2c_dt_ids); | ||
413 | |||
396 | static struct platform_driver mxs_i2c_driver = { | 414 | static struct platform_driver mxs_i2c_driver = { |
397 | .driver = { | 415 | .driver = { |
398 | .name = DRIVER_NAME, | 416 | .name = DRIVER_NAME, |
399 | .owner = THIS_MODULE, | 417 | .owner = THIS_MODULE, |
418 | .of_match_table = mxs_i2c_dt_ids, | ||
400 | }, | 419 | }, |
401 | .remove = __devexit_p(mxs_i2c_remove), | 420 | .remove = __devexit_p(mxs_i2c_remove), |
402 | }; | 421 | }; |
diff --git a/drivers/mmc/host/mxs-mmc.c b/drivers/mmc/host/mxs-mmc.c index e3f5af96ab87..34a90266ab11 100644 --- a/drivers/mmc/host/mxs-mmc.c +++ b/drivers/mmc/host/mxs-mmc.c | |||
@@ -23,6 +23,9 @@ | |||
23 | #include <linux/kernel.h> | 23 | #include <linux/kernel.h> |
24 | #include <linux/init.h> | 24 | #include <linux/init.h> |
25 | #include <linux/ioport.h> | 25 | #include <linux/ioport.h> |
26 | #include <linux/of.h> | ||
27 | #include <linux/of_device.h> | ||
28 | #include <linux/of_gpio.h> | ||
26 | #include <linux/platform_device.h> | 29 | #include <linux/platform_device.h> |
27 | #include <linux/delay.h> | 30 | #include <linux/delay.h> |
28 | #include <linux/interrupt.h> | 31 | #include <linux/interrupt.h> |
@@ -39,18 +42,16 @@ | |||
39 | #include <linux/regulator/consumer.h> | 42 | #include <linux/regulator/consumer.h> |
40 | #include <linux/module.h> | 43 | #include <linux/module.h> |
41 | #include <linux/fsl/mxs-dma.h> | 44 | #include <linux/fsl/mxs-dma.h> |
42 | 45 | #include <linux/pinctrl/consumer.h> | |
43 | #include <mach/mxs.h> | 46 | #include <linux/stmp_device.h> |
44 | #include <mach/common.h> | 47 | #include <linux/mmc/mxs-mmc.h> |
45 | #include <mach/mmc.h> | ||
46 | 48 | ||
47 | #define DRIVER_NAME "mxs-mmc" | 49 | #define DRIVER_NAME "mxs-mmc" |
48 | 50 | ||
49 | /* card detect polling timeout */ | 51 | /* card detect polling timeout */ |
50 | #define MXS_MMC_DETECT_TIMEOUT (HZ/2) | 52 | #define MXS_MMC_DETECT_TIMEOUT (HZ/2) |
51 | 53 | ||
52 | #define SSP_VERSION_LATEST 4 | 54 | #define ssp_is_old(host) ((host)->devid == IMX23_MMC) |
53 | #define ssp_is_old() (host->version < SSP_VERSION_LATEST) | ||
54 | 55 | ||
55 | /* SSP registers */ | 56 | /* SSP registers */ |
56 | #define HW_SSP_CTRL0 0x000 | 57 | #define HW_SSP_CTRL0 0x000 |
@@ -85,14 +86,14 @@ | |||
85 | #define BM_SSP_BLOCK_SIZE_BLOCK_COUNT (0xffffff << 4) | 86 | #define BM_SSP_BLOCK_SIZE_BLOCK_COUNT (0xffffff << 4) |
86 | #define BP_SSP_BLOCK_SIZE_BLOCK_SIZE (0) | 87 | #define BP_SSP_BLOCK_SIZE_BLOCK_SIZE (0) |
87 | #define BM_SSP_BLOCK_SIZE_BLOCK_SIZE (0xf) | 88 | #define BM_SSP_BLOCK_SIZE_BLOCK_SIZE (0xf) |
88 | #define HW_SSP_TIMING (ssp_is_old() ? 0x050 : 0x070) | 89 | #define HW_SSP_TIMING(h) (ssp_is_old(h) ? 0x050 : 0x070) |
89 | #define BP_SSP_TIMING_TIMEOUT (16) | 90 | #define BP_SSP_TIMING_TIMEOUT (16) |
90 | #define BM_SSP_TIMING_TIMEOUT (0xffff << 16) | 91 | #define BM_SSP_TIMING_TIMEOUT (0xffff << 16) |
91 | #define BP_SSP_TIMING_CLOCK_DIVIDE (8) | 92 | #define BP_SSP_TIMING_CLOCK_DIVIDE (8) |
92 | #define BM_SSP_TIMING_CLOCK_DIVIDE (0xff << 8) | 93 | #define BM_SSP_TIMING_CLOCK_DIVIDE (0xff << 8) |
93 | #define BP_SSP_TIMING_CLOCK_RATE (0) | 94 | #define BP_SSP_TIMING_CLOCK_RATE (0) |
94 | #define BM_SSP_TIMING_CLOCK_RATE (0xff) | 95 | #define BM_SSP_TIMING_CLOCK_RATE (0xff) |
95 | #define HW_SSP_CTRL1 (ssp_is_old() ? 0x060 : 0x080) | 96 | #define HW_SSP_CTRL1(h) (ssp_is_old(h) ? 0x060 : 0x080) |
96 | #define BM_SSP_CTRL1_SDIO_IRQ (1 << 31) | 97 | #define BM_SSP_CTRL1_SDIO_IRQ (1 << 31) |
97 | #define BM_SSP_CTRL1_SDIO_IRQ_EN (1 << 30) | 98 | #define BM_SSP_CTRL1_SDIO_IRQ_EN (1 << 30) |
98 | #define BM_SSP_CTRL1_RESP_ERR_IRQ (1 << 29) | 99 | #define BM_SSP_CTRL1_RESP_ERR_IRQ (1 << 29) |
@@ -115,15 +116,13 @@ | |||
115 | #define BM_SSP_CTRL1_WORD_LENGTH (0xf << 4) | 116 | #define BM_SSP_CTRL1_WORD_LENGTH (0xf << 4) |
116 | #define BP_SSP_CTRL1_SSP_MODE (0) | 117 | #define BP_SSP_CTRL1_SSP_MODE (0) |
117 | #define BM_SSP_CTRL1_SSP_MODE (0xf) | 118 | #define BM_SSP_CTRL1_SSP_MODE (0xf) |
118 | #define HW_SSP_SDRESP0 (ssp_is_old() ? 0x080 : 0x0a0) | 119 | #define HW_SSP_SDRESP0(h) (ssp_is_old(h) ? 0x080 : 0x0a0) |
119 | #define HW_SSP_SDRESP1 (ssp_is_old() ? 0x090 : 0x0b0) | 120 | #define HW_SSP_SDRESP1(h) (ssp_is_old(h) ? 0x090 : 0x0b0) |
120 | #define HW_SSP_SDRESP2 (ssp_is_old() ? 0x0a0 : 0x0c0) | 121 | #define HW_SSP_SDRESP2(h) (ssp_is_old(h) ? 0x0a0 : 0x0c0) |
121 | #define HW_SSP_SDRESP3 (ssp_is_old() ? 0x0b0 : 0x0d0) | 122 | #define HW_SSP_SDRESP3(h) (ssp_is_old(h) ? 0x0b0 : 0x0d0) |
122 | #define HW_SSP_STATUS (ssp_is_old() ? 0x0c0 : 0x100) | 123 | #define HW_SSP_STATUS(h) (ssp_is_old(h) ? 0x0c0 : 0x100) |
123 | #define BM_SSP_STATUS_CARD_DETECT (1 << 28) | 124 | #define BM_SSP_STATUS_CARD_DETECT (1 << 28) |
124 | #define BM_SSP_STATUS_SDIO_IRQ (1 << 17) | 125 | #define BM_SSP_STATUS_SDIO_IRQ (1 << 17) |
125 | #define HW_SSP_VERSION (cpu_is_mx23() ? 0x110 : 0x130) | ||
126 | #define BP_SSP_VERSION_MAJOR (24) | ||
127 | 126 | ||
128 | #define BF_SSP(value, field) (((value) << BP_SSP_##field) & BM_SSP_##field) | 127 | #define BF_SSP(value, field) (((value) << BP_SSP_##field) & BM_SSP_##field) |
129 | 128 | ||
@@ -138,6 +137,11 @@ | |||
138 | 137 | ||
139 | #define SSP_PIO_NUM 3 | 138 | #define SSP_PIO_NUM 3 |
140 | 139 | ||
140 | enum mxs_mmc_id { | ||
141 | IMX23_MMC, | ||
142 | IMX28_MMC, | ||
143 | }; | ||
144 | |||
141 | struct mxs_mmc_host { | 145 | struct mxs_mmc_host { |
142 | struct mmc_host *mmc; | 146 | struct mmc_host *mmc; |
143 | struct mmc_request *mrq; | 147 | struct mmc_request *mrq; |
@@ -145,9 +149,7 @@ struct mxs_mmc_host { | |||
145 | struct mmc_data *data; | 149 | struct mmc_data *data; |
146 | 150 | ||
147 | void __iomem *base; | 151 | void __iomem *base; |
148 | int irq; | 152 | int dma_channel; |
149 | struct resource *res; | ||
150 | struct resource *dma_res; | ||
151 | struct clk *clk; | 153 | struct clk *clk; |
152 | unsigned int clk_rate; | 154 | unsigned int clk_rate; |
153 | 155 | ||
@@ -157,32 +159,28 @@ struct mxs_mmc_host { | |||
157 | enum dma_transfer_direction slave_dirn; | 159 | enum dma_transfer_direction slave_dirn; |
158 | u32 ssp_pio_words[SSP_PIO_NUM]; | 160 | u32 ssp_pio_words[SSP_PIO_NUM]; |
159 | 161 | ||
160 | unsigned int version; | 162 | enum mxs_mmc_id devid; |
161 | unsigned char bus_width; | 163 | unsigned char bus_width; |
162 | spinlock_t lock; | 164 | spinlock_t lock; |
163 | int sdio_irq_en; | 165 | int sdio_irq_en; |
166 | int wp_gpio; | ||
164 | }; | 167 | }; |
165 | 168 | ||
166 | static int mxs_mmc_get_ro(struct mmc_host *mmc) | 169 | static int mxs_mmc_get_ro(struct mmc_host *mmc) |
167 | { | 170 | { |
168 | struct mxs_mmc_host *host = mmc_priv(mmc); | 171 | struct mxs_mmc_host *host = mmc_priv(mmc); |
169 | struct mxs_mmc_platform_data *pdata = | ||
170 | mmc_dev(host->mmc)->platform_data; | ||
171 | |||
172 | if (!pdata) | ||
173 | return -EFAULT; | ||
174 | 172 | ||
175 | if (!gpio_is_valid(pdata->wp_gpio)) | 173 | if (!gpio_is_valid(host->wp_gpio)) |
176 | return -EINVAL; | 174 | return -EINVAL; |
177 | 175 | ||
178 | return gpio_get_value(pdata->wp_gpio); | 176 | return gpio_get_value(host->wp_gpio); |
179 | } | 177 | } |
180 | 178 | ||
181 | static int mxs_mmc_get_cd(struct mmc_host *mmc) | 179 | static int mxs_mmc_get_cd(struct mmc_host *mmc) |
182 | { | 180 | { |
183 | struct mxs_mmc_host *host = mmc_priv(mmc); | 181 | struct mxs_mmc_host *host = mmc_priv(mmc); |
184 | 182 | ||
185 | return !(readl(host->base + HW_SSP_STATUS) & | 183 | return !(readl(host->base + HW_SSP_STATUS(host)) & |
186 | BM_SSP_STATUS_CARD_DETECT); | 184 | BM_SSP_STATUS_CARD_DETECT); |
187 | } | 185 | } |
188 | 186 | ||
@@ -190,7 +188,7 @@ static void mxs_mmc_reset(struct mxs_mmc_host *host) | |||
190 | { | 188 | { |
191 | u32 ctrl0, ctrl1; | 189 | u32 ctrl0, ctrl1; |
192 | 190 | ||
193 | mxs_reset_block(host->base); | 191 | stmp_reset_block(host->base); |
194 | 192 | ||
195 | ctrl0 = BM_SSP_CTRL0_IGNORE_CRC; | 193 | ctrl0 = BM_SSP_CTRL0_IGNORE_CRC; |
196 | ctrl1 = BF_SSP(0x3, CTRL1_SSP_MODE) | | 194 | ctrl1 = BF_SSP(0x3, CTRL1_SSP_MODE) | |
@@ -206,7 +204,7 @@ static void mxs_mmc_reset(struct mxs_mmc_host *host) | |||
206 | writel(BF_SSP(0xffff, TIMING_TIMEOUT) | | 204 | writel(BF_SSP(0xffff, TIMING_TIMEOUT) | |
207 | BF_SSP(2, TIMING_CLOCK_DIVIDE) | | 205 | BF_SSP(2, TIMING_CLOCK_DIVIDE) | |
208 | BF_SSP(0, TIMING_CLOCK_RATE), | 206 | BF_SSP(0, TIMING_CLOCK_RATE), |
209 | host->base + HW_SSP_TIMING); | 207 | host->base + HW_SSP_TIMING(host)); |
210 | 208 | ||
211 | if (host->sdio_irq_en) { | 209 | if (host->sdio_irq_en) { |
212 | ctrl0 |= BM_SSP_CTRL0_SDIO_IRQ_CHECK; | 210 | ctrl0 |= BM_SSP_CTRL0_SDIO_IRQ_CHECK; |
@@ -214,7 +212,7 @@ static void mxs_mmc_reset(struct mxs_mmc_host *host) | |||
214 | } | 212 | } |
215 | 213 | ||
216 | writel(ctrl0, host->base + HW_SSP_CTRL0); | 214 | writel(ctrl0, host->base + HW_SSP_CTRL0); |
217 | writel(ctrl1, host->base + HW_SSP_CTRL1); | 215 | writel(ctrl1, host->base + HW_SSP_CTRL1(host)); |
218 | } | 216 | } |
219 | 217 | ||
220 | static void mxs_mmc_start_cmd(struct mxs_mmc_host *host, | 218 | static void mxs_mmc_start_cmd(struct mxs_mmc_host *host, |
@@ -228,12 +226,12 @@ static void mxs_mmc_request_done(struct mxs_mmc_host *host) | |||
228 | 226 | ||
229 | if (mmc_resp_type(cmd) & MMC_RSP_PRESENT) { | 227 | if (mmc_resp_type(cmd) & MMC_RSP_PRESENT) { |
230 | if (mmc_resp_type(cmd) & MMC_RSP_136) { | 228 | if (mmc_resp_type(cmd) & MMC_RSP_136) { |
231 | cmd->resp[3] = readl(host->base + HW_SSP_SDRESP0); | 229 | cmd->resp[3] = readl(host->base + HW_SSP_SDRESP0(host)); |
232 | cmd->resp[2] = readl(host->base + HW_SSP_SDRESP1); | 230 | cmd->resp[2] = readl(host->base + HW_SSP_SDRESP1(host)); |
233 | cmd->resp[1] = readl(host->base + HW_SSP_SDRESP2); | 231 | cmd->resp[1] = readl(host->base + HW_SSP_SDRESP2(host)); |
234 | cmd->resp[0] = readl(host->base + HW_SSP_SDRESP3); | 232 | cmd->resp[0] = readl(host->base + HW_SSP_SDRESP3(host)); |
235 | } else { | 233 | } else { |
236 | cmd->resp[0] = readl(host->base + HW_SSP_SDRESP0); | 234 | cmd->resp[0] = readl(host->base + HW_SSP_SDRESP0(host)); |
237 | } | 235 | } |
238 | } | 236 | } |
239 | 237 | ||
@@ -276,9 +274,9 @@ static irqreturn_t mxs_mmc_irq_handler(int irq, void *dev_id) | |||
276 | 274 | ||
277 | spin_lock(&host->lock); | 275 | spin_lock(&host->lock); |
278 | 276 | ||
279 | stat = readl(host->base + HW_SSP_CTRL1); | 277 | stat = readl(host->base + HW_SSP_CTRL1(host)); |
280 | writel(stat & MXS_MMC_IRQ_BITS, | 278 | writel(stat & MXS_MMC_IRQ_BITS, |
281 | host->base + HW_SSP_CTRL1 + MXS_CLR_ADDR); | 279 | host->base + HW_SSP_CTRL1(host) + STMP_OFFSET_REG_CLR); |
282 | 280 | ||
283 | if ((stat & BM_SSP_CTRL1_SDIO_IRQ) && (stat & BM_SSP_CTRL1_SDIO_IRQ_EN)) | 281 | if ((stat & BM_SSP_CTRL1_SDIO_IRQ) && (stat & BM_SSP_CTRL1_SDIO_IRQ_EN)) |
284 | mmc_signal_sdio_irq(host->mmc); | 282 | mmc_signal_sdio_irq(host->mmc); |
@@ -484,7 +482,7 @@ static void mxs_mmc_adtc(struct mxs_mmc_host *host) | |||
484 | blocks = 1; | 482 | blocks = 1; |
485 | 483 | ||
486 | /* xfer count, block size and count need to be set differently */ | 484 | /* xfer count, block size and count need to be set differently */ |
487 | if (ssp_is_old()) { | 485 | if (ssp_is_old(host)) { |
488 | ctrl0 |= BF_SSP(data_size, CTRL0_XFER_COUNT); | 486 | ctrl0 |= BF_SSP(data_size, CTRL0_XFER_COUNT); |
489 | cmd0 |= BF_SSP(log2_blksz, CMD0_BLOCK_SIZE) | | 487 | cmd0 |= BF_SSP(log2_blksz, CMD0_BLOCK_SIZE) | |
490 | BF_SSP(blocks - 1, CMD0_BLOCK_COUNT); | 488 | BF_SSP(blocks - 1, CMD0_BLOCK_COUNT); |
@@ -508,10 +506,10 @@ static void mxs_mmc_adtc(struct mxs_mmc_host *host) | |||
508 | 506 | ||
509 | /* set the timeout count */ | 507 | /* set the timeout count */ |
510 | timeout = mxs_ns_to_ssp_ticks(host->clk_rate, data->timeout_ns); | 508 | timeout = mxs_ns_to_ssp_ticks(host->clk_rate, data->timeout_ns); |
511 | val = readl(host->base + HW_SSP_TIMING); | 509 | val = readl(host->base + HW_SSP_TIMING(host)); |
512 | val &= ~(BM_SSP_TIMING_TIMEOUT); | 510 | val &= ~(BM_SSP_TIMING_TIMEOUT); |
513 | val |= BF_SSP(timeout, TIMING_TIMEOUT); | 511 | val |= BF_SSP(timeout, TIMING_TIMEOUT); |
514 | writel(val, host->base + HW_SSP_TIMING); | 512 | writel(val, host->base + HW_SSP_TIMING(host)); |
515 | 513 | ||
516 | /* pio */ | 514 | /* pio */ |
517 | host->ssp_pio_words[0] = ctrl0; | 515 | host->ssp_pio_words[0] = ctrl0; |
@@ -597,11 +595,11 @@ static void mxs_mmc_set_clk_rate(struct mxs_mmc_host *host, unsigned int rate) | |||
597 | 595 | ||
598 | ssp_sck = ssp_clk / clock_divide / (1 + clock_rate); | 596 | ssp_sck = ssp_clk / clock_divide / (1 + clock_rate); |
599 | 597 | ||
600 | val = readl(host->base + HW_SSP_TIMING); | 598 | val = readl(host->base + HW_SSP_TIMING(host)); |
601 | val &= ~(BM_SSP_TIMING_CLOCK_DIVIDE | BM_SSP_TIMING_CLOCK_RATE); | 599 | val &= ~(BM_SSP_TIMING_CLOCK_DIVIDE | BM_SSP_TIMING_CLOCK_RATE); |
602 | val |= BF_SSP(clock_divide, TIMING_CLOCK_DIVIDE); | 600 | val |= BF_SSP(clock_divide, TIMING_CLOCK_DIVIDE); |
603 | val |= BF_SSP(clock_rate, TIMING_CLOCK_RATE); | 601 | val |= BF_SSP(clock_rate, TIMING_CLOCK_RATE); |
604 | writel(val, host->base + HW_SSP_TIMING); | 602 | writel(val, host->base + HW_SSP_TIMING(host)); |
605 | 603 | ||
606 | host->clk_rate = ssp_sck; | 604 | host->clk_rate = ssp_sck; |
607 | 605 | ||
@@ -636,18 +634,19 @@ static void mxs_mmc_enable_sdio_irq(struct mmc_host *mmc, int enable) | |||
636 | 634 | ||
637 | if (enable) { | 635 | if (enable) { |
638 | writel(BM_SSP_CTRL0_SDIO_IRQ_CHECK, | 636 | writel(BM_SSP_CTRL0_SDIO_IRQ_CHECK, |
639 | host->base + HW_SSP_CTRL0 + MXS_SET_ADDR); | 637 | host->base + HW_SSP_CTRL0 + STMP_OFFSET_REG_SET); |
640 | writel(BM_SSP_CTRL1_SDIO_IRQ_EN, | 638 | writel(BM_SSP_CTRL1_SDIO_IRQ_EN, |
641 | host->base + HW_SSP_CTRL1 + MXS_SET_ADDR); | 639 | host->base + HW_SSP_CTRL1(host) + STMP_OFFSET_REG_SET); |
642 | 640 | ||
643 | if (readl(host->base + HW_SSP_STATUS) & BM_SSP_STATUS_SDIO_IRQ) | 641 | if (readl(host->base + HW_SSP_STATUS(host)) & |
642 | BM_SSP_STATUS_SDIO_IRQ) | ||
644 | mmc_signal_sdio_irq(host->mmc); | 643 | mmc_signal_sdio_irq(host->mmc); |
645 | 644 | ||
646 | } else { | 645 | } else { |
647 | writel(BM_SSP_CTRL0_SDIO_IRQ_CHECK, | 646 | writel(BM_SSP_CTRL0_SDIO_IRQ_CHECK, |
648 | host->base + HW_SSP_CTRL0 + MXS_CLR_ADDR); | 647 | host->base + HW_SSP_CTRL0 + STMP_OFFSET_REG_CLR); |
649 | writel(BM_SSP_CTRL1_SDIO_IRQ_EN, | 648 | writel(BM_SSP_CTRL1_SDIO_IRQ_EN, |
650 | host->base + HW_SSP_CTRL1 + MXS_CLR_ADDR); | 649 | host->base + HW_SSP_CTRL1(host) + STMP_OFFSET_REG_CLR); |
651 | } | 650 | } |
652 | 651 | ||
653 | spin_unlock_irqrestore(&host->lock, flags); | 652 | spin_unlock_irqrestore(&host->lock, flags); |
@@ -668,7 +667,7 @@ static bool mxs_mmc_dma_filter(struct dma_chan *chan, void *param) | |||
668 | if (!mxs_dma_is_apbh(chan)) | 667 | if (!mxs_dma_is_apbh(chan)) |
669 | return false; | 668 | return false; |
670 | 669 | ||
671 | if (chan->chan_id != host->dma_res->start) | 670 | if (chan->chan_id != host->dma_channel) |
672 | return false; | 671 | return false; |
673 | 672 | ||
674 | chan->private = &host->dma_data; | 673 | chan->private = &host->dma_data; |
@@ -676,12 +675,36 @@ static bool mxs_mmc_dma_filter(struct dma_chan *chan, void *param) | |||
676 | return true; | 675 | return true; |
677 | } | 676 | } |
678 | 677 | ||
678 | static struct platform_device_id mxs_mmc_ids[] = { | ||
679 | { | ||
680 | .name = "imx23-mmc", | ||
681 | .driver_data = IMX23_MMC, | ||
682 | }, { | ||
683 | .name = "imx28-mmc", | ||
684 | .driver_data = IMX28_MMC, | ||
685 | }, { | ||
686 | /* sentinel */ | ||
687 | } | ||
688 | }; | ||
689 | MODULE_DEVICE_TABLE(platform, mxs_mmc_ids); | ||
690 | |||
691 | static const struct of_device_id mxs_mmc_dt_ids[] = { | ||
692 | { .compatible = "fsl,imx23-mmc", .data = (void *) IMX23_MMC, }, | ||
693 | { .compatible = "fsl,imx28-mmc", .data = (void *) IMX28_MMC, }, | ||
694 | { /* sentinel */ } | ||
695 | }; | ||
696 | MODULE_DEVICE_TABLE(of, mxs_mmc_dt_ids); | ||
697 | |||
679 | static int mxs_mmc_probe(struct platform_device *pdev) | 698 | static int mxs_mmc_probe(struct platform_device *pdev) |
680 | { | 699 | { |
700 | const struct of_device_id *of_id = | ||
701 | of_match_device(mxs_mmc_dt_ids, &pdev->dev); | ||
702 | struct device_node *np = pdev->dev.of_node; | ||
681 | struct mxs_mmc_host *host; | 703 | struct mxs_mmc_host *host; |
682 | struct mmc_host *mmc; | 704 | struct mmc_host *mmc; |
683 | struct resource *iores, *dmares, *r; | 705 | struct resource *iores, *dmares; |
684 | struct mxs_mmc_platform_data *pdata; | 706 | struct mxs_mmc_platform_data *pdata; |
707 | struct pinctrl *pinctrl; | ||
685 | int ret = 0, irq_err, irq_dma; | 708 | int ret = 0, irq_err, irq_dma; |
686 | dma_cap_mask_t mask; | 709 | dma_cap_mask_t mask; |
687 | 710 | ||
@@ -689,40 +712,51 @@ static int mxs_mmc_probe(struct platform_device *pdev) | |||
689 | dmares = platform_get_resource(pdev, IORESOURCE_DMA, 0); | 712 | dmares = platform_get_resource(pdev, IORESOURCE_DMA, 0); |
690 | irq_err = platform_get_irq(pdev, 0); | 713 | irq_err = platform_get_irq(pdev, 0); |
691 | irq_dma = platform_get_irq(pdev, 1); | 714 | irq_dma = platform_get_irq(pdev, 1); |
692 | if (!iores || !dmares || irq_err < 0 || irq_dma < 0) | 715 | if (!iores || irq_err < 0 || irq_dma < 0) |
693 | return -EINVAL; | 716 | return -EINVAL; |
694 | 717 | ||
695 | r = request_mem_region(iores->start, resource_size(iores), pdev->name); | ||
696 | if (!r) | ||
697 | return -EBUSY; | ||
698 | |||
699 | mmc = mmc_alloc_host(sizeof(struct mxs_mmc_host), &pdev->dev); | 718 | mmc = mmc_alloc_host(sizeof(struct mxs_mmc_host), &pdev->dev); |
700 | if (!mmc) { | 719 | if (!mmc) |
701 | ret = -ENOMEM; | 720 | return -ENOMEM; |
702 | goto out_release_mem; | ||
703 | } | ||
704 | 721 | ||
705 | host = mmc_priv(mmc); | 722 | host = mmc_priv(mmc); |
706 | host->base = ioremap(r->start, resource_size(r)); | 723 | host->base = devm_request_and_ioremap(&pdev->dev, iores); |
707 | if (!host->base) { | 724 | if (!host->base) { |
708 | ret = -ENOMEM; | 725 | ret = -EADDRNOTAVAIL; |
709 | goto out_mmc_free; | 726 | goto out_mmc_free; |
710 | } | 727 | } |
711 | 728 | ||
712 | /* only major verion does matter */ | 729 | if (np) { |
713 | host->version = readl(host->base + HW_SSP_VERSION) >> | 730 | host->devid = (enum mxs_mmc_id) of_id->data; |
714 | BP_SSP_VERSION_MAJOR; | 731 | /* |
732 | * TODO: This is a temporary solution and should be changed | ||
733 | * to use generic DMA binding later when the helpers get in. | ||
734 | */ | ||
735 | ret = of_property_read_u32(np, "fsl,ssp-dma-channel", | ||
736 | &host->dma_channel); | ||
737 | if (ret) { | ||
738 | dev_err(mmc_dev(host->mmc), | ||
739 | "failed to get dma channel\n"); | ||
740 | goto out_mmc_free; | ||
741 | } | ||
742 | } else { | ||
743 | host->devid = pdev->id_entry->driver_data; | ||
744 | host->dma_channel = dmares->start; | ||
745 | } | ||
715 | 746 | ||
716 | host->mmc = mmc; | 747 | host->mmc = mmc; |
717 | host->res = r; | ||
718 | host->dma_res = dmares; | ||
719 | host->irq = irq_err; | ||
720 | host->sdio_irq_en = 0; | 748 | host->sdio_irq_en = 0; |
721 | 749 | ||
750 | pinctrl = devm_pinctrl_get_select_default(&pdev->dev); | ||
751 | if (IS_ERR(pinctrl)) { | ||
752 | ret = PTR_ERR(pinctrl); | ||
753 | goto out_mmc_free; | ||
754 | } | ||
755 | |||
722 | host->clk = clk_get(&pdev->dev, NULL); | 756 | host->clk = clk_get(&pdev->dev, NULL); |
723 | if (IS_ERR(host->clk)) { | 757 | if (IS_ERR(host->clk)) { |
724 | ret = PTR_ERR(host->clk); | 758 | ret = PTR_ERR(host->clk); |
725 | goto out_iounmap; | 759 | goto out_mmc_free; |
726 | } | 760 | } |
727 | clk_prepare_enable(host->clk); | 761 | clk_prepare_enable(host->clk); |
728 | 762 | ||
@@ -744,11 +778,20 @@ static int mxs_mmc_probe(struct platform_device *pdev) | |||
744 | MMC_CAP_SDIO_IRQ | MMC_CAP_NEEDS_POLL; | 778 | MMC_CAP_SDIO_IRQ | MMC_CAP_NEEDS_POLL; |
745 | 779 | ||
746 | pdata = mmc_dev(host->mmc)->platform_data; | 780 | pdata = mmc_dev(host->mmc)->platform_data; |
747 | if (pdata) { | 781 | if (!pdata) { |
782 | u32 bus_width = 0; | ||
783 | of_property_read_u32(np, "bus-width", &bus_width); | ||
784 | if (bus_width == 4) | ||
785 | mmc->caps |= MMC_CAP_4_BIT_DATA; | ||
786 | else if (bus_width == 8) | ||
787 | mmc->caps |= MMC_CAP_4_BIT_DATA | MMC_CAP_8_BIT_DATA; | ||
788 | host->wp_gpio = of_get_named_gpio(np, "wp-gpios", 0); | ||
789 | } else { | ||
748 | if (pdata->flags & SLOTF_8_BIT_CAPABLE) | 790 | if (pdata->flags & SLOTF_8_BIT_CAPABLE) |
749 | mmc->caps |= MMC_CAP_4_BIT_DATA | MMC_CAP_8_BIT_DATA; | 791 | mmc->caps |= MMC_CAP_4_BIT_DATA | MMC_CAP_8_BIT_DATA; |
750 | if (pdata->flags & SLOTF_4_BIT_CAPABLE) | 792 | if (pdata->flags & SLOTF_4_BIT_CAPABLE) |
751 | mmc->caps |= MMC_CAP_4_BIT_DATA; | 793 | mmc->caps |= MMC_CAP_4_BIT_DATA; |
794 | host->wp_gpio = pdata->wp_gpio; | ||
752 | } | 795 | } |
753 | 796 | ||
754 | mmc->f_min = 400000; | 797 | mmc->f_min = 400000; |
@@ -757,13 +800,14 @@ static int mxs_mmc_probe(struct platform_device *pdev) | |||
757 | 800 | ||
758 | mmc->max_segs = 52; | 801 | mmc->max_segs = 52; |
759 | mmc->max_blk_size = 1 << 0xf; | 802 | mmc->max_blk_size = 1 << 0xf; |
760 | mmc->max_blk_count = (ssp_is_old()) ? 0xff : 0xffffff; | 803 | mmc->max_blk_count = (ssp_is_old(host)) ? 0xff : 0xffffff; |
761 | mmc->max_req_size = (ssp_is_old()) ? 0xffff : 0xffffffff; | 804 | mmc->max_req_size = (ssp_is_old(host)) ? 0xffff : 0xffffffff; |
762 | mmc->max_seg_size = dma_get_max_seg_size(host->dmach->device->dev); | 805 | mmc->max_seg_size = dma_get_max_seg_size(host->dmach->device->dev); |
763 | 806 | ||
764 | platform_set_drvdata(pdev, mmc); | 807 | platform_set_drvdata(pdev, mmc); |
765 | 808 | ||
766 | ret = request_irq(host->irq, mxs_mmc_irq_handler, 0, DRIVER_NAME, host); | 809 | ret = devm_request_irq(&pdev->dev, irq_err, mxs_mmc_irq_handler, 0, |
810 | DRIVER_NAME, host); | ||
767 | if (ret) | 811 | if (ret) |
768 | goto out_free_dma; | 812 | goto out_free_dma; |
769 | 813 | ||
@@ -771,26 +815,20 @@ static int mxs_mmc_probe(struct platform_device *pdev) | |||
771 | 815 | ||
772 | ret = mmc_add_host(mmc); | 816 | ret = mmc_add_host(mmc); |
773 | if (ret) | 817 | if (ret) |
774 | goto out_free_irq; | 818 | goto out_free_dma; |
775 | 819 | ||
776 | dev_info(mmc_dev(host->mmc), "initialized\n"); | 820 | dev_info(mmc_dev(host->mmc), "initialized\n"); |
777 | 821 | ||
778 | return 0; | 822 | return 0; |
779 | 823 | ||
780 | out_free_irq: | ||
781 | free_irq(host->irq, host); | ||
782 | out_free_dma: | 824 | out_free_dma: |
783 | if (host->dmach) | 825 | if (host->dmach) |
784 | dma_release_channel(host->dmach); | 826 | dma_release_channel(host->dmach); |
785 | out_clk_put: | 827 | out_clk_put: |
786 | clk_disable_unprepare(host->clk); | 828 | clk_disable_unprepare(host->clk); |
787 | clk_put(host->clk); | 829 | clk_put(host->clk); |
788 | out_iounmap: | ||
789 | iounmap(host->base); | ||
790 | out_mmc_free: | 830 | out_mmc_free: |
791 | mmc_free_host(mmc); | 831 | mmc_free_host(mmc); |
792 | out_release_mem: | ||
793 | release_mem_region(iores->start, resource_size(iores)); | ||
794 | return ret; | 832 | return ret; |
795 | } | 833 | } |
796 | 834 | ||
@@ -798,12 +836,9 @@ static int mxs_mmc_remove(struct platform_device *pdev) | |||
798 | { | 836 | { |
799 | struct mmc_host *mmc = platform_get_drvdata(pdev); | 837 | struct mmc_host *mmc = platform_get_drvdata(pdev); |
800 | struct mxs_mmc_host *host = mmc_priv(mmc); | 838 | struct mxs_mmc_host *host = mmc_priv(mmc); |
801 | struct resource *res = host->res; | ||
802 | 839 | ||
803 | mmc_remove_host(mmc); | 840 | mmc_remove_host(mmc); |
804 | 841 | ||
805 | free_irq(host->irq, host); | ||
806 | |||
807 | platform_set_drvdata(pdev, NULL); | 842 | platform_set_drvdata(pdev, NULL); |
808 | 843 | ||
809 | if (host->dmach) | 844 | if (host->dmach) |
@@ -812,12 +847,8 @@ static int mxs_mmc_remove(struct platform_device *pdev) | |||
812 | clk_disable_unprepare(host->clk); | 847 | clk_disable_unprepare(host->clk); |
813 | clk_put(host->clk); | 848 | clk_put(host->clk); |
814 | 849 | ||
815 | iounmap(host->base); | ||
816 | |||
817 | mmc_free_host(mmc); | 850 | mmc_free_host(mmc); |
818 | 851 | ||
819 | release_mem_region(res->start, resource_size(res)); | ||
820 | |||
821 | return 0; | 852 | return 0; |
822 | } | 853 | } |
823 | 854 | ||
@@ -857,11 +888,13 @@ static const struct dev_pm_ops mxs_mmc_pm_ops = { | |||
857 | static struct platform_driver mxs_mmc_driver = { | 888 | static struct platform_driver mxs_mmc_driver = { |
858 | .probe = mxs_mmc_probe, | 889 | .probe = mxs_mmc_probe, |
859 | .remove = mxs_mmc_remove, | 890 | .remove = mxs_mmc_remove, |
891 | .id_table = mxs_mmc_ids, | ||
860 | .driver = { | 892 | .driver = { |
861 | .name = DRIVER_NAME, | 893 | .name = DRIVER_NAME, |
862 | .owner = THIS_MODULE, | 894 | .owner = THIS_MODULE, |
863 | #ifdef CONFIG_PM | 895 | #ifdef CONFIG_PM |
864 | .pm = &mxs_mmc_pm_ops, | 896 | .pm = &mxs_mmc_pm_ops, |
897 | .of_match_table = mxs_mmc_dt_ids, | ||
865 | #endif | 898 | #endif |
866 | }, | 899 | }, |
867 | }; | 900 | }; |
diff --git a/drivers/mmc/host/sdhci-esdhc-imx.c b/drivers/mmc/host/sdhci-esdhc-imx.c index 8abdaf6697a8..d190d04636a7 100644 --- a/drivers/mmc/host/sdhci-esdhc-imx.c +++ b/drivers/mmc/host/sdhci-esdhc-imx.c | |||
@@ -24,6 +24,7 @@ | |||
24 | #include <linux/of.h> | 24 | #include <linux/of.h> |
25 | #include <linux/of_device.h> | 25 | #include <linux/of_device.h> |
26 | #include <linux/of_gpio.h> | 26 | #include <linux/of_gpio.h> |
27 | #include <linux/pinctrl/consumer.h> | ||
27 | #include <mach/esdhc.h> | 28 | #include <mach/esdhc.h> |
28 | #include "sdhci-pltfm.h" | 29 | #include "sdhci-pltfm.h" |
29 | #include "sdhci-esdhc.h" | 30 | #include "sdhci-esdhc.h" |
@@ -68,6 +69,7 @@ struct pltfm_imx_data { | |||
68 | int flags; | 69 | int flags; |
69 | u32 scratchpad; | 70 | u32 scratchpad; |
70 | enum imx_esdhc_type devtype; | 71 | enum imx_esdhc_type devtype; |
72 | struct pinctrl *pinctrl; | ||
71 | struct esdhc_platform_data boarddata; | 73 | struct esdhc_platform_data boarddata; |
72 | }; | 74 | }; |
73 | 75 | ||
@@ -467,6 +469,12 @@ static int __devinit sdhci_esdhc_imx_probe(struct platform_device *pdev) | |||
467 | clk_prepare_enable(clk); | 469 | clk_prepare_enable(clk); |
468 | pltfm_host->clk = clk; | 470 | pltfm_host->clk = clk; |
469 | 471 | ||
472 | imx_data->pinctrl = devm_pinctrl_get_select_default(&pdev->dev); | ||
473 | if (IS_ERR(imx_data->pinctrl)) { | ||
474 | err = PTR_ERR(imx_data->pinctrl); | ||
475 | goto pin_err; | ||
476 | } | ||
477 | |||
470 | host->quirks |= SDHCI_QUIRK_BROKEN_TIMEOUT_VAL; | 478 | host->quirks |= SDHCI_QUIRK_BROKEN_TIMEOUT_VAL; |
471 | 479 | ||
472 | if (is_imx25_esdhc(imx_data) || is_imx35_esdhc(imx_data)) | 480 | if (is_imx25_esdhc(imx_data) || is_imx35_esdhc(imx_data)) |
@@ -558,6 +566,7 @@ no_card_detect_irq: | |||
558 | gpio_free(boarddata->wp_gpio); | 566 | gpio_free(boarddata->wp_gpio); |
559 | no_card_detect_pin: | 567 | no_card_detect_pin: |
560 | no_board_data: | 568 | no_board_data: |
569 | pin_err: | ||
561 | clk_disable_unprepare(pltfm_host->clk); | 570 | clk_disable_unprepare(pltfm_host->clk); |
562 | clk_put(pltfm_host->clk); | 571 | clk_put(pltfm_host->clk); |
563 | err_clk_get: | 572 | err_clk_get: |
diff --git a/drivers/mtd/nand/gpmi-nand/gpmi-nand.c b/drivers/mtd/nand/gpmi-nand/gpmi-nand.c index 9ec51cec2e14..8478fd9701a3 100644 --- a/drivers/mtd/nand/gpmi-nand/gpmi-nand.c +++ b/drivers/mtd/nand/gpmi-nand/gpmi-nand.c | |||
@@ -24,6 +24,7 @@ | |||
24 | #include <linux/module.h> | 24 | #include <linux/module.h> |
25 | #include <linux/mtd/gpmi-nand.h> | 25 | #include <linux/mtd/gpmi-nand.h> |
26 | #include <linux/mtd/partitions.h> | 26 | #include <linux/mtd/partitions.h> |
27 | #include <linux/pinctrl/consumer.h> | ||
27 | #include "gpmi-nand.h" | 28 | #include "gpmi-nand.h" |
28 | 29 | ||
29 | /* add our owner bbt descriptor */ | 30 | /* add our owner bbt descriptor */ |
@@ -476,6 +477,7 @@ acquire_err: | |||
476 | static int __devinit acquire_resources(struct gpmi_nand_data *this) | 477 | static int __devinit acquire_resources(struct gpmi_nand_data *this) |
477 | { | 478 | { |
478 | struct resources *res = &this->resources; | 479 | struct resources *res = &this->resources; |
480 | struct pinctrl *pinctrl; | ||
479 | int ret; | 481 | int ret; |
480 | 482 | ||
481 | ret = acquire_register_block(this, GPMI_NAND_GPMI_REGS_ADDR_RES_NAME); | 483 | ret = acquire_register_block(this, GPMI_NAND_GPMI_REGS_ADDR_RES_NAME); |
@@ -494,6 +496,12 @@ static int __devinit acquire_resources(struct gpmi_nand_data *this) | |||
494 | if (ret) | 496 | if (ret) |
495 | goto exit_dma_channels; | 497 | goto exit_dma_channels; |
496 | 498 | ||
499 | pinctrl = devm_pinctrl_get_select_default(&pdev->dev); | ||
500 | if (IS_ERR(pinctrl)) { | ||
501 | ret = PTR_ERR(pinctrl); | ||
502 | goto exit_pin; | ||
503 | } | ||
504 | |||
497 | res->clock = clk_get(&this->pdev->dev, NULL); | 505 | res->clock = clk_get(&this->pdev->dev, NULL); |
498 | if (IS_ERR(res->clock)) { | 506 | if (IS_ERR(res->clock)) { |
499 | pr_err("can not get the clock\n"); | 507 | pr_err("can not get the clock\n"); |
@@ -503,6 +511,7 @@ static int __devinit acquire_resources(struct gpmi_nand_data *this) | |||
503 | return 0; | 511 | return 0; |
504 | 512 | ||
505 | exit_clock: | 513 | exit_clock: |
514 | exit_pin: | ||
506 | release_dma_channels(this); | 515 | release_dma_channels(this); |
507 | exit_dma_channels: | 516 | exit_dma_channels: |
508 | release_bch_irq(this); | 517 | release_bch_irq(this); |
diff --git a/drivers/net/can/flexcan.c b/drivers/net/can/flexcan.c index 1efb08386c61..38c0690df5c8 100644 --- a/drivers/net/can/flexcan.c +++ b/drivers/net/can/flexcan.c | |||
@@ -35,6 +35,7 @@ | |||
35 | #include <linux/module.h> | 35 | #include <linux/module.h> |
36 | #include <linux/of.h> | 36 | #include <linux/of.h> |
37 | #include <linux/platform_device.h> | 37 | #include <linux/platform_device.h> |
38 | #include <linux/pinctrl/consumer.h> | ||
38 | 39 | ||
39 | #define DRV_NAME "flexcan" | 40 | #define DRV_NAME "flexcan" |
40 | 41 | ||
@@ -927,11 +928,16 @@ static int __devinit flexcan_probe(struct platform_device *pdev) | |||
927 | struct flexcan_priv *priv; | 928 | struct flexcan_priv *priv; |
928 | struct resource *mem; | 929 | struct resource *mem; |
929 | struct clk *clk = NULL; | 930 | struct clk *clk = NULL; |
931 | struct pinctrl *pinctrl; | ||
930 | void __iomem *base; | 932 | void __iomem *base; |
931 | resource_size_t mem_size; | 933 | resource_size_t mem_size; |
932 | int err, irq; | 934 | int err, irq; |
933 | u32 clock_freq = 0; | 935 | u32 clock_freq = 0; |
934 | 936 | ||
937 | pinctrl = devm_pinctrl_get_select_default(&pdev->dev); | ||
938 | if (IS_ERR(pinctrl)) | ||
939 | return PTR_ERR(pinctrl); | ||
940 | |||
935 | if (pdev->dev.of_node) { | 941 | if (pdev->dev.of_node) { |
936 | const u32 *clock_freq_p; | 942 | const u32 *clock_freq_p; |
937 | 943 | ||
diff --git a/drivers/net/ethernet/freescale/fec.c b/drivers/net/ethernet/freescale/fec.c index a12b3f5bc025..500c106af86e 100644 --- a/drivers/net/ethernet/freescale/fec.c +++ b/drivers/net/ethernet/freescale/fec.c | |||
@@ -48,6 +48,7 @@ | |||
48 | #include <linux/of_device.h> | 48 | #include <linux/of_device.h> |
49 | #include <linux/of_gpio.h> | 49 | #include <linux/of_gpio.h> |
50 | #include <linux/of_net.h> | 50 | #include <linux/of_net.h> |
51 | #include <linux/pinctrl/consumer.h> | ||
51 | 52 | ||
52 | #include <asm/cacheflush.h> | 53 | #include <asm/cacheflush.h> |
53 | 54 | ||
@@ -1542,6 +1543,7 @@ fec_probe(struct platform_device *pdev) | |||
1542 | struct resource *r; | 1543 | struct resource *r; |
1543 | const struct of_device_id *of_id; | 1544 | const struct of_device_id *of_id; |
1544 | static int dev_id; | 1545 | static int dev_id; |
1546 | struct pinctrl *pinctrl; | ||
1545 | 1547 | ||
1546 | of_id = of_match_device(fec_dt_ids, &pdev->dev); | 1548 | of_id = of_match_device(fec_dt_ids, &pdev->dev); |
1547 | if (of_id) | 1549 | if (of_id) |
@@ -1609,6 +1611,12 @@ fec_probe(struct platform_device *pdev) | |||
1609 | } | 1611 | } |
1610 | } | 1612 | } |
1611 | 1613 | ||
1614 | pinctrl = devm_pinctrl_get_select_default(&pdev->dev); | ||
1615 | if (IS_ERR(pinctrl)) { | ||
1616 | ret = PTR_ERR(pinctrl); | ||
1617 | goto failed_pin; | ||
1618 | } | ||
1619 | |||
1612 | fep->clk = clk_get(&pdev->dev, NULL); | 1620 | fep->clk = clk_get(&pdev->dev, NULL); |
1613 | if (IS_ERR(fep->clk)) { | 1621 | if (IS_ERR(fep->clk)) { |
1614 | ret = PTR_ERR(fep->clk); | 1622 | ret = PTR_ERR(fep->clk); |
@@ -1639,6 +1647,7 @@ failed_mii_init: | |||
1639 | failed_init: | 1647 | failed_init: |
1640 | clk_disable_unprepare(fep->clk); | 1648 | clk_disable_unprepare(fep->clk); |
1641 | clk_put(fep->clk); | 1649 | clk_put(fep->clk); |
1650 | failed_pin: | ||
1642 | failed_clk: | 1651 | failed_clk: |
1643 | for (i = 0; i < FEC_IRQ_NUM; i++) { | 1652 | for (i = 0; i < FEC_IRQ_NUM; i++) { |
1644 | irq = platform_get_irq(pdev, i); | 1653 | irq = platform_get_irq(pdev, i); |
diff --git a/drivers/spi/spi-imx.c b/drivers/spi/spi-imx.c index 570f22053be8..69c9a6601f45 100644 --- a/drivers/spi/spi-imx.c +++ b/drivers/spi/spi-imx.c | |||
@@ -37,6 +37,7 @@ | |||
37 | #include <linux/of.h> | 37 | #include <linux/of.h> |
38 | #include <linux/of_device.h> | 38 | #include <linux/of_device.h> |
39 | #include <linux/of_gpio.h> | 39 | #include <linux/of_gpio.h> |
40 | #include <linux/pinctrl/consumer.h> | ||
40 | 41 | ||
41 | #include <mach/spi.h> | 42 | #include <mach/spi.h> |
42 | 43 | ||
@@ -758,6 +759,7 @@ static int __devinit spi_imx_probe(struct platform_device *pdev) | |||
758 | struct spi_master *master; | 759 | struct spi_master *master; |
759 | struct spi_imx_data *spi_imx; | 760 | struct spi_imx_data *spi_imx; |
760 | struct resource *res; | 761 | struct resource *res; |
762 | struct pinctrl *pinctrl; | ||
761 | int i, ret, num_cs; | 763 | int i, ret, num_cs; |
762 | 764 | ||
763 | if (!np && !mxc_platform_info) { | 765 | if (!np && !mxc_platform_info) { |
@@ -845,6 +847,12 @@ static int __devinit spi_imx_probe(struct platform_device *pdev) | |||
845 | goto out_iounmap; | 847 | goto out_iounmap; |
846 | } | 848 | } |
847 | 849 | ||
850 | pinctrl = devm_pinctrl_get_select_default(&pdev->dev); | ||
851 | if (IS_ERR(pinctrl)) { | ||
852 | ret = PTR_ERR(pinctrl); | ||
853 | goto out_free_irq; | ||
854 | } | ||
855 | |||
848 | spi_imx->clk = clk_get(&pdev->dev, NULL); | 856 | spi_imx->clk = clk_get(&pdev->dev, NULL); |
849 | if (IS_ERR(spi_imx->clk)) { | 857 | if (IS_ERR(spi_imx->clk)) { |
850 | dev_err(&pdev->dev, "unable to get clock\n"); | 858 | dev_err(&pdev->dev, "unable to get clock\n"); |
diff --git a/drivers/tty/serial/amba-pl011.c b/drivers/tty/serial/amba-pl011.c index 3d569cd68f58..062ef8c2b3cb 100644 --- a/drivers/tty/serial/amba-pl011.c +++ b/drivers/tty/serial/amba-pl011.c | |||
@@ -52,6 +52,7 @@ | |||
52 | #include <linux/scatterlist.h> | 52 | #include <linux/scatterlist.h> |
53 | #include <linux/delay.h> | 53 | #include <linux/delay.h> |
54 | #include <linux/types.h> | 54 | #include <linux/types.h> |
55 | #include <linux/pinctrl/consumer.h> | ||
55 | 56 | ||
56 | #include <asm/io.h> | 57 | #include <asm/io.h> |
57 | #include <asm/sizes.h> | 58 | #include <asm/sizes.h> |
@@ -1916,6 +1917,7 @@ static int pl011_probe(struct amba_device *dev, const struct amba_id *id) | |||
1916 | { | 1917 | { |
1917 | struct uart_amba_port *uap; | 1918 | struct uart_amba_port *uap; |
1918 | struct vendor_data *vendor = id->data; | 1919 | struct vendor_data *vendor = id->data; |
1920 | struct pinctrl *pinctrl; | ||
1919 | void __iomem *base; | 1921 | void __iomem *base; |
1920 | int i, ret; | 1922 | int i, ret; |
1921 | 1923 | ||
@@ -1940,6 +1942,12 @@ static int pl011_probe(struct amba_device *dev, const struct amba_id *id) | |||
1940 | goto free; | 1942 | goto free; |
1941 | } | 1943 | } |
1942 | 1944 | ||
1945 | pinctrl = devm_pinctrl_get_select_default(&dev->dev); | ||
1946 | if (IS_ERR(pinctrl)) { | ||
1947 | ret = PTR_ERR(pinctrl); | ||
1948 | goto unmap; | ||
1949 | } | ||
1950 | |||
1943 | uap->clk = clk_get(&dev->dev, NULL); | 1951 | uap->clk = clk_get(&dev->dev, NULL); |
1944 | if (IS_ERR(uap->clk)) { | 1952 | if (IS_ERR(uap->clk)) { |
1945 | ret = PTR_ERR(uap->clk); | 1953 | ret = PTR_ERR(uap->clk); |
diff --git a/drivers/tty/serial/imx.c b/drivers/tty/serial/imx.c index e7feceeebc2f..ec206732f68c 100644 --- a/drivers/tty/serial/imx.c +++ b/drivers/tty/serial/imx.c | |||
@@ -47,6 +47,7 @@ | |||
47 | #include <linux/slab.h> | 47 | #include <linux/slab.h> |
48 | #include <linux/of.h> | 48 | #include <linux/of.h> |
49 | #include <linux/of_device.h> | 49 | #include <linux/of_device.h> |
50 | #include <linux/pinctrl/consumer.h> | ||
50 | 51 | ||
51 | #include <asm/io.h> | 52 | #include <asm/io.h> |
52 | #include <asm/irq.h> | 53 | #include <asm/irq.h> |
@@ -1464,6 +1465,7 @@ static int serial_imx_probe(struct platform_device *pdev) | |||
1464 | void __iomem *base; | 1465 | void __iomem *base; |
1465 | int ret = 0; | 1466 | int ret = 0; |
1466 | struct resource *res; | 1467 | struct resource *res; |
1468 | struct pinctrl *pinctrl; | ||
1467 | 1469 | ||
1468 | sport = kzalloc(sizeof(*sport), GFP_KERNEL); | 1470 | sport = kzalloc(sizeof(*sport), GFP_KERNEL); |
1469 | if (!sport) | 1471 | if (!sport) |
@@ -1503,6 +1505,12 @@ static int serial_imx_probe(struct platform_device *pdev) | |||
1503 | sport->timer.function = imx_timeout; | 1505 | sport->timer.function = imx_timeout; |
1504 | sport->timer.data = (unsigned long)sport; | 1506 | sport->timer.data = (unsigned long)sport; |
1505 | 1507 | ||
1508 | pinctrl = devm_pinctrl_get_select_default(&pdev->dev); | ||
1509 | if (IS_ERR(pinctrl)) { | ||
1510 | ret = PTR_ERR(pinctrl); | ||
1511 | goto unmap; | ||
1512 | } | ||
1513 | |||
1506 | sport->clk = clk_get(&pdev->dev, "uart"); | 1514 | sport->clk = clk_get(&pdev->dev, "uart"); |
1507 | if (IS_ERR(sport->clk)) { | 1515 | if (IS_ERR(sport->clk)) { |
1508 | ret = PTR_ERR(sport->clk); | 1516 | ret = PTR_ERR(sport->clk); |
diff --git a/drivers/tty/serial/mxs-auart.c b/drivers/tty/serial/mxs-auart.c index 55fd362b9879..7081600bede4 100644 --- a/drivers/tty/serial/mxs-auart.c +++ b/drivers/tty/serial/mxs-auart.c | |||
@@ -32,6 +32,7 @@ | |||
32 | #include <linux/clk.h> | 32 | #include <linux/clk.h> |
33 | #include <linux/delay.h> | 33 | #include <linux/delay.h> |
34 | #include <linux/io.h> | 34 | #include <linux/io.h> |
35 | #include <linux/pinctrl/consumer.h> | ||
35 | 36 | ||
36 | #include <asm/cacheflush.h> | 37 | #include <asm/cacheflush.h> |
37 | 38 | ||
@@ -678,6 +679,7 @@ static int __devinit mxs_auart_probe(struct platform_device *pdev) | |||
678 | u32 version; | 679 | u32 version; |
679 | int ret = 0; | 680 | int ret = 0; |
680 | struct resource *r; | 681 | struct resource *r; |
682 | struct pinctrl *pinctrl; | ||
681 | 683 | ||
682 | s = kzalloc(sizeof(struct mxs_auart_port), GFP_KERNEL); | 684 | s = kzalloc(sizeof(struct mxs_auart_port), GFP_KERNEL); |
683 | if (!s) { | 685 | if (!s) { |
@@ -685,6 +687,12 @@ static int __devinit mxs_auart_probe(struct platform_device *pdev) | |||
685 | goto out; | 687 | goto out; |
686 | } | 688 | } |
687 | 689 | ||
690 | pinctrl = devm_pinctrl_get_select_default(&pdev->dev); | ||
691 | if (IS_ERR(pinctrl)) { | ||
692 | ret = PTR_ERR(pinctrl); | ||
693 | goto out_free; | ||
694 | } | ||
695 | |||
688 | s->clk = clk_get(&pdev->dev, NULL); | 696 | s->clk = clk_get(&pdev->dev, NULL); |
689 | if (IS_ERR(s->clk)) { | 697 | if (IS_ERR(s->clk)) { |
690 | ret = PTR_ERR(s->clk); | 698 | ret = PTR_ERR(s->clk); |
diff --git a/drivers/video/mxsfb.c b/drivers/video/mxsfb.c index 4a89f889852d..6c6bc578d0fc 100644 --- a/drivers/video/mxsfb.c +++ b/drivers/video/mxsfb.c | |||
@@ -45,6 +45,7 @@ | |||
45 | #include <linux/clk.h> | 45 | #include <linux/clk.h> |
46 | #include <linux/dma-mapping.h> | 46 | #include <linux/dma-mapping.h> |
47 | #include <linux/io.h> | 47 | #include <linux/io.h> |
48 | #include <linux/pinctrl/consumer.h> | ||
48 | #include <mach/mxsfb.h> | 49 | #include <mach/mxsfb.h> |
49 | 50 | ||
50 | #define REG_SET 4 | 51 | #define REG_SET 4 |
@@ -756,6 +757,7 @@ static int __devinit mxsfb_probe(struct platform_device *pdev) | |||
756 | struct mxsfb_info *host; | 757 | struct mxsfb_info *host; |
757 | struct fb_info *fb_info; | 758 | struct fb_info *fb_info; |
758 | struct fb_modelist *modelist; | 759 | struct fb_modelist *modelist; |
760 | struct pinctrl *pinctrl; | ||
759 | int i, ret; | 761 | int i, ret; |
760 | 762 | ||
761 | if (!pdata) { | 763 | if (!pdata) { |
@@ -793,6 +795,12 @@ static int __devinit mxsfb_probe(struct platform_device *pdev) | |||
793 | 795 | ||
794 | host->devdata = &mxsfb_devdata[pdev->id_entry->driver_data]; | 796 | host->devdata = &mxsfb_devdata[pdev->id_entry->driver_data]; |
795 | 797 | ||
798 | pinctrl = devm_pinctrl_get_select_default(&pdev->dev); | ||
799 | if (IS_ERR(pinctrl)) { | ||
800 | ret = PTR_ERR(pinctrl); | ||
801 | goto error_getpin; | ||
802 | } | ||
803 | |||
796 | host->clk = clk_get(&host->pdev->dev, NULL); | 804 | host->clk = clk_get(&host->pdev->dev, NULL); |
797 | if (IS_ERR(host->clk)) { | 805 | if (IS_ERR(host->clk)) { |
798 | ret = PTR_ERR(host->clk); | 806 | ret = PTR_ERR(host->clk); |
@@ -848,6 +856,7 @@ error_init_fb: | |||
848 | error_pseudo_pallette: | 856 | error_pseudo_pallette: |
849 | clk_put(host->clk); | 857 | clk_put(host->clk); |
850 | error_getclock: | 858 | error_getclock: |
859 | error_getpin: | ||
851 | iounmap(host->base); | 860 | iounmap(host->base); |
852 | error_ioremap: | 861 | error_ioremap: |
853 | framebuffer_release(fb_info); | 862 | framebuffer_release(fb_info); |