/* * Copyright (C) 2009-2010 Freescale Semiconductor, Inc. All Rights Reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program; if not, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "device.h" #include "mx23_pins.h" #include "mx23evk.h" #include "mach/mx23.h" #if defined(CONFIG_SERIAL_MXS_DUART) || \ defined(CONFIG_SERIAL_MXS_DUART_MODULE) static struct resource duart_resource[] = { { .flags = IORESOURCE_MEM, .start = DUART_PHYS_ADDR, .end = DUART_PHYS_ADDR + 0x1000 - 1, }, { .flags = IORESOURCE_IRQ, .start = IRQ_DEBUG_UART , .end = IRQ_DEBUG_UART , }, }; static void __init mx23_init_duart(void) { struct platform_device *pdev; pdev = mxs_get_device("mxs-duart", 0); if (pdev == NULL || IS_ERR(pdev)) return; pdev->resource = duart_resource; pdev->num_resources = ARRAY_SIZE(duart_resource); mxs_add_device(pdev, 3); } #else static void mx23_init_duart(void) { } #endif #if defined(CONFIG_MXS_DMA_ENGINE) static struct resource mxs_ahb_apbh_res = { .flags = IORESOURCE_MEM, .start = APBH_DMA_PHYS_ADDR, .end = APBH_DMA_PHYS_ADDR + 0x2000 - 1, }; static struct mxs_dma_plat_data mxs_ahb_apbh_data = { .chan_base = MXS_DMA_CHANNEL_AHB_APBH, .chan_num = 8, }; static struct resource mxs_ahb_apbx_res = { .flags = IORESOURCE_MEM, .start = APBX_DMA_PHYS_ADDR, .end = APBX_DMA_PHYS_ADDR + 0x2000 - 1, }; static struct mxs_dma_plat_data mxs_ahb_apbx_data = { .chan_base = MXS_DMA_CHANNEL_AHB_APBX, .chan_num = 16, }; static void __init mx23_init_dma(void) { int i; struct mxs_dev_lookup *lookup; struct platform_device *pdev; lookup = mxs_get_devices("mxs-dma"); if (lookup == NULL || IS_ERR(lookup)) return; for (i = 0; i < lookup->size; i++) { pdev = lookup->pdev + i; if (!strcmp(pdev->name, "mxs-dma-apbh")) { pdev->resource = &mxs_ahb_apbh_res; pdev->dev.platform_data = &mxs_ahb_apbh_data; } else if (!strcmp(pdev->name, "mxs-dma-apbx")) { pdev->resource = &mxs_ahb_apbx_res; pdev->dev.platform_data = &mxs_ahb_apbx_data; } else continue; pdev->num_resources = 1; mxs_add_device(pdev, 0); } } #else static void mx23_init_dma(void) { ; } #endif #if defined(CONFIG_FB_MXS) || defined(CONFIG_FB_MXS_MODULE) static struct resource framebuffer_resource[] = { { .flags = IORESOURCE_MEM, .start = LCDIF_PHYS_ADDR, .end = LCDIF_PHYS_ADDR + 0x2000 - 1, }, { .flags = IORESOURCE_IRQ, .start = IRQ_LCDIF_ERROR, .end = IRQ_LCDIF_ERROR, }, }; static struct mxs_platform_fb_data mxs_framebuffer_pdata = { .list = LIST_HEAD_INIT(mxs_framebuffer_pdata.list), }; static void __init mx23_init_lcdif(void) { struct platform_device *pdev; pdev = mxs_get_device("mxs-fb", 0); if (pdev == NULL || IS_ERR(pdev)) return; pdev->resource = framebuffer_resource; pdev->num_resources = ARRAY_SIZE(framebuffer_resource); pdev->dev.platform_data = &mxs_framebuffer_pdata; mxs_add_device(pdev, 3); } #else static void __init mx23_init_lcdif(void) { ; } #endif #if defined(CONFIG_VIDEO_MXS_PXP) || \ defined(CONFIG_VIDEO_MXS_PXP_MODULE) static struct resource pxp_resource[] = { { .flags = IORESOURCE_MEM, .start = (unsigned int)IO_ADDRESS(PXP_PHYS_ADDR), .end = (unsigned int)IO_ADDRESS(PXP_PHYS_ADDR) + 0x2000 - 1, }, { .flags = IORESOURCE_IRQ, .start = IRQ_PXP, .end = IRQ_PXP, }, }; static void __init mx23_init_pxp(void) { struct platform_device *pdev; pdev = mxs_get_device("mxs-pxp", 0); if (pdev == NULL || IS_ERR(pdev)) return; pdev->resource = pxp_resource; pdev->num_resources = ARRAY_SIZE(pxp_resource); mxs_add_device(pdev, 3); } #else static void __init mx23_init_pxp(void) { ; } #endif #if defined(CONFIG_MXS_VIIM) || defined(CONFIG_MXS_VIIM_MODULE) struct resource viim_resources[] = { [0] = { .start = DIGCTL_PHYS_ADDR, .end = DIGCTL_PHYS_ADDR + PAGE_SIZE - 1, .flags = IORESOURCE_MEM, }, [1] = { .start = OCOTP_PHYS_ADDR, .end = OCOTP_PHYS_ADDR + PAGE_SIZE - 1, .flags = IORESOURCE_MEM, }, }; static void __init mx23_init_viim(void) { struct platform_device *pdev; pdev = mxs_get_device("mxs_viim", 0); if (pdev == NULL || IS_ERR(pdev)) return; pdev->resource = viim_resources; pdev->num_resources = ARRAY_SIZE(viim_resources); mxs_add_device(pdev, 2); } #else static void __init mx23_init_viim(void) { } #endif #if defined(CONFIG_I2C_MXS) || \ defined(CONFIG_I2C_MXS_MODULE) static struct resource i2c_resource[] = { { .flags = IORESOURCE_MEM, .start = I2C0_PHYS_ADDR, .end = I2C0_PHYS_ADDR + 0x2000 - 1, }, { .flags = IORESOURCE_DMA, .start = MXS_DMA_CHANNEL_AHB_APBX_I2C, .end = MXS_DMA_CHANNEL_AHB_APBX_I2C, }, { .flags = IORESOURCE_IRQ, .start = IRQ_I2C_ERROR, .end = IRQ_I2C_ERROR, }, { .flags = IORESOURCE_IRQ, .start = IRQ_I2C_DMA, .end = IRQ_I2C_DMA, }, }; static struct mxs_i2c_plat_data i2c_platdata = { #ifdef CONFIG_I2C_MXS_SELECT0_PIOQUEUE_MODE .pioqueue_mode = 0, #endif }; static void __init mx23_init_i2c(void) { struct platform_device *pdev; pdev = mxs_get_device("mxs-i2c", 0); if (pdev == NULL || IS_ERR(pdev)) return; pdev->resource = i2c_resource; pdev->num_resources = ARRAY_SIZE(i2c_resource); pdev->dev.platform_data = &i2c_platdata; mxs_add_device(pdev, 2); } #else static void __init mx23_init_i2c(void) { } #endif #if defined(CONFIG_MXS_WATCHDOG) || defined(CONFIG_MXS_WATCHDOG_MODULE) static struct resource mx23_wdt_res = { .flags = IORESOURCE_MEM, .start = RTC_PHYS_ADDR, .end = RTC_PHYS_ADDR + 0x2000 - 1, }; static void __init mx23_init_wdt(void) { struct platform_device *pdev; pdev = mxs_get_device("mxs-wdt", 0); if (pdev == NULL || IS_ERR(pdev)) return; pdev->resource = &mx23_wdt_res; pdev->num_resources = 1; mxs_add_device(pdev, 3); } #else static void __init mx23_init_wdt(void) { ; } #endif #if defined(CONFIG_RTC_DRV_MXS) || defined(CONFIG_RTC_DRV_MXS_MODULE) static struct resource mx23_rtc_res[] = { { .flags = IORESOURCE_MEM, .start = RTC_PHYS_ADDR, .end = RTC_PHYS_ADDR + 0x2000 - 1, }, { .flags = IORESOURCE_IRQ, .start = IRQ_RTC_ALARM, .end = IRQ_RTC_ALARM, }, { .flags = IORESOURCE_IRQ, .start = IRQ_RTC_1MSEC, .end = IRQ_RTC_1MSEC, }, }; static void __init mx23_init_rtc(void) { struct platform_device *pdev; pdev = mxs_get_device("mxs-rtc", 0); if (pdev == NULL || IS_ERR(pdev)) return; pdev->resource = mx23_rtc_res; pdev->num_resources = ARRAY_SIZE(mx23_rtc_res); mxs_add_device(pdev, 3); } #else static void __init mx23_init_rtc(void) { ; } #endif #ifdef CONFIG_MXS_LRADC struct mxs_lradc_plat_data mx23_lradc_data = { .vddio_voltage = BV_LRADC_CTRL4_LRADC6SELECT__CHANNEL6, .battery_voltage = BV_LRADC_CTRL4_LRADC7SELECT__CHANNEL7, }; static struct resource mx23_lradc_res[] = { { .flags = IORESOURCE_MEM, .start = LRADC_PHYS_ADDR, .end = LRADC_PHYS_ADDR + 0x2000 - 1, }, }; static void __init mx23_init_lradc(void) { struct platform_device *pdev; pdev = mxs_get_device("mxs-lradc", 0); if (pdev == NULL || IS_ERR(pdev)) return; pdev->resource = mx23_lradc_res; pdev->num_resources = ARRAY_SIZE(mx23_lradc_res); pdev->dev.platform_data = &mx23_lradc_data; mxs_add_device(pdev, 0); } #else static void __init mx23_init_lradc(void) { ; } #endif #if defined(CONFIG_KEYBOARD_MXS) || defined(CONFIG_KEYBOARD_MXS_MODULE) static struct mxskbd_keypair keyboard_data[] = { { 100, KEY_F1 }, { 306, KEY_RIGHT}, { 626, KEY_F2}, { 932, KEY_LEFT }, { 1584, KEY_UP }, { 2207, KEY_DOWN }, { 1907, KEY_F3 }, { 2831, KEY_SELECT }, { -1, 0 }, }; static struct mxs_kbd_plat_data mxs_kbd_data = { .keypair = keyboard_data, .channel = LRADC_CH0, }; static struct resource mx23_kbd_res[] = { { .flags = IORESOURCE_MEM, .start = LRADC_PHYS_ADDR, .end = LRADC_PHYS_ADDR + 0x2000 - 1, }, { .flags = IORESOURCE_IRQ, .start = IRQ_LRADC_CH0, .end = IRQ_LRADC_CH0, }, }; static void __init mx23_init_kbd(void) { struct platform_device *pdev; pdev = mxs_get_device("mxs-kbd", 0); if (pdev == NULL || IS_ERR(pdev)) return; pdev->resource = mx23_kbd_res; pdev->num_resources = ARRAY_SIZE(mx23_kbd_res); pdev->dev.platform_data = &mxs_kbd_data; mxs_add_device(pdev, 3); } #else static void __init mx23_init_kbd(void) { ; } #endif #if defined(CONFIG_TOUCHSCREEN_MXS) || defined(CONFIG_TOUCHSCREEN_MXS_MODULE) static struct mxs_touchscreen_plat_data mx23_ts_data = { .x_plus_chan = LRADC_TOUCH_X_PLUS, .x_minus_chan = LRADC_TOUCH_X_MINUS, .y_plus_chan = LRADC_TOUCH_Y_PLUS, .y_minus_chan = LRADC_TOUCH_Y_MINUS, .x_plus_val = BM_LRADC_CTRL0_XPLUS_ENABLE, .x_minus_val = BM_LRADC_CTRL0_XMINUS_ENABLE, .y_plus_val = BM_LRADC_CTRL0_YPLUS_ENABLE, .y_minus_val = BM_LRADC_CTRL0_YMINUS_ENABLE, .x_plus_mask = BM_LRADC_CTRL0_XPLUS_ENABLE, .x_minus_mask = BM_LRADC_CTRL0_XMINUS_ENABLE, .y_plus_mask = BM_LRADC_CTRL0_YPLUS_ENABLE, .y_minus_mask = BM_LRADC_CTRL0_YMINUS_ENABLE, }; static struct resource mx23_ts_res[] = { { .flags = IORESOURCE_MEM, .start = LRADC_PHYS_ADDR, .end = LRADC_PHYS_ADDR + 0x2000 - 1, }, { .flags = IORESOURCE_IRQ, .start = IRQ_TOUCH_DETECT, .end = IRQ_TOUCH_DETECT, }, { .flags = IORESOURCE_IRQ, .start = IRQ_LRADC_CH5, .end = IRQ_LRADC_CH5, }, }; static void __init mx23_init_ts(void) { struct platform_device *pdev; pdev = mxs_get_device("mxs-ts", 0); if (pdev == NULL || IS_ERR(pdev)) return; pdev->resource = mx23_ts_res; pdev->num_resources = ARRAY_SIZE(mx23_ts_res); pdev->dev.platform_data = &mx23_ts_data; mxs_add_device(pdev, 3); } #else static void __init mx23_init_ts(void) { ; } #endif #if defined(CONFIG_CRYPTO_DEV_DCP) static struct resource dcp_resources[] = { { .flags = IORESOURCE_MEM, .start = DCP_PHYS_ADDR, .end = DCP_PHYS_ADDR + 0x2000 - 1, }, { .flags = IORESOURCE_IRQ, .start = IRQ_DCP_VMI, .end = IRQ_DCP_VMI, }, { .flags = IORESOURCE_IRQ, .start = IRQ_DCP, .end = IRQ_DCP, }, }; static void __init mx23_init_dcp(void) { struct platform_device *pdev; pdev = mxs_get_device("dcp", 0); if (pdev == NULL || IS_ERR(pdev)) return; pdev->resource = dcp_resources; pdev->num_resources = ARRAY_SIZE(dcp_resources); mxs_add_device(pdev, 3); } #else static void __init mx23_init_dcp(void) { ; } #endif #if defined(CONFIG_MTD_NAND_GPMI_NFC) static int gpmi_nfc_platform_init(unsigned int max_chip_count) { return 0; } static void gpmi_nfc_platform_exit(unsigned int max_chip_count) { } static const char *gpmi_nfc_partition_source_types[] = { "cmdlinepart", 0 }; static struct gpmi_nfc_platform_data gpmi_nfc_platform_data = { .nfc_version = 0, .boot_rom_version = 0, .clock_name = "gpmi", .platform_init = gpmi_nfc_platform_init, .platform_exit = gpmi_nfc_platform_exit, .min_prop_delay_in_ns = 5, .max_prop_delay_in_ns = 9, .max_chip_count = 2, .boot_area_size_in_bytes = 20 * SZ_1M, .partition_source_types = gpmi_nfc_partition_source_types, .partitions = 0, .partition_count = 0, }; static struct resource gpmi_nfc_resources[] = { { .name = GPMI_NFC_GPMI_REGS_ADDR_RES_NAME, .flags = IORESOURCE_MEM, .start = GPMI_PHYS_ADDR, .end = GPMI_PHYS_ADDR + SZ_8K - 1, }, { .name = GPMI_NFC_GPMI_INTERRUPT_RES_NAME, .flags = IORESOURCE_IRQ, .start = IRQ_GPMI_ATTENTION, .end = IRQ_GPMI_ATTENTION, }, { .name = GPMI_NFC_BCH_REGS_ADDR_RES_NAME, .flags = IORESOURCE_MEM, .start = BCH_PHYS_ADDR, .end = BCH_PHYS_ADDR + SZ_8K - 1, }, { .name = GPMI_NFC_BCH_INTERRUPT_RES_NAME, .flags = IORESOURCE_IRQ, .start = IRQ_BCH, .end = IRQ_BCH, }, { .name = GPMI_NFC_DMA_CHANNELS_RES_NAME, .flags = IORESOURCE_DMA, .start = MXS_DMA_CHANNEL_AHB_APBH_GPMI0, .end = MXS_DMA_CHANNEL_AHB_APBH_GPMI3, }, { .name = GPMI_NFC_DMA_INTERRUPT_RES_NAME, .flags = IORESOURCE_IRQ, .start = IRQ_GPMI_DMA, .end = IRQ_GPMI_DMA, }, }; static void __init mx23_init_gpmi_nfc(void) { struct platform_device *pdev; pdev = mxs_get_device(GPMI_NFC_DRIVER_NAME, 0); if (pdev == NULL || IS_ERR(pdev)) return; pdev->dev.platform_data = &gpmi_nfc_platform_data; pdev->resource = gpmi_nfc_resources; pdev->num_resources = ARRAY_SIZE(gpmi_nfc_resources); mxs_add_device(pdev, 1); } #else static void mx23_init_gpmi_nfc(void) { } #endif #if defined(CONFIG_MMC_MXS) || defined(CONFIG_MMC_MXS_MODULE) static unsigned long mxs_mmc_setclock_mmc0(unsigned long hz) { struct clk *ssp = clk_get(NULL, "ssp.0"); clk_set_rate(ssp, 2 * hz); clk_put(ssp); return hz; } static struct mxs_mmc_platform_data mx23_mmc0_data = { .hw_init = mxs_mmc_hw_init_mmc0, .hw_release = mxs_mmc_hw_release_mmc0, .get_wp = mxs_mmc_get_wp_mmc0, .cmd_pullup = mxs_mmc_cmd_pullup_mmc0, /* Don't change ssp clock because ssp1 and ssp2 share one ssp clock source ssp module have own divider. .setclock = mxs_mmc_setclock_mmc0, */ .caps = MMC_CAP_4_BIT_DATA, .min_clk = 400000, .max_clk = 48000000, .read_uA = 50000, .write_uA = 70000, .clock_mmc = "ssp.0", .power_mmc = NULL, }; static struct resource mx23_mmc0_resource[] = { { .flags = IORESOURCE_MEM, .start = SSP1_PHYS_ADDR, .end = SSP1_PHYS_ADDR + 0x2000 - 1, }, { .flags = IORESOURCE_DMA, .start = MXS_DMA_CHANNEL_AHB_APBH_SSP1, .end = MXS_DMA_CHANNEL_AHB_APBH_SSP1, }, { .flags = IORESOURCE_IRQ, .start = IRQ_SSP1_DMA, .end = IRQ_SSP1_DMA, }, { .flags = IORESOURCE_IRQ, .start = IRQ_SSP_ERROR, .end = IRQ_SSP_ERROR, }, }; static void __init mx23_init_mmc(void) { struct platform_device *pdev; pdev = mxs_get_device("mxs-mmc", 0); if (pdev == NULL || IS_ERR(pdev)) return; pdev->resource = mx23_mmc0_resource; pdev->num_resources = ARRAY_SIZE(mx23_mmc0_resource); pdev->dev.platform_data = &mx23_mmc0_data; mxs_add_device(pdev, 2); } #else static void mx23_init_mmc(void) { ; } #endif #if defined(CONFIG_SPI_MXS) || defined(CONFIG_SPI_MXS_MODULE) static struct resource ssp1_resources[] = { { .start = SSP1_PHYS_ADDR, .end = SSP1_PHYS_ADDR + 0x1FFF, .flags = IORESOURCE_MEM, }, { .start = IRQ_SSP1_DMA, .end = IRQ_SSP1_DMA, .flags = IORESOURCE_IRQ, }, { .start = IRQ_SSP_ERROR, .end = IRQ_SSP_ERROR, .flags = IORESOURCE_IRQ, }, { .start = MXS_DMA_CHANNEL_AHB_APBH_SSP1, .end = MXS_DMA_CHANNEL_AHB_APBH_SSP1, .flags = IORESOURCE_DMA, }, }; static void __init mx23_init_spi1(void) { struct platform_device *pdev; pdev = mxs_get_device("mxs-spi", 0); if (pdev == NULL || IS_ERR(pdev)) return; pdev->resource = ssp1_resources; pdev->num_resources = ARRAY_SIZE(ssp1_resources); mxs_add_device(pdev, 3); } #else static void mx23_init_spi1(void) { ; } #endif #define CMDLINE_DEVICE_CHOOSE(name, dev1, dev2) \ static char *cmdline_device_##name; \ static int cmdline_device_##name##_setup(char *dev) \ { \ cmdline_device_##name = dev + 1; \ return 0; \ } \ __setup(#name, cmdline_device_##name##_setup); \ void mx23_init_##name(void) \ { \ if (!cmdline_device_##name || \ !strcmp(cmdline_device_##name, #dev1)) \ mx23_init_##dev1(); \ else if (!strcmp(cmdline_device_##name, #dev2)) \ mx23_init_##dev2(); \ else \ pr_err("Unknown %s assignment '%s'.\n", \ #name, cmdline_device_##name); \ } CMDLINE_DEVICE_CHOOSE(ssp1, mmc, spi1) #if defined(CONFIG_BATTERY_MXS) /* battery info data */ static ddi_bc_Cfg_t battery_data = { .u32StateMachinePeriod = 100, /* ms */ .u16CurrentRampSlope = 75, /* mA/s */ .u16ConditioningThresholdVoltage = 2900, /* mV */ .u16ConditioningMaxVoltage = 3000, /* mV */ .u16ConditioningCurrent = 60, /* mA */ .u32ConditioningTimeout = 4*60*60*1000, /* ms (4 hours) */ .u16ChargingVoltage = 4200, /* mV */ /* FIXME: the current comparator could have h/w bugs in current * detection through POWER_STS.CHRGSTS bit */ .u16ChargingCurrent = 600, /* mA 600 */ .u16ChargingThresholdCurrent = 60, /* mA 60 */ .u32ChargingTimeout = 4*60*60*1000,/* ms (4 hours) */ .u32TopOffPeriod = 30*60*1000, /* ms (30 minutes) */ .monitorDieTemp = 1, /* Monitor the die */ .u8DieTempHigh = 75, /* deg centigrade */ .u8DieTempLow = 65, /* deg centigrade */ .u16DieTempSafeCurrent = 0, /* mA */ .monitorBatteryTemp = 0, /* Monitor the battery*/ .u8BatteryTempChannel = 1, /* LRADC 1 */ .u16BatteryTempHigh = 642, /* Unknown units */ .u16BatteryTempLow = 497, /* Unknown units */ .u16BatteryTempSafeCurrent = 0, /* mA */ }; static struct resource battery_resource[] = { {/* 0 */ .flags = IORESOURCE_IRQ, .start = IRQ_VDD5V, .end = IRQ_VDD5V, }, {/* 1 */ .flags = IORESOURCE_IRQ, .start = IRQ_DCDC4P2_BO, .end = IRQ_DCDC4P2_BO, }, {/* 2 */ .flags = IORESOURCE_IRQ, .start = IRQ_BATT_BRNOUT, .end = IRQ_BATT_BRNOUT, }, {/* 3 */ .flags = IORESOURCE_IRQ, .start = IRQ_VDDD_BRNOUT, .end = IRQ_VDDD_BRNOUT, }, {/* 4 */ .flags = IORESOURCE_IRQ, .start = IRQ_VDD18_BRNOUT, .end = IRQ_VDD18_BRNOUT, }, {/* 5 */ .flags = IORESOURCE_IRQ, .start = IRQ_VDDIO_BRNOUT, .end = IRQ_VDDIO_BRNOUT, }, {/* 6 */ .flags = IORESOURCE_IRQ, .start = IRQ_VDD5V_DROOP, .end = IRQ_VDD5V_DROOP, }, }; static void mx23_init_battery(void) { struct platform_device *pdev; pdev = mxs_get_device("mxs-battery", 0); if (pdev == NULL || IS_ERR(pdev)) return; pdev->resource = battery_resource, pdev->num_resources = ARRAY_SIZE(battery_resource), pdev->dev.platform_data = &battery_data; mxs_add_device(pdev, 3); } #else static void mx23_init_battery(void) { } #endif #if defined(CONFIG_SND_SOC_MXS_SPDIF) || \ defined(CONFIG_SND_SOC_MXS_SPDIF_MODULE) void __init mx23_init_spdif(void) { struct platform_device *pdev; pdev = mxs_get_device("mxs-spdif", 0); if (pdev == NULL || IS_ERR(pdev)) return; mxs_add_device(pdev, 3); } #else static inline void mx23_init_spdif(void) { } #endif #if defined(CONFIG_MXS_PERSISTENT) static const struct mxs_persistent_bit_config mx23_persistent_bit_config[] = { { .reg = 0, .start = 0, .width = 1, .name = "CLOCKSOURCE" }, { .reg = 0, .start = 1, .width = 1, .name = "ALARM_WAKE_EN" }, { .reg = 0, .start = 2, .width = 1, .name = "ALARM_EN" }, { .reg = 0, .start = 3, .width = 1, .name = "CLK_SECS" }, { .reg = 0, .start = 4, .width = 1, .name = "XTAL24MHZ_PWRUP" }, { .reg = 0, .start = 5, .width = 1, .name = "XTAL32MHZ_PWRUP" }, { .reg = 0, .start = 6, .width = 1, .name = "XTAL32_FREQ" }, { .reg = 0, .start = 7, .width = 1, .name = "ALARM_WAKE" }, { .reg = 0, .start = 8, .width = 5, .name = "MSEC_RES" }, { .reg = 0, .start = 13, .width = 1, .name = "DISABLE_XTALOK" }, { .reg = 0, .start = 14, .width = 2, .name = "LOWERBIAS" }, { .reg = 0, .start = 16, .width = 1, .name = "DISABLE_PSWITCH" }, { .reg = 0, .start = 17, .width = 1, .name = "AUTO_RESTART" }, { .reg = 0, .start = 18, .width = 14, .name = "SPARE_ANALOG" }, { .reg = 1, .start = 0, .width = 1, .name = "FORCE_RECOVERY" }, { .reg = 1, .start = 1, .width = 1, .name = "NAND_SECONDARY_BOOT" }, { .reg = 1, .start = 2, .width = 1, .name = "NAND_SDK_BLOCK_REWRITE" }, { .reg = 1, .start = 3, .width = 1, .name = "SD_SPEED_ENABLE" }, { .reg = 1, .start = 4, .width = 1, .name = "SD_INIT_SEQ_1_DISABLE" }, { .reg = 1, .start = 5, .width = 1, .name = "SD_CMD0_DISABLE" }, { .reg = 1, .start = 6, .width = 1, .name = "SD_INIT_SEQ_2_ENABLE" }, { .reg = 1, .start = 7, .width = 1, .name = "OTG_ATL_ROLE_BIT" }, { .reg = 1, .start = 8, .width = 1, .name = "OTG_HNP_BIT" }, { .reg = 1, .start = 9, .width = 1, .name = "USB_LOW_POWER_MODE" }, { .reg = 1, .start = 10, .width = 1, .name = "SKIP_CHECKDISK" }, { .reg = 1, .start = 11, .width = 1, .name = "USB_BOOT_PLAYER_MODE" }, { .reg = 1, .start = 12, .width = 1, .name = "ENUMERATE_500MA_TWICE" }, { .reg = 1, .start = 13, .width = 19, .name = "SPARE_GENERAL" }, { .reg = 2, .start = 0, .width = 32, .name = "SPARE_2" }, { .reg = 3, .start = 0, .width = 32, .name = "SPARE_3" }, { .reg = 4, .start = 0, .width = 32, .name = "SPARE_4" }, { .reg = 5, .start = 0, .width = 32, .name = "SPARE_5" }, }; static struct mxs_platform_persistent_data mx23_persistent_data = { .bit_config_tab = mx23_persistent_bit_config, .bit_config_cnt = ARRAY_SIZE(mx23_persistent_bit_config), }; static struct resource mx23_persistent_res[] = { { .flags = IORESOURCE_MEM, .start = RTC_PHYS_ADDR, .end = RTC_PHYS_ADDR + 0x2000 - 1, }, }; static void mx23_init_persistent(void) { struct platform_device *pdev; pdev = mxs_get_device("mxs-persistent", 0); if (pdev == NULL || IS_ERR(pdev)) return; pdev->dev.platform_data = &mx23_persistent_data; pdev->resource = mx23_persistent_res, pdev->num_resources = ARRAY_SIZE(mx23_persistent_res), mxs_add_device(pdev, 3); } #else static void mx23_init_persistent() { } #endif int __init mx23_device_init(void) { mx23_init_dma(); mx23_init_viim(); mx23_init_duart(); mx23_init_auart(); mx23_init_lradc(); mx23_init_i2c(); mx23_init_kbd(); mx23_init_wdt(); mx23_init_ts(); mx23_init_rtc(); mx23_init_dcp(); mx23_init_ssp1(); mx23_init_gpmi_nfc(); mx23_init_spdif(); mx23_init_lcdif(); mx23_init_pxp(); mx23_init_battery(); mx23_init_persistent(); return 0; } static struct __initdata map_desc mx23_io_desc[] = { { .virtual = MX23_SOC_IO_VIRT_BASE, .pfn = __phys_to_pfn(MX23_SOC_IO_PHYS_BASE), .length = MX23_SOC_IO_AREA_SIZE, .type = MT_DEVICE, }, { .virtual = MX23_OCRAM_BASE, .pfn = __phys_to_pfn(MX23_OCRAM_PHBASE), .length = MX23_OCRAM_SIZE, .type = MT_DEVICE, }, }; void __init mx23_map_io(void) { iotable_init(mx23_io_desc, ARRAY_SIZE(mx23_io_desc)); } void __init mx23_irq_init(void) { avic_init_irq(IO_ADDRESS(ICOLL_PHYS_ADDR), ARCH_NR_IRQS); } static void mx23_timer_init(void) { int i, reg; mx23_clock_init(); mx23_timer.clk = clk_get(NULL, "clk_32k"); if (mx23_timer.clk == NULL || IS_ERR(mx23_timer.clk)) return; __raw_writel(BM_TIMROT_ROTCTRL_SFTRST, mx23_timer.base + HW_TIMROT_ROTCTRL_CLR); for (i = 0; i < 10000; i++) { reg = __raw_readl(mx23_timer.base + HW_TIMROT_ROTCTRL); if (!(reg & BM_TIMROT_ROTCTRL_SFTRST)) break; udelay(2); } if (i >= 10000) return; __raw_writel(BM_TIMROT_ROTCTRL_CLKGATE, mx23_timer.base + HW_TIMROT_ROTCTRL_CLR); reg = __raw_readl(mx23_timer.base + HW_TIMROT_ROTCTRL); mxs_nomatch_timer_init(&mx23_timer); } struct mxs_sys_timer mx23_timer = { .timer = { .init = mx23_timer_init, }, .clk_sel = BV_TIMROT_TIMCTRLn_SELECT__32KHZ_XTAL, .base = IO_ADDRESS(TIMROT_PHYS_ADDR), };