/* * Copyright 2009 Freescale Semiconductor, Inc. All Rights Reserved. * Copyright 2009 - 2010 Digi International, Inc. All Rights Reserved. */ /* * The code contained herein is licensed under the GNU General Public * License. You may obtain a copy of the GNU General Public License * Version 2 or later at the following locations: * * http://www.opensource.org/licenses/gpl-license.html * http://www.gnu.org/copyleft/gpl.html */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "board-ccwmx51.h" #include "iomux.h" #include "crm_regs.h" #include "devices.h" #include "mx51_pins.h" #include "displays/displays.h" #include #if defined(CONFIG_MTD) || defined(CONFIG_MTD_MODULE) #include #include #include #include #endif #if defined(CONFIG_MTD_NAND_MXC) \ || defined(CONFIG_MTD_NAND_MXC_MODULE) \ || defined(CONFIG_MTD_NAND_MXC_V2) \ || defined(CONFIG_MTD_NAND_MXC_V2_MODULE) \ || defined(CONFIG_MTD_NAND_MXC_V3) \ || defined(CONFIG_MTD_NAND_MXC_V3_MODULE) extern void gpio_nand_active(void); extern void gpio_nand_inactive(void); static int nand_init(void) { /* Configure the pins */ gpio_nand_active(); return 0; } static void nand_exit(void) { /* Free the pins */ gpio_nand_inactive(); } struct flash_platform_data mxc_nand_data = { .width = 1, .init = nand_init, .exit = nand_exit, }; #endif #if defined(CONFIG_SMSC911X) || defined(CONFIG_SMSC911X_MODULE) struct smsc911x_platform_config ccwmx51_smsc9118 = { .flags = SMSC911X_USE_32BIT, .irq_polarity = SMSC911X_IRQ_POLARITY_ACTIVE_LOW, .irq_type = SMSC911X_IRQ_POLARITY_ACTIVE_HIGH, /* push-pull irq */ }; #endif #if defined(CONFIG_MMC_IMX_ESDHCI) || defined(CONFIG_MMC_IMX_ESDHCI_MODULE) static int sdhc_write_protect(struct device *dev) { unsigned short rc = 0; if (to_platform_device(dev)->id == 0) rc = 0; /* Not supported WP on JSK board, therefore write is enabled */ else if (to_platform_device(dev)->id == 2) rc = gpio_get_value(IOMUX_TO_GPIO(MX51_PIN_NANDF_CS1)); return rc; } static unsigned int sdhc_get_card_det_status(struct device *dev) { int ret = 0; if (to_platform_device(dev)->id == 0) ret = gpio_get_value(IOMUX_TO_GPIO(MX51_PIN_GPIO1_0)); else if (to_platform_device(dev)->id == 2) ret = gpio_get_value(IOMUX_TO_GPIO(MX51_PIN_GPIO_NAND)); return ret; } struct mxc_mmc_platform_data mmc1_data = { .ocr_mask = MMC_VDD_31_32, .caps = MMC_CAP_4_BIT_DATA, .min_clk = 400000, .max_clk = 52000000, .card_inserted_state = 0, .status = sdhc_get_card_det_status, .wp_status = sdhc_write_protect, .clock_mmc = "esdhc_clk", .power_mmc = NULL, }; struct mxc_mmc_platform_data mmc3_data = { .ocr_mask = MMC_VDD_27_28 | MMC_VDD_28_29 | MMC_VDD_29_30 | MMC_VDD_31_32, .caps = MMC_CAP_4_BIT_DATA, .min_clk = 150000, .max_clk = 50000000, .card_inserted_state = 1, .status = sdhc_get_card_det_status, .wp_status = sdhc_write_protect, .clock_mmc = "esdhc_clk", .power_mmc = NULL, }; #endif #if defined(CONFIG_FB_MXC_SYNC_PANEL) || defined(CONFIG_FB_MXC_SYNC_PANEL_MODULE) struct resource mxcfb_resources[1] = { { .flags = IORESOURCE_MEM, }, }; #endif static struct i2c_board_info ccwmx51_i2c_devices[] __initdata = { #if defined(CONFIG_INPUT_MMA7455L) || defined(CONFIG_INPUT_MMA7455L_MODULE) { I2C_BOARD_INFO("mma7455l", 0x1d), .irq = IOMUX_TO_IRQ(MX51_PIN_GPIO1_7), }, #endif #if defined(CONFIG_SND_SOC_IMX_CCWMX51_WM8753) || defined(CONFIG_SND_SOC_IMX_CCWMX51_WM8753_MODULE) { I2C_BOARD_INFO("wm8753", 0x1A), }, #endif }; int __init ccwmx51_init_i2c2(void) { return i2c_register_board_info(1, ccwmx51_i2c_devices , ARRAY_SIZE(ccwmx51_i2c_devices) ); } struct mxc_i2c_platform_data mxci2c_data = { .i2c_clk = 100000, }; struct mxc_i2c_platform_data mxci2c_hs_data = { .i2c_clk = 400000, }; #if defined(CONFIG_SPI_MXC_SELECT1_SS1) && (defined(CONFIG_SPI_MXC) || defined(CONFIG_SPI_MXC_MODULE)) static struct spi_board_info spi_devices[] = { #if defined(CONFIG_SPI_SPIDEV) || defined(CONFIG_SPI_SPIDEV_MODULE) { /* SPIDEV */ .modalias = "spidev", .max_speed_hz = 6000000, .bus_num = 1, .chip_select = 1, }, /* Add here other SPI devices, if any... */ #endif }; void ccwmx51_init_spidevices(void) { spi_register_board_info(spi_devices, ARRAY_SIZE(spi_devices)); } #else void ccwmx51_init_spidevices(void) { } #endif extern void ccwmx51_gpio_spi_chipselect_active(int cspi_mode, int status, int chipselect); extern void ccwmx51_gpio_spi_chipselect_inactive(int cspi_mode, int status, int chipselect); struct mxc_spi_master mxcspi1_data = { .maxchipselect = 4, .spi_version = 23, .chipselect_active = ccwmx51_gpio_spi_chipselect_active, .chipselect_inactive = ccwmx51_gpio_spi_chipselect_inactive, }; struct mxc_srtc_platform_data srtc_data = { .srtc_sec_mode_addr = 0x83F98840, }; struct mxc_ipu_config mxc_ipu_data = { .rev = 2, }; #if defined(CONFIG_W1_MASTER_MXC) || defined(CONFIG_W1_MASTER_MXC_MODULE) struct mxc_w1_config mxc_w1_data = { .search_rom_accelerator = 1, }; #endif #if defined(CONFIG_SMSC911X) || defined(CONFIG_SMSC911X_MODULE) static struct resource smsc911x_device_resources[] = { { .name = "smsc911x-memory", .start = CS5_BASE_ADDR, .end = CS5_BASE_ADDR + SZ_4K - 1, .flags = IORESOURCE_MEM, }, { .start = IOMUX_TO_IRQ(MX51_PIN_GPIO1_9), .end = IOMUX_TO_IRQ(MX51_PIN_GPIO1_9), .flags = IORESOURCE_IRQ, }, }; struct platform_device smsc911x_device = { .name = "smsc911x", .id = -1, .num_resources = ARRAY_SIZE(smsc911x_device_resources), .resource = smsc911x_device_resources, }; /* WEIM registers */ #define CSGCR1 0x00 #define CSGCR2 0x04 #define CSRCR1 0x08 #define CSRCR2 0x0C #define CSWCR1 0x10 static void __init ccwmx51_init_ext_eth_mac(void) { __iomem u32 *weim_vbaddr; weim_vbaddr = ioremap(WEIM_BASE_ADDR, SZ_4K); if (weim_vbaddr == 0) { printk(KERN_ERR "Unable to ioremap 0x%08x in %s\n", WEIM_BASE_ADDR, __func__); return; } /** Configure the CS timming, bus width, etc. * 16 bit on DATA[31..16], not multiplexed, async * RWSC=50, RADVA=2, RADVN=6, OEA=0, OEN=0, RCSA=0, RCSN=0, APR=0 * WAL=0, WBED=1, WWSC=50, WADVA=2, WADVN=6, WEA=0, WEN=0, WCSA=0 */ writel(0x00420081, (unsigned int)(weim_vbaddr) + 0x78 + CSGCR1); writel(0, (unsigned int)(weim_vbaddr) + 0x78 + CSGCR2); writel(0x32260000, (unsigned int)(weim_vbaddr) + 0x78 + CSRCR1); writel(0, (unsigned int)(weim_vbaddr) + 0x78 + CSRCR2); writel(0x72080f00, (unsigned int)(weim_vbaddr) + 0x78 + CSWCR1); iounmap(weim_vbaddr); /* Configure interrupt line as GPIO input, the iomux should be already setup */ gpio_request(IOMUX_TO_GPIO(MX51_PIN_GPIO1_9), "LAN2-irq"); gpio_direction_input(IOMUX_TO_GPIO(MX51_PIN_GPIO1_9)); } #endif #if defined(CONFIG_SND_SOC_IMX_CCWMX51_WM8753) || defined(CONFIG_SND_SOC_IMX_CCWMX51_WM8753_MODULE) struct platform_device mxc_wm8753_device = { .name = "ccwmx51js", }; #endif struct mxc_spdif_platform_data mxc_spdif_data = { .spdif_tx = 1, .spdif_rx = 0, .spdif_clk_44100 = 0, /* spdif_ext_clk source for 44.1KHz */ .spdif_clk_48000 = 7, /* audio osc source */ .spdif_clkid = 0, .spdif_clk = NULL, /* spdif bus clk */ }; struct tve_platform_data tve_data = { .dac_reg = "VVIDEO", .dig_reg = "VDIG", }; struct mxc_dvfs_platform_data dvfs_core_data = { .reg_id = "SW1", .clk1_id = "cpu_clk", .clk2_id = "gpc_dvfs_clk", .gpc_cntr_reg_addr = MXC_GPC_CNTR, .gpc_vcr_reg_addr = MXC_GPC_VCR, .ccm_cdcr_reg_addr = MXC_CCM_CDCR, .ccm_cacrr_reg_addr = MXC_CCM_CACRR, .ccm_cdhipr_reg_addr = MXC_CCM_CDHIPR, .dvfs_thrs_reg_addr = MXC_DVFSTHRS, .dvfs_coun_reg_addr = MXC_DVFSCOUN, .dvfs_emac_reg_addr = MXC_DVFSEMAC, .dvfs_cntr_reg_addr = MXC_DVFSCNTR, .prediv_mask = 0x1F800, .prediv_offset = 11, .prediv_val = 3, .div3ck_mask = 0xE0000000, .div3ck_offset = 29, .div3ck_val = 2, .emac_val = 0x08, .upthr_val = 25, .dnthr_val = 9, .pncthr_val = 33, .upcnt_val = 10, .dncnt_val = 10, .delay_time = 30, .num_wp = 3, }; struct mxc_dvfsper_data dvfs_per_data = { .reg_id = "SW2", .clk_id = "gpc_dvfs_clk", .gpc_cntr_reg_addr = MXC_GPC_CNTR, .gpc_vcr_reg_addr = MXC_GPC_VCR, .gpc_adu = 0x0, .vai_mask = MXC_DVFSPMCR0_FSVAI_MASK, .vai_offset = MXC_DVFSPMCR0_FSVAI_OFFSET, .dvfs_enable_bit = MXC_DVFSPMCR0_DVFEN, .irq_mask = MXC_DVFSPMCR0_FSVAIM, .div3_offset = 0, .div3_mask = 0x7, .div3_div = 2, .lp_high = 1200000, .lp_low = 1200000, }; struct platform_pwm_backlight_data mxc_pwm_backlight_data = { .pwm_id = 0, .max_brightness = 255, .dft_brightness = 128, .pwm_period_ns = 78770, }; struct mxc_audio_platform_data wm8753_data = { .ssi_num = 1, .src_port = 2, .ext_port = 3, .sysclk = 12000000, }; struct mxc_fb_platform_data mx51_fb_data[] = { /*VGA*/ { .interface_pix_fmt = IPU_PIX_FMT_RGB24, .mode_str = "1024x768M-16@60", /* Default */ } }; #if defined(CONFIG_UIO_PDRV_GENIRQ) || defined(CONFIG_UIO_PDRV_GENIRQ_MODULE) struct uio_info gpu2d_platform_data = { .name = "imx_gpu2d", .version = "1", .irq = MXC_INT_GPU2_IRQ, .open = gpu2d_open, .release = gpu2d_release, .mmap = gpu2d_mmap, }; #endif #if defined(CONFIG_FB_MXC_SYNC_PANEL) || defined(CONFIG_FB_MXC_SYNC_PANEL_MODULE) struct ccwmx51_lcd_pdata * plcd_platform_data; struct ccwmx51_lcd_pdata * ccwmx51_get_display(char *name) { #if defined(CONFIG_CCWMX51_LQ070Y3DG3B) || defined(CONFIG_CCWMX51_CUSTOM) int i; for (i = 0; i < ARRAY_SIZE(lcd_display_list); i++) if (!strncmp(lcd_display_list[i].fb_pdata.mode->name, name, strlen(lcd_display_list[i].fb_pdata.mode->name))) return &lcd_display_list[i]; #endif return NULL; } int __init ccwmx51_init_fb(void) { char *options = NULL, *p; if (fb_get_options("displayfb", &options)) pr_warning("no display information available in command line\n"); if (!options) return -ENODEV; if (!strncasecmp(options, "VGA", 3)) { pr_info("VGA interface is primary\n"); /* Get the desired configuration provided by the bootloader */ if (options[3] != '@') { pr_info("Video resolution for VGA interface not provided, using default\n"); /* TODO set default video here */ } else { options = &options[4]; if (((p = strsep (&options, "@")) != NULL) && *p) { if (!strcmp(p, "640x480x16")) { strcpy(mx51_fb_data[0].mode_str, "640x480M-16@60"); } else if (!strcmp(p, "800x600x16")) { strcpy(mx51_fb_data[0].mode_str, "800x600M-16@60"); } else if (!strcmp(p, "1024x768x16")) { strcpy(mx51_fb_data[0].mode_str, "1024x768M-16@60"); } else if (!strcmp(p, "1280x1024x16")) { strcpy(mx51_fb_data[0].mode_str, "1280x1024M-16@60"); } else pr_warning("Unsuported video resolution: %s, using default\n", p); } } } else { if ((plcd_platform_data = ccwmx51_get_display(options)) != NULL) { memcpy(&mx51_fb_data[0], &plcd_platform_data->fb_pdata, sizeof(struct mxc_fb_platform_data)); plcd_platform_data->vif = 0; /* Select video interface 0 */ } } return 0; } device_initcall(ccwmx51_init_fb); #endif void __init ccwmx51_init_devices ( void ) { #if defined(CONFIG_SMSC911X) || defined(CONFIG_SMSC911X_MODULE) ccwmx51_init_ext_eth_mac(); #endif }