1/* 2 * linux/arch/arm/mach-sa1100/simpad.c 3 */ 4 5#include <linux/module.h> 6#include <linux/init.h> 7#include <linux/kernel.h> 8#include <linux/tty.h> 9#include <linux/proc_fs.h> 10#include <linux/string.h> 11#include <linux/pm.h> 12#include <linux/platform_data/sa11x0-serial.h> 13#include <linux/platform_device.h> 14#include <linux/mfd/ucb1x00.h> 15#include <linux/mtd/mtd.h> 16#include <linux/mtd/partitions.h> 17#include <linux/io.h> 18#include <linux/gpio.h> 19 20#include <mach/hardware.h> 21#include <asm/setup.h> 22#include <asm/irq.h> 23 24#include <asm/mach-types.h> 25#include <asm/mach/arch.h> 26#include <asm/mach/flash.h> 27#include <asm/mach/map.h> 28#include <linux/platform_data/mfd-mcp-sa11x0.h> 29#include <mach/simpad.h> 30#include <mach/irqs.h> 31 32#include <linux/serial_core.h> 33#include <linux/ioport.h> 34#include <linux/input.h> 35#include <linux/gpio_keys.h> 36#include <linux/leds.h> 37#include <linux/i2c-gpio.h> 38 39#include "generic.h" 40 41/* 42 * CS3 support 43 */ 44 45static long cs3_shadow; 46static spinlock_t cs3_lock; 47static struct gpio_chip cs3_gpio; 48 49long simpad_get_cs3_ro(void) 50{ 51 return readl(CS3_BASE); 52} 53EXPORT_SYMBOL(simpad_get_cs3_ro); 54 55long simpad_get_cs3_shadow(void) 56{ 57 return cs3_shadow; 58} 59EXPORT_SYMBOL(simpad_get_cs3_shadow); 60 61static void __simpad_write_cs3(void) 62{ 63 writel(cs3_shadow, CS3_BASE); 64} 65 66void simpad_set_cs3_bit(int value) 67{ 68 unsigned long flags; 69 70 spin_lock_irqsave(&cs3_lock, flags); 71 cs3_shadow |= value; 72 __simpad_write_cs3(); 73 spin_unlock_irqrestore(&cs3_lock, flags); 74} 75EXPORT_SYMBOL(simpad_set_cs3_bit); 76 77void simpad_clear_cs3_bit(int value) 78{ 79 unsigned long flags; 80 81 spin_lock_irqsave(&cs3_lock, flags); 82 cs3_shadow &= ~value; 83 __simpad_write_cs3(); 84 spin_unlock_irqrestore(&cs3_lock, flags); 85} 86EXPORT_SYMBOL(simpad_clear_cs3_bit); 87 88static void cs3_gpio_set(struct gpio_chip *chip, unsigned offset, int value) 89{ 90 if (offset > 15) 91 return; 92 if (value) 93 simpad_set_cs3_bit(1 << offset); 94 else 95 simpad_clear_cs3_bit(1 << offset); 96}; 97 98static int cs3_gpio_get(struct gpio_chip *chip, unsigned offset) 99{ 100 if (offset > 15) 101 return simpad_get_cs3_ro() & (1 << (offset - 16)); 102 return simpad_get_cs3_shadow() & (1 << offset); 103}; 104 105static int cs3_gpio_direction_input(struct gpio_chip *chip, unsigned offset) 106{ 107 if (offset > 15) 108 return 0; 109 return -EINVAL; 110}; 111 112static int cs3_gpio_direction_output(struct gpio_chip *chip, unsigned offset, 113 int value) 114{ 115 if (offset > 15) 116 return -EINVAL; 117 cs3_gpio_set(chip, offset, value); 118 return 0; 119}; 120 121static struct map_desc simpad_io_desc[] __initdata = { 122 { /* MQ200 */ 123 .virtual = 0xf2800000, 124 .pfn = __phys_to_pfn(0x4b800000), 125 .length = 0x00800000, 126 .type = MT_DEVICE 127 }, { /* Simpad CS3 */ 128 .virtual = (unsigned long)CS3_BASE, 129 .pfn = __phys_to_pfn(SA1100_CS3_PHYS), 130 .length = 0x00100000, 131 .type = MT_DEVICE 132 }, 133}; 134 135 136static void simpad_uart_pm(struct uart_port *port, u_int state, u_int oldstate) 137{ 138 if (port->mapbase == (u_int)&Ser1UTCR0) { 139 if (state) 140 { 141 simpad_clear_cs3_bit(RS232_ON); 142 simpad_clear_cs3_bit(DECT_POWER_ON); 143 }else 144 { 145 simpad_set_cs3_bit(RS232_ON); 146 simpad_set_cs3_bit(DECT_POWER_ON); 147 } 148 } 149} 150 151static struct sa1100_port_fns simpad_port_fns __initdata = { 152 .pm = simpad_uart_pm, 153}; 154 155 156static struct mtd_partition simpad_partitions[] = { 157 { 158 .name = "SIMpad boot firmware", 159 .size = 0x00080000, 160 .offset = 0, 161 .mask_flags = MTD_WRITEABLE, 162 }, { 163 .name = "SIMpad kernel", 164 .size = 0x0010000, 165 .offset = MTDPART_OFS_APPEND, 166 }, { 167 .name = "SIMpad root jffs2", 168 .size = MTDPART_SIZ_FULL, 169 .offset = MTDPART_OFS_APPEND, 170 } 171}; 172 173static struct flash_platform_data simpad_flash_data = { 174 .map_name = "cfi_probe", 175 .parts = simpad_partitions, 176 .nr_parts = ARRAY_SIZE(simpad_partitions), 177}; 178 179 180static struct resource simpad_flash_resources [] = { 181 DEFINE_RES_MEM(SA1100_CS0_PHYS, SZ_16M), 182 DEFINE_RES_MEM(SA1100_CS1_PHYS, SZ_16M), 183}; 184 185static struct ucb1x00_plat_data simpad_ucb1x00_data = { 186 .gpio_base = SIMPAD_UCB1X00_GPIO_BASE, 187}; 188 189static struct mcp_plat_data simpad_mcp_data = { 190 .mccr0 = MCCR0_ADM, 191 .sclk_rate = 11981000, 192 .codec_pdata = &simpad_ucb1x00_data, 193}; 194 195 196 197static void __init simpad_map_io(void) 198{ 199 sa1100_map_io(); 200 201 iotable_init(simpad_io_desc, ARRAY_SIZE(simpad_io_desc)); 202 203 /* Initialize CS3 */ 204 cs3_shadow = (EN1 | EN0 | LED2_ON | DISPLAY_ON | 205 RS232_ON | ENABLE_5V | RESET_SIMCARD | DECT_POWER_ON); 206 __simpad_write_cs3(); /* Spinlocks not yet initialized */ 207 208 sa1100_register_uart_fns(&simpad_port_fns); 209 sa1100_register_uart(0, 3); /* serial interface */ 210 sa1100_register_uart(1, 1); /* DECT */ 211 212 // Reassign UART 1 pins 213 GAFR |= GPIO_UART_TXD | GPIO_UART_RXD; 214 GPDR |= GPIO_UART_TXD | GPIO_LDD13 | GPIO_LDD15; 215 GPDR &= ~GPIO_UART_RXD; 216 PPAR |= PPAR_UPR; 217 218 /* 219 * Set up registers for sleep mode. 220 */ 221 222 223 PWER = PWER_GPIO0| PWER_RTC; 224 PGSR = 0x818; 225 PCFR = 0; 226 PSDR = 0; 227 228} 229 230static void simpad_power_off(void) 231{ 232 local_irq_disable(); 233 cs3_shadow = SD_MEDIAQ; 234 __simpad_write_cs3(); /* Bypass spinlock here */ 235 236 /* disable internal oscillator, float CS lines */ 237 PCFR = (PCFR_OPDE | PCFR_FP | PCFR_FS); 238 /* enable wake-up on GPIO0 */ 239 PWER = GFER = GRER = PWER_GPIO0; 240 /* 241 * set scratchpad to zero, just in case it is used as a 242 * restart address by the bootloader. 243 */ 244 PSPR = 0; 245 PGSR = 0; 246 /* enter sleep mode */ 247 PMCR = PMCR_SF; 248 while(1); 249 250 local_irq_enable(); /* we won't ever call it */ 251 252 253} 254 255/* 256 * gpio_keys 257*/ 258 259static struct gpio_keys_button simpad_button_table[] = { 260 { KEY_POWER, IRQ_GPIO_POWER_BUTTON, 1, "power button" }, 261}; 262 263static struct gpio_keys_platform_data simpad_keys_data = { 264 .buttons = simpad_button_table, 265 .nbuttons = ARRAY_SIZE(simpad_button_table), 266}; 267 268static struct platform_device simpad_keys = { 269 .name = "gpio-keys", 270 .dev = { 271 .platform_data = &simpad_keys_data, 272 }, 273}; 274 275static struct gpio_keys_button simpad_polled_button_table[] = { 276 { KEY_PROG1, SIMPAD_UCB1X00_GPIO_PROG1, 1, "prog1 button" }, 277 { KEY_PROG2, SIMPAD_UCB1X00_GPIO_PROG2, 1, "prog2 button" }, 278 { KEY_UP, SIMPAD_UCB1X00_GPIO_UP, 1, "up button" }, 279 { KEY_DOWN, SIMPAD_UCB1X00_GPIO_DOWN, 1, "down button" }, 280 { KEY_LEFT, SIMPAD_UCB1X00_GPIO_LEFT, 1, "left button" }, 281 { KEY_RIGHT, SIMPAD_UCB1X00_GPIO_RIGHT, 1, "right button" }, 282}; 283 284static struct gpio_keys_platform_data simpad_polled_keys_data = { 285 .buttons = simpad_polled_button_table, 286 .nbuttons = ARRAY_SIZE(simpad_polled_button_table), 287 .poll_interval = 50, 288}; 289 290static struct platform_device simpad_polled_keys = { 291 .name = "gpio-keys-polled", 292 .dev = { 293 .platform_data = &simpad_polled_keys_data, 294 }, 295}; 296 297/* 298 * GPIO LEDs 299 */ 300 301static struct gpio_led simpad_leds[] = { 302 { 303 .name = "simpad:power", 304 .gpio = SIMPAD_CS3_LED2_ON, 305 .active_low = 0, 306 .default_trigger = "default-on", 307 }, 308}; 309 310static struct gpio_led_platform_data simpad_led_data = { 311 .num_leds = ARRAY_SIZE(simpad_leds), 312 .leds = simpad_leds, 313}; 314 315static struct platform_device simpad_gpio_leds = { 316 .name = "leds-gpio", 317 .id = 0, 318 .dev = { 319 .platform_data = &simpad_led_data, 320 }, 321}; 322 323/* 324 * i2c 325 */ 326static struct i2c_gpio_platform_data simpad_i2c_data = { 327 .sda_pin = GPIO_GPIO21, 328 .scl_pin = GPIO_GPIO25, 329 .udelay = 10, 330 .timeout = HZ, 331}; 332 333static struct platform_device simpad_i2c = { 334 .name = "i2c-gpio", 335 .id = 0, 336 .dev = { 337 .platform_data = &simpad_i2c_data, 338 }, 339}; 340 341/* 342 * MediaQ Video Device 343 */ 344static struct platform_device simpad_mq200fb = { 345 .name = "simpad-mq200", 346 .id = 0, 347}; 348 349static struct platform_device *devices[] __initdata = { 350 &simpad_keys, 351 &simpad_polled_keys, 352 &simpad_mq200fb, 353 &simpad_gpio_leds, 354 &simpad_i2c, 355}; 356 357 358 359static int __init simpad_init(void) 360{ 361 int ret; 362 363 spin_lock_init(&cs3_lock); 364 365 cs3_gpio.label = "simpad_cs3"; 366 cs3_gpio.base = SIMPAD_CS3_GPIO_BASE; 367 cs3_gpio.ngpio = 24; 368 cs3_gpio.set = cs3_gpio_set; 369 cs3_gpio.get = cs3_gpio_get; 370 cs3_gpio.direction_input = cs3_gpio_direction_input; 371 cs3_gpio.direction_output = cs3_gpio_direction_output; 372 ret = gpiochip_add(&cs3_gpio); 373 if (ret) 374 printk(KERN_WARNING "simpad: Unable to register cs3 GPIO device"); 375 376 pm_power_off = simpad_power_off; 377 378 sa11x0_ppc_configure_mcp(); 379 sa11x0_register_mtd(&simpad_flash_data, simpad_flash_resources, 380 ARRAY_SIZE(simpad_flash_resources)); 381 sa11x0_register_mcp(&simpad_mcp_data); 382 383 ret = platform_add_devices(devices, ARRAY_SIZE(devices)); 384 if(ret) 385 printk(KERN_WARNING "simpad: Unable to register mq200 framebuffer device"); 386 387 return 0; 388} 389 390arch_initcall(simpad_init); 391 392 393MACHINE_START(SIMPAD, "Simpad") 394 /* Maintainer: Holger Freyther */ 395 .atag_offset = 0x100, 396 .map_io = simpad_map_io, 397 .nr_irqs = SA1100_NR_IRQS, 398 .init_irq = sa1100_init_irq, 399 .init_late = sa11x0_init_late, 400 .init_time = sa1100_timer_init, 401 .restart = sa11x0_restart, 402MACHINE_END 403