Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 /*
0003  *  linux/arch/arm/mach-pxa/trizeps4.c
0004  *
0005  *  Support for the Keith und Koep Trizeps4 Module Platform.
0006  *
0007  *  Author: Jürgen Schindele
0008  *  Created:    20 02, 2006
0009  *  Copyright:  Jürgen Schindele
0010  */
0011 
0012 #include <linux/init.h>
0013 #include <linux/kernel.h>
0014 #include <linux/platform_device.h>
0015 #include <linux/interrupt.h>
0016 #include <linux/leds.h>
0017 #include <linux/export.h>
0018 #include <linux/sched.h>
0019 #include <linux/bitops.h>
0020 #include <linux/fb.h>
0021 #include <linux/ioport.h>
0022 #include <linux/delay.h>
0023 #include <linux/gpio.h>
0024 #include <linux/dm9000.h>
0025 #include <linux/mtd/physmap.h>
0026 #include <linux/mtd/partitions.h>
0027 #include <linux/regulator/machine.h>
0028 #include <linux/platform_data/i2c-pxa.h>
0029 
0030 #include <asm/types.h>
0031 #include <asm/setup.h>
0032 #include <asm/memory.h>
0033 #include <asm/mach-types.h>
0034 #include <asm/irq.h>
0035 #include <linux/sizes.h>
0036 
0037 #include <asm/mach/arch.h>
0038 #include <asm/mach/map.h>
0039 #include <asm/mach/irq.h>
0040 #include <asm/mach/flash.h>
0041 
0042 #include "pxa27x.h"
0043 #include "trizeps4.h"
0044 #include <linux/platform_data/asoc-pxa.h>
0045 #include <linux/platform_data/video-pxafb.h>
0046 #include <linux/platform_data/mmc-pxamci.h>
0047 #include <linux/platform_data/irda-pxaficp.h>
0048 #include <linux/platform_data/usb-ohci-pxa27x.h>
0049 #include "smemc.h"
0050 
0051 #include "generic.h"
0052 #include "devices.h"
0053 
0054 /*  comment out the following line if you want to use the
0055  *  Standard UART from PXA for serial / irda transmission
0056  *  and acivate it if you have status leds connected */
0057 #define STATUS_LEDS_ON_STUART_PINS 1
0058 
0059 /*****************************************************************************
0060  * MultiFunctionPins of CPU
0061  *****************************************************************************/
0062 static unsigned long trizeps4_pin_config[] __initdata = {
0063     /* Chip Selects */
0064     GPIO15_nCS_1,       /* DiskOnChip CS */
0065     GPIO93_GPIO,        /* TRIZEPS4_DOC_IRQ */
0066     GPIO94_GPIO,        /* DOC lock */
0067 
0068     GPIO78_nCS_2,       /* DM9000 CS */
0069     GPIO101_GPIO,       /* TRIZEPS4_ETH_IRQ */
0070 
0071     GPIO79_nCS_3,       /* Logic CS */
0072     GPIO0_GPIO | WAKEUP_ON_EDGE_RISE,   /* Logic irq */
0073 
0074     /* AC97 */
0075     GPIO28_AC97_BITCLK,
0076     GPIO29_AC97_SDATA_IN_0,
0077     GPIO30_AC97_SDATA_OUT,
0078     GPIO31_AC97_SYNC,
0079 
0080     /* LCD - 16bpp Active TFT */
0081     GPIOxx_LCD_TFT_16BPP,
0082 
0083     /* UART */
0084     GPIO9_FFUART_CTS,
0085     GPIO10_FFUART_DCD,
0086     GPIO16_FFUART_TXD,
0087     GPIO33_FFUART_DSR,
0088     GPIO38_FFUART_RI,
0089     GPIO82_FFUART_DTR,
0090     GPIO83_FFUART_RTS,
0091     GPIO96_FFUART_RXD,
0092 
0093     GPIO42_BTUART_RXD,
0094     GPIO43_BTUART_TXD,
0095     GPIO44_BTUART_CTS,
0096     GPIO45_BTUART_RTS,
0097 #ifdef STATUS_LEDS_ON_STUART_PINS
0098     GPIO46_GPIO,
0099     GPIO47_GPIO,
0100 #else
0101     GPIO46_STUART_RXD,
0102     GPIO47_STUART_TXD,
0103 #endif
0104     /* PCMCIA */
0105     GPIO11_GPIO,            /* TRIZEPS4_CD_IRQ */
0106     GPIO13_GPIO,            /* TRIZEPS4_READY_NINT */
0107     GPIO48_nPOE,
0108     GPIO49_nPWE,
0109     GPIO50_nPIOR,
0110     GPIO51_nPIOW,
0111     GPIO54_nPCE_2,
0112     GPIO55_nPREG,
0113     GPIO56_nPWAIT,
0114     GPIO57_nIOIS16,
0115     GPIO102_nPCE_1,
0116     GPIO104_PSKTSEL,
0117 
0118     /* MultiMediaCard */
0119     GPIO32_MMC_CLK,
0120     GPIO92_MMC_DAT_0,
0121     GPIO109_MMC_DAT_1,
0122     GPIO110_MMC_DAT_2,
0123     GPIO111_MMC_DAT_3,
0124     GPIO112_MMC_CMD,
0125     GPIO12_GPIO,            /* TRIZEPS4_MMC_IRQ */
0126 
0127     /* USB OHCI */
0128     GPIO88_USBH1_PWR,       /* USBHPWR1 */
0129     GPIO89_USBH1_PEN,       /* USBHPEN1 */
0130 
0131     /* I2C */
0132     GPIO117_I2C_SCL,
0133     GPIO118_I2C_SDA,
0134 };
0135 
0136 static unsigned long trizeps4wl_pin_config[] __initdata = {
0137     /* SSP 2 */
0138     GPIO14_SSP2_SFRM,
0139     GPIO19_SSP2_SCLK,
0140     GPIO53_GPIO,            /* TRIZEPS4_SPI_IRQ */
0141     GPIO86_SSP2_RXD,
0142     GPIO87_SSP2_TXD,
0143 };
0144 
0145 /****************************************************************************
0146  * ONBOARD FLASH
0147  ****************************************************************************/
0148 static struct mtd_partition trizeps4_partitions[] = {
0149     {
0150         .name =     "Bootloader",
0151         .offset =   0x00000000,
0152         .size =     0x00040000,
0153         .mask_flags =   MTD_WRITEABLE  /* force read-only */
0154     }, {
0155         .name =     "Backup",
0156         .offset =   0x00040000,
0157         .size =     0x00040000,
0158     }, {
0159         .name =     "Image",
0160         .offset =   0x00080000,
0161         .size =     0x01080000,
0162     }, {
0163         .name =     "IPSM",
0164         .offset =   0x01100000,
0165         .size =     0x00e00000,
0166     }, {
0167         .name =     "Registry",
0168         .offset =   0x01f00000,
0169         .size =     MTDPART_SIZ_FULL,
0170     }
0171 };
0172 
0173 static struct physmap_flash_data trizeps4_flash_data[] = {
0174     {
0175         .width      = 4,            /* bankwidth in bytes */
0176         .parts      = trizeps4_partitions,
0177         .nr_parts   = ARRAY_SIZE(trizeps4_partitions)
0178     }
0179 };
0180 
0181 static struct resource flash_resource = {
0182     .start  = PXA_CS0_PHYS,
0183     .end    = PXA_CS0_PHYS + SZ_32M - 1,
0184     .flags  = IORESOURCE_MEM,
0185 };
0186 
0187 static struct platform_device flash_device = {
0188     .name       = "physmap-flash",
0189     .id     = 0,
0190     .dev = {
0191         .platform_data = trizeps4_flash_data,
0192     },
0193     .resource = &flash_resource,
0194     .num_resources = 1,
0195 };
0196 
0197 /****************************************************************************
0198  * DAVICOM DM9000 Ethernet
0199  ****************************************************************************/
0200 static struct resource dm9000_resources[] = {
0201     [0] = {
0202         .start  = TRIZEPS4_ETH_PHYS+0x300,
0203         .end    = TRIZEPS4_ETH_PHYS+0x400-1,
0204         .flags  = IORESOURCE_MEM,
0205     },
0206     [1] = {
0207         .start  = TRIZEPS4_ETH_PHYS+0x8300,
0208         .end    = TRIZEPS4_ETH_PHYS+0x8400-1,
0209         .flags  = IORESOURCE_MEM,
0210     },
0211     [2] = {
0212         .start  = TRIZEPS4_ETH_IRQ,
0213         .end    = TRIZEPS4_ETH_IRQ,
0214         .flags  = IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHEDGE,
0215     },
0216 };
0217 
0218 static struct dm9000_plat_data tri_dm9000_platdata = {
0219     .flags      = DM9000_PLATF_32BITONLY,
0220 };
0221 
0222 static struct platform_device dm9000_device = {
0223     .name       = "dm9000",
0224     .id     = -1,
0225     .num_resources  = ARRAY_SIZE(dm9000_resources),
0226     .resource   = dm9000_resources,
0227     .dev        = {
0228         .platform_data = &tri_dm9000_platdata,
0229     }
0230 };
0231 
0232 /****************************************************************************
0233  * LED's on GPIO pins of PXA
0234  ****************************************************************************/
0235 static struct gpio_led trizeps4_led[] = {
0236 #ifdef STATUS_LEDS_ON_STUART_PINS
0237     {
0238         .name = "led0:orange:heartbeat",    /* */
0239         .default_trigger = "heartbeat",
0240         .gpio = GPIO_HEARTBEAT_LED,
0241         .active_low = 1,
0242     },
0243     {
0244         .name = "led1:yellow:cpubusy",      /* */
0245         .default_trigger = "cpu-busy",
0246         .gpio = GPIO_SYS_BUSY_LED,
0247         .active_low = 1,
0248     },
0249 #endif
0250 };
0251 
0252 static struct gpio_led_platform_data trizeps4_led_data = {
0253     .leds       = trizeps4_led,
0254     .num_leds   = ARRAY_SIZE(trizeps4_led),
0255 };
0256 
0257 static struct platform_device leds_devices = {
0258     .name       = "leds-gpio",
0259     .id     = -1,
0260     .dev        = {
0261         .platform_data  = &trizeps4_led_data,
0262     },
0263 };
0264 
0265 static struct platform_device *trizeps4_devices[] __initdata = {
0266     &flash_device,
0267     &dm9000_device,
0268     &leds_devices,
0269 };
0270 
0271 static struct platform_device *trizeps4wl_devices[] __initdata = {
0272     &flash_device,
0273     &leds_devices,
0274 };
0275 
0276 static short trizeps_conxs_bcr;
0277 
0278 /* PCCARD power switching supports only 3,3V */
0279 void board_pcmcia_power(int power)
0280 {
0281     if (power) {
0282         /* switch power on, put in reset and enable buffers */
0283         trizeps_conxs_bcr |= power;
0284         trizeps_conxs_bcr |= ConXS_BCR_CF_RESET;
0285         trizeps_conxs_bcr &= ~ConXS_BCR_CF_BUF_EN;
0286         BCR_writew(trizeps_conxs_bcr);
0287         /* wait a little */
0288         udelay(2000);
0289         /* take reset away */
0290         trizeps_conxs_bcr &= ~ConXS_BCR_CF_RESET;
0291         BCR_writew(trizeps_conxs_bcr);
0292         udelay(2000);
0293     } else {
0294         /* put in reset */
0295         trizeps_conxs_bcr |= ConXS_BCR_CF_RESET;
0296         BCR_writew(trizeps_conxs_bcr);
0297         udelay(1000);
0298         /* switch power off */
0299         trizeps_conxs_bcr &= ~0xf;
0300         BCR_writew(trizeps_conxs_bcr);
0301     }
0302     pr_debug("%s: o%s 0x%x\n", __func__, power ? "n" : "ff",
0303             trizeps_conxs_bcr);
0304 }
0305 EXPORT_SYMBOL(board_pcmcia_power);
0306 
0307 /* backlight power switching for LCD panel */
0308 static void board_backlight_power(int on)
0309 {
0310     if (on)
0311         trizeps_conxs_bcr |= ConXS_BCR_L_DISP;
0312     else
0313         trizeps_conxs_bcr &= ~ConXS_BCR_L_DISP;
0314 
0315     pr_debug("%s: o%s 0x%x\n", __func__, on ? "n" : "ff",
0316             trizeps_conxs_bcr);
0317     BCR_writew(trizeps_conxs_bcr);
0318 }
0319 
0320 /* a I2C based RTC is known on CONXS board */
0321 static struct i2c_board_info trizeps4_i2c_devices[] __initdata = {
0322     { I2C_BOARD_INFO("rtc-pcf8593", 0x51) }
0323 };
0324 
0325 /****************************************************************************
0326  * MMC card slot external to module
0327  ****************************************************************************/
0328 static int trizeps4_mci_init(struct device *dev, irq_handler_t mci_detect_int,
0329         void *data)
0330 {
0331     int err;
0332 
0333     err = request_irq(TRIZEPS4_MMC_IRQ, mci_detect_int,
0334               IRQF_TRIGGER_RISING, "MMC card detect", data);
0335     if (err) {
0336         printk(KERN_ERR "trizeps4_mci_init: MMC/SD: can't request"
0337                         "MMC card detect IRQ\n");
0338         return -1;
0339     }
0340     return 0;
0341 }
0342 
0343 static void trizeps4_mci_exit(struct device *dev, void *data)
0344 {
0345     free_irq(TRIZEPS4_MMC_IRQ, data);
0346 }
0347 
0348 static struct pxamci_platform_data trizeps4_mci_platform_data = {
0349     .ocr_mask   = MMC_VDD_32_33|MMC_VDD_33_34,
0350     .detect_delay_ms= 10,
0351     .init       = trizeps4_mci_init,
0352     .exit       = trizeps4_mci_exit,
0353     .get_ro     = NULL, /* write-protection not supported */
0354     .setpower   = NULL, /* power-switching not supported */
0355 };
0356 
0357 /****************************************************************************
0358  * IRDA mode switching on stuart
0359  ****************************************************************************/
0360 #ifndef STATUS_LEDS_ON_STUART_PINS
0361 static short trizeps_conxs_ircr;
0362 
0363 static int trizeps4_irda_startup(struct device *dev)
0364 {
0365     trizeps_conxs_ircr &= ~ConXS_IRCR_SD;
0366     IRCR_writew(trizeps_conxs_ircr);
0367     return 0;
0368 }
0369 
0370 static void trizeps4_irda_shutdown(struct device *dev)
0371 {
0372     trizeps_conxs_ircr |= ConXS_IRCR_SD;
0373     IRCR_writew(trizeps_conxs_ircr);
0374 }
0375 
0376 static void trizeps4_irda_transceiver_mode(struct device *dev, int mode)
0377 {
0378     unsigned long flags;
0379 
0380     local_irq_save(flags);
0381     /* Switch mode */
0382     if (mode & IR_SIRMODE)
0383         trizeps_conxs_ircr &= ~ConXS_IRCR_MODE; /* Slow mode */
0384     else if (mode & IR_FIRMODE)
0385         trizeps_conxs_ircr |= ConXS_IRCR_MODE;  /* Fast mode */
0386 
0387     /* Switch power */
0388     if (mode & IR_OFF)
0389         trizeps_conxs_ircr |= ConXS_IRCR_SD;
0390     else
0391         trizeps_conxs_ircr &= ~ConXS_IRCR_SD;
0392 
0393     IRCR_writew(trizeps_conxs_ircr);
0394     local_irq_restore(flags);
0395 
0396     pxa2xx_transceiver_mode(dev, mode);
0397 }
0398 
0399 static struct pxaficp_platform_data trizeps4_ficp_platform_data = {
0400     .gpio_pwdown        = -1,
0401     .transceiver_cap    = IR_SIRMODE | IR_FIRMODE | IR_OFF,
0402     .transceiver_mode   = trizeps4_irda_transceiver_mode,
0403     .startup        = trizeps4_irda_startup,
0404     .shutdown       = trizeps4_irda_shutdown,
0405 };
0406 #endif
0407 
0408 /****************************************************************************
0409  * OHCI USB port
0410  ****************************************************************************/
0411 static struct pxaohci_platform_data trizeps4_ohci_platform_data = {
0412     .port_mode  = PMM_PERPORT_MODE,
0413     .flags      = ENABLE_PORT_ALL | POWER_CONTROL_LOW | POWER_SENSE_LOW,
0414 };
0415 
0416 static struct map_desc trizeps4_io_desc[] __initdata = {
0417     {   /* ConXS CFSR */
0418         .virtual    = TRIZEPS4_CFSR_VIRT,
0419         .pfn        = __phys_to_pfn(TRIZEPS4_CFSR_PHYS),
0420         .length     = 0x00001000,
0421         .type       = MT_DEVICE
0422     },
0423     {   /* ConXS BCR */
0424         .virtual    = TRIZEPS4_BOCR_VIRT,
0425         .pfn        = __phys_to_pfn(TRIZEPS4_BOCR_PHYS),
0426         .length     = 0x00001000,
0427         .type       = MT_DEVICE
0428     },
0429     {   /* ConXS IRCR */
0430         .virtual    = TRIZEPS4_IRCR_VIRT,
0431         .pfn        = __phys_to_pfn(TRIZEPS4_IRCR_PHYS),
0432         .length     = 0x00001000,
0433         .type       = MT_DEVICE
0434     },
0435     {   /* ConXS DCR */
0436         .virtual    = TRIZEPS4_DICR_VIRT,
0437         .pfn        = __phys_to_pfn(TRIZEPS4_DICR_PHYS),
0438         .length     = 0x00001000,
0439         .type       = MT_DEVICE
0440     },
0441     {   /* ConXS UPSR */
0442         .virtual    = TRIZEPS4_UPSR_VIRT,
0443         .pfn        = __phys_to_pfn(TRIZEPS4_UPSR_PHYS),
0444         .length     = 0x00001000,
0445         .type       = MT_DEVICE
0446     }
0447 };
0448 
0449 static struct pxafb_mode_info sharp_lcd_mode = {
0450     .pixclock   = 78000,
0451     .xres       = 640,
0452     .yres       = 480,
0453     .bpp        = 8,
0454     .hsync_len  = 4,
0455     .left_margin    = 4,
0456     .right_margin   = 4,
0457     .vsync_len  = 2,
0458     .upper_margin   = 0,
0459     .lower_margin   = 0,
0460     .sync       = FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
0461     .cmap_greyscale = 0,
0462 };
0463 
0464 static struct pxafb_mach_info sharp_lcd = {
0465     .modes      = &sharp_lcd_mode,
0466     .num_modes  = 1,
0467     .lcd_conn   = LCD_COLOR_DSTN_16BPP | LCD_PCLK_EDGE_FALL,
0468     .cmap_inverse   = 0,
0469     .cmap_static    = 0,
0470     .pxafb_backlight_power = board_backlight_power,
0471 };
0472 
0473 static struct pxafb_mode_info toshiba_lcd_mode = {
0474     .pixclock   = 39720,
0475     .xres       = 640,
0476     .yres       = 480,
0477     .bpp        = 8,
0478     .hsync_len  = 63,
0479     .left_margin    = 12,
0480     .right_margin   = 12,
0481     .vsync_len  = 4,
0482     .upper_margin   = 32,
0483     .lower_margin   = 10,
0484     .sync       = 0,
0485     .cmap_greyscale = 0,
0486 };
0487 
0488 static struct pxafb_mach_info toshiba_lcd = {
0489     .modes      = &toshiba_lcd_mode,
0490     .num_modes  = 1,
0491     .lcd_conn   = (LCD_COLOR_TFT_16BPP | LCD_PCLK_EDGE_FALL),
0492     .cmap_inverse   = 0,
0493     .cmap_static    = 0,
0494     .pxafb_backlight_power = board_backlight_power,
0495 };
0496 
0497 static void __init trizeps4_init(void)
0498 {
0499     pxa2xx_mfp_config(ARRAY_AND_SIZE(trizeps4_pin_config));
0500     if (machine_is_trizeps4wl()) {
0501         pxa2xx_mfp_config(ARRAY_AND_SIZE(trizeps4wl_pin_config));
0502         platform_add_devices(trizeps4wl_devices,
0503                     ARRAY_SIZE(trizeps4wl_devices));
0504     } else {
0505         platform_add_devices(trizeps4_devices,
0506                     ARRAY_SIZE(trizeps4_devices));
0507     }
0508 
0509     pxa_set_ffuart_info(NULL);
0510     pxa_set_btuart_info(NULL);
0511     pxa_set_stuart_info(NULL);
0512 
0513     if (0)  /* dont know how to determine LCD */
0514         pxa_set_fb_info(NULL, &sharp_lcd);
0515     else
0516         pxa_set_fb_info(NULL, &toshiba_lcd);
0517 
0518     pxa_set_mci_info(&trizeps4_mci_platform_data);
0519 #ifndef STATUS_LEDS_ON_STUART_PINS
0520     pxa_set_ficp_info(&trizeps4_ficp_platform_data);
0521 #endif
0522     pxa_set_ohci_info(&trizeps4_ohci_platform_data);
0523     pxa_set_ac97_info(NULL);
0524     pxa_set_i2c_info(NULL);
0525     i2c_register_board_info(0, trizeps4_i2c_devices,
0526                     ARRAY_SIZE(trizeps4_i2c_devices));
0527 
0528     /* this is the reset value */
0529     trizeps_conxs_bcr = 0x00A0;
0530 
0531     BCR_writew(trizeps_conxs_bcr);
0532     board_backlight_power(1);
0533 
0534     regulator_has_full_constraints();
0535 }
0536 
0537 static void __init trizeps4_map_io(void)
0538 {
0539     pxa27x_map_io();
0540     iotable_init(trizeps4_io_desc, ARRAY_SIZE(trizeps4_io_desc));
0541 
0542     if ((__raw_readl(MSC0) & 0x8) && (__raw_readl(BOOT_DEF) & 0x1)) {
0543         /* if flash is 16 bit wide its a Trizeps4 WL */
0544         __machine_arch_type = MACH_TYPE_TRIZEPS4WL;
0545         trizeps4_flash_data[0].width = 2;
0546     } else {
0547         /* if flash is 32 bit wide its a Trizeps4 */
0548         __machine_arch_type = MACH_TYPE_TRIZEPS4;
0549         trizeps4_flash_data[0].width = 4;
0550     }
0551 }
0552 
0553 MACHINE_START(TRIZEPS4, "Keith und Koep Trizeps IV module")
0554     /* MAINTAINER("Jürgen Schindele") */
0555     .atag_offset    = 0x100,
0556     .init_machine   = trizeps4_init,
0557     .map_io     = trizeps4_map_io,
0558     .nr_irqs    = PXA_NR_IRQS,
0559     .init_irq   = pxa27x_init_irq,
0560     .handle_irq = pxa27x_handle_irq,
0561     .init_time  = pxa_timer_init,
0562     .restart    = pxa_restart,
0563 MACHINE_END
0564 
0565 MACHINE_START(TRIZEPS4WL, "Keith und Koep Trizeps IV-WL module")
0566     /* MAINTAINER("Jürgen Schindele") */
0567     .atag_offset    = 0x100,
0568     .init_machine   = trizeps4_init,
0569     .map_io     = trizeps4_map_io,
0570     .nr_irqs    = PXA_NR_IRQS,
0571     .init_irq   = pxa27x_init_irq,
0572     .handle_irq = pxa27x_handle_irq,
0573     .init_time  = pxa_timer_init,
0574     .restart    = pxa_restart,
0575 MACHINE_END