trizeps4.c (14412B)
1// SPDX-License-Identifier: GPL-2.0-only 2/* 3 * linux/arch/arm/mach-pxa/trizeps4.c 4 * 5 * Support for the Keith und Koep Trizeps4 Module Platform. 6 * 7 * Author: Jürgen Schindele 8 * Created: 20 02, 2006 9 * Copyright: Jürgen Schindele 10 */ 11 12#include <linux/init.h> 13#include <linux/kernel.h> 14#include <linux/platform_device.h> 15#include <linux/interrupt.h> 16#include <linux/leds.h> 17#include <linux/export.h> 18#include <linux/sched.h> 19#include <linux/bitops.h> 20#include <linux/fb.h> 21#include <linux/ioport.h> 22#include <linux/delay.h> 23#include <linux/gpio.h> 24#include <linux/dm9000.h> 25#include <linux/mtd/physmap.h> 26#include <linux/mtd/partitions.h> 27#include <linux/regulator/machine.h> 28#include <linux/platform_data/i2c-pxa.h> 29 30#include <asm/types.h> 31#include <asm/setup.h> 32#include <asm/memory.h> 33#include <asm/mach-types.h> 34#include <asm/irq.h> 35#include <linux/sizes.h> 36 37#include <asm/mach/arch.h> 38#include <asm/mach/map.h> 39#include <asm/mach/irq.h> 40#include <asm/mach/flash.h> 41 42#include "pxa27x.h" 43#include "trizeps4.h" 44#include <linux/platform_data/asoc-pxa.h> 45#include <linux/platform_data/video-pxafb.h> 46#include <linux/platform_data/mmc-pxamci.h> 47#include <linux/platform_data/irda-pxaficp.h> 48#include <linux/platform_data/usb-ohci-pxa27x.h> 49#include "smemc.h" 50 51#include "generic.h" 52#include "devices.h" 53 54/* comment out the following line if you want to use the 55 * Standard UART from PXA for serial / irda transmission 56 * and acivate it if you have status leds connected */ 57#define STATUS_LEDS_ON_STUART_PINS 1 58 59/***************************************************************************** 60 * MultiFunctionPins of CPU 61 *****************************************************************************/ 62static unsigned long trizeps4_pin_config[] __initdata = { 63 /* Chip Selects */ 64 GPIO15_nCS_1, /* DiskOnChip CS */ 65 GPIO93_GPIO, /* TRIZEPS4_DOC_IRQ */ 66 GPIO94_GPIO, /* DOC lock */ 67 68 GPIO78_nCS_2, /* DM9000 CS */ 69 GPIO101_GPIO, /* TRIZEPS4_ETH_IRQ */ 70 71 GPIO79_nCS_3, /* Logic CS */ 72 GPIO0_GPIO | WAKEUP_ON_EDGE_RISE, /* Logic irq */ 73 74 /* AC97 */ 75 GPIO28_AC97_BITCLK, 76 GPIO29_AC97_SDATA_IN_0, 77 GPIO30_AC97_SDATA_OUT, 78 GPIO31_AC97_SYNC, 79 80 /* LCD - 16bpp Active TFT */ 81 GPIOxx_LCD_TFT_16BPP, 82 83 /* UART */ 84 GPIO9_FFUART_CTS, 85 GPIO10_FFUART_DCD, 86 GPIO16_FFUART_TXD, 87 GPIO33_FFUART_DSR, 88 GPIO38_FFUART_RI, 89 GPIO82_FFUART_DTR, 90 GPIO83_FFUART_RTS, 91 GPIO96_FFUART_RXD, 92 93 GPIO42_BTUART_RXD, 94 GPIO43_BTUART_TXD, 95 GPIO44_BTUART_CTS, 96 GPIO45_BTUART_RTS, 97#ifdef STATUS_LEDS_ON_STUART_PINS 98 GPIO46_GPIO, 99 GPIO47_GPIO, 100#else 101 GPIO46_STUART_RXD, 102 GPIO47_STUART_TXD, 103#endif 104 /* PCMCIA */ 105 GPIO11_GPIO, /* TRIZEPS4_CD_IRQ */ 106 GPIO13_GPIO, /* TRIZEPS4_READY_NINT */ 107 GPIO48_nPOE, 108 GPIO49_nPWE, 109 GPIO50_nPIOR, 110 GPIO51_nPIOW, 111 GPIO54_nPCE_2, 112 GPIO55_nPREG, 113 GPIO56_nPWAIT, 114 GPIO57_nIOIS16, 115 GPIO102_nPCE_1, 116 GPIO104_PSKTSEL, 117 118 /* MultiMediaCard */ 119 GPIO32_MMC_CLK, 120 GPIO92_MMC_DAT_0, 121 GPIO109_MMC_DAT_1, 122 GPIO110_MMC_DAT_2, 123 GPIO111_MMC_DAT_3, 124 GPIO112_MMC_CMD, 125 GPIO12_GPIO, /* TRIZEPS4_MMC_IRQ */ 126 127 /* USB OHCI */ 128 GPIO88_USBH1_PWR, /* USBHPWR1 */ 129 GPIO89_USBH1_PEN, /* USBHPEN1 */ 130 131 /* I2C */ 132 GPIO117_I2C_SCL, 133 GPIO118_I2C_SDA, 134}; 135 136static unsigned long trizeps4wl_pin_config[] __initdata = { 137 /* SSP 2 */ 138 GPIO14_SSP2_SFRM, 139 GPIO19_SSP2_SCLK, 140 GPIO53_GPIO, /* TRIZEPS4_SPI_IRQ */ 141 GPIO86_SSP2_RXD, 142 GPIO87_SSP2_TXD, 143}; 144 145/**************************************************************************** 146 * ONBOARD FLASH 147 ****************************************************************************/ 148static struct mtd_partition trizeps4_partitions[] = { 149 { 150 .name = "Bootloader", 151 .offset = 0x00000000, 152 .size = 0x00040000, 153 .mask_flags = MTD_WRITEABLE /* force read-only */ 154 }, { 155 .name = "Backup", 156 .offset = 0x00040000, 157 .size = 0x00040000, 158 }, { 159 .name = "Image", 160 .offset = 0x00080000, 161 .size = 0x01080000, 162 }, { 163 .name = "IPSM", 164 .offset = 0x01100000, 165 .size = 0x00e00000, 166 }, { 167 .name = "Registry", 168 .offset = 0x01f00000, 169 .size = MTDPART_SIZ_FULL, 170 } 171}; 172 173static struct physmap_flash_data trizeps4_flash_data[] = { 174 { 175 .width = 4, /* bankwidth in bytes */ 176 .parts = trizeps4_partitions, 177 .nr_parts = ARRAY_SIZE(trizeps4_partitions) 178 } 179}; 180 181static struct resource flash_resource = { 182 .start = PXA_CS0_PHYS, 183 .end = PXA_CS0_PHYS + SZ_32M - 1, 184 .flags = IORESOURCE_MEM, 185}; 186 187static struct platform_device flash_device = { 188 .name = "physmap-flash", 189 .id = 0, 190 .dev = { 191 .platform_data = trizeps4_flash_data, 192 }, 193 .resource = &flash_resource, 194 .num_resources = 1, 195}; 196 197/**************************************************************************** 198 * DAVICOM DM9000 Ethernet 199 ****************************************************************************/ 200static struct resource dm9000_resources[] = { 201 [0] = { 202 .start = TRIZEPS4_ETH_PHYS+0x300, 203 .end = TRIZEPS4_ETH_PHYS+0x400-1, 204 .flags = IORESOURCE_MEM, 205 }, 206 [1] = { 207 .start = TRIZEPS4_ETH_PHYS+0x8300, 208 .end = TRIZEPS4_ETH_PHYS+0x8400-1, 209 .flags = IORESOURCE_MEM, 210 }, 211 [2] = { 212 .start = TRIZEPS4_ETH_IRQ, 213 .end = TRIZEPS4_ETH_IRQ, 214 .flags = IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHEDGE, 215 }, 216}; 217 218static struct dm9000_plat_data tri_dm9000_platdata = { 219 .flags = DM9000_PLATF_32BITONLY, 220}; 221 222static struct platform_device dm9000_device = { 223 .name = "dm9000", 224 .id = -1, 225 .num_resources = ARRAY_SIZE(dm9000_resources), 226 .resource = dm9000_resources, 227 .dev = { 228 .platform_data = &tri_dm9000_platdata, 229 } 230}; 231 232/**************************************************************************** 233 * LED's on GPIO pins of PXA 234 ****************************************************************************/ 235static struct gpio_led trizeps4_led[] = { 236#ifdef STATUS_LEDS_ON_STUART_PINS 237 { 238 .name = "led0:orange:heartbeat", /* */ 239 .default_trigger = "heartbeat", 240 .gpio = GPIO_HEARTBEAT_LED, 241 .active_low = 1, 242 }, 243 { 244 .name = "led1:yellow:cpubusy", /* */ 245 .default_trigger = "cpu-busy", 246 .gpio = GPIO_SYS_BUSY_LED, 247 .active_low = 1, 248 }, 249#endif 250}; 251 252static struct gpio_led_platform_data trizeps4_led_data = { 253 .leds = trizeps4_led, 254 .num_leds = ARRAY_SIZE(trizeps4_led), 255}; 256 257static struct platform_device leds_devices = { 258 .name = "leds-gpio", 259 .id = -1, 260 .dev = { 261 .platform_data = &trizeps4_led_data, 262 }, 263}; 264 265static struct platform_device *trizeps4_devices[] __initdata = { 266 &flash_device, 267 &dm9000_device, 268 &leds_devices, 269}; 270 271static struct platform_device *trizeps4wl_devices[] __initdata = { 272 &flash_device, 273 &leds_devices, 274}; 275 276static short trizeps_conxs_bcr; 277 278/* PCCARD power switching supports only 3,3V */ 279void board_pcmcia_power(int power) 280{ 281 if (power) { 282 /* switch power on, put in reset and enable buffers */ 283 trizeps_conxs_bcr |= power; 284 trizeps_conxs_bcr |= ConXS_BCR_CF_RESET; 285 trizeps_conxs_bcr &= ~ConXS_BCR_CF_BUF_EN; 286 BCR_writew(trizeps_conxs_bcr); 287 /* wait a little */ 288 udelay(2000); 289 /* take reset away */ 290 trizeps_conxs_bcr &= ~ConXS_BCR_CF_RESET; 291 BCR_writew(trizeps_conxs_bcr); 292 udelay(2000); 293 } else { 294 /* put in reset */ 295 trizeps_conxs_bcr |= ConXS_BCR_CF_RESET; 296 BCR_writew(trizeps_conxs_bcr); 297 udelay(1000); 298 /* switch power off */ 299 trizeps_conxs_bcr &= ~0xf; 300 BCR_writew(trizeps_conxs_bcr); 301 } 302 pr_debug("%s: o%s 0x%x\n", __func__, power ? "n" : "ff", 303 trizeps_conxs_bcr); 304} 305EXPORT_SYMBOL(board_pcmcia_power); 306 307/* backlight power switching for LCD panel */ 308static void board_backlight_power(int on) 309{ 310 if (on) 311 trizeps_conxs_bcr |= ConXS_BCR_L_DISP; 312 else 313 trizeps_conxs_bcr &= ~ConXS_BCR_L_DISP; 314 315 pr_debug("%s: o%s 0x%x\n", __func__, on ? "n" : "ff", 316 trizeps_conxs_bcr); 317 BCR_writew(trizeps_conxs_bcr); 318} 319 320/* a I2C based RTC is known on CONXS board */ 321static struct i2c_board_info trizeps4_i2c_devices[] __initdata = { 322 { I2C_BOARD_INFO("rtc-pcf8593", 0x51) } 323}; 324 325/**************************************************************************** 326 * MMC card slot external to module 327 ****************************************************************************/ 328static int trizeps4_mci_init(struct device *dev, irq_handler_t mci_detect_int, 329 void *data) 330{ 331 int err; 332 333 err = request_irq(TRIZEPS4_MMC_IRQ, mci_detect_int, 334 IRQF_TRIGGER_RISING, "MMC card detect", data); 335 if (err) { 336 printk(KERN_ERR "trizeps4_mci_init: MMC/SD: can't request" 337 "MMC card detect IRQ\n"); 338 return -1; 339 } 340 return 0; 341} 342 343static void trizeps4_mci_exit(struct device *dev, void *data) 344{ 345 free_irq(TRIZEPS4_MMC_IRQ, data); 346} 347 348static struct pxamci_platform_data trizeps4_mci_platform_data = { 349 .ocr_mask = MMC_VDD_32_33|MMC_VDD_33_34, 350 .detect_delay_ms= 10, 351 .init = trizeps4_mci_init, 352 .exit = trizeps4_mci_exit, 353 .get_ro = NULL, /* write-protection not supported */ 354 .setpower = NULL, /* power-switching not supported */ 355}; 356 357/**************************************************************************** 358 * IRDA mode switching on stuart 359 ****************************************************************************/ 360#ifndef STATUS_LEDS_ON_STUART_PINS 361static short trizeps_conxs_ircr; 362 363static int trizeps4_irda_startup(struct device *dev) 364{ 365 trizeps_conxs_ircr &= ~ConXS_IRCR_SD; 366 IRCR_writew(trizeps_conxs_ircr); 367 return 0; 368} 369 370static void trizeps4_irda_shutdown(struct device *dev) 371{ 372 trizeps_conxs_ircr |= ConXS_IRCR_SD; 373 IRCR_writew(trizeps_conxs_ircr); 374} 375 376static void trizeps4_irda_transceiver_mode(struct device *dev, int mode) 377{ 378 unsigned long flags; 379 380 local_irq_save(flags); 381 /* Switch mode */ 382 if (mode & IR_SIRMODE) 383 trizeps_conxs_ircr &= ~ConXS_IRCR_MODE; /* Slow mode */ 384 else if (mode & IR_FIRMODE) 385 trizeps_conxs_ircr |= ConXS_IRCR_MODE; /* Fast mode */ 386 387 /* Switch power */ 388 if (mode & IR_OFF) 389 trizeps_conxs_ircr |= ConXS_IRCR_SD; 390 else 391 trizeps_conxs_ircr &= ~ConXS_IRCR_SD; 392 393 IRCR_writew(trizeps_conxs_ircr); 394 local_irq_restore(flags); 395 396 pxa2xx_transceiver_mode(dev, mode); 397} 398 399static struct pxaficp_platform_data trizeps4_ficp_platform_data = { 400 .gpio_pwdown = -1, 401 .transceiver_cap = IR_SIRMODE | IR_FIRMODE | IR_OFF, 402 .transceiver_mode = trizeps4_irda_transceiver_mode, 403 .startup = trizeps4_irda_startup, 404 .shutdown = trizeps4_irda_shutdown, 405}; 406#endif 407 408/**************************************************************************** 409 * OHCI USB port 410 ****************************************************************************/ 411static struct pxaohci_platform_data trizeps4_ohci_platform_data = { 412 .port_mode = PMM_PERPORT_MODE, 413 .flags = ENABLE_PORT_ALL | POWER_CONTROL_LOW | POWER_SENSE_LOW, 414}; 415 416static struct map_desc trizeps4_io_desc[] __initdata = { 417 { /* ConXS CFSR */ 418 .virtual = TRIZEPS4_CFSR_VIRT, 419 .pfn = __phys_to_pfn(TRIZEPS4_CFSR_PHYS), 420 .length = 0x00001000, 421 .type = MT_DEVICE 422 }, 423 { /* ConXS BCR */ 424 .virtual = TRIZEPS4_BOCR_VIRT, 425 .pfn = __phys_to_pfn(TRIZEPS4_BOCR_PHYS), 426 .length = 0x00001000, 427 .type = MT_DEVICE 428 }, 429 { /* ConXS IRCR */ 430 .virtual = TRIZEPS4_IRCR_VIRT, 431 .pfn = __phys_to_pfn(TRIZEPS4_IRCR_PHYS), 432 .length = 0x00001000, 433 .type = MT_DEVICE 434 }, 435 { /* ConXS DCR */ 436 .virtual = TRIZEPS4_DICR_VIRT, 437 .pfn = __phys_to_pfn(TRIZEPS4_DICR_PHYS), 438 .length = 0x00001000, 439 .type = MT_DEVICE 440 }, 441 { /* ConXS UPSR */ 442 .virtual = TRIZEPS4_UPSR_VIRT, 443 .pfn = __phys_to_pfn(TRIZEPS4_UPSR_PHYS), 444 .length = 0x00001000, 445 .type = MT_DEVICE 446 } 447}; 448 449static struct pxafb_mode_info sharp_lcd_mode = { 450 .pixclock = 78000, 451 .xres = 640, 452 .yres = 480, 453 .bpp = 8, 454 .hsync_len = 4, 455 .left_margin = 4, 456 .right_margin = 4, 457 .vsync_len = 2, 458 .upper_margin = 0, 459 .lower_margin = 0, 460 .sync = FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, 461 .cmap_greyscale = 0, 462}; 463 464static struct pxafb_mach_info sharp_lcd = { 465 .modes = &sharp_lcd_mode, 466 .num_modes = 1, 467 .lcd_conn = LCD_COLOR_DSTN_16BPP | LCD_PCLK_EDGE_FALL, 468 .cmap_inverse = 0, 469 .cmap_static = 0, 470 .pxafb_backlight_power = board_backlight_power, 471}; 472 473static struct pxafb_mode_info toshiba_lcd_mode = { 474 .pixclock = 39720, 475 .xres = 640, 476 .yres = 480, 477 .bpp = 8, 478 .hsync_len = 63, 479 .left_margin = 12, 480 .right_margin = 12, 481 .vsync_len = 4, 482 .upper_margin = 32, 483 .lower_margin = 10, 484 .sync = 0, 485 .cmap_greyscale = 0, 486}; 487 488static struct pxafb_mach_info toshiba_lcd = { 489 .modes = &toshiba_lcd_mode, 490 .num_modes = 1, 491 .lcd_conn = (LCD_COLOR_TFT_16BPP | LCD_PCLK_EDGE_FALL), 492 .cmap_inverse = 0, 493 .cmap_static = 0, 494 .pxafb_backlight_power = board_backlight_power, 495}; 496 497static void __init trizeps4_init(void) 498{ 499 pxa2xx_mfp_config(ARRAY_AND_SIZE(trizeps4_pin_config)); 500 if (machine_is_trizeps4wl()) { 501 pxa2xx_mfp_config(ARRAY_AND_SIZE(trizeps4wl_pin_config)); 502 platform_add_devices(trizeps4wl_devices, 503 ARRAY_SIZE(trizeps4wl_devices)); 504 } else { 505 platform_add_devices(trizeps4_devices, 506 ARRAY_SIZE(trizeps4_devices)); 507 } 508 509 pxa_set_ffuart_info(NULL); 510 pxa_set_btuart_info(NULL); 511 pxa_set_stuart_info(NULL); 512 513 if (0) /* dont know how to determine LCD */ 514 pxa_set_fb_info(NULL, &sharp_lcd); 515 else 516 pxa_set_fb_info(NULL, &toshiba_lcd); 517 518 pxa_set_mci_info(&trizeps4_mci_platform_data); 519#ifndef STATUS_LEDS_ON_STUART_PINS 520 pxa_set_ficp_info(&trizeps4_ficp_platform_data); 521#endif 522 pxa_set_ohci_info(&trizeps4_ohci_platform_data); 523 pxa_set_ac97_info(NULL); 524 pxa_set_i2c_info(NULL); 525 i2c_register_board_info(0, trizeps4_i2c_devices, 526 ARRAY_SIZE(trizeps4_i2c_devices)); 527 528 /* this is the reset value */ 529 trizeps_conxs_bcr = 0x00A0; 530 531 BCR_writew(trizeps_conxs_bcr); 532 board_backlight_power(1); 533 534 regulator_has_full_constraints(); 535} 536 537static void __init trizeps4_map_io(void) 538{ 539 pxa27x_map_io(); 540 iotable_init(trizeps4_io_desc, ARRAY_SIZE(trizeps4_io_desc)); 541 542 if ((__raw_readl(MSC0) & 0x8) && (__raw_readl(BOOT_DEF) & 0x1)) { 543 /* if flash is 16 bit wide its a Trizeps4 WL */ 544 __machine_arch_type = MACH_TYPE_TRIZEPS4WL; 545 trizeps4_flash_data[0].width = 2; 546 } else { 547 /* if flash is 32 bit wide its a Trizeps4 */ 548 __machine_arch_type = MACH_TYPE_TRIZEPS4; 549 trizeps4_flash_data[0].width = 4; 550 } 551} 552 553MACHINE_START(TRIZEPS4, "Keith und Koep Trizeps IV module") 554 /* MAINTAINER("Jürgen Schindele") */ 555 .atag_offset = 0x100, 556 .init_machine = trizeps4_init, 557 .map_io = trizeps4_map_io, 558 .nr_irqs = PXA_NR_IRQS, 559 .init_irq = pxa27x_init_irq, 560 .handle_irq = pxa27x_handle_irq, 561 .init_time = pxa_timer_init, 562 .restart = pxa_restart, 563MACHINE_END 564 565MACHINE_START(TRIZEPS4WL, "Keith und Koep Trizeps IV-WL module") 566 /* MAINTAINER("Jürgen Schindele") */ 567 .atag_offset = 0x100, 568 .init_machine = trizeps4_init, 569 .map_io = trizeps4_map_io, 570 .nr_irqs = PXA_NR_IRQS, 571 .init_irq = pxa27x_init_irq, 572 .handle_irq = pxa27x_handle_irq, 573 .init_time = pxa_timer_init, 574 .restart = pxa_restart, 575MACHINE_END