summaryrefslogtreecommitdiff
path: root/arch/arm/mach-mx6/board-mx6q_sabresd.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/arm/mach-mx6/board-mx6q_sabresd.c')
-rw-r--r--arch/arm/mach-mx6/board-mx6q_sabresd.c345
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
}
/*