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