1/* 2 * Support for Sharp SL-C7xx PDAs 3 * Models: SL-C700 (Corgi), SL-C750 (Shepherd), SL-C760 (Husky) 4 * 5 * Copyright (c) 2004-2005 Richard Purdie 6 * 7 * Based on Sharp's 2.4 kernel patches/lubbock.c 8 * 9 * This program is free software; you can redistribute it and/or modify 10 * it under the terms of the GNU General Public License version 2 as 11 * published by the Free Software Foundation. 12 * 13 */ 14 15#include <linux/kernel.h> 16#include <linux/init.h> 17#include <linux/platform_device.h> 18#include <linux/major.h> 19#include <linux/fs.h> 20#include <linux/interrupt.h> 21#include <linux/mmc/host.h> 22#include <linux/pm.h> 23 24#include <asm/setup.h> 25#include <asm/memory.h> 26#include <asm/mach-types.h> 27#include <asm/hardware.h> 28#include <asm/irq.h> 29#include <asm/io.h> 30#include <asm/system.h> 31 32#include <asm/mach/arch.h> 33#include <asm/mach/map.h> 34#include <asm/mach/irq.h> 35 36#include <asm/arch/pxa-regs.h> 37#include <asm/arch/irda.h> 38#include <asm/arch/mmc.h> 39#include <asm/arch/udc.h> 40#include <asm/arch/corgi.h> 41#include <asm/arch/sharpsl.h> 42 43#include <asm/mach/sharpsl_param.h> 44#include <asm/hardware/scoop.h> 45 46#include "generic.h" 47#include "sharpsl.h" 48 49 50/* 51 * Corgi SCOOP Device 52 */ 53static struct resource corgi_scoop_resources[] = { 54 [0] = { 55 .start = 0x10800000, 56 .end = 0x10800fff, 57 .flags = IORESOURCE_MEM, 58 }, 59}; 60 61static struct scoop_config corgi_scoop_setup = { 62 .io_dir = CORGI_SCOOP_IO_DIR, 63 .io_out = CORGI_SCOOP_IO_OUT, 64}; 65 66struct platform_device corgiscoop_device = { 67 .name = "sharp-scoop", 68 .id = -1, 69 .dev = { 70 .platform_data = &corgi_scoop_setup, 71 }, 72 .num_resources = ARRAY_SIZE(corgi_scoop_resources), 73 .resource = corgi_scoop_resources, 74}; 75 76static void corgi_pcmcia_init(void) 77{ 78 /* Setup default state of GPIO outputs 79 before we enable them as outputs. */ 80 GPSR(GPIO48_nPOE) = GPIO_bit(GPIO48_nPOE) | 81 GPIO_bit(GPIO49_nPWE) | GPIO_bit(GPIO50_nPIOR) | 82 GPIO_bit(GPIO51_nPIOW) | GPIO_bit(GPIO52_nPCE_1) | 83 GPIO_bit(GPIO53_nPCE_2); 84 85 pxa_gpio_mode(GPIO48_nPOE_MD); 86 pxa_gpio_mode(GPIO49_nPWE_MD); 87 pxa_gpio_mode(GPIO50_nPIOR_MD); 88 pxa_gpio_mode(GPIO51_nPIOW_MD); 89 pxa_gpio_mode(GPIO55_nPREG_MD); 90 pxa_gpio_mode(GPIO56_nPWAIT_MD); 91 pxa_gpio_mode(GPIO57_nIOIS16_MD); 92 pxa_gpio_mode(GPIO52_nPCE_1_MD); 93 pxa_gpio_mode(GPIO53_nPCE_2_MD); 94 pxa_gpio_mode(GPIO54_pSKTSEL_MD); 95} 96 97static struct scoop_pcmcia_dev corgi_pcmcia_scoop[] = { 98{ 99 .dev = &corgiscoop_device.dev, 100 .irq = CORGI_IRQ_GPIO_CF_IRQ, 101 .cd_irq = CORGI_IRQ_GPIO_CF_CD, 102 .cd_irq_str = "PCMCIA0 CD", 103}, 104}; 105 106static struct scoop_pcmcia_config corgi_pcmcia_config = { 107 .devs = &corgi_pcmcia_scoop[0], 108 .num_devs = 1, 109 .pcmcia_init = corgi_pcmcia_init, 110}; 111 112EXPORT_SYMBOL(corgiscoop_device); 113 114 115/* 116 * Corgi SSP Device 117 * 118 * Set the parent as the scoop device because a lot of SSP devices 119 * also use scoop functions and this makes the power up/down order 120 * work correctly. 121 */ 122struct platform_device corgissp_device = { 123 .name = "corgi-ssp", 124 .dev = { 125 .parent = &corgiscoop_device.dev, 126 }, 127 .id = -1, 128}; 129 130struct corgissp_machinfo corgi_ssp_machinfo = { 131 .port = 1, 132 .cs_lcdcon = CORGI_GPIO_LCDCON_CS, 133 .cs_ads7846 = CORGI_GPIO_ADS7846_CS, 134 .cs_max1111 = CORGI_GPIO_MAX1111_CS, 135 .clk_lcdcon = 76, 136 .clk_ads7846 = 2, 137 .clk_max1111 = 8, 138}; 139 140 141/* 142 * Corgi Backlight Device 143 */ 144static struct corgibl_machinfo corgi_bl_machinfo = { 145 .max_intensity = 0x2f, 146 .default_intensity = 0x1f, 147 .limit_mask = 0x0b, 148 .set_bl_intensity = corgi_bl_set_intensity, 149}; 150 151static struct platform_device corgibl_device = { 152 .name = "corgi-bl", 153 .dev = { 154 .parent = &corgifb_device.dev, 155 .platform_data = &corgi_bl_machinfo, 156 }, 157 .id = -1, 158}; 159 160 161/* 162 * Corgi Keyboard Device 163 */ 164static struct platform_device corgikbd_device = { 165 .name = "corgi-keyboard", 166 .id = -1, 167}; 168 169 170/* 171 * Corgi LEDs 172 */ 173static struct platform_device corgiled_device = { 174 .name = "corgi-led", 175 .id = -1, 176}; 177 178/* 179 * Corgi Touch Screen Device 180 */ 181static struct resource corgits_resources[] = { 182 [0] = { 183 .start = CORGI_IRQ_GPIO_TP_INT, 184 .end = CORGI_IRQ_GPIO_TP_INT, 185 .flags = IORESOURCE_IRQ, 186 }, 187}; 188 189static struct corgits_machinfo corgi_ts_machinfo = { 190 .get_hsync_len = corgi_get_hsync_len, 191 .put_hsync = corgi_put_hsync, 192 .wait_hsync = corgi_wait_hsync, 193}; 194 195static struct platform_device corgits_device = { 196 .name = "corgi-ts", 197 .dev = { 198 .parent = &corgissp_device.dev, 199 .platform_data = &corgi_ts_machinfo, 200 }, 201 .id = -1, 202 .num_resources = ARRAY_SIZE(corgits_resources), 203 .resource = corgits_resources, 204}; 205 206 207/* 208 * MMC/SD Device 209 * 210 * The card detect interrupt isn't debounced so we delay it by 250ms 211 * to give the card a chance to fully insert/eject. 212 */ 213static struct pxamci_platform_data corgi_mci_platform_data; 214 215static int corgi_mci_init(struct device *dev, irq_handler_t corgi_detect_int, void *data) 216{ 217 int err; 218 219 /* setup GPIO for PXA25x MMC controller */ 220 pxa_gpio_mode(GPIO6_MMCCLK_MD); 221 pxa_gpio_mode(GPIO8_MMCCS0_MD); 222 pxa_gpio_mode(CORGI_GPIO_nSD_DETECT | GPIO_IN); 223 pxa_gpio_mode(CORGI_GPIO_SD_PWR | GPIO_OUT); 224 225 corgi_mci_platform_data.detect_delay = msecs_to_jiffies(250); 226 227 err = request_irq(CORGI_IRQ_GPIO_nSD_DETECT, corgi_detect_int, 228 IRQF_DISABLED | IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING, 229 "MMC card detect", data); 230 if (err) { 231 printk(KERN_ERR "corgi_mci_init: MMC/SD: can't request MMC card detect IRQ\n"); 232 return -1; 233 } 234 235 return 0; 236} 237 238static void corgi_mci_setpower(struct device *dev, unsigned int vdd) 239{ 240 struct pxamci_platform_data* p_d = dev->platform_data; 241 242 if (( 1 << vdd) & p_d->ocr_mask) 243 GPSR1 = GPIO_bit(CORGI_GPIO_SD_PWR); 244 else 245 GPCR1 = GPIO_bit(CORGI_GPIO_SD_PWR); 246} 247 248static int corgi_mci_get_ro(struct device *dev) 249{ 250 return GPLR(CORGI_GPIO_nSD_WP) & GPIO_bit(CORGI_GPIO_nSD_WP); 251} 252 253static void corgi_mci_exit(struct device *dev, void *data) 254{ 255 free_irq(CORGI_IRQ_GPIO_nSD_DETECT, data); 256} 257 258static struct pxamci_platform_data corgi_mci_platform_data = { 259 .ocr_mask = MMC_VDD_32_33|MMC_VDD_33_34, 260 .init = corgi_mci_init, 261 .get_ro = corgi_mci_get_ro, 262 .setpower = corgi_mci_setpower, 263 .exit = corgi_mci_exit, 264}; 265 266 267/* 268 * Irda 269 */ 270static void corgi_irda_transceiver_mode(struct device *dev, int mode) 271{ 272 if (mode & IR_OFF) 273 GPSR(CORGI_GPIO_IR_ON) = GPIO_bit(CORGI_GPIO_IR_ON); 274 else 275 GPCR(CORGI_GPIO_IR_ON) = GPIO_bit(CORGI_GPIO_IR_ON); 276} 277 278static struct pxaficp_platform_data corgi_ficp_platform_data = { 279 .transceiver_cap = IR_SIRMODE | IR_OFF, 280 .transceiver_mode = corgi_irda_transceiver_mode, 281}; 282 283 284/* 285 * USB Device Controller 286 */ 287static struct pxa2xx_udc_mach_info udc_info __initdata = { 288 /* no connect GPIO; corgi can't tell connection status */ 289 .gpio_pullup = CORGI_GPIO_USB_PULLUP, 290}; 291 292 293static struct platform_device *devices[] __initdata = { 294 &corgiscoop_device, 295 &corgissp_device, 296 &corgifb_device, 297 &corgikbd_device, 298 &corgibl_device, 299 &corgits_device, 300 &corgiled_device, 301}; 302 303static void corgi_poweroff(void) 304{ 305 RCSR = RCSR_HWR | RCSR_WDR | RCSR_SMR | RCSR_GPR; 306 307 if (!machine_is_corgi()) 308 /* Green LED off tells the bootloader to halt */ 309 reset_scoop_gpio(&corgiscoop_device.dev, CORGI_SCP_LED_GREEN); 310 arm_machine_restart('h'); 311} 312 313static void corgi_restart(char mode) 314{ 315 RCSR = RCSR_HWR | RCSR_WDR | RCSR_SMR | RCSR_GPR; 316 317 if (!machine_is_corgi()) 318 /* Green LED on tells the bootloader to reboot */ 319 set_scoop_gpio(&corgiscoop_device.dev, CORGI_SCP_LED_GREEN); 320 arm_machine_restart('h'); 321} 322 323static void __init corgi_init(void) 324{ 325 pm_power_off = corgi_poweroff; 326 arm_pm_restart = corgi_restart; 327 328 /* setup sleep mode values */ 329 PWER = 0x00000002; 330 PFER = 0x00000000; 331 PRER = 0x00000002; 332 PGSR0 = 0x0158C000; 333 PGSR1 = 0x00FF0080; 334 PGSR2 = 0x0001C004; 335 /* Stop 3.6MHz and drive HIGH to PCMCIA and CS */ 336 PCFR |= PCFR_OPDE; 337 338 corgi_ssp_set_machinfo(&corgi_ssp_machinfo); 339 340 pxa_gpio_mode(CORGI_GPIO_IR_ON | GPIO_OUT); 341 pxa_gpio_mode(CORGI_GPIO_HSYNC | GPIO_IN); 342 343 pxa_set_udc_info(&udc_info); 344 pxa_set_mci_info(&corgi_mci_platform_data); 345 pxa_set_ficp_info(&corgi_ficp_platform_data); 346 347 platform_scoop_config = &corgi_pcmcia_config; 348 349 platform_add_devices(devices, ARRAY_SIZE(devices)); 350} 351 352static void __init fixup_corgi(struct machine_desc *desc, 353 struct tag *tags, char **cmdline, struct meminfo *mi) 354{ 355 sharpsl_save_param(); 356 mi->nr_banks=1; 357 mi->bank[0].start = 0xa0000000; 358 mi->bank[0].node = 0; 359 if (machine_is_corgi()) 360 mi->bank[0].size = (32*1024*1024); 361 else 362 mi->bank[0].size = (64*1024*1024); 363} 364 365#ifdef CONFIG_MACH_CORGI 366MACHINE_START(CORGI, "SHARP Corgi") 367 .phys_io = 0x40000000, 368 .io_pg_offst = (io_p2v(0x40000000) >> 18) & 0xfffc, 369 .fixup = fixup_corgi, 370 .map_io = pxa_map_io, 371 .init_irq = pxa_init_irq, 372 .init_machine = corgi_init, 373 .timer = &pxa_timer, 374MACHINE_END 375#endif 376 377#ifdef CONFIG_MACH_SHEPHERD 378MACHINE_START(SHEPHERD, "SHARP Shepherd") 379 .phys_io = 0x40000000, 380 .io_pg_offst = (io_p2v(0x40000000) >> 18) & 0xfffc, 381 .fixup = fixup_corgi, 382 .map_io = pxa_map_io, 383 .init_irq = pxa_init_irq, 384 .init_machine = corgi_init, 385 .timer = &pxa_timer, 386MACHINE_END 387#endif 388 389#ifdef CONFIG_MACH_HUSKY 390MACHINE_START(HUSKY, "SHARP Husky") 391 .phys_io = 0x40000000, 392 .io_pg_offst = (io_p2v(0x40000000) >> 18) & 0xfffc, 393 .fixup = fixup_corgi, 394 .map_io = pxa_map_io, 395 .init_irq = pxa_init_irq, 396 .init_machine = corgi_init, 397 .timer = &pxa_timer, 398MACHINE_END 399#endif 400