diff options
Diffstat (limited to 'arch/arm/mach-mxs/mach-mxs.c')
-rw-r--r-- | arch/arm/mach-mxs/mach-mxs.c | 215 |
1 files changed, 210 insertions, 5 deletions
diff --git a/arch/arm/mach-mxs/mach-mxs.c b/arch/arm/mach-mxs/mach-mxs.c index 8cac94b33020..648bdd05d38b 100644 --- a/arch/arm/mach-mxs/mach-mxs.c +++ b/arch/arm/mach-mxs/mach-mxs.c | |||
@@ -16,12 +16,95 @@ | |||
16 | #include <linux/init.h> | 16 | #include <linux/init.h> |
17 | #include <linux/init.h> | 17 | #include <linux/init.h> |
18 | #include <linux/irqdomain.h> | 18 | #include <linux/irqdomain.h> |
19 | #include <linux/micrel_phy.h> | ||
20 | #include <linux/mxsfb.h> | ||
19 | #include <linux/of_irq.h> | 21 | #include <linux/of_irq.h> |
20 | #include <linux/of_platform.h> | 22 | #include <linux/of_platform.h> |
23 | #include <linux/phy.h> | ||
21 | #include <asm/mach/arch.h> | 24 | #include <asm/mach/arch.h> |
22 | #include <asm/mach/time.h> | 25 | #include <asm/mach/time.h> |
23 | #include <mach/common.h> | 26 | #include <mach/common.h> |
24 | 27 | ||
28 | static struct fb_videomode mx23evk_video_modes[] = { | ||
29 | { | ||
30 | .name = "Samsung-LMS430HF02", | ||
31 | .refresh = 60, | ||
32 | .xres = 480, | ||
33 | .yres = 272, | ||
34 | .pixclock = 108096, /* picosecond (9.2 MHz) */ | ||
35 | .left_margin = 15, | ||
36 | .right_margin = 8, | ||
37 | .upper_margin = 12, | ||
38 | .lower_margin = 4, | ||
39 | .hsync_len = 1, | ||
40 | .vsync_len = 1, | ||
41 | .sync = FB_SYNC_DATA_ENABLE_HIGH_ACT | | ||
42 | FB_SYNC_DOTCLK_FAILING_ACT, | ||
43 | }, | ||
44 | }; | ||
45 | |||
46 | static struct fb_videomode mx28evk_video_modes[] = { | ||
47 | { | ||
48 | .name = "Seiko-43WVF1G", | ||
49 | .refresh = 60, | ||
50 | .xres = 800, | ||
51 | .yres = 480, | ||
52 | .pixclock = 29851, /* picosecond (33.5 MHz) */ | ||
53 | .left_margin = 89, | ||
54 | .right_margin = 164, | ||
55 | .upper_margin = 23, | ||
56 | .lower_margin = 10, | ||
57 | .hsync_len = 10, | ||
58 | .vsync_len = 10, | ||
59 | .sync = FB_SYNC_DATA_ENABLE_HIGH_ACT | | ||
60 | FB_SYNC_DOTCLK_FAILING_ACT, | ||
61 | }, | ||
62 | }; | ||
63 | |||
64 | static struct fb_videomode m28evk_video_modes[] = { | ||
65 | { | ||
66 | .name = "Ampire AM-800480R2TMQW-T01H", | ||
67 | .refresh = 60, | ||
68 | .xres = 800, | ||
69 | .yres = 480, | ||
70 | .pixclock = 30066, /* picosecond (33.26 MHz) */ | ||
71 | .left_margin = 0, | ||
72 | .right_margin = 256, | ||
73 | .upper_margin = 0, | ||
74 | .lower_margin = 45, | ||
75 | .hsync_len = 1, | ||
76 | .vsync_len = 1, | ||
77 | .sync = FB_SYNC_DATA_ENABLE_HIGH_ACT, | ||
78 | }, | ||
79 | }; | ||
80 | |||
81 | static struct fb_videomode apx4devkit_video_modes[] = { | ||
82 | { | ||
83 | .name = "HannStar PJ70112A", | ||
84 | .refresh = 60, | ||
85 | .xres = 800, | ||
86 | .yres = 480, | ||
87 | .pixclock = 33333, /* picosecond (30.00 MHz) */ | ||
88 | .left_margin = 88, | ||
89 | .right_margin = 40, | ||
90 | .upper_margin = 32, | ||
91 | .lower_margin = 13, | ||
92 | .hsync_len = 48, | ||
93 | .vsync_len = 3, | ||
94 | .sync = FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT | | ||
95 | FB_SYNC_DATA_ENABLE_HIGH_ACT | | ||
96 | FB_SYNC_DOTCLK_FAILING_ACT, | ||
97 | }, | ||
98 | }; | ||
99 | |||
100 | static struct mxsfb_platform_data mxsfb_pdata __initdata; | ||
101 | |||
102 | static struct of_dev_auxdata mxs_auxdata_lookup[] __initdata = { | ||
103 | OF_DEV_AUXDATA("fsl,imx23-lcdif", 0x80030000, NULL, &mxsfb_pdata), | ||
104 | OF_DEV_AUXDATA("fsl,imx28-lcdif", 0x80030000, NULL, &mxsfb_pdata), | ||
105 | { /* sentinel */ } | ||
106 | }; | ||
107 | |||
25 | static int __init mxs_icoll_add_irq_domain(struct device_node *np, | 108 | static int __init mxs_icoll_add_irq_domain(struct device_node *np, |
26 | struct device_node *interrupt_parent) | 109 | struct device_node *interrupt_parent) |
27 | { | 110 | { |
@@ -71,33 +154,155 @@ static struct sys_timer imx28_timer = { | |||
71 | .init = imx28_timer_init, | 154 | .init = imx28_timer_init, |
72 | }; | 155 | }; |
73 | 156 | ||
74 | static void __init imx28_evk_init(void) | 157 | enum mac_oui { |
158 | OUI_FSL, | ||
159 | OUI_DENX, | ||
160 | }; | ||
161 | |||
162 | static void __init update_fec_mac_prop(enum mac_oui oui) | ||
163 | { | ||
164 | struct device_node *np, *from = NULL; | ||
165 | struct property *oldmac, *newmac; | ||
166 | const u32 *ocotp = mxs_get_ocotp(); | ||
167 | u8 *macaddr; | ||
168 | u32 val; | ||
169 | int i; | ||
170 | |||
171 | for (i = 0; i < 2; i++) { | ||
172 | np = of_find_compatible_node(from, NULL, "fsl,imx28-fec"); | ||
173 | if (!np) | ||
174 | return; | ||
175 | from = np; | ||
176 | |||
177 | newmac = kzalloc(sizeof(*newmac) + 6, GFP_KERNEL); | ||
178 | if (!newmac) | ||
179 | return; | ||
180 | newmac->value = newmac + 1; | ||
181 | newmac->length = 6; | ||
182 | |||
183 | newmac->name = kstrdup("local-mac-address", GFP_KERNEL); | ||
184 | if (!newmac->name) { | ||
185 | kfree(newmac); | ||
186 | return; | ||
187 | } | ||
188 | |||
189 | /* | ||
190 | * OCOTP only stores the last 4 octets for each mac address, | ||
191 | * so hard-code OUI here. | ||
192 | */ | ||
193 | macaddr = newmac->value; | ||
194 | switch (oui) { | ||
195 | case OUI_FSL: | ||
196 | macaddr[0] = 0x00; | ||
197 | macaddr[1] = 0x04; | ||
198 | macaddr[2] = 0x9f; | ||
199 | break; | ||
200 | case OUI_DENX: | ||
201 | macaddr[0] = 0xc0; | ||
202 | macaddr[1] = 0xe5; | ||
203 | macaddr[2] = 0x4e; | ||
204 | break; | ||
205 | } | ||
206 | val = ocotp[i]; | ||
207 | macaddr[3] = (val >> 16) & 0xff; | ||
208 | macaddr[4] = (val >> 8) & 0xff; | ||
209 | macaddr[5] = (val >> 0) & 0xff; | ||
210 | |||
211 | oldmac = of_find_property(np, newmac->name, NULL); | ||
212 | if (oldmac) | ||
213 | prom_update_property(np, newmac, oldmac); | ||
214 | else | ||
215 | prom_add_property(np, newmac); | ||
216 | } | ||
217 | } | ||
218 | |||
219 | static void __init imx23_evk_init(void) | ||
220 | { | ||
221 | mxsfb_pdata.mode_list = mx23evk_video_modes; | ||
222 | mxsfb_pdata.mode_count = ARRAY_SIZE(mx23evk_video_modes); | ||
223 | mxsfb_pdata.default_bpp = 32; | ||
224 | mxsfb_pdata.ld_intf_width = STMLCDIF_24BIT; | ||
225 | } | ||
226 | |||
227 | static inline void enable_clk_enet_out(void) | ||
75 | { | 228 | { |
76 | struct clk *clk; | 229 | struct clk *clk = clk_get_sys("enet_out", NULL); |
77 | 230 | ||
78 | /* Enable fec phy clock */ | ||
79 | clk = clk_get_sys("enet_out", NULL); | ||
80 | if (!IS_ERR(clk)) | 231 | if (!IS_ERR(clk)) |
81 | clk_prepare_enable(clk); | 232 | clk_prepare_enable(clk); |
82 | } | 233 | } |
83 | 234 | ||
235 | static void __init imx28_evk_init(void) | ||
236 | { | ||
237 | enable_clk_enet_out(); | ||
238 | update_fec_mac_prop(OUI_FSL); | ||
239 | |||
240 | mxsfb_pdata.mode_list = mx28evk_video_modes; | ||
241 | mxsfb_pdata.mode_count = ARRAY_SIZE(mx28evk_video_modes); | ||
242 | mxsfb_pdata.default_bpp = 32; | ||
243 | mxsfb_pdata.ld_intf_width = STMLCDIF_24BIT; | ||
244 | } | ||
245 | |||
246 | static void __init m28evk_init(void) | ||
247 | { | ||
248 | enable_clk_enet_out(); | ||
249 | update_fec_mac_prop(OUI_DENX); | ||
250 | |||
251 | mxsfb_pdata.mode_list = m28evk_video_modes; | ||
252 | mxsfb_pdata.mode_count = ARRAY_SIZE(m28evk_video_modes); | ||
253 | mxsfb_pdata.default_bpp = 16; | ||
254 | mxsfb_pdata.ld_intf_width = STMLCDIF_18BIT; | ||
255 | } | ||
256 | |||
257 | static int apx4devkit_phy_fixup(struct phy_device *phy) | ||
258 | { | ||
259 | phy->dev_flags |= MICREL_PHY_50MHZ_CLK; | ||
260 | return 0; | ||
261 | } | ||
262 | |||
263 | static void __init apx4devkit_init(void) | ||
264 | { | ||
265 | enable_clk_enet_out(); | ||
266 | |||
267 | if (IS_BUILTIN(CONFIG_PHYLIB)) | ||
268 | phy_register_fixup_for_uid(PHY_ID_KS8051, MICREL_PHY_ID_MASK, | ||
269 | apx4devkit_phy_fixup); | ||
270 | |||
271 | mxsfb_pdata.mode_list = apx4devkit_video_modes; | ||
272 | mxsfb_pdata.mode_count = ARRAY_SIZE(apx4devkit_video_modes); | ||
273 | mxsfb_pdata.default_bpp = 32; | ||
274 | mxsfb_pdata.ld_intf_width = STMLCDIF_24BIT; | ||
275 | } | ||
276 | |||
84 | static void __init mxs_machine_init(void) | 277 | static void __init mxs_machine_init(void) |
85 | { | 278 | { |
86 | if (of_machine_is_compatible("fsl,imx28-evk")) | 279 | if (of_machine_is_compatible("fsl,imx28-evk")) |
87 | imx28_evk_init(); | 280 | imx28_evk_init(); |
281 | else if (of_machine_is_compatible("fsl,imx23-evk")) | ||
282 | imx23_evk_init(); | ||
283 | else if (of_machine_is_compatible("denx,m28evk")) | ||
284 | m28evk_init(); | ||
285 | else if (of_machine_is_compatible("bluegiga,apx4devkit")) | ||
286 | apx4devkit_init(); | ||
88 | 287 | ||
89 | of_platform_populate(NULL, of_default_bus_match_table, | 288 | of_platform_populate(NULL, of_default_bus_match_table, |
90 | NULL, NULL); | 289 | mxs_auxdata_lookup, NULL); |
91 | } | 290 | } |
92 | 291 | ||
93 | static const char *imx23_dt_compat[] __initdata = { | 292 | static const char *imx23_dt_compat[] __initdata = { |
94 | "fsl,imx23-evk", | 293 | "fsl,imx23-evk", |
294 | "fsl,stmp378x_devb" | ||
295 | "olimex,imx23-olinuxino", | ||
95 | "fsl,imx23", | 296 | "fsl,imx23", |
96 | NULL, | 297 | NULL, |
97 | }; | 298 | }; |
98 | 299 | ||
99 | static const char *imx28_dt_compat[] __initdata = { | 300 | static const char *imx28_dt_compat[] __initdata = { |
301 | "bluegiga,apx4devkit", | ||
302 | "crystalfontz,cfa10036", | ||
303 | "denx,m28evk", | ||
100 | "fsl,imx28-evk", | 304 | "fsl,imx28-evk", |
305 | "karo,tx28", | ||
101 | "fsl,imx28", | 306 | "fsl,imx28", |
102 | NULL, | 307 | NULL, |
103 | }; | 308 | }; |