diff options
Diffstat (limited to 'arch/arm/mach-mx6/board-mx6q_sabresd.c')
-rw-r--r-- | arch/arm/mach-mx6/board-mx6q_sabresd.c | 345 |
1 files changed, 281 insertions, 64 deletions
diff --git a/arch/arm/mach-mx6/board-mx6q_sabresd.c b/arch/arm/mach-mx6/board-mx6q_sabresd.c index ac9b8f8391d9..9971ff55a765 100644 --- a/arch/arm/mach-mx6/board-mx6q_sabresd.c +++ b/arch/arm/mach-mx6/board-mx6q_sabresd.c @@ -45,6 +45,7 @@ #include <linux/fec.h> #include <linux/memblock.h> #include <linux/gpio.h> +#include <linux/ion.h> #include <linux/etherdevice.h> #include <linux/power/sabresd_battery.h> #include <linux/regulator/anatop-regulator.h> @@ -82,8 +83,10 @@ #include "cpu_op-mx6.h" #include "board-mx6q_sabresd.h" #include "board-mx6dl_sabresd.h" +#include <mach/imx_rfkill.h> #define SABRESD_USR_DEF_GRN_LED IMX_GPIO_NR(1, 1) +#define SABRESD_BT_RESET IMX_GPIO_NR(1, 2) #define SABRESD_USR_DEF_RED_LED IMX_GPIO_NR(1, 2) #define SABRESD_VOLUME_UP IMX_GPIO_NR(1, 4) #define SABRESD_VOLUME_DN IMX_GPIO_NR(1, 5) @@ -207,10 +210,11 @@ static struct clk *sata_clk; static struct clk *clko; -static int mma8451_position = 1; -static int mag3110_position = 2; +static int mma8451_position; +static int mag3110_position = 1; static int max11801_mode = 1; static int caam_enabled; +static int uart5_enabled; extern char *gp_reg_id; extern char *soc_reg_id; @@ -226,6 +230,7 @@ static const struct esdhc_platform_data mx6q_sabresd_sd2_data __initconst = { .support_8bit = 1, .delay_line = 0, .cd_type = ESDHC_CD_CONTROLLER, + .runtime_pm = 1, }; static const struct esdhc_platform_data mx6q_sabresd_sd3_data __initconst = { @@ -235,6 +240,7 @@ static const struct esdhc_platform_data mx6q_sabresd_sd3_data __initconst = { .support_8bit = 1, .delay_line = 0, .cd_type = ESDHC_CD_CONTROLLER, + .runtime_pm = 1, }; static const struct esdhc_platform_data mx6q_sabresd_sd4_data __initconst = { @@ -250,6 +256,12 @@ static const struct anatop_thermal_platform_data .name = "anatop_thermal", }; +static const struct imxuart_platform_data mx6q_sd_uart5_data __initconst = { + .flags = IMXUART_HAVE_RTSCTS, + .dma_req_rx = MX6Q_DMA_REQ_UART5_RX, + .dma_req_tx = MX6Q_DMA_REQ_UART5_TX, +}; + static inline void mx6q_sabresd_init_uart(void) { imx6q_add_imx_uart(2, NULL); @@ -851,6 +863,10 @@ static struct i2c_board_info mxc_i2c2_board_info[] __initdata = { I2C_BOARD_INFO("elan-touch", 0x10), .irq = gpio_to_irq(SABRESD_ELAN_INT), }, + { + I2C_BOARD_INFO("mxc_ldb_i2c", 0x50), + .platform_data = (void *)1, /* lvds port1 */ + }, }; static int epdc_get_pins(void) @@ -1244,7 +1260,7 @@ static const struct flexcan_platform_data }; static struct viv_gpu_platform_data imx6q_gpu_pdata __initdata = { - .reserved_mem_size = SZ_128M, + .reserved_mem_size = SZ_128M + SZ_64M - SZ_16M, }; static struct imx_asrc_platform_data imx_asrc_data = { @@ -1283,22 +1299,16 @@ static struct ipuv3_fb_platform_data sabresd_fb_data[] = { .int_clk = false, .late_init = false, }, { - .disp_dev = "ldb", - .interface_pix_fmt = IPU_PIX_FMT_RGB666, - .mode_str = "LDB-XGA", - .default_bpp = 16, - .int_clk = false, - }, { - .disp_dev = "lcd", - .interface_pix_fmt = IPU_PIX_FMT_RGB565, - .mode_str = "CLAA-WVGA", - .default_bpp = 16, + .disp_dev = "hdmi", + .interface_pix_fmt = IPU_PIX_FMT_RGB24, + .mode_str = "1920x1080M@60", + .default_bpp = 32, .int_clk = false, .late_init = false, }, { .disp_dev = "ldb", .interface_pix_fmt = IPU_PIX_FMT_RGB666, - .mode_str = "LDB-VGA", + .mode_str = "LDB-XGA", .default_bpp = 16, .int_clk = false, .late_init = false, @@ -1361,7 +1371,7 @@ static struct fsl_mxc_hdmi_platform_data hdmi_data = { }; static struct fsl_mxc_hdmi_core_platform_data hdmi_core_data = { - .ipu_id = 0, + .ipu_id = 1, .disp_id = 0, }; @@ -1372,11 +1382,11 @@ static struct fsl_mxc_lcd_platform_data lcdif_data = { }; static struct fsl_mxc_ldb_platform_data ldb_data = { - .ipu_id = 1, + .ipu_id = 0, .disp_id = 1, .ext_ref = 1, .mode = LDB_SEP1, - .sec_ipu_id = 1, + .sec_ipu_id = 0, .sec_disp_id = 0, }; @@ -1410,6 +1420,19 @@ static struct imx_ipuv3_platform_data ipu_data[] = { }, }; +static struct ion_platform_data imx_ion_data = { + .nr = 1, + .heaps = { + { + .id = 0, + .type = ION_HEAP_TYPE_CARVEOUT, + .name = "vpu_ion", + .size = SZ_16M, + .cacheable = 1, + }, + }, +}; + static struct fsl_mxc_capture_platform_data capture_data[] = { { .csi = 0, @@ -1424,7 +1447,33 @@ static struct fsl_mxc_capture_platform_data capture_data[] = { }, }; +static void mx6q_sd_bt_reset(void) +{ + printk(KERN_INFO "mx6q_sd_bt_reset"); + gpio_request(SABRESD_BT_RESET, "bt-reset"); + gpio_direction_output(SABRESD_BT_RESET, 0); + /* pull down reset pin at least >5ms */ + mdelay(6); + /* pull up after power supply BT */ + gpio_direction_output(SABRESD_BT_RESET, 1); + gpio_free(SABRESD_BT_RESET); + msleep(100); +} + +static int mx6q_sd_bt_power_change(int status) +{ + if (status) + mx6q_sd_bt_reset(); + return 0; +} +static struct platform_device mxc_bt_rfkill = { + .name = "mxc_bt_rfkill", +}; + +static struct imx_bt_rfkill_platform_data mxc_bt_rfkill_data = { + .power_change = mx6q_sd_bt_power_change, +}; static void sabresd_suspend_enter(void) { /* suspend preparation */ @@ -1490,31 +1539,6 @@ static int __init imx6q_init_audio(void) return 0; } -#ifndef CONFIG_IMX_PCIE -static void pcie_3v3_power(void) -{ - /* disable PCIE_3V3 first */ - gpio_request(SABRESD_PCIE_PWR_EN, "pcie_3v3_en"); - gpio_direction_output(SABRESD_PCIE_PWR_EN, 0); - mdelay(10); - /* enable PCIE_3V3 again */ - gpio_set_value(SABRESD_PCIE_PWR_EN, 1); - gpio_free(SABRESD_PCIE_PWR_EN); -} - -static void pcie_3v3_reset(void) -{ - /* reset miniPCIe */ - gpio_request(SABRESD_PCIE_RST_B_REVB, "pcie_reset_rebB"); - gpio_direction_output(SABRESD_PCIE_RST_B_REVB, 0); - /* The PCI Express Mini CEM specification states that PREST# is - deasserted minimum 1ms after 3.3vVaux has been applied and stable*/ - mdelay(1); - gpio_set_value(SABRESD_PCIE_RST_B_REVB, 1); - gpio_free(SABRESD_PCIE_RST_B_REVB); -} -#endif - static void gps_power_on(bool on) { /* Enable/disable aux_3v15 */ @@ -1571,9 +1595,13 @@ static struct platform_device imx6q_gpio_led_device = { } }; +/* For BT_PWD_L is conflict with charger's LED trigger gpio on sabresd_revC. + * add mutual exclusion here to be decided which one to be used by board config + */ static void __init imx6q_add_device_gpio_leds(void) { - platform_device_register(&imx6q_gpio_led_device); + if (!uart5_enabled) + platform_device_register(&imx6q_gpio_led_device); } #else static void __init imx6q_add_device_gpio_leds(void) {} @@ -1591,29 +1619,65 @@ static void __init imx6q_add_device_gpio_leds(void) {} .debounce_interval = debounce, \ } -static struct gpio_keys_button imx6q_buttons[] = { +static struct gpio_keys_button sabresd_buttons[] = { + GPIO_BUTTON(SABRESD_VOLUME_UP, KEY_VOLUMEUP, 1, "volume-up", 0, 1), + GPIO_BUTTON(SABRESD_VOLUME_DN, KEY_POWER, 1, "volume-down", 1, 1), +}; + +static struct gpio_keys_platform_data sabresd_button_data = { + .buttons = sabresd_buttons, + .nbuttons = ARRAY_SIZE(sabresd_buttons), +}; + +static struct gpio_keys_button new_sabresd_buttons[] = { GPIO_BUTTON(SABRESD_VOLUME_UP, KEY_VOLUMEUP, 1, "volume-up", 0, 1), GPIO_BUTTON(SABRESD_VOLUME_DN, KEY_VOLUMEDOWN, 1, "volume-down", 0, 1), - GPIO_BUTTON(SABRESD_POWER_OFF, KEY_POWER, 1, "power", 1, 1), + GPIO_BUTTON(SABRESD_POWER_OFF, KEY_POWER, 1, "power-key", 1, 1), }; -static struct gpio_keys_platform_data imx6q_button_data = { - .buttons = imx6q_buttons, - .nbuttons = ARRAY_SIZE(imx6q_buttons), +static struct gpio_keys_platform_data new_sabresd_button_data = { + .buttons = new_sabresd_buttons, + .nbuttons = ARRAY_SIZE(new_sabresd_buttons), }; -static struct platform_device imx6q_button_device = { +static struct platform_device sabresd_button_device = { .name = "gpio-keys", .id = -1, .num_resources = 0, - .dev = { - .platform_data = &imx6q_button_data, - } }; static void __init imx6q_add_device_buttons(void) { - platform_device_register(&imx6q_button_device); + /* fix me */ + /* For new sabresd(RevB4 ane above) change the + * ONOFF key(SW1) design, the SW1 now connect + * to GPIO_3_29, it can be use as a general power + * key that Android reuired. But those old sabresd + * such as RevB or older could not support this + * change, so it needs a way to distinguish different + * boards. Before board id/rev are defined cleary, + * there is a simple way to achive this, that is using + * SOC revison to identify differnt board revison. + * + * With the new sabresd change and SW mapping the + * SW1 as power key, below function related to power + * key are OK on new sabresd board(B4 or above). + * 1 Act as power button to power on the device when device is power off + * 2 Act as power button to power on the device(need keep press SW1 >5s) + * 3 Act as power key to let device suspend/resume + * 4 Act screenshort(hold power key and volume down key for 2s) + */ + if (mx6q_revision() >= IMX_CHIP_REVISION_1_2 || + mx6dl_revision() >= IMX_CHIP_REVISION_1_1) + platform_device_add_data(&sabresd_button_device, + &new_sabresd_button_data, + sizeof(new_sabresd_button_data)); + else + platform_device_add_data(&sabresd_button_device, + &sabresd_button_data, + sizeof(sabresd_button_data)); + + platform_device_register(&sabresd_button_device); } #else static void __init imx6q_add_device_buttons(void) {} @@ -1653,6 +1717,49 @@ static struct mxc_dvfs_platform_data sabresd_dvfscore_data = { static void __init fixup_mxc_board(struct machine_desc *desc, struct tag *tags, char **cmdline, struct meminfo *mi) { + char *str; + struct tag *t; + int i = 0; + struct ipuv3_fb_platform_data *pdata_fb = sabresd_fb_data; + + for_each_tag(t, tags) { + if (t->hdr.tag == ATAG_CMDLINE) { + str = t->u.cmdline.cmdline; + str = strstr(str, "fbmem="); + if (str != NULL) { + str += 6; + pdata_fb[i++].res_size[0] = memparse(str, &str); + while (*str == ',' && + i < ARRAY_SIZE(sabresd_fb_data)) { + str++; + pdata_fb[i++].res_size[0] = memparse(str, &str); + } + } + /* ION reserved memory */ + str = t->u.cmdline.cmdline; + str = strstr(str, "ionmem="); + if (str != NULL) { + str += 7; + imx_ion_data.heaps[0].size = memparse(str, &str); + } + /* Primary framebuffer base address */ + str = t->u.cmdline.cmdline; + str = strstr(str, "fb0base="); + if (str != NULL) { + str += 8; + pdata_fb[0].res_base[0] = + simple_strtol(str, &str, 16); + } + /* GPU reserved memory */ + str = t->u.cmdline.cmdline; + str = strstr(str, "gpumem="); + if (str != NULL) { + str += 7; + imx6q_gpu_pdata.reserved_mem_size = memparse(str, &str); + } + break; + } + } } static struct mipi_csi2_platform_data mipi_csi2_pdata = { @@ -1687,8 +1794,65 @@ static const struct imx_pcie_platform_data mx6_sabresd_pcie_data __initconst = { .pcie_rst = SABRESD_PCIE_RST_B_REVB, .pcie_wake_up = SABRESD_PCIE_WAKE_B, .pcie_dis = SABRESD_PCIE_DIS_B, + .pcie_power_always_on = 1, +}; + +#ifdef CONFIG_ANDROID_RAM_CONSOLE +static struct resource ram_console_resource = { + .name = "android ram console", + .flags = IORESOURCE_MEM, }; +static struct platform_device android_ram_console = { + .name = "ram_console", + .num_resources = 1, + .resource = &ram_console_resource, +}; + +static int __init imx6x_add_ram_console(void) +{ + return platform_device_register(&android_ram_console); +} +#else +#define imx6x_add_ram_console() do {} while (0) +#endif + +static iomux_v3_cfg_t mx6q_uart5_pads[] = { + MX6Q_PAD_KEY_ROW1__UART5_RXD, + MX6Q_PAD_KEY_COL1__UART5_TXD, + MX6Q_PAD_KEY_COL4__UART5_RTS, + MX6Q_PAD_KEY_ROW4__UART5_CTS, + /* gpio for reset */ + MX6Q_PAD_GPIO_2__GPIO_1_2, +}; + +static iomux_v3_cfg_t mx6dl_uart5_pads[] = { + MX6DL_PAD_KEY_ROW1__UART5_RXD, + MX6DL_PAD_KEY_COL1__UART5_TXD, + MX6DL_PAD_KEY_COL4__UART5_RTS, + MX6DL_PAD_KEY_ROW4__UART5_CTS, + /* gpio for reset */ + MX6DL_PAD_GPIO_2__GPIO_1_2, +}; +static int __init uart5_setup(char * __unused) +{ + uart5_enabled = 1; + return 1; +} +__setup("bluetooth", uart5_setup); + +static void __init uart5_init(void) +{ + printk(KERN_INFO "uart5 is added\n"); + if (cpu_is_mx6q()) + mxc_iomux_v3_setup_multiple_pads(mx6q_uart5_pads, + ARRAY_SIZE(mx6q_uart5_pads)); + else if (cpu_is_mx6dl()) + mxc_iomux_v3_setup_multiple_pads(mx6dl_uart5_pads, + ARRAY_SIZE(mx6dl_uart5_pads)); + imx6q_add_imx_uart(4, &mx6q_sd_uart5_data); +} + /*! * Board specific initialization. */ @@ -1720,7 +1884,13 @@ static void __init mx6_sabresd_board_init(void) gp_reg_id = sabresd_dvfscore_data.reg_id; soc_reg_id = sabresd_dvfscore_data.soc_id; mx6q_sabresd_init_uart(); + imx6x_add_ram_console(); + /*add bt support*/ + if (uart5_enabled) { + uart5_init(); + mxc_register_device(&mxc_bt_rfkill, &mxc_bt_rfkill_data); + } /* * MX6DL/Solo only supports single IPU * The following codes are used to change ipu id @@ -1730,6 +1900,11 @@ static void __init mx6_sabresd_board_init(void) */ if (cpu_is_mx6dl()) { ldb_data.ipu_id = 0; + ldb_data.disp_id = 1; + hdmi_core_data.ipu_id = 0; + hdmi_core_data.disp_id = 0; + mipi_dsi_pdata.ipu_id = 0; + mipi_dsi_pdata.disp_id = 1; ldb_data.sec_ipu_id = 0; } imx6q_add_mxc_hdmi_core(&hdmi_core_data); @@ -1802,8 +1977,8 @@ static void __init mx6_sabresd_board_init(void) Mfgtools want emmc is mmcblk0 and other sd card is mmcblk1. */ imx6q_add_sdhci_usdhc_imx(3, &mx6q_sabresd_sd4_data); - imx6q_add_sdhci_usdhc_imx(1, &mx6q_sabresd_sd2_data); imx6q_add_sdhci_usdhc_imx(2, &mx6q_sabresd_sd3_data); + imx6q_add_sdhci_usdhc_imx(1, &mx6q_sabresd_sd2_data); imx_add_viv_gpu(&imx6_gpu_data, &imx6q_gpu_pdata); imx6q_sabresd_init_usb(); /* SATA is not supported by MX6DL/Solo */ @@ -1845,6 +2020,11 @@ static void __init mx6_sabresd_board_init(void) imx6q_add_dma(); imx6q_add_dvfs_core(&sabresd_dvfscore_data); + + if (imx_ion_data.heaps[0].size) + imx6q_add_ion(0, &imx_ion_data, + sizeof(imx_ion_data) + sizeof(struct ion_platform_heap)); + imx6q_add_device_buttons(); /* enable sensor 3v3 and 1v8 */ @@ -1901,21 +2081,17 @@ static void __init mx6_sabresd_board_init(void) gpio_direction_output(SABRESD_AUX_5V_EN, 1); gpio_set_value(SABRESD_AUX_5V_EN, 1); -#ifndef CONFIG_IMX_PCIE - /* enable pcie 3v3 power without pcie driver */ - pcie_3v3_power(); - mdelay(10); - pcie_3v3_reset(); -#endif - gps_power_on(true); /* Register charger chips */ platform_device_register(&sabresd_max8903_charger_1); pm_power_off = mx6_snvs_poweroff; imx6q_add_busfreq(); - /* Add PCIe RC interface support */ - imx6q_add_pcie(&mx6_sabresd_pcie_data); + /* Add PCIe RC interface support + * uart5 has pin mux with pcie. or you will use uart5 or use pcie + */ + if (!uart5_enabled) + imx6q_add_pcie(&mx6_sabresd_pcie_data); if (cpu_is_mx6dl()) { mxc_iomux_v3_setup_multiple_pads(mx6dl_arm2_elan_pads, ARRAY_SIZE(mx6dl_arm2_elan_pads)); @@ -1962,9 +2138,42 @@ static struct sys_timer mx6_sabresd_timer = { static void __init mx6q_sabresd_reserve(void) { -#if defined(CONFIG_MXC_GPU_VIV) || defined(CONFIG_MXC_GPU_VIV_MODULE) phys_addr_t phys; + int i, fb0_reserved = 0, fb_array_size; + /* + * Reserve primary framebuffer memory if its base address + * is set by kernel command line. + */ + fb_array_size = ARRAY_SIZE(sabresd_fb_data); + if (fb_array_size > 0 && sabresd_fb_data[0].res_base[0] && + sabresd_fb_data[0].res_size[0]) { + memblock_reserve(sabresd_fb_data[0].res_base[0], + sabresd_fb_data[0].res_size[0]); + memblock_remove(sabresd_fb_data[0].res_base[0], + sabresd_fb_data[0].res_size[0]); + sabresd_fb_data[0].late_init = true; + ipu_data[ldb_data.ipu_id].bypass_reset = true; + fb0_reserved = 1; + } + for (i = fb0_reserved; i < fb_array_size; i++) + if (sabresd_fb_data[i].res_size[0]) { + /* Reserve for other background buffer. */ + phys = memblock_alloc(sabresd_fb_data[i].res_size[0], + SZ_4K); + memblock_remove(phys, sabresd_fb_data[i].res_size[0]); + sabresd_fb_data[i].res_base[0] = phys; + } + +#ifdef CONFIG_ANDROID_RAM_CONSOLE + phys = memblock_alloc_base(SZ_128K, SZ_4K, SZ_1G); + memblock_remove(phys, SZ_128K); + memblock_free(phys, SZ_128K); + ram_console_resource.start = phys; + ram_console_resource.end = phys + SZ_128K - 1; +#endif + +#if defined(CONFIG_MXC_GPU_VIV) || defined(CONFIG_MXC_GPU_VIV_MODULE) if (imx6q_gpu_pdata.reserved_mem_size) { phys = memblock_alloc_base(imx6q_gpu_pdata.reserved_mem_size, SZ_4K, SZ_1G); @@ -1972,6 +2181,14 @@ static void __init mx6q_sabresd_reserve(void) imx6q_gpu_pdata.reserved_mem_base = phys; } #endif + +#if defined(CONFIG_ION) + if (imx_ion_data.heaps[0].size) { + phys = memblock_alloc(imx_ion_data.heaps[0].size, SZ_4K); + memblock_remove(phys, imx_ion_data.heaps[0].size); + imx_ion_data.heaps[0].base = phys; + } +#endif } /* |