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 31#include <mach/hardware.h> 32#include <asm/mach-types.h> 33#include <asm/mach/arch.h> 34#include <asm/mach/flash.h> 35 36#include <mach/gpio.h> 37#include <plat/led.h> 38#include <plat/usb.h> 39#include <plat/board.h> 40#include <plat/common.h> 41#include <plat/gpmc.h> 42#include <plat/control.h> 43 44#include "mux.h" 45 46/* LED & Switch macros */ 47#define LED0_GPIO13 13 48#define LED1_GPIO14 14 49#define LED2_GPIO15 15 50#define SW_ENTER_GPIO16 16 51#define SW_UP_GPIO17 17 52#define SW_DOWN_GPIO58 58 53 54#define APOLLON_FLASH_CS 0 55#define APOLLON_ETH_CS 1 56#define APOLLON_ETHR_GPIO_IRQ 74 57 58static struct mtd_partition apollon_partitions[] = { 59 { 60 .name = "X-Loader + U-Boot", 61 .offset = 0, 62 .size = SZ_128K, 63 .mask_flags = MTD_WRITEABLE, 64 }, 65 { 66 .name = "params", 67 .offset = MTDPART_OFS_APPEND, 68 .size = SZ_128K, 69 }, 70 { 71 .name = "kernel", 72 .offset = MTDPART_OFS_APPEND, 73 .size = SZ_2M, 74 }, 75 { 76 .name = "rootfs", 77 .offset = MTDPART_OFS_APPEND, 78 .size = SZ_16M, 79 }, 80 { 81 .name = "filesystem00", 82 .offset = MTDPART_OFS_APPEND, 83 .size = SZ_32M, 84 }, 85 { 86 .name = "filesystem01", 87 .offset = MTDPART_OFS_APPEND, 88 .size = MTDPART_SIZ_FULL, 89 }, 90}; 91 92static struct onenand_platform_data apollon_flash_data = { 93 .parts = apollon_partitions, 94 .nr_parts = ARRAY_SIZE(apollon_partitions), 95}; 96 97static struct resource apollon_flash_resource[] = { 98 [0] = { 99 .flags = IORESOURCE_MEM, 100 }, 101}; 102 103static struct platform_device apollon_onenand_device = { 104 .name = "onenand-flash", 105 .id = -1, 106 .dev = { 107 .platform_data = &apollon_flash_data, 108 }, 109 .num_resources = ARRAY_SIZE(apollon_flash_resource), 110 .resource = apollon_flash_resource, 111}; 112 113static void __init apollon_flash_init(void) 114{ 115 unsigned long base; 116 117 if (gpmc_cs_request(APOLLON_FLASH_CS, SZ_128K, &base) < 0) { 118 printk(KERN_ERR "Cannot request OneNAND GPMC CS\n"); 119 return; 120 } 121 apollon_flash_resource[0].start = base; 122 apollon_flash_resource[0].end = base + SZ_128K - 1; 123} 124 125static struct smc91x_platdata appolon_smc91x_info = { 126 .flags = SMC91X_USE_16BIT | SMC91X_NOWAIT, 127 .leda = RPC_LED_100_10, 128 .ledb = RPC_LED_TX_RX, 129}; 130 131static struct resource apollon_smc91x_resources[] = { 132 [0] = { 133 .flags = IORESOURCE_MEM, 134 }, 135 [1] = { 136 .start = OMAP_GPIO_IRQ(APOLLON_ETHR_GPIO_IRQ), 137 .end = OMAP_GPIO_IRQ(APOLLON_ETHR_GPIO_IRQ), 138 .flags = IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHEDGE, 139 }, 140}; 141 142static struct platform_device apollon_smc91x_device = { 143 .name = "smc91x", 144 .id = -1, 145 .dev = { 146 .platform_data = &appolon_smc91x_info, 147 }, 148 .num_resources = ARRAY_SIZE(apollon_smc91x_resources), 149 .resource = apollon_smc91x_resources, 150}; 151 152static struct platform_device apollon_lcd_device = { 153 .name = "apollon_lcd", 154 .id = -1, 155}; 156 157static struct omap_led_config apollon_led_config[] = { 158 { 159 .cdev = { 160 .name = "apollon:led0", 161 }, 162 .gpio = LED0_GPIO13, 163 }, 164 { 165 .cdev = { 166 .name = "apollon:led1", 167 }, 168 .gpio = LED1_GPIO14, 169 }, 170 { 171 .cdev = { 172 .name = "apollon:led2", 173 }, 174 .gpio = LED2_GPIO15, 175 }, 176}; 177 178static struct omap_led_platform_data apollon_led_data = { 179 .nr_leds = ARRAY_SIZE(apollon_led_config), 180 .leds = apollon_led_config, 181}; 182 183static struct platform_device apollon_led_device = { 184 .name = "omap-led", 185 .id = -1, 186 .dev = { 187 .platform_data = &apollon_led_data, 188 }, 189}; 190 191static struct platform_device *apollon_devices[] __initdata = { 192 &apollon_onenand_device, 193 &apollon_smc91x_device, 194 &apollon_lcd_device, 195 &apollon_led_device, 196}; 197 198static inline void __init apollon_init_smc91x(void) 199{ 200 unsigned long base; 201 202 unsigned int rate; 203 struct clk *gpmc_fck; 204 int eth_cs; 205 206 gpmc_fck = clk_get(NULL, "gpmc_fck"); /* Always on ENABLE_ON_INIT */ 207 if (IS_ERR(gpmc_fck)) { 208 WARN_ON(1); 209 return; 210 } 211 212 clk_enable(gpmc_fck); 213 rate = clk_get_rate(gpmc_fck); 214 215 eth_cs = APOLLON_ETH_CS; 216 217 /* Make sure CS1 timings are correct */ 218 gpmc_cs_write_reg(eth_cs, GPMC_CS_CONFIG1, 0x00011200); 219 220 if (rate >= 160000000) { 221 gpmc_cs_write_reg(eth_cs, GPMC_CS_CONFIG2, 0x001f1f01); 222 gpmc_cs_write_reg(eth_cs, GPMC_CS_CONFIG3, 0x00080803); 223 gpmc_cs_write_reg(eth_cs, GPMC_CS_CONFIG4, 0x1c0b1c0a); 224 gpmc_cs_write_reg(eth_cs, GPMC_CS_CONFIG5, 0x041f1F1F); 225 gpmc_cs_write_reg(eth_cs, GPMC_CS_CONFIG6, 0x000004C4); 226 } else if (rate >= 130000000) { 227 gpmc_cs_write_reg(eth_cs, GPMC_CS_CONFIG2, 0x001f1f00); 228 gpmc_cs_write_reg(eth_cs, GPMC_CS_CONFIG3, 0x00080802); 229 gpmc_cs_write_reg(eth_cs, GPMC_CS_CONFIG4, 0x1C091C09); 230 gpmc_cs_write_reg(eth_cs, GPMC_CS_CONFIG5, 0x041f1F1F); 231 gpmc_cs_write_reg(eth_cs, GPMC_CS_CONFIG6, 0x000004C4); 232 } else {/* rate = 100000000 */ 233 gpmc_cs_write_reg(eth_cs, GPMC_CS_CONFIG2, 0x001f1f00); 234 gpmc_cs_write_reg(eth_cs, GPMC_CS_CONFIG3, 0x00080802); 235 gpmc_cs_write_reg(eth_cs, GPMC_CS_CONFIG4, 0x1C091C09); 236 gpmc_cs_write_reg(eth_cs, GPMC_CS_CONFIG5, 0x031A1F1F); 237 gpmc_cs_write_reg(eth_cs, GPMC_CS_CONFIG6, 0x000003C2); 238 } 239 240 if (gpmc_cs_request(APOLLON_ETH_CS, SZ_16M, &base) < 0) { 241 printk(KERN_ERR "Failed to request GPMC CS for smc91x\n"); 242 goto out; 243 } 244 apollon_smc91x_resources[0].start = base + 0x300; 245 apollon_smc91x_resources[0].end = base + 0x30f; 246 udelay(100); 247 248 omap_mux_init_gpio(74, 0); 249 if (gpio_request(APOLLON_ETHR_GPIO_IRQ, "SMC91x irq") < 0) { 250 printk(KERN_ERR "Failed to request GPIO%d for smc91x IRQ\n", 251 APOLLON_ETHR_GPIO_IRQ); 252 gpmc_cs_free(APOLLON_ETH_CS); 253 goto out; 254 } 255 gpio_direction_input(APOLLON_ETHR_GPIO_IRQ); 256 257out: 258 clk_disable(gpmc_fck); 259 clk_put(gpmc_fck); 260} 261 262static struct omap_usb_config apollon_usb_config __initdata = { 263 .register_dev = 1, 264 .hmc_mode = 0x14, /* 0:dev 1:host1 2:disable */ 265 266 .pins[0] = 6, 267}; 268 269static struct omap_lcd_config apollon_lcd_config __initdata = { 270 .ctrl_name = "internal", 271}; 272 273static struct omap_board_config_kernel apollon_config[] = { 274 { OMAP_TAG_LCD, &apollon_lcd_config }, 275}; 276 277static void __init omap_apollon_init_irq(void) 278{ 279 omap_board_config = apollon_config; 280 omap_board_config_size = ARRAY_SIZE(apollon_config); 281 omap2_init_common_hw(NULL, NULL); 282 omap_init_irq(); 283 omap_gpio_init(); 284 apollon_init_smc91x(); 285} 286 287static void __init apollon_led_init(void) 288{ 289 /* LED0 - AA10 */ 290 omap_mux_init_signal("vlynq_clk.gpio_13", 0); 291 gpio_request(LED0_GPIO13, "LED0"); 292 gpio_direction_output(LED0_GPIO13, 0); 293 /* LED1 - AA6 */ 294 omap_mux_init_signal("vlynq_rx1.gpio_14", 0); 295 gpio_request(LED1_GPIO14, "LED1"); 296 gpio_direction_output(LED1_GPIO14, 0); 297 /* LED2 - AA4 */ 298 omap_mux_init_signal("vlynq_rx0.gpio_15", 0); 299 gpio_request(LED2_GPIO15, "LED2"); 300 gpio_direction_output(LED2_GPIO15, 0); 301} 302 303static void __init apollon_usb_init(void) 304{ 305 /* USB device */ 306 /* DEVICE_SUSPEND */ 307 omap_mux_init_signal("mcbsp2_clkx.gpio_12", 0); 308 gpio_request(12, "USB suspend"); 309 gpio_direction_output(12, 0); 310 omap2_usbfs_init(&apollon_usb_config); 311} 312 313#ifdef CONFIG_OMAP_MUX 314static struct omap_board_mux board_mux[] __initdata = { 315 { .reg_offset = OMAP_MUX_TERMINATOR }, 316}; 317#else 318#define board_mux NULL 319#endif 320 321static void __init omap_apollon_init(void) 322{ 323 u32 v; 324 325 omap2420_mux_init(board_mux, OMAP_PACKAGE_ZAC); 326 327 apollon_led_init(); 328 apollon_flash_init(); 329 apollon_usb_init(); 330 331 /* REVISIT: where's the correct place */ 332 omap_mux_init_signal("sys_nirq", OMAP_PULL_ENA | OMAP_PULL_UP); 333 334 /* LCD PWR_EN */ 335 omap_mux_init_signal("mcbsp2_dr.gpio_11", OMAP_PULL_ENA | OMAP_PULL_UP); 336 337 /* Use Interal loop-back in MMC/SDIO Module Input Clock selection */ 338 v = omap_ctrl_readl(OMAP2_CONTROL_DEVCONF0); 339 v |= (1 << 24); 340 omap_ctrl_writel(v, OMAP2_CONTROL_DEVCONF0); 341 342 /* 343 * Make sure the serial ports are muxed on at this point. 344 * You have to mux them off in device drivers later on 345 * if not needed. 346 */ 347 platform_add_devices(apollon_devices, ARRAY_SIZE(apollon_devices)); 348 omap_serial_init(); 349} 350 351static void __init omap_apollon_map_io(void) 352{ 353 omap2_set_globals_242x(); 354 omap242x_map_common_io(); 355} 356 357MACHINE_START(OMAP_APOLLON, "OMAP24xx Apollon") 358 /* Maintainer: Kyungmin Park <kyungmin.park@samsung.com> */ 359 .phys_io = 0x48000000, 360 .io_pg_offst = ((0xfa000000) >> 18) & 0xfffc, 361 .boot_params = 0x80000100, 362 .map_io = omap_apollon_map_io, 363 .reserve = omap_reserve, 364 .init_irq = omap_apollon_init_irq, 365 .init_machine = omap_apollon_init, 366 .timer = &omap_timer, 367MACHINE_END 368