1// SPDX-License-Identifier: GPL-2.0-only 2/* 3 * linux/arch/arm/mach-pxa/lubbock.c 4 * 5 * Support for the Intel DBPXA250 Development Platform. 6 * 7 * Author: Nicolas Pitre 8 * Created: Jun 15, 2001 9 * Copyright: MontaVista Software Inc. 10 */ 11#include <linux/clkdev.h> 12#include <linux/gpio.h> 13#include <linux/gpio/gpio-reg.h> 14#include <linux/gpio/machine.h> 15#include <linux/module.h> 16#include <linux/kernel.h> 17#include <linux/init.h> 18#include <linux/io.h> 19#include <linux/platform_device.h> 20#include <linux/syscore_ops.h> 21#include <linux/major.h> 22#include <linux/fb.h> 23#include <linux/interrupt.h> 24#include <linux/mtd/mtd.h> 25#include <linux/mtd/partitions.h> 26#include <linux/smc91x.h> 27#include <linux/slab.h> 28#include <linux/leds.h> 29 30#include <linux/spi/spi.h> 31#include <linux/spi/ads7846.h> 32#include <linux/spi/pxa2xx_spi.h> 33 34#include <asm/setup.h> 35#include <asm/memory.h> 36#include <asm/mach-types.h> 37#include <mach/hardware.h> 38#include <asm/irq.h> 39#include <linux/sizes.h> 40 41#include <asm/mach/arch.h> 42#include <asm/mach/map.h> 43#include <asm/mach/irq.h> 44#include <asm/mach/flash.h> 45 46#include <asm/hardware/sa1111.h> 47 48#include "pxa25x.h" 49#include <mach/audio.h> 50#include <mach/lubbock.h> 51#include "udc.h" 52#include <linux/platform_data/irda-pxaficp.h> 53#include <linux/platform_data/video-pxafb.h> 54#include <linux/platform_data/mmc-pxamci.h> 55#include "pm.h" 56#include <mach/smemc.h> 57 58#include "generic.h" 59#include "devices.h" 60 61static unsigned long lubbock_pin_config[] __initdata = { 62 GPIO15_nCS_1, /* CS1 - Flash */ 63 GPIO78_nCS_2, /* CS2 - Baseboard FGPA */ 64 GPIO79_nCS_3, /* CS3 - SMC ethernet */ 65 GPIO80_nCS_4, /* CS4 - SA1111 */ 66 67 /* SSP data pins */ 68 GPIO23_SSP1_SCLK, 69 GPIO25_SSP1_TXD, 70 GPIO26_SSP1_RXD, 71 72 /* AC97 */ 73 GPIO28_AC97_BITCLK, 74 GPIO29_AC97_SDATA_IN_0, 75 GPIO30_AC97_SDATA_OUT, 76 GPIO31_AC97_SYNC, 77 78 /* LCD - 16bpp DSTN */ 79 GPIOxx_LCD_DSTN_16BPP, 80 81 /* BTUART */ 82 GPIO42_BTUART_RXD, 83 GPIO43_BTUART_TXD, 84 GPIO44_BTUART_CTS, 85 GPIO45_BTUART_RTS, 86 87 /* PC Card */ 88 GPIO48_nPOE, 89 GPIO49_nPWE, 90 GPIO50_nPIOR, 91 GPIO51_nPIOW, 92 GPIO52_nPCE_1, 93 GPIO53_nPCE_2, 94 GPIO54_nPSKTSEL, 95 GPIO55_nPREG, 96 GPIO56_nPWAIT, 97 GPIO57_nIOIS16, 98 99 /* MMC */ 100 GPIO6_MMC_CLK, 101 GPIO8_MMC_CS0, 102 103 /* SA1111 chip */ 104 GPIO11_3_6MHz, 105 106 /* wakeup */ 107 GPIO1_GPIO | WAKEUP_ON_EDGE_RISE, 108}; 109 110#define LUB_HEXLED __LUB_REG(LUBBOCK_FPGA_PHYS + 0x010) 111 112void lubbock_set_hexled(uint32_t value) 113{ 114 LUB_HEXLED = value; 115} 116 117static struct gpio_chip *lubbock_misc_wr_gc; 118 119static void lubbock_set_misc_wr(unsigned int mask, unsigned int set) 120{ 121 unsigned long m = mask, v = set; 122 lubbock_misc_wr_gc->set_multiple(lubbock_misc_wr_gc, &m, &v); 123} 124 125static int lubbock_udc_is_connected(void) 126{ 127 return (LUB_MISC_RD & (1 << 9)) == 0; 128} 129 130static struct pxa2xx_udc_mach_info udc_info __initdata = { 131 .udc_is_connected = lubbock_udc_is_connected, 132 // no D+ pullup; lubbock can't connect/disconnect in software 133}; 134 135/* GPIOs for SA1111 PCMCIA */ 136static struct gpiod_lookup_table sa1111_pcmcia_gpio_table = { 137 .dev_id = "1800", 138 .table = { 139 { "sa1111", 0, "a0vpp", GPIO_ACTIVE_HIGH }, 140 { "sa1111", 1, "a1vpp", GPIO_ACTIVE_HIGH }, 141 { "sa1111", 2, "a0vcc", GPIO_ACTIVE_HIGH }, 142 { "sa1111", 3, "a1vcc", GPIO_ACTIVE_HIGH }, 143 { "lubbock", 14, "b0vcc", GPIO_ACTIVE_HIGH }, 144 { "lubbock", 15, "b1vcc", GPIO_ACTIVE_HIGH }, 145 { }, 146 }, 147}; 148 149static void lubbock_init_pcmcia(void) 150{ 151 struct clk *clk; 152 153 gpiod_add_lookup_table(&sa1111_pcmcia_gpio_table); 154 155 /* Add an alias for the SA1111 PCMCIA clock */ 156 clk = clk_get_sys("pxa2xx-pcmcia", NULL); 157 if (!IS_ERR(clk)) { 158 clkdev_create(clk, NULL, "1800"); 159 clk_put(clk); 160 } 161} 162 163static struct resource sa1111_resources[] = { 164 [0] = { 165 .start = 0x10000000, 166 .end = 0x10001fff, 167 .flags = IORESOURCE_MEM, 168 }, 169 [1] = { 170 .start = LUBBOCK_SA1111_IRQ, 171 .end = LUBBOCK_SA1111_IRQ, 172 .flags = IORESOURCE_IRQ, 173 }, 174}; 175 176static struct sa1111_platform_data sa1111_info = { 177 .irq_base = LUBBOCK_SA1111_IRQ_BASE, 178 .disable_devs = SA1111_DEVID_SAC, 179}; 180 181static struct platform_device sa1111_device = { 182 .name = "sa1111", 183 .id = -1, 184 .num_resources = ARRAY_SIZE(sa1111_resources), 185 .resource = sa1111_resources, 186 .dev = { 187 .platform_data = &sa1111_info, 188 }, 189}; 190 191/* ADS7846 is connected through SSP ... and if your board has J5 populated, 192 * you can select it to replace the ucb1400 by switching the touchscreen cable 193 * (to J5) and poking board registers (as done below). Else it's only useful 194 * for the temperature sensors. 195 */ 196static struct pxa2xx_spi_controller pxa_ssp_master_info = { 197 .num_chipselect = 1, 198}; 199 200static int lubbock_ads7846_pendown_state(void) 201{ 202 /* TS_BUSY is bit 8 in LUB_MISC_RD, but pendown is irq-only */ 203 return 0; 204} 205 206static struct ads7846_platform_data ads_info = { 207 .model = 7846, 208 .vref_delay_usecs = 100, /* internal, no cap */ 209 .get_pendown_state = lubbock_ads7846_pendown_state, 210 // .x_plate_ohms = 500, /* GUESS! */ 211 // .y_plate_ohms = 500, /* GUESS! */ 212}; 213 214static void ads7846_cs(u32 command) 215{ 216 static const unsigned TS_nCS = 1 << 11; 217 lubbock_set_misc_wr(TS_nCS, (command == PXA2XX_CS_ASSERT) ? 0 : TS_nCS); 218} 219 220static struct pxa2xx_spi_chip ads_hw = { 221 .tx_threshold = 1, 222 .rx_threshold = 2, 223 .cs_control = ads7846_cs, 224}; 225 226static struct spi_board_info spi_board_info[] __initdata = { { 227 .modalias = "ads7846", 228 .platform_data = &ads_info, 229 .controller_data = &ads_hw, 230 .irq = LUBBOCK_BB_IRQ, 231 .max_speed_hz = 120000 /* max sample rate at 3V */ 232 * 26 /* command + data + overhead */, 233 .bus_num = 1, 234 .chip_select = 0, 235}, 236}; 237 238static struct resource smc91x_resources[] = { 239 [0] = { 240 .name = "smc91x-regs", 241 .start = 0x0c000c00, 242 .end = 0x0c0fffff, 243 .flags = IORESOURCE_MEM, 244 }, 245 [1] = { 246 .start = LUBBOCK_ETH_IRQ, 247 .end = LUBBOCK_ETH_IRQ, 248 .flags = IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHEDGE, 249 }, 250 [2] = { 251 .name = "smc91x-attrib", 252 .start = 0x0e000000, 253 .end = 0x0e0fffff, 254 .flags = IORESOURCE_MEM, 255 }, 256}; 257 258static struct smc91x_platdata lubbock_smc91x_info = { 259 .flags = SMC91X_USE_16BIT | SMC91X_NOWAIT | SMC91X_IO_SHIFT_2, 260}; 261 262static struct platform_device smc91x_device = { 263 .name = "smc91x", 264 .id = -1, 265 .num_resources = ARRAY_SIZE(smc91x_resources), 266 .resource = smc91x_resources, 267 .dev = { 268 .platform_data = &lubbock_smc91x_info, 269 }, 270}; 271 272static struct resource flash_resources[] = { 273 [0] = { 274 .start = 0x00000000, 275 .end = SZ_64M - 1, 276 .flags = IORESOURCE_MEM, 277 }, 278 [1] = { 279 .start = 0x04000000, 280 .end = 0x04000000 + SZ_64M - 1, 281 .flags = IORESOURCE_MEM, 282 }, 283}; 284 285static struct mtd_partition lubbock_partitions[] = { 286 { 287 .name = "Bootloader", 288 .size = 0x00040000, 289 .offset = 0, 290 .mask_flags = MTD_WRITEABLE /* force read-only */ 291 },{ 292 .name = "Kernel", 293 .size = 0x00100000, 294 .offset = 0x00040000, 295 },{ 296 .name = "Filesystem", 297 .size = MTDPART_SIZ_FULL, 298 .offset = 0x00140000 299 } 300}; 301 302static struct flash_platform_data lubbock_flash_data[2] = { 303 { 304 .map_name = "cfi_probe", 305 .parts = lubbock_partitions, 306 .nr_parts = ARRAY_SIZE(lubbock_partitions), 307 }, { 308 .map_name = "cfi_probe", 309 .parts = NULL, 310 .nr_parts = 0, 311 } 312}; 313 314static struct platform_device lubbock_flash_device[2] = { 315 { 316 .name = "pxa2xx-flash", 317 .id = 0, 318 .dev = { 319 .platform_data = &lubbock_flash_data[0], 320 }, 321 .resource = &flash_resources[0], 322 .num_resources = 1, 323 }, 324 { 325 .name = "pxa2xx-flash", 326 .id = 1, 327 .dev = { 328 .platform_data = &lubbock_flash_data[1], 329 }, 330 .resource = &flash_resources[1], 331 .num_resources = 1, 332 }, 333}; 334 335static struct resource lubbock_cplds_resources[] = { 336 [0] = { 337 .start = LUBBOCK_FPGA_PHYS + 0xc0, 338 .end = LUBBOCK_FPGA_PHYS + 0xe0 - 1, 339 .flags = IORESOURCE_MEM, 340 }, 341 [1] = { 342 .start = PXA_GPIO_TO_IRQ(0), 343 .end = PXA_GPIO_TO_IRQ(0), 344 .flags = IORESOURCE_IRQ | IORESOURCE_IRQ_LOWEDGE, 345 }, 346 [2] = { 347 .start = LUBBOCK_IRQ(0), 348 .end = LUBBOCK_IRQ(6), 349 .flags = IORESOURCE_IRQ, 350 }, 351}; 352 353static struct platform_device lubbock_cplds_device = { 354 .name = "pxa_cplds_irqs", 355 .id = -1, 356 .resource = &lubbock_cplds_resources[0], 357 .num_resources = 3, 358}; 359 360 361static struct platform_device *devices[] __initdata = { 362 &sa1111_device, 363 &smc91x_device, 364 &lubbock_flash_device[0], 365 &lubbock_flash_device[1], 366 &lubbock_cplds_device, 367}; 368 369static struct pxafb_mode_info sharp_lm8v31_mode = { 370 .pixclock = 270000, 371 .xres = 640, 372 .yres = 480, 373 .bpp = 16, 374 .hsync_len = 1, 375 .left_margin = 3, 376 .right_margin = 3, 377 .vsync_len = 1, 378 .upper_margin = 0, 379 .lower_margin = 0, 380 .sync = FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, 381 .cmap_greyscale = 0, 382}; 383 384static struct pxafb_mach_info sharp_lm8v31 = { 385 .modes = &sharp_lm8v31_mode, 386 .num_modes = 1, 387 .cmap_inverse = 0, 388 .cmap_static = 0, 389 .lcd_conn = LCD_COLOR_DSTN_16BPP | LCD_PCLK_EDGE_FALL | 390 LCD_AC_BIAS_FREQ(255), 391}; 392 393#define MMC_POLL_RATE msecs_to_jiffies(1000) 394 395static irq_handler_t mmc_detect_int; 396static void *mmc_detect_int_data; 397static struct timer_list mmc_timer; 398 399static void lubbock_mmc_poll(struct timer_list *unused) 400{ 401 unsigned long flags; 402 403 /* clear any previous irq state, then ... */ 404 local_irq_save(flags); 405 LUB_IRQ_SET_CLR &= ~(1 << 0); 406 local_irq_restore(flags); 407 408 /* poll until mmc/sd card is removed */ 409 if (LUB_IRQ_SET_CLR & (1 << 0)) 410 mod_timer(&mmc_timer, jiffies + MMC_POLL_RATE); 411 else { 412 (void) mmc_detect_int(LUBBOCK_SD_IRQ, mmc_detect_int_data); 413 enable_irq(LUBBOCK_SD_IRQ); 414 } 415} 416 417static irqreturn_t lubbock_detect_int(int irq, void *data) 418{ 419 /* IRQ is level triggered; disable, and poll for removal */ 420 disable_irq(irq); 421 mod_timer(&mmc_timer, jiffies + MMC_POLL_RATE); 422 423 return mmc_detect_int(irq, data); 424} 425 426static int lubbock_mci_init(struct device *dev, 427 irq_handler_t detect_int, 428 void *data) 429{ 430 /* detect card insert/eject */ 431 mmc_detect_int = detect_int; 432 mmc_detect_int_data = data; 433 timer_setup(&mmc_timer, lubbock_mmc_poll, 0); 434 return request_irq(LUBBOCK_SD_IRQ, lubbock_detect_int, 435 0, "lubbock-sd-detect", data); 436} 437 438static int lubbock_mci_get_ro(struct device *dev) 439{ 440 return (LUB_MISC_RD & (1 << 2)) != 0; 441} 442 443static void lubbock_mci_exit(struct device *dev, void *data) 444{ 445 free_irq(LUBBOCK_SD_IRQ, data); 446 del_timer_sync(&mmc_timer); 447} 448 449static struct pxamci_platform_data lubbock_mci_platform_data = { 450 .ocr_mask = MMC_VDD_32_33|MMC_VDD_33_34, 451 .detect_delay_ms = 10, 452 .init = lubbock_mci_init, 453 .get_ro = lubbock_mci_get_ro, 454 .exit = lubbock_mci_exit, 455}; 456 457static void lubbock_irda_transceiver_mode(struct device *dev, int mode) 458{ 459 unsigned long flags; 460 461 local_irq_save(flags); 462 if (mode & IR_SIRMODE) { 463 lubbock_set_misc_wr(BIT(4), 0); 464 } else if (mode & IR_FIRMODE) { 465 lubbock_set_misc_wr(BIT(4), BIT(4)); 466 } 467 pxa2xx_transceiver_mode(dev, mode); 468 local_irq_restore(flags); 469} 470 471static struct pxaficp_platform_data lubbock_ficp_platform_data = { 472 .gpio_pwdown = -1, 473 .transceiver_cap = IR_SIRMODE | IR_FIRMODE, 474 .transceiver_mode = lubbock_irda_transceiver_mode, 475}; 476 477static void __init lubbock_init(void) 478{ 479 int flashboot = (LUB_CONF_SWITCHES & 1); 480 481 pxa2xx_mfp_config(ARRAY_AND_SIZE(lubbock_pin_config)); 482 483 lubbock_misc_wr_gc = gpio_reg_init(NULL, (void *)&LUB_MISC_WR, 484 -1, 16, "lubbock", 0, LUB_MISC_WR, 485 NULL, NULL, NULL); 486 if (IS_ERR(lubbock_misc_wr_gc)) { 487 pr_err("Lubbock: unable to register lubbock GPIOs: %ld\n", 488 PTR_ERR(lubbock_misc_wr_gc)); 489 lubbock_misc_wr_gc = NULL; 490 } 491 492 pxa_set_ffuart_info(NULL); 493 pxa_set_btuart_info(NULL); 494 pxa_set_stuart_info(NULL); 495 496 lubbock_init_pcmcia(); 497 498 clk_add_alias("SA1111_CLK", NULL, "GPIO11_CLK", NULL); 499 pxa_set_udc_info(&udc_info); 500 pxa_set_fb_info(NULL, &sharp_lm8v31); 501 pxa_set_mci_info(&lubbock_mci_platform_data); 502 pxa_set_ficp_info(&lubbock_ficp_platform_data); 503 pxa_set_ac97_info(NULL); 504 505 lubbock_flash_data[0].width = lubbock_flash_data[1].width = 506 (__raw_readl(BOOT_DEF) & 1) ? 2 : 4; 507 /* Compensate for the nROMBT switch which swaps the flash banks */ 508 printk(KERN_NOTICE "Lubbock configured to boot from %s (bank %d)\n", 509 flashboot?"Flash":"ROM", flashboot); 510 511 lubbock_flash_data[flashboot^1].name = "application-flash"; 512 lubbock_flash_data[flashboot].name = "boot-rom"; 513 (void) platform_add_devices(devices, ARRAY_SIZE(devices)); 514 515 pxa2xx_set_spi_info(1, &pxa_ssp_master_info); 516 spi_register_board_info(spi_board_info, ARRAY_SIZE(spi_board_info)); 517} 518 519static struct map_desc lubbock_io_desc[] __initdata = { 520 { /* CPLD */ 521 .virtual = LUBBOCK_FPGA_VIRT, 522 .pfn = __phys_to_pfn(LUBBOCK_FPGA_PHYS), 523 .length = 0x00100000, 524 .type = MT_DEVICE 525 } 526}; 527 528static void __init lubbock_map_io(void) 529{ 530 pxa25x_map_io(); 531 iotable_init(lubbock_io_desc, ARRAY_SIZE(lubbock_io_desc)); 532 533 PCFR |= PCFR_OPDE; 534} 535 536/* 537 * Driver for the 8 discrete LEDs available for general use: 538 * Note: bits [15-8] are used to enable/blank the 8 7 segment hex displays 539 * so be sure to not monkey with them here. 540 */ 541 542#if defined(CONFIG_NEW_LEDS) && defined(CONFIG_LEDS_CLASS) 543struct lubbock_led { 544 struct led_classdev cdev; 545 u8 mask; 546}; 547 548/* 549 * The triggers lines up below will only be used if the 550 * LED triggers are compiled in. 551 */ 552static const struct { 553 const char *name; 554 const char *trigger; 555} lubbock_leds[] = { 556 { "lubbock:D28", "default-on", }, 557 { "lubbock:D27", "cpu0", }, 558 { "lubbock:D26", "heartbeat" }, 559 { "lubbock:D25", }, 560 { "lubbock:D24", }, 561 { "lubbock:D23", }, 562 { "lubbock:D22", }, 563 { "lubbock:D21", }, 564}; 565 566static void lubbock_led_set(struct led_classdev *cdev, 567 enum led_brightness b) 568{ 569 struct lubbock_led *led = container_of(cdev, 570 struct lubbock_led, cdev); 571 u32 reg = LUB_DISC_BLNK_LED; 572 573 if (b != LED_OFF) 574 reg |= led->mask; 575 else 576 reg &= ~led->mask; 577 578 LUB_DISC_BLNK_LED = reg; 579} 580 581static enum led_brightness lubbock_led_get(struct led_classdev *cdev) 582{ 583 struct lubbock_led *led = container_of(cdev, 584 struct lubbock_led, cdev); 585 u32 reg = LUB_DISC_BLNK_LED; 586 587 return (reg & led->mask) ? LED_FULL : LED_OFF; 588} 589 590static int __init lubbock_leds_init(void) 591{ 592 int i; 593 594 if (!machine_is_lubbock()) 595 return -ENODEV; 596 597 /* All ON */ 598 LUB_DISC_BLNK_LED |= 0xff; 599 for (i = 0; i < ARRAY_SIZE(lubbock_leds); i++) { 600 struct lubbock_led *led; 601 602 led = kzalloc(sizeof(*led), GFP_KERNEL); 603 if (!led) 604 break; 605 606 led->cdev.name = lubbock_leds[i].name; 607 led->cdev.brightness_set = lubbock_led_set; 608 led->cdev.brightness_get = lubbock_led_get; 609 led->cdev.default_trigger = lubbock_leds[i].trigger; 610 led->mask = BIT(i); 611 612 if (led_classdev_register(NULL, &led->cdev) < 0) { 613 kfree(led); 614 break; 615 } 616 } 617 618 return 0; 619} 620 621/* 622 * Since we may have triggers on any subsystem, defer registration 623 * until after subsystem_init. 624 */ 625fs_initcall(lubbock_leds_init); 626#endif 627 628MACHINE_START(LUBBOCK, "Intel DBPXA250 Development Platform (aka Lubbock)") 629 /* Maintainer: MontaVista Software Inc. */ 630 .map_io = lubbock_map_io, 631 .nr_irqs = LUBBOCK_NR_IRQS, 632 .init_irq = pxa25x_init_irq, 633 .handle_irq = pxa25x_handle_irq, 634 .init_time = pxa_timer_init, 635 .init_machine = lubbock_init, 636 .restart = pxa_restart, 637MACHINE_END 638