9aea158ba51441d0b2a26bc7b8f5fe3d9849392c
[firefly-linux-kernel-4.4.55.git] / arch / arm / mach-omap2 / board-apollon.c
1 /*
2  * linux/arch/arm/mach-omap2/board-apollon.c
3  *
4  * Copyright (C) 2005,2006 Samsung Electronics
5  * Author: Kyungmin Park <kyungmin.park@samsung.com>
6  *
7  * Modified from mach-omap/omap2/board-h4.c
8  *
9  * Code for apollon OMAP2 board. Should work on many OMAP2 systems where
10  * the bootloader passes the board-specific data to the kernel.
11  * Do not put any board specific code to this file; create a new machine
12  * type if you need custom low-level initializations.
13  *
14  * This program is free software; you can redistribute it and/or modify
15  * it under the terms of the GNU General Public License version 2 as
16  * published by the Free Software Foundation.
17  */
18
19 #include <linux/kernel.h>
20 #include <linux/init.h>
21 #include <linux/platform_device.h>
22 #include <linux/mtd/mtd.h>
23 #include <linux/mtd/partitions.h>
24 #include <linux/mtd/onenand.h>
25 #include <linux/delay.h>
26 #include <linux/leds.h>
27 #include <linux/err.h>
28 #include <linux/clk.h>
29 #include <linux/smc91x.h>
30 #include <linux/gpio.h>
31
32 #include <mach/hardware.h>
33 #include <asm/mach-types.h>
34 #include <asm/mach/arch.h>
35 #include <asm/mach/flash.h>
36
37 #include <plat/led.h>
38 #include <plat/usb.h>
39 #include <plat/board.h>
40 #include "common.h"
41 #include <plat/gpmc.h>
42
43 #include <video/omapdss.h>
44 #include <video/omap-panel-generic-dpi.h>
45
46 #include "mux.h"
47 #include "control.h"
48
49 /* LED & Switch macros */
50 #define LED0_GPIO13             13
51 #define LED1_GPIO14             14
52 #define LED2_GPIO15             15
53 #define SW_ENTER_GPIO16         16
54 #define SW_UP_GPIO17            17
55 #define SW_DOWN_GPIO58          58
56
57 #define APOLLON_FLASH_CS        0
58 #define APOLLON_ETH_CS          1
59 #define APOLLON_ETHR_GPIO_IRQ   74
60
61 static struct mtd_partition apollon_partitions[] = {
62         {
63                 .name           = "X-Loader + U-Boot",
64                 .offset         = 0,
65                 .size           = SZ_128K,
66                 .mask_flags     = MTD_WRITEABLE,
67         },
68         {
69                 .name           = "params",
70                 .offset         = MTDPART_OFS_APPEND,
71                 .size           = SZ_128K,
72         },
73         {
74                 .name           = "kernel",
75                 .offset         = MTDPART_OFS_APPEND,
76                 .size           = SZ_2M,
77         },
78         {
79                 .name           = "rootfs",
80                 .offset         = MTDPART_OFS_APPEND,
81                 .size           = SZ_16M,
82         },
83         {
84                 .name           = "filesystem00",
85                 .offset         = MTDPART_OFS_APPEND,
86                 .size           = SZ_32M,
87         },
88         {
89                 .name           = "filesystem01",
90                 .offset         = MTDPART_OFS_APPEND,
91                 .size           = MTDPART_SIZ_FULL,
92         },
93 };
94
95 static struct onenand_platform_data apollon_flash_data = {
96         .parts          = apollon_partitions,
97         .nr_parts       = ARRAY_SIZE(apollon_partitions),
98 };
99
100 static struct resource apollon_flash_resource[] = {
101         [0] = {
102                 .flags          = IORESOURCE_MEM,
103         },
104 };
105
106 static struct platform_device apollon_onenand_device = {
107         .name           = "onenand-flash",
108         .id             = -1,
109         .dev            = {
110                 .platform_data  = &apollon_flash_data,
111         },
112         .num_resources  = ARRAY_SIZE(apollon_flash_resource),
113         .resource       = apollon_flash_resource,
114 };
115
116 static void __init apollon_flash_init(void)
117 {
118         unsigned long base;
119
120         if (gpmc_cs_request(APOLLON_FLASH_CS, SZ_128K, &base) < 0) {
121                 printk(KERN_ERR "Cannot request OneNAND GPMC CS\n");
122                 return;
123         }
124         apollon_flash_resource[0].start = base;
125         apollon_flash_resource[0].end   = base + SZ_128K - 1;
126 }
127
128 static struct smc91x_platdata appolon_smc91x_info = {
129         .flags  = SMC91X_USE_16BIT | SMC91X_NOWAIT,
130         .leda   = RPC_LED_100_10,
131         .ledb   = RPC_LED_TX_RX,
132 };
133
134 static struct resource apollon_smc91x_resources[] = {
135         [0] = {
136                 .flags  = IORESOURCE_MEM,
137         },
138         [1] = {
139                 .start  = OMAP_GPIO_IRQ(APOLLON_ETHR_GPIO_IRQ),
140                 .end    = OMAP_GPIO_IRQ(APOLLON_ETHR_GPIO_IRQ),
141                 .flags  = IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHEDGE,
142         },
143 };
144
145 static struct platform_device apollon_smc91x_device = {
146         .name           = "smc91x",
147         .id             = -1,
148         .dev    = {
149                 .platform_data  = &appolon_smc91x_info,
150         },
151         .num_resources  = ARRAY_SIZE(apollon_smc91x_resources),
152         .resource       = apollon_smc91x_resources,
153 };
154
155 static struct omap_led_config apollon_led_config[] = {
156         {
157                 .cdev   = {
158                         .name   = "apollon:led0",
159                 },
160                 .gpio   = LED0_GPIO13,
161         },
162         {
163                 .cdev   = {
164                         .name   = "apollon:led1",
165                 },
166                 .gpio   = LED1_GPIO14,
167         },
168         {
169                 .cdev   = {
170                         .name   = "apollon:led2",
171                 },
172                 .gpio   = LED2_GPIO15,
173         },
174 };
175
176 static struct omap_led_platform_data apollon_led_data = {
177         .nr_leds        = ARRAY_SIZE(apollon_led_config),
178         .leds           = apollon_led_config,
179 };
180
181 static struct platform_device apollon_led_device = {
182         .name           = "omap-led",
183         .id             = -1,
184         .dev            = {
185                 .platform_data  = &apollon_led_data,
186         },
187 };
188
189 static struct platform_device *apollon_devices[] __initdata = {
190         &apollon_onenand_device,
191         &apollon_smc91x_device,
192         &apollon_led_device,
193 };
194
195 static inline void __init apollon_init_smc91x(void)
196 {
197         unsigned long base;
198
199         unsigned int rate;
200         struct clk *gpmc_fck;
201         int eth_cs;
202         int err;
203
204         gpmc_fck = clk_get(NULL, "gpmc_fck");   /* Always on ENABLE_ON_INIT */
205         if (IS_ERR(gpmc_fck)) {
206                 WARN_ON(1);
207                 return;
208         }
209
210         clk_enable(gpmc_fck);
211         rate = clk_get_rate(gpmc_fck);
212
213         eth_cs = APOLLON_ETH_CS;
214
215         /* Make sure CS1 timings are correct */
216         gpmc_cs_write_reg(eth_cs, GPMC_CS_CONFIG1, 0x00011200);
217
218         if (rate >= 160000000) {
219                 gpmc_cs_write_reg(eth_cs, GPMC_CS_CONFIG2, 0x001f1f01);
220                 gpmc_cs_write_reg(eth_cs, GPMC_CS_CONFIG3, 0x00080803);
221                 gpmc_cs_write_reg(eth_cs, GPMC_CS_CONFIG4, 0x1c0b1c0a);
222                 gpmc_cs_write_reg(eth_cs, GPMC_CS_CONFIG5, 0x041f1F1F);
223                 gpmc_cs_write_reg(eth_cs, GPMC_CS_CONFIG6, 0x000004C4);
224         } else if (rate >= 130000000) {
225                 gpmc_cs_write_reg(eth_cs, GPMC_CS_CONFIG2, 0x001f1f00);
226                 gpmc_cs_write_reg(eth_cs, GPMC_CS_CONFIG3, 0x00080802);
227                 gpmc_cs_write_reg(eth_cs, GPMC_CS_CONFIG4, 0x1C091C09);
228                 gpmc_cs_write_reg(eth_cs, GPMC_CS_CONFIG5, 0x041f1F1F);
229                 gpmc_cs_write_reg(eth_cs, GPMC_CS_CONFIG6, 0x000004C4);
230         } else {/* rate = 100000000 */
231                 gpmc_cs_write_reg(eth_cs, GPMC_CS_CONFIG2, 0x001f1f00);
232                 gpmc_cs_write_reg(eth_cs, GPMC_CS_CONFIG3, 0x00080802);
233                 gpmc_cs_write_reg(eth_cs, GPMC_CS_CONFIG4, 0x1C091C09);
234                 gpmc_cs_write_reg(eth_cs, GPMC_CS_CONFIG5, 0x031A1F1F);
235                 gpmc_cs_write_reg(eth_cs, GPMC_CS_CONFIG6, 0x000003C2);
236         }
237
238         if (gpmc_cs_request(APOLLON_ETH_CS, SZ_16M, &base) < 0) {
239                 printk(KERN_ERR "Failed to request GPMC CS for smc91x\n");
240                 goto out;
241         }
242         apollon_smc91x_resources[0].start = base + 0x300;
243         apollon_smc91x_resources[0].end   = base + 0x30f;
244         udelay(100);
245
246         omap_mux_init_gpio(APOLLON_ETHR_GPIO_IRQ, 0);
247         err = gpio_request_one(APOLLON_ETHR_GPIO_IRQ, GPIOF_IN, "SMC91x irq");
248         if (err) {
249                 printk(KERN_ERR "Failed to request GPIO%d for smc91x IRQ\n",
250                         APOLLON_ETHR_GPIO_IRQ);
251                 gpmc_cs_free(APOLLON_ETH_CS);
252         }
253 out:
254         clk_disable(gpmc_fck);
255         clk_put(gpmc_fck);
256 }
257
258 static struct omap_usb_config apollon_usb_config __initdata = {
259         .register_dev   = 1,
260         .hmc_mode       = 0x14, /* 0:dev 1:host1 2:disable */
261
262         .pins[0]        = 6,
263 };
264
265 static struct panel_generic_dpi_data apollon_panel_data = {
266         .name                   = "apollon",
267 };
268
269 static struct omap_dss_device apollon_lcd_device = {
270         .name                   = "lcd",
271         .driver_name            = "generic_dpi_panel",
272         .type                   = OMAP_DISPLAY_TYPE_DPI,
273         .phy.dpi.data_lines     = 18,
274         .data                   = &apollon_panel_data,
275 };
276
277 static struct omap_dss_device *apollon_dss_devices[] = {
278         &apollon_lcd_device,
279 };
280
281 static struct omap_dss_board_info apollon_dss_data = {
282         .num_devices    = ARRAY_SIZE(apollon_dss_devices),
283         .devices        = apollon_dss_devices,
284         .default_device = &apollon_lcd_device,
285 };
286
287 static struct gpio apollon_gpio_leds[] __initdata = {
288         { LED0_GPIO13, GPIOF_OUT_INIT_LOW, "LED0" }, /* LED0 - AA10 */
289         { LED1_GPIO14, GPIOF_OUT_INIT_LOW, "LED1" }, /* LED1 - AA6  */
290         { LED2_GPIO15, GPIOF_OUT_INIT_LOW, "LED2" }, /* LED2 - AA4  */
291 };
292
293 static void __init apollon_led_init(void)
294 {
295         omap_mux_init_signal("vlynq_clk.gpio_13", 0);
296         omap_mux_init_signal("vlynq_rx1.gpio_14", 0);
297         omap_mux_init_signal("vlynq_rx0.gpio_15", 0);
298
299         gpio_request_array(apollon_gpio_leds, ARRAY_SIZE(apollon_gpio_leds));
300 }
301
302 static void __init apollon_usb_init(void)
303 {
304         /* USB device */
305         /* DEVICE_SUSPEND */
306         omap_mux_init_signal("mcbsp2_clkx.gpio_12", 0);
307         gpio_request_one(12, GPIOF_OUT_INIT_LOW, "USB suspend");
308         omap2_usbfs_init(&apollon_usb_config);
309 }
310
311 #ifdef CONFIG_OMAP_MUX
312 static struct omap_board_mux board_mux[] __initdata = {
313         { .reg_offset = OMAP_MUX_TERMINATOR },
314 };
315 #endif
316
317 static void __init omap_apollon_init(void)
318 {
319         u32 v;
320
321         omap2420_mux_init(board_mux, OMAP_PACKAGE_ZAC);
322
323         apollon_init_smc91x();
324         apollon_led_init();
325         apollon_flash_init();
326         apollon_usb_init();
327
328         /* REVISIT: where's the correct place */
329         omap_mux_init_signal("sys_nirq", OMAP_PULL_ENA | OMAP_PULL_UP);
330
331         /* LCD PWR_EN */
332         omap_mux_init_signal("mcbsp2_dr.gpio_11", OMAP_PULL_ENA | OMAP_PULL_UP);
333
334         /* Use Interal loop-back in MMC/SDIO Module Input Clock selection */
335         v = omap_ctrl_readl(OMAP2_CONTROL_DEVCONF0);
336         v |= (1 << 24);
337         omap_ctrl_writel(v, OMAP2_CONTROL_DEVCONF0);
338
339         /*
340          * Make sure the serial ports are muxed on at this point.
341          * You have to mux them off in device drivers later on
342          * if not needed.
343          */
344         platform_add_devices(apollon_devices, ARRAY_SIZE(apollon_devices));
345         omap_serial_init();
346         omap_sdrc_init(NULL, NULL);
347         omap_display_init(&apollon_dss_data);
348 }
349
350 MACHINE_START(OMAP_APOLLON, "OMAP24xx Apollon")
351         /* Maintainer: Kyungmin Park <kyungmin.park@samsung.com> */
352         .atag_offset    = 0x100,
353         .reserve        = omap_reserve,
354         .map_io         = omap242x_map_io,
355         .init_early     = omap2420_init_early,
356         .init_irq       = omap2_init_irq,
357         .init_machine   = omap_apollon_init,
358         .timer          = &omap2_timer,
359 MACHINE_END