1/* 2 * linux/arch/arm/mach-realview/core.c 3 * 4 * Copyright (C) 1999 - 2003 ARM Limited 5 * Copyright (C) 2000 Deep Blue Solutions Ltd 6 * 7 * This program is free software; you can redistribute it and/or modify 8 * it under the terms of the GNU General Public License as published by 9 * the Free Software Foundation; either version 2 of the License, or 10 * (at your option) any later version. 11 * 12 * This program is distributed in the hope that it will be useful, 13 * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 * GNU General Public License for more details. 16 * 17 * You should have received a copy of the GNU General Public License 18 * along with this program; if not, write to the Free Software 19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 20 */ 21#include <linux/init.h> 22#include <linux/platform_device.h> 23#include <linux/dma-mapping.h> 24#include <linux/device.h> 25#include <linux/interrupt.h> 26#include <linux/amba/bus.h> 27#include <linux/amba/clcd.h> 28#include <linux/platform_data/video-clcd-versatile.h> 29#include <linux/io.h> 30#include <linux/smsc911x.h> 31#include <linux/smc91x.h> 32#include <linux/ata_platform.h> 33#include <linux/amba/mmci.h> 34#include <linux/gfp.h> 35#include <linux/mtd/physmap.h> 36#include <linux/memblock.h> 37 38#include <mach/hardware.h> 39#include <asm/irq.h> 40#include <asm/mach-types.h> 41#include <asm/hardware/arm_timer.h> 42#include <asm/hardware/icst.h> 43 44#include <asm/mach/arch.h> 45#include <asm/mach/irq.h> 46#include <asm/mach/map.h> 47 48 49#include <mach/platform.h> 50#include <mach/irqs.h> 51#include <asm/hardware/timer-sp.h> 52 53#include <plat/sched_clock.h> 54 55#include "core.h" 56 57#define REALVIEW_FLASHCTRL (__io_address(REALVIEW_SYS_BASE) + REALVIEW_SYS_FLASH_OFFSET) 58 59static void realview_flash_set_vpp(struct platform_device *pdev, int on) 60{ 61 u32 val; 62 63 val = __raw_readl(REALVIEW_FLASHCTRL); 64 if (on) 65 val |= REALVIEW_FLASHPROG_FLVPPEN; 66 else 67 val &= ~REALVIEW_FLASHPROG_FLVPPEN; 68 __raw_writel(val, REALVIEW_FLASHCTRL); 69} 70 71static struct physmap_flash_data realview_flash_data = { 72 .width = 4, 73 .set_vpp = realview_flash_set_vpp, 74}; 75 76struct platform_device realview_flash_device = { 77 .name = "physmap-flash", 78 .id = 0, 79 .dev = { 80 .platform_data = &realview_flash_data, 81 }, 82}; 83 84int realview_flash_register(struct resource *res, u32 num) 85{ 86 realview_flash_device.resource = res; 87 realview_flash_device.num_resources = num; 88 return platform_device_register(&realview_flash_device); 89} 90 91static struct smsc911x_platform_config smsc911x_config = { 92 .flags = SMSC911X_USE_32BIT, 93 .irq_polarity = SMSC911X_IRQ_POLARITY_ACTIVE_HIGH, 94 .irq_type = SMSC911X_IRQ_TYPE_PUSH_PULL, 95 .phy_interface = PHY_INTERFACE_MODE_MII, 96}; 97 98static struct smc91x_platdata smc91x_platdata = { 99 .flags = SMC91X_USE_32BIT | SMC91X_NOWAIT, 100}; 101 102static struct platform_device realview_eth_device = { 103 .name = "smsc911x", 104 .id = 0, 105 .num_resources = 2, 106}; 107 108int realview_eth_register(const char *name, struct resource *res) 109{ 110 if (name) 111 realview_eth_device.name = name; 112 realview_eth_device.resource = res; 113 if (strcmp(realview_eth_device.name, "smsc911x") == 0) 114 realview_eth_device.dev.platform_data = &smsc911x_config; 115 else 116 realview_eth_device.dev.platform_data = &smc91x_platdata; 117 118 return platform_device_register(&realview_eth_device); 119} 120 121struct platform_device realview_usb_device = { 122 .name = "isp1760", 123 .num_resources = 2, 124}; 125 126int realview_usb_register(struct resource *res) 127{ 128 realview_usb_device.resource = res; 129 return platform_device_register(&realview_usb_device); 130} 131 132static struct pata_platform_info pata_platform_data = { 133 .ioport_shift = 1, 134}; 135 136static struct resource pata_resources[] = { 137 [0] = { 138 .start = REALVIEW_CF_BASE, 139 .end = REALVIEW_CF_BASE + 0xff, 140 .flags = IORESOURCE_MEM, 141 }, 142 [1] = { 143 .start = REALVIEW_CF_BASE + 0x100, 144 .end = REALVIEW_CF_BASE + SZ_4K - 1, 145 .flags = IORESOURCE_MEM, 146 }, 147}; 148 149struct platform_device realview_cf_device = { 150 .name = "pata_platform", 151 .id = -1, 152 .num_resources = ARRAY_SIZE(pata_resources), 153 .resource = pata_resources, 154 .dev = { 155 .platform_data = &pata_platform_data, 156 }, 157}; 158 159static struct resource realview_leds_resources[] = { 160 { 161 .start = REALVIEW_SYS_BASE + REALVIEW_SYS_LED_OFFSET, 162 .end = REALVIEW_SYS_BASE + REALVIEW_SYS_LED_OFFSET + 4, 163 .flags = IORESOURCE_MEM, 164 }, 165}; 166 167struct platform_device realview_leds_device = { 168 .name = "versatile-leds", 169 .id = -1, 170 .num_resources = ARRAY_SIZE(realview_leds_resources), 171 .resource = realview_leds_resources, 172}; 173 174static struct resource realview_i2c_resource = { 175 .start = REALVIEW_I2C_BASE, 176 .end = REALVIEW_I2C_BASE + SZ_4K - 1, 177 .flags = IORESOURCE_MEM, 178}; 179 180struct platform_device realview_i2c_device = { 181 .name = "versatile-i2c", 182 .id = 0, 183 .num_resources = 1, 184 .resource = &realview_i2c_resource, 185}; 186 187static struct i2c_board_info realview_i2c_board_info[] = { 188 { 189 I2C_BOARD_INFO("ds1338", 0xd0 >> 1), 190 }, 191}; 192 193static int __init realview_i2c_init(void) 194{ 195 return i2c_register_board_info(0, realview_i2c_board_info, 196 ARRAY_SIZE(realview_i2c_board_info)); 197} 198arch_initcall(realview_i2c_init); 199 200#define REALVIEW_SYSMCI (__io_address(REALVIEW_SYS_BASE) + REALVIEW_SYS_MCI_OFFSET) 201 202/* 203 * This is only used if GPIOLIB support is disabled 204 */ 205static unsigned int realview_mmc_status(struct device *dev) 206{ 207 struct amba_device *adev = container_of(dev, struct amba_device, dev); 208 u32 mask; 209 210 if (machine_is_realview_pb1176()) { 211 static bool inserted = false; 212 213 /* 214 * The PB1176 does not have the status register, 215 * assume it is inserted at startup, then invert 216 * for each call so card insertion/removal will 217 * be detected anyway. This will not be called if 218 * GPIO on PL061 is active, which is the proper 219 * way to do this on the PB1176. 220 */ 221 inserted = !inserted; 222 return inserted ? 0 : 1; 223 } 224 225 if (adev->res.start == REALVIEW_MMCI0_BASE) 226 mask = 1; 227 else 228 mask = 2; 229 230 return readl(REALVIEW_SYSMCI) & mask; 231} 232 233struct mmci_platform_data realview_mmc0_plat_data = { 234 .ocr_mask = MMC_VDD_32_33|MMC_VDD_33_34, 235 .status = realview_mmc_status, 236 .gpio_wp = 17, 237 .gpio_cd = 16, 238 .cd_invert = true, 239}; 240 241struct mmci_platform_data realview_mmc1_plat_data = { 242 .ocr_mask = MMC_VDD_32_33|MMC_VDD_33_34, 243 .status = realview_mmc_status, 244 .gpio_wp = 19, 245 .gpio_cd = 18, 246 .cd_invert = true, 247}; 248 249void __init realview_init_early(void) 250{ 251 void __iomem *sys = __io_address(REALVIEW_SYS_BASE); 252 253 versatile_sched_clock_init(sys + REALVIEW_SYS_24MHz_OFFSET, 24000000); 254} 255 256/* 257 * CLCD support. 258 */ 259#define SYS_CLCD_NLCDIOON (1 << 2) 260#define SYS_CLCD_VDDPOSSWITCH (1 << 3) 261#define SYS_CLCD_PWR3V5SWITCH (1 << 4) 262#define SYS_CLCD_ID_MASK (0x1f << 8) 263#define SYS_CLCD_ID_SANYO_3_8 (0x00 << 8) 264#define SYS_CLCD_ID_UNKNOWN_8_4 (0x01 << 8) 265#define SYS_CLCD_ID_EPSON_2_2 (0x02 << 8) 266#define SYS_CLCD_ID_SANYO_2_5 (0x07 << 8) 267#define SYS_CLCD_ID_VGA (0x1f << 8) 268 269/* 270 * Disable all display connectors on the interface module. 271 */ 272static void realview_clcd_disable(struct clcd_fb *fb) 273{ 274 void __iomem *sys_clcd = __io_address(REALVIEW_SYS_BASE) + REALVIEW_SYS_CLCD_OFFSET; 275 u32 val; 276 277 val = readl(sys_clcd); 278 val &= ~SYS_CLCD_NLCDIOON | SYS_CLCD_PWR3V5SWITCH; 279 writel(val, sys_clcd); 280} 281 282/* 283 * Enable the relevant connector on the interface module. 284 */ 285static void realview_clcd_enable(struct clcd_fb *fb) 286{ 287 void __iomem *sys_clcd = __io_address(REALVIEW_SYS_BASE) + REALVIEW_SYS_CLCD_OFFSET; 288 u32 val; 289 290 /* 291 * Enable the PSUs 292 */ 293 val = readl(sys_clcd); 294 val |= SYS_CLCD_NLCDIOON | SYS_CLCD_PWR3V5SWITCH; 295 writel(val, sys_clcd); 296} 297 298/* 299 * Detect which LCD panel is connected, and return the appropriate 300 * clcd_panel structure. Note: we do not have any information on 301 * the required timings for the 8.4in panel, so we presently assume 302 * VGA timings. 303 */ 304static int realview_clcd_setup(struct clcd_fb *fb) 305{ 306 void __iomem *sys_clcd = __io_address(REALVIEW_SYS_BASE) + REALVIEW_SYS_CLCD_OFFSET; 307 const char *panel_name, *vga_panel_name; 308 unsigned long framesize; 309 u32 val; 310 311 if (machine_is_realview_eb()) { 312 /* VGA, 16bpp */ 313 framesize = 640 * 480 * 2; 314 vga_panel_name = "VGA"; 315 } else { 316 /* XVGA, 16bpp */ 317 framesize = 1024 * 768 * 2; 318 vga_panel_name = "XVGA"; 319 } 320 321 val = readl(sys_clcd) & SYS_CLCD_ID_MASK; 322 if (val == SYS_CLCD_ID_SANYO_3_8) 323 panel_name = "Sanyo TM38QV67A02A"; 324 else if (val == SYS_CLCD_ID_SANYO_2_5) 325 panel_name = "Sanyo QVGA Portrait"; 326 else if (val == SYS_CLCD_ID_EPSON_2_2) 327 panel_name = "Epson L2F50113T00"; 328 else if (val == SYS_CLCD_ID_VGA) 329 panel_name = vga_panel_name; 330 else { 331 pr_err("CLCD: unknown LCD panel ID 0x%08x, using VGA\n", val); 332 panel_name = vga_panel_name; 333 } 334 335 fb->panel = versatile_clcd_get_panel(panel_name); 336 if (!fb->panel) 337 return -EINVAL; 338 339 return versatile_clcd_setup_dma(fb, framesize); 340} 341 342struct clcd_board clcd_plat_data = { 343 .name = "RealView", 344 .caps = CLCD_CAP_ALL, 345 .check = clcdfb_check, 346 .decode = clcdfb_decode, 347 .disable = realview_clcd_disable, 348 .enable = realview_clcd_enable, 349 .setup = realview_clcd_setup, 350 .mmap = versatile_clcd_mmap_dma, 351 .remove = versatile_clcd_remove_dma, 352}; 353 354/* 355 * Where is the timer (VA)? 356 */ 357void __iomem *timer0_va_base; 358void __iomem *timer1_va_base; 359void __iomem *timer2_va_base; 360void __iomem *timer3_va_base; 361 362/* 363 * Set up the clock source and clock events devices 364 */ 365void __init realview_timer_init(unsigned int timer_irq) 366{ 367 u32 val; 368 369 /* 370 * set clock frequency: 371 * REALVIEW_REFCLK is 32KHz 372 * REALVIEW_TIMCLK is 1MHz 373 */ 374 val = readl(__io_address(REALVIEW_SCTL_BASE)); 375 writel((REALVIEW_TIMCLK << REALVIEW_TIMER1_EnSel) | 376 (REALVIEW_TIMCLK << REALVIEW_TIMER2_EnSel) | 377 (REALVIEW_TIMCLK << REALVIEW_TIMER3_EnSel) | 378 (REALVIEW_TIMCLK << REALVIEW_TIMER4_EnSel) | val, 379 __io_address(REALVIEW_SCTL_BASE)); 380 381 /* 382 * Initialise to a known state (all timers off) 383 */ 384 writel(0, timer0_va_base + TIMER_CTRL); 385 writel(0, timer1_va_base + TIMER_CTRL); 386 writel(0, timer2_va_base + TIMER_CTRL); 387 writel(0, timer3_va_base + TIMER_CTRL); 388 389 sp804_clocksource_init(timer3_va_base, "timer3"); 390 sp804_clockevents_init(timer0_va_base, timer_irq, "timer0"); 391} 392 393/* 394 * Setup the memory banks. 395 */ 396void realview_fixup(struct tag *tags, char **from) 397{ 398 /* 399 * Most RealView platforms have 512MB contiguous RAM at 0x70000000. 400 * Half of this is mirrored at 0. 401 */ 402#ifdef CONFIG_REALVIEW_HIGH_PHYS_OFFSET 403 memblock_add(0x70000000, SZ_512M); 404#else 405 memblock_add(0, SZ_256M); 406#endif 407} 408