/* * Copyright (C) 2008 Google, Inc. * Copyright (c) 2008-2012, Code Aurora Forum. All rights reserved. * Author: Brian Swetland * * This software is licensed under the terms of the GNU General Public * License version 2, as published by the Free Software Foundation, and * may be copied, distributed, and modified under those terms. * * 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. * */ #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 #include #include #include #include #include #include #include #include #ifdef CONFIG_CACHE_L2X0 #include #endif #ifdef CONFIG_USB_G_ANDROID #include #include #endif #ifdef CONFIG_USB_ANDROID #include #endif #include "devices.h" #include "clock.h" #include "acpuclock.h" #include "msm-keypad-devices.h" #include "pm.h" #include "pm-boot.h" #ifdef CONFIG_ARCH_MSM7X27 #define MSM_PMEM_MDP_SIZE 0x1B76000 #define MSM_PMEM_ADSP_SIZE 0xC8A000 #define MSM_PMEM_AUDIO_SIZE 0x5B000 #ifdef CONFIG_FB_MSM_TRIPLE_BUFFER #define MSM_FB_SIZE 0xE1000 #else #define MSM_FB_SIZE 0x96000 #endif #define PMEM_KERNEL_EBI1_SIZE 0x1C000 #endif #define ADSP_RPC_PROG 0x3000000a int i2c_bus_num=2; /*+++++++++++++++++++++++++++++++++++++++++++++++++++Android Composite USB Support+++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ #ifdef CONFIG_USB_ANDROID char *usb_functions_lge_all[] = { #ifdef CONFIG_USB_ANDROID_MTP "mtp", #endif #ifdef CONFIG_USB_ANDROID_RNDIS "rndis", #endif #ifdef CONFIG_USB_ANDROID_ACM "acm", #endif #ifdef CONFIG_USB_ANDROID_DIAG "diag", #endif #ifdef CONFIG_USB_ANDROID_CDC_ECM "ecm", "acm2", #endif #ifdef CONFIG_USB_F_SERIAL "nmea", #endif #ifdef CONFIG_USB_SUPPORT_LGE_ANDROID_AUTORUN "usb_cdrom_storage", "charge_only", #endif "usb_mass_storage", "adb", }; char *usb_functions_lge_android_plat[] = { "acm", "diag", "nmea", "usb_mass_storage", }; char *usb_functions_lge_android_plat_adb[] = { "acm", "diag", "nmea", "usb_mass_storage", "adb", }; #ifdef CONFIG_USB_ANDROID_CDC_ECM char *usb_functions_lge_android_net[] = { "diag", "ecm", "acm2", "nmea", "usb_mass_storage", }; char *usb_functions_lge_android_net_adb[] = { "diag", "ecm", "acm2", "nmea", "usb_mass_storage", "adb", }; #endif #ifdef CONFIG_USB_ANDROID_RNDIS char *usb_functions_lge_android_rndis[] = { "rndis", }; char *usb_functions_lge_android_rndis_adb[] = { "rndis", "adb", }; #endif #ifdef CONFIG_USB_ANDROID_MTP char *usb_functions_lge_android_mtp[] = { "mtp", }; char *usb_functions_lge_android_mtp_adb[] = { "mtp", "adb", }; #endif char *usb_functions_lge_manufacturing[] = { "acm", "diag", }; char *usb_functions_lge_mass_storage_only[] = { "usb_mass_storage", }; #ifdef CONFIG_USB_SUPPORT_LGE_ANDROID_AUTORUN char *usb_functions_lge_cdrom_storage_only[] = { "usb_cdrom_storage", }; char *usb_functions_lge_cdrom_storage_adb[] = { "usb_cdrom_storage", "adb", }; char *usb_functions_lge_charge_only[] = { "charge_only", }; #endif struct android_usb_product usb_products[] = { { .product_id = 0x618E, .num_functions = ARRAY_SIZE(usb_functions_lge_android_plat), .functions = usb_functions_lge_android_plat, }, { .product_id = 0x618E, .num_functions = ARRAY_SIZE(usb_functions_lge_android_plat_adb), .functions = usb_functions_lge_android_plat_adb, }, #ifdef CONFIG_USB_ANDROID_CDC_ECM { .product_id = 0x61A2, .num_functions = ARRAY_SIZE(usb_functions_lge_android_net), .functions = usb_functions_lge_android_net, }, { .product_id = 0x61A1, .num_functions = ARRAY_SIZE(usb_functions_lge_android_net_adb), .functions = usb_functions_lge_android_net_adb, }, #endif #ifdef CONFIG_USB_ANDROID_RNDIS { .product_id = 0x61DA, .num_functions = ARRAY_SIZE(usb_functions_lge_android_rndis), .functions = usb_functions_lge_android_rndis, }, { .product_id = 0x61D9, .num_functions = ARRAY_SIZE(usb_functions_lge_android_rndis_adb), .functions = usb_functions_lge_android_rndis_adb, }, #endif #ifdef CONFIG_USB_ANDROID_MTP { .product_id = 0x61C7, .num_functions = ARRAY_SIZE(usb_functions_lge_android_mtp), .functions = usb_functions_lge_android_mtp, }, { .product_id = 0x61F9, .num_functions = ARRAY_SIZE(usb_functions_lge_android_mtp_adb), .functions = usb_functions_lge_android_mtp_adb, }, #endif { .product_id = 0x6000, .num_functions = ARRAY_SIZE(usb_functions_lge_manufacturing), .functions = usb_functions_lge_manufacturing, }, { .product_id = 0x61C5, .num_functions = ARRAY_SIZE(usb_functions_lge_mass_storage_only), .functions = usb_functions_lge_mass_storage_only, }, #ifdef CONFIG_USB_SUPPORT_LGE_ANDROID_AUTORUN { .product_id = 0x91C8, .num_functions = ARRAY_SIZE(usb_functions_lge_cdrom_storage_only), .functions = usb_functions_lge_cdrom_storage_only, }, { .product_id = 0x61A6, .num_functions = ARRAY_SIZE(usb_functions_lge_cdrom_storage_adb), .functions = usb_functions_lge_cdrom_storage_adb, }, { .product_id = 0xFFFF, .num_functions = ARRAY_SIZE(usb_functions_lge_charge_only), .functions = usb_functions_lge_charge_only, }, #endif }; struct usb_mass_storage_platform_data mass_storage_pdata = { .nluns = 1, .vendor = "LGE", .product = "Android Platform", .release = 0x0100, }; struct platform_device usb_mass_storage_device = { .name = "usb_mass_storage", .id = -1, .dev = { .platform_data = &mass_storage_pdata, }, }; struct usb_ether_platform_data rndis_pdata = { .vendorID = 0x1004, .vendorDescr = "LG Electronics Inc.", }; struct platform_device rndis_device = { .name = "rndis", .id = -1, .dev = { .platform_data = &rndis_pdata, }, }; #ifdef CONFIG_USB_ANDROID_CDC_ECM struct usb_ether_platform_data ecm_pdata = { .vendorID = 0x1004, .vendorDescr = "LG Electronics Inc.", }; struct platform_device ecm_device = { .name = "ecm", .id = -1, .dev = { .platform_data = &ecm_pdata, }, }; #endif #ifdef CONFIG_USB_ANDROID_ACM struct acm_platform_data acm_pdata = { .num_inst = 1, }; struct platform_device acm_device = { .name = "acm", .id = -1, .dev = { .platform_data = &acm_pdata, }, }; #endif #ifdef CONFIG_USB_SUPPORT_LGE_ANDROID_AUTORUN struct usb_cdrom_storage_platform_data cdrom_storage_pdata = { .nluns = 1, .vendor = "LGE", .product = "Android Platform", .release = 0x0100, }; struct platform_device usb_cdrom_storage_device = { .name = "usb_cdrom_storage", .id = -1, .dev = { .platform_data = &cdrom_storage_pdata, }, }; #endif struct android_usb_platform_data android_usb_pdata = { .vendor_id = 0x1004, .product_id = 0x618E, .version = 0x0100, .product_name = "LGE USB Device", .manufacturer_name = "LG Electronics Inc.", .num_products = ARRAY_SIZE(usb_products), .products = usb_products, .num_functions = ARRAY_SIZE(usb_functions_lge_all), .functions = usb_functions_lge_all, .serial_number = "LG_ANDROID_P500_GB_", }; static struct platform_device android_usb_device = { .name = "android_usb", .id = -1, .dev = { .platform_data = &android_usb_pdata, }, }; static int __init board_serialno_setup(char *serialno) { int i; char *src = serialno; /* create a fake MAC address from our serial number. * first byte is 0x02 to signify locally administered. */ rndis_pdata.ethaddr[0] = 0x02; for (i = 0; *src; i++) { /* XOR the USB serial across the remaining bytes */ rndis_pdata.ethaddr[i % (ETH_ALEN - 1) + 1] ^= *src++; } android_usb_pdata.serial_number = serialno; return 1; } __setup("androidboot.serialno=", board_serialno_setup); #endif /* CONFIG_USB_ANDROID */ /*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ /*+++++++++++++++++++++++++++++++++++++++++++++++++setting board revision information++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ int lge_bd_rev; static int __init board_revno_setup(char *rev_info) { char *rev_str[] = { "evb", "rev_a", "rev_b", "rev_c", "rev_d", "rev_e", "rev_f","rev_10","rev_11","rev_12","rev_13",}; int i; lge_bd_rev = LGE_REV_TOT_NUM; for (i = 0; i < LGE_REV_TOT_NUM; i++) if (!strncmp(rev_info, rev_str[i], 6)) { lge_bd_rev = i; break; } printk(KERN_INFO"BOARD: LGE %s\n", rev_str[lge_bd_rev]); return 1; } __setup("lge.rev=", board_revno_setup); /*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ /*++++++++++++++++++++++++++++++++++++++++++setting whether uart console is enalbed or disabled++++++++++++++++++++++++++++++++++++++++++++*/ static int uart_console_mode = 0; int __init lge_get_uart_mode(void) { return uart_console_mode; } static int __init lge_uart_mode(char *uart_mode) { if (!strncmp("enable", uart_mode, 5)) { printk(KERN_INFO"UART CONSOLE : enable\n"); uart_console_mode = 1; } else printk(KERN_INFO"UART CONSOLE : disable\n"); return 1; } __setup("uart_console=", lge_uart_mode); /*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ /*+++++++++++++++++++++++++++++++++++++++++++++Android RAM Console Support+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ #ifdef CONFIG_ANDROID_RAM_CONSOLE static struct resource ram_console_resource[] = { { .name = "ram_console", .flags = IORESOURCE_MEM, } }; static struct platform_device ram_console_device = { .name = "ram_console", .id = -1, .num_resources = ARRAY_SIZE(ram_console_resource), .resource = ram_console_resource, }; void __init lge_add_ramconsole_devices(void) { struct resource *res = ram_console_resource; struct membank *bank = &meminfo.bank[0]; res->start = MSM7X27_EBI1_CS0_BASE + bank->size; res->end = res->start + LGE_RAM_CONSOLE_SIZE - 1; printk("RAM CONSOLE START ADDR : %d\n", res->start); printk("RAM CONSOLE END ADDR : %d\n", res->end); platform_device_register(&ram_console_device); } __WEAK struct lge_panic_handler_platform_data panic_handler_data; static struct platform_device panic_handler_device = { .name = "panic-handler", .dev = { .platform_data = &panic_handler_data, } }; void __init lge_add_panic_handler_devices(void) { platform_device_register(&panic_handler_device); } static struct platform_device ers_kernel = { .name = "ers-kernel", }; void __init lge_add_ers_devices(void) { platform_device_register(&ers_kernel); } #endif /*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ /*+++++++++++++++++++++++++++++++++++++++++++++++++++USB Support+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ #ifdef CONFIG_USB_G_ANDROID static struct android_usb_platform_data android_usb_pdata = { .update_pid_and_serial_num = usb_diag_update_pid_and_serial_num, }; static struct platform_device android_usb_device = { .name = "android_usb", .id = -1, .dev = { .platform_data = &android_usb_pdata, }, }; #endif #ifdef CONFIG_USB_EHCI_MSM_72K static void msm_hsusb_vbus_power(unsigned phy_info, int on) { if (on) msm_hsusb_vbus_powerup(); else msm_hsusb_vbus_shutdown(); } static struct msm_usb_host_platform_data msm_usb_host_pdata = { .phy_info = (USB_PHY_INTEGRATED | USB_PHY_MODEL_65NM), }; static void __init msm7x2x_init_host(void) { if (machine_is_msm7x25_ffa() || machine_is_msm7x27_ffa()) return; msm_add_host(0, &msm_usb_host_pdata); } #endif #ifdef CONFIG_USB_MSM_OTG_72K static int hsusb_rpc_connect(int connect) { if (connect) return msm_hsusb_rpc_connect(); else return msm_hsusb_rpc_close(); } #endif #ifdef CONFIG_USB_MSM_OTG_72K static int msm_hsusb_ldo_init(int init) { static struct vreg *reg_hsusb; int rc; if (init) { reg_hsusb = vreg_get(NULL, "usb"); if (IS_ERR(reg_hsusb)) { rc = PTR_ERR(reg_hsusb); pr_err("%s: could not get regulator: %d\n", __func__, rc); goto out; } rc = vreg_set_level(reg_hsusb, 3300); if (rc < 0) { pr_err("%s: could not set voltage: %d\n", __func__, rc); goto usb_reg_fail; } rc = vreg_enable(reg_hsusb); if (rc < 0) { pr_err("%s: could not enable regulator: %d\n", __func__, rc); goto usb_reg_fail; } /* * PHY 3.3V analog domain(VDDA33) is powered up by * an always enabled power supply (LP5900TL-3.3). * USB VREG default source is VBUS line. Turning * on USB VREG has a side effect on the USB suspend * current. Hence USB VREG is explicitly turned * off here. */ rc = vreg_disable(reg_hsusb); if (rc < 0) { pr_err("%s: could not disable regulator: %d\n", __func__, rc); goto usb_reg_fail; } vreg_put(reg_hsusb); } return 0; usb_reg_fail: vreg_put(reg_hsusb); out: return rc; } static int msm_hsusb_pmic_notif_init(void (*callback)(int online), int init) { int ret; if (init) { ret = msm_pm_app_rpc_init(callback); } else { msm_pm_app_rpc_deinit(callback); ret = 0; } return ret; } static int msm_otg_rpc_phy_reset(void __iomem *regs) { return msm_hsusb_phy_reset(); } static struct msm_otg_platform_data msm_otg_pdata = { .rpc_connect = hsusb_rpc_connect, #ifdef CONFIG_ARCH_MSM7X27 .phy_reset = msm_otg_rpc_phy_reset, #endif .pmic_vbus_notif_init = msm_hsusb_pmic_notif_init, .chg_vbus_draw = hsusb_chg_vbus_draw, .chg_connected = hsusb_chg_connected, .chg_init = hsusb_chg_init, #ifdef CONFIG_USB_EHCI_MSM_72K .vbus_power = msm_hsusb_vbus_power, #endif .ldo_init = msm_hsusb_ldo_init, .pclk_required_during_lpm = 1, }; #ifdef CONFIG_USB_GADGET static struct msm_hsusb_gadget_platform_data msm_gadget_pdata; #endif #endif /*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ /*+++++++++++++++++++++++++++++++++++++++++++++++++++++++==Sound Support+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ #define SND(desc, num) { .name = #desc, .id = num } static struct snd_endpoint snd_endpoints_list[] = { SND(HANDSET_LOOPBACK,5), SND(HANDSET, 6), SND(HEADSET_LOOPBACK, 1), SND(HEADSET, 2), SND(HEADSET_STEREO, 3), SND(SPEAKER, 0), SND(SPEAKER_IN_CALL, 7), SND(SPEAKER_RING, 8), SND(HEADSET_AND_SPEAKER, 8), SND(FM_HEADSET, 10), SND(FM_SPEAKER, 11), SND(BT, 13), SND(TTY_HEADSET, 15), SND(TTY_VCO, 16), SND(TTY_HCO, 17), SND(TTY_HCO_SPEAKER, 18), SND(HANDSET_VR, 20), SND(HEADSET_VR, 21), SND(BT_VR, 23), SND(CURRENT, 30), }; #undef SND static struct msm_snd_endpoints msm_device_snd_endpoints = { .endpoints = snd_endpoints_list, .num = sizeof(snd_endpoints_list) / sizeof(struct snd_endpoint) }; static struct platform_device msm_device_snd = { .name = "msm_snd", .id = -1, .dev = { .platform_data = &msm_device_snd_endpoints }, }; #define DEC0_FORMAT ((1<bluetooth_power; ret = (*power_control)((state == RFKILL_USER_STATE_SOFT_BLOCKED) ? 1 : 0); return ret; } static int thunderg_bluetooth_power(int on) { int pin, rc; static struct regulator *vreg_bt; printk(KERN_DEBUG "%s\n", __func__); /* do not have vreg bt defined, gp6 is the same */ /* vreg_get parameter 1 (struct device *) is ignored */ if (on) { for (pin = 0; pin < ARRAY_SIZE(bt_config_power_on); pin++) { rc = gpio_tlmm_config(bt_config_power_on[pin],GPIO_CFG_ENABLE); if (rc) { printk(KERN_ERR"%s: gpio_tlmm_config(%#x)=%d\n",__func__, bt_config_power_on[pin], rc); return -EIO; } } //Turn Bluetooth Power On if and only if not turned on by WLAN yet. if (!gpio_get_value(CONFIG_BCM4325_GPIO_WL_REGON)) //#23 gpio_set_value(CONFIG_BCM4325_GPIO_WL_REGON, 1); //#23 mdelay(100); gpio_set_value(BT_RESET_N, 0); mdelay(100); gpio_set_value(BT_RESET_N, 1); mdelay(100); } else { //Turn Bluetooth Power Off if and only if not used by WLAN anymore. if (!gpio_get_value(CONFIG_BCM4325_GPIO_WL_RESET)) //#93 gpio_set_value(CONFIG_BCM4325_GPIO_WL_REGON, 0); //#23 for (pin = 0; pin < ARRAY_SIZE(bt_config_power_off); pin++) { rc = gpio_tlmm_config(bt_config_power_off[pin],GPIO_CFG_ENABLE); if (rc) { printk(KERN_ERR"%s: gpio_tlmm_config(%#x)=%d\n",__func__, bt_config_power_off[pin], rc); return -EIO; } } } return 0; } static struct bluetooth_platform_data thunderg_bluetooth_data = { .bluetooth_power = thunderg_bluetooth_power, .bluetooth_toggle_radio = thunderg_bluetooth_toggle_radio, }; static struct platform_device msm_bt_power_device = { .name = "bt_power", .dev = { .platform_data = &thunderg_bluetooth_data, }, }; static void __init bt_power_init(void) { gpio_set_value(23, 1); ssleep(1); /* 1 sec */ gpio_set_value(23, 0); } #else #define bt_power_init(x) do {} while (0) #endif static struct resource bluesleep_resources[] = { { .name = "gpio_host_wake", .start = BT_HOST_WAKE, .end = BT_HOST_WAKE, .flags = IORESOURCE_IO, }, { .name = "gpio_ext_wake", .start = BT_WAKE, .end = BT_WAKE, .flags = IORESOURCE_IO, }, { .name = "host_wake", .start = MSM_GPIO_TO_INT(BT_HOST_WAKE), .end = MSM_GPIO_TO_INT(BT_HOST_WAKE), .flags = IORESOURCE_IRQ, }, }; static struct bluesleep_platform_data thunderg_bluesleep_data = { .bluetooth_port_num = 0, }; static struct platform_device msm_bluesleep_device = { .name = "bluesleep", .id = -1, .num_resources = ARRAY_SIZE(bluesleep_resources), .resource = bluesleep_resources, .dev = { .platform_data = &thunderg_bluesleep_data, }, }; /*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ /*+++++++++++++++++++++++++++++++++++++++++++++++++++++Button Backlight Support++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ static struct platform_device msm_device_pmic_leds = { .name = "pmic-leds", .id = -1, .dev.platform_data = "button-backlight", }; /*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ /*++++++++++++++++++++++++++++++++++++++++++++++++++++Camera Support+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ struct i2c_board_info i2c_devices[1] = { #if defined (CONFIG_ISX005) { I2C_BOARD_INFO("isx005", CAM_I2C_SLAVE_ADDR), }, #endif }; #ifdef CONFIG_MSM_CAMERA static uint32_t camera_off_gpio_table[] = { /* parallel CAMERA interfaces */ GPIO_CFG(4, 0, GPIO_CFG_INPUT, GPIO_CFG_PULL_DOWN, GPIO_CFG_2MA), /* DAT0 */ GPIO_CFG(5, 0, GPIO_CFG_INPUT, GPIO_CFG_PULL_DOWN, GPIO_CFG_2MA), /* DAT1 */ GPIO_CFG(6, 0, GPIO_CFG_INPUT, GPIO_CFG_PULL_DOWN, GPIO_CFG_2MA), /* DAT2 */ GPIO_CFG(7, 0, GPIO_CFG_INPUT, GPIO_CFG_PULL_DOWN, GPIO_CFG_2MA), /* DAT3 */ GPIO_CFG(8, 0, GPIO_CFG_INPUT, GPIO_CFG_PULL_DOWN, GPIO_CFG_2MA), /* DAT4 */ GPIO_CFG(9, 0, GPIO_CFG_INPUT, GPIO_CFG_PULL_DOWN, GPIO_CFG_2MA), /* DAT5 */ GPIO_CFG(10, 0, GPIO_CFG_INPUT, GPIO_CFG_PULL_DOWN, GPIO_CFG_2MA), /* DAT6 */ GPIO_CFG(11, 0, GPIO_CFG_INPUT, GPIO_CFG_PULL_DOWN, GPIO_CFG_2MA), /* DAT7 */ GPIO_CFG(12, 0, GPIO_CFG_INPUT, GPIO_CFG_PULL_DOWN, GPIO_CFG_2MA), /* PCLK */ GPIO_CFG(13, 0, GPIO_CFG_INPUT, GPIO_CFG_PULL_DOWN, GPIO_CFG_2MA), /* HSYNC_IN */ GPIO_CFG(14, 0, GPIO_CFG_INPUT, GPIO_CFG_PULL_DOWN, GPIO_CFG_2MA), /* VSYNC_IN */ GPIO_CFG(GPIO_CAM_MCLK, 0, GPIO_CFG_OUTPUT, GPIO_CFG_NO_PULL, GPIO_CFG_2MA), /* MCLK */ }; static uint32_t camera_on_gpio_table[] = { /* parallel CAMERA interfaces */ GPIO_CFG(4, 1, GPIO_CFG_INPUT, GPIO_CFG_PULL_DOWN, GPIO_CFG_2MA), /* DAT0 */ GPIO_CFG(5, 1, GPIO_CFG_INPUT, GPIO_CFG_PULL_DOWN, GPIO_CFG_2MA), /* DAT1 */ GPIO_CFG(6, 1, GPIO_CFG_INPUT, GPIO_CFG_PULL_DOWN, GPIO_CFG_2MA), /* DAT2 */ GPIO_CFG(7, 1, GPIO_CFG_INPUT, GPIO_CFG_PULL_DOWN, GPIO_CFG_2MA), /* DAT3 */ GPIO_CFG(8, 1, GPIO_CFG_INPUT, GPIO_CFG_PULL_DOWN, GPIO_CFG_2MA), /* DAT4 */ GPIO_CFG(9, 1, GPIO_CFG_INPUT, GPIO_CFG_PULL_DOWN, GPIO_CFG_2MA), /* DAT5 */ GPIO_CFG(10, 1, GPIO_CFG_INPUT, GPIO_CFG_PULL_DOWN, GPIO_CFG_2MA), /* DAT6 */ GPIO_CFG(11, 1, GPIO_CFG_INPUT, GPIO_CFG_PULL_DOWN, GPIO_CFG_2MA), /* DAT7 */ GPIO_CFG(12, 1, GPIO_CFG_INPUT, GPIO_CFG_PULL_DOWN, GPIO_CFG_16MA), /* PCLK */ GPIO_CFG(13, 1, GPIO_CFG_INPUT, GPIO_CFG_PULL_DOWN, GPIO_CFG_2MA), /* HSYNC_IN */ GPIO_CFG(14, 1, GPIO_CFG_INPUT, GPIO_CFG_PULL_DOWN, GPIO_CFG_2MA), /* VSYNC_IN */ GPIO_CFG(GPIO_CAM_MCLK, 1, GPIO_CFG_OUTPUT, GPIO_CFG_PULL_DOWN, GPIO_CFG_16MA), /* MCLK */ }; static void config_gpio_table(uint32_t *table, int len) { int n, rc; for (n = 0; n < len; n++) { rc = gpio_tlmm_config(table[n], GPIO_CFG_ENABLE); if (rc) { printk(KERN_ERR "%s: gpio_tlmm_config(%#x)=%d\n", __func__, table[n], rc); break; } } } static int config_camera_on_gpios(void) { config_gpio_table(camera_on_gpio_table, ARRAY_SIZE(camera_on_gpio_table)); return 0; } static void config_camera_off_gpios(void) { config_gpio_table(camera_off_gpio_table, ARRAY_SIZE(camera_off_gpio_table)); } int camera_power_on (void) { int rc; struct device *dev = thunderg_backlight_dev(); camera_power_mutex_lock(); if(lcd_bl_power_state == BL_POWER_SUSPEND) { thunderg_pwrsink_resume(); mdelay(50); } /* clear RESET, PWDN to Low*/ gpio_set_value(GPIO_CAM_RESET, 0); gpio_set_value(GPIO_CAM_PWDN, 0); /*AVDD power 2.8V*/ if (lge_bd_rev == LGE_REV_B) { rc = aat28xx_ldo_set_level(dev, LDO_CAM_AF_NO, 2800); if (rc < 0) { printk(KERN_ERR "%s: ldo %d set level error\n", __func__, LDO_CAM_AF_NO); goto power_on_fail; } rc = aat28xx_ldo_enable(dev, LDO_CAM_AF_NO, 1); if (rc < 0) { printk(KERN_ERR "%s: ldo %d control error\n", __func__, LDO_CAM_AF_NO); goto power_on_fail; } } else { /* it is for rev.c and default */ struct vreg *vreg_mmc = vreg_get(0, "mmc"); vreg_set_level(vreg_mmc, 2800); vreg_enable(vreg_mmc); } /* DVDD power 1.2V */ rc = aat28xx_ldo_set_level(dev, LDO_CAM_DVDD_NO, 1200); if (rc < 0) { printk(KERN_ERR "%s: ldo %d set level error\n", __func__, LDO_CAM_DVDD_NO); goto power_on_fail; } rc = aat28xx_ldo_enable(dev, LDO_CAM_DVDD_NO, 1); if (rc < 0) { printk(KERN_ERR "%s: ldo %d control error\n", __func__, LDO_CAM_DVDD_NO); goto power_on_fail; } /*IOVDD power 2.6V*/ rc = aat28xx_ldo_set_level(dev, LDO_CAM_IOVDD_NO, 2600); if (rc < 0) { printk(KERN_ERR "%s: ldo %d set level error\n", __func__, LDO_CAM_IOVDD_NO); goto power_on_fail; } rc = aat28xx_ldo_enable(dev, LDO_CAM_IOVDD_NO, 1); if (rc < 0) { printk(KERN_ERR "%s: ldo %d control error\n", __func__, LDO_CAM_IOVDD_NO); goto power_on_fail; } /*AVDD power 2.7V*/ /* LGE_CHANGE * Change AVDD level from 2.7V to 2.8V in order to reduce camera noise in dard environment. * 2010-08-03. minjong.gong@lge.com */ rc = aat28xx_ldo_set_level(dev, LDO_CAM_AVDD_NO, 2800); if (rc < 0) { printk(KERN_ERR "%s: ldo %d set level error\n", __func__, LDO_CAM_AVDD_NO); goto power_on_fail; } rc = aat28xx_ldo_enable(dev, LDO_CAM_AVDD_NO, 1); if (rc < 0) { printk(KERN_ERR "%s: ldo %d control error\n", __func__, LDO_CAM_AVDD_NO); goto power_on_fail; } mdelay(5); /*M Clock -24Mhz*/ msm_camio_clk_rate_set(mclk_rate); mdelay(5); msm_camio_camif_pad_reg_reset(); mdelay(5); /*reset high*/ gpio_set_value(GPIO_CAM_RESET, 1); mdelay(5); /*Nstandby high*/ gpio_set_value(GPIO_CAM_PWDN, 1); mdelay(8); // T2 camera_power_state = CAM_POWER_ON; power_on_fail: camera_power_mutex_unlock(); return rc; } int camera_power_off (void) { int rc; struct device *dev = thunderg_backlight_dev(); camera_power_mutex_lock(); if (lcd_bl_power_state == BL_POWER_SUSPEND) { thunderg_pwrsink_resume(); mdelay(50); } /*Nstandby low*/ gpio_set_value(GPIO_CAM_PWDN, 0); mdelay(5); /*reset low*/ gpio_set_value(GPIO_CAM_RESET, 0); /*AVDD power 2.8V*/ if (lge_bd_rev == LGE_REV_A) { rc = aat28xx_ldo_set_level(dev, LDO_CAM_AF_NO, 0); if (rc < 0) { printk(KERN_ERR "%s: ldo %d set level error\n", __func__, LDO_CAM_AF_NO); goto power_off_fail; } rc = aat28xx_ldo_enable(dev, LDO_CAM_AF_NO, 0); if (rc < 0) { printk(KERN_ERR "%s: ldo %d control error\n", __func__, LDO_CAM_AF_NO); goto power_off_fail; } } else { /* it is for rev.c and default */ struct vreg *vreg_mmc = vreg_get(0, "mmc"); vreg_set_level(vreg_mmc, 0); vreg_disable(vreg_mmc); } /*AVDD power 2.7V*/ rc = aat28xx_ldo_set_level(dev, LDO_CAM_AVDD_NO, 0); if (rc < 0) { printk(KERN_ERR "%s: ldo %d set level error\n", __func__, LDO_CAM_AVDD_NO); goto power_off_fail; } rc = aat28xx_ldo_enable(dev, LDO_CAM_AVDD_NO, 0); if (rc < 0) { printk(KERN_ERR "%s: ldo %d control error\n", __func__, LDO_CAM_AVDD_NO); goto power_off_fail; } /*IOVDD power 2.6V*/ rc = aat28xx_ldo_set_level(dev, LDO_CAM_IOVDD_NO, 0); if (rc < 0) { printk(KERN_ERR "%s: ldo %d set level error\n", __func__, LDO_CAM_IOVDD_NO); goto power_off_fail; } rc = aat28xx_ldo_enable(dev, LDO_CAM_IOVDD_NO, 0); if (rc < 0) { printk(KERN_ERR "%s: ldo %d control error\n", __func__, LDO_CAM_IOVDD_NO); goto power_off_fail; } /* DVDD power 1.2V*/ rc = aat28xx_ldo_set_level(dev, LDO_CAM_DVDD_NO, 0); if (rc < 0) { printk(KERN_ERR "%s: ldo %d set level error\n", __func__, LDO_CAM_DVDD_NO); goto power_off_fail; } rc = aat28xx_ldo_enable(dev, LDO_CAM_DVDD_NO, 0); if (rc < 0) { printk(KERN_ERR "%s: ldo %d control error\n", __func__, LDO_CAM_DVDD_NO); goto power_off_fail; } camera_power_state = CAM_POWER_OFF; power_off_fail: camera_power_mutex_unlock(); return rc; } static struct msm_camera_device_platform_data msm_camera_device_data = { .camera_gpio_on = config_camera_on_gpios, .camera_gpio_off = config_camera_off_gpios, .ioext.mdcphy = MSM7XXX_MDC_PHYS, .ioext.mdcsz = MSM7XXX_MDC_SIZE, .ioext.appphy = MSM7XXX_CLK_CTL_PHYS, .ioext.appsz = MSM7XXX_CLK_CTL_SIZE, .camera_power_on = camera_power_on, .camera_power_off = camera_power_off, }; #if defined (CONFIG_ISX005) static struct msm_camera_sensor_flash_data flash_none = { .flash_type = MSM_CAMERA_FLASH_NONE, }; static struct msm_camera_sensor_info msm_camera_sensor_isx005_data = { .sensor_name = "isx005", .sensor_reset = GPIO_CAM_RESET, .sensor_pwd = GPIO_CAM_PWDN, .vcm_pwd = 0, .vcm_enable = 0, .pdata = &msm_camera_device_data, .flash_data = &flash_none, }; static struct platform_device msm_camera_sensor_isx005 = { .name = "msm_camera_isx005", .dev = { .platform_data = &msm_camera_sensor_isx005_data, }, }; #endif #endif /*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ /*+++++++++++++++++++++++++++++++++++++++++++++++++++++++Battery Support+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ static u32 msm_calculate_batt_capacity(u32 current_voltage); static struct msm_psy_batt_pdata msm_psy_batt_data = { .voltage_min_design = 2800, .voltage_max_design = 4300, .avail_chg_sources = AC_CHG | USB_CHG , .batt_technology = POWER_SUPPLY_TECHNOLOGY_LION, .calculate_capacity = &msm_calculate_batt_capacity, }; static u32 msm_calculate_batt_capacity(u32 current_voltage) { u32 low_voltage = msm_psy_batt_data.voltage_min_design; u32 high_voltage = msm_psy_batt_data.voltage_max_design; return (current_voltage - low_voltage) * 100 / (high_voltage - low_voltage); } static struct platform_device msm_batt_device = { .name = "msm-battery", .id = -1, .dev.platform_data = &msm_psy_batt_data, }; /*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++Dock State Driver Support++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ static char *dock_state_string[] = { "0", "1", "2", }; enum { DOCK_STATE_UNDOCKED = 0, DOCK_STATE_DESK = 1, /* multikit */ DOCK_STATE_CAR = 2, /* carkit */ DOCK_STATE_UNKNOWN, }; enum { KIT_DOCKED = 0, KIT_UNDOCKED = 1, }; static void thunderg_desk_dock_detect_callback(int state) { int ret; if (state) state = DOCK_STATE_DESK; ret = lge_gpio_switch_pass_event("dock", state); if (ret) printk(KERN_INFO "%s: desk dock event report fail\n", __func__); return; } static int thunderg_register_callback(void) { rpc_server_hs_register_callback(thunderg_desk_dock_detect_callback); return 0; } static int thunderg_gpio_carkit_work_func(void) { return DOCK_STATE_UNDOCKED; } static char *thunderg_gpio_carkit_print_state(int state) { return dock_state_string[state]; } static int thunderg_gpio_carkit_sysfs_store(const char *buf, size_t size) { int state; if (!strncmp(buf, "undock", size-1)) state = DOCK_STATE_UNDOCKED; else if (!strncmp(buf, "desk", size-1)) state = DOCK_STATE_DESK; else if (!strncmp(buf, "car", size-1)) state = DOCK_STATE_CAR; else return -EINVAL; return state; } static unsigned thunderg_carkit_gpios[] = { }; static struct lge_gpio_switch_platform_data thunderg_carkit_data = { .name = "dock", .gpios = thunderg_carkit_gpios, .num_gpios = ARRAY_SIZE(thunderg_carkit_gpios), .irqflags = IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING, .wakeup_flag = 1, .work_func = thunderg_gpio_carkit_work_func, .print_state = thunderg_gpio_carkit_print_state, .sysfs_store = thunderg_gpio_carkit_sysfs_store, .additional_init = thunderg_register_callback, }; static struct platform_device thunderg_carkit_device = { .name = "lge-switch-gpio", .id = 0, .dev = { .platform_data = &thunderg_carkit_data, }, }; /*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ /*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++Vibrator Driver Support+++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ #define VIBE_IC_VOLTAGE 3300 #define GPIO_LIN_MOTOR_PWM 28 #define GP_MN_CLK_MDIV_REG 0x004C #define GP_MN_CLK_NDIV_REG 0x0050 #define GP_MN_CLK_DUTY_REG 0x0054 /* about 22.93 kHz, should be checked */ #define GPMN_M_DEFAULT 21 #define GPMN_N_DEFAULT 4500 /* default duty cycle = disable motor ic */ #define GPMN_D_DEFAULT (GPMN_N_DEFAULT >> 1) #define PWM_MAX_HALF_DUTY ((GPMN_N_DEFAULT >> 1) - 60) /* minimum operating spec. should be checked */ #define GPMN_M_MASK 0x01FF #define GPMN_N_MASK 0x1FFF #define GPMN_D_MASK 0x1FFF #define REG_WRITEL(value, reg) writel(value, (MSM_WEB_BASE+reg)) int thunderg_vibrator_power_set(int enable) { static int is_enabled = 0; struct device *dev = thunderg_backlight_dev(); if (dev==NULL) { printk(KERN_ERR "%s: backlight devive get failed\n", __FUNCTION__); return -1; } if (enable) { if (is_enabled) { printk(KERN_INFO "vibrator power was enabled, already\n"); return 0; } /* 3300 mV for Motor IC */ if (aat28xx_ldo_set_level(dev, 1, VIBE_IC_VOLTAGE) < 0) { printk(KERN_ERR "%s: vibrator LDO set failed\n", __FUNCTION__); return -EIO; } if (aat28xx_ldo_enable(dev, 1, 1) < 0) { printk(KERN_ERR "%s: vibrator LDO enable failed\n", __FUNCTION__); return -EIO; } is_enabled = 1; } else { if (!is_enabled) { printk(KERN_INFO "vibrator power was disabled, already\n"); return 0; } if (aat28xx_ldo_set_level(dev, 1, 0) < 0) { printk(KERN_ERR "%s: vibrator LDO set failed\n", __FUNCTION__); return -EIO; } if (aat28xx_ldo_enable(dev, 1, 0) < 0) { printk(KERN_ERR "%s: vibrator LDO disable failed\n", __FUNCTION__); return -EIO; } is_enabled = 0; } return 0; } int thunderg_vibrator_pwm_set(int enable, int amp) { int gain = ((PWM_MAX_HALF_DUTY*amp) >> 7)+ GPMN_D_DEFAULT; REG_WRITEL((GPMN_M_DEFAULT & GPMN_M_MASK), GP_MN_CLK_MDIV_REG); REG_WRITEL((~( GPMN_N_DEFAULT - GPMN_M_DEFAULT )&GPMN_N_MASK), GP_MN_CLK_NDIV_REG); if (enable) { REG_WRITEL((gain & GPMN_D_MASK), GP_MN_CLK_DUTY_REG); gpio_direction_output(GPIO_LIN_MOTOR_PWM, 1); } else { REG_WRITEL(GPMN_D_DEFAULT, GP_MN_CLK_DUTY_REG); gpio_direction_output(GPIO_LIN_MOTOR_PWM, 0); } return 0; } int thunderg_vibrator_ic_enable_set(int enable) { /* nothing to do, thunder does not using Motor Enable pin */ return 0; } int thunderg_vibrator_gpio_request(void) { int rc = 0; rc = gpio_request(GPIO_LIN_MOTOR_PWM, "lin_motor_pwm"); if (rc) return rc; return 0; } static struct android_vibrator_platform_data thunderg_vibrator_data = { .enable_status = 0, .power_set = thunderg_vibrator_power_set, .pwm_set = thunderg_vibrator_pwm_set, .ic_enable_set = thunderg_vibrator_ic_enable_set, .gpio_request = thunderg_vibrator_gpio_request, .amp_value = 115, }; static struct platform_device android_vibrator_device = { .name = "android-vibrator", .id = -1, .dev = { .platform_data = &thunderg_vibrator_data, }, }; /*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ /*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++Ear Sense Driver Support++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ static char *ear_state_string[] = { "0", "1", }; enum { EAR_STATE_EJECT = 0, EAR_STATE_INJECT = 1, }; enum { EAR_EJECT = 0, EAR_INJECT = 1, }; static int thunderg_gpio_earsense_work_func(void) { int state; int gpio_value; gpio_value = gpio_get_value(GPIO_EAR_SENSE); printk(KERN_INFO"%s: ear sense detected : %s\n", __func__,gpio_value?"injected":"ejected"); if (gpio_value == EAR_EJECT) { state = EAR_STATE_EJECT; gpio_set_value(GPIO_HS_MIC_BIAS_EN, 0); } else { state = EAR_STATE_INJECT; gpio_set_value(GPIO_HS_MIC_BIAS_EN, 1); } return state; } static char *thunderg_gpio_earsense_print_state(int state) { return ear_state_string[state]; } static int thunderg_gpio_earsense_sysfs_store(const char *buf, size_t size) { int state; if (!strncmp(buf, "eject", size - 1)) state = EAR_STATE_EJECT; else if (!strncmp(buf, "inject", size - 1)) state = EAR_STATE_INJECT; else return -EINVAL; return state; } static unsigned thunderg_earsense_gpios[] = { GPIO_EAR_SENSE, }; static struct lge_gpio_switch_platform_data thunderg_earsense_data = { .name = "h2w", .gpios = thunderg_earsense_gpios, .num_gpios = ARRAY_SIZE(thunderg_earsense_gpios), .irqflags = IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING, .wakeup_flag = 1, .work_func = thunderg_gpio_earsense_work_func, .print_state = thunderg_gpio_earsense_print_state, .sysfs_store = thunderg_gpio_earsense_sysfs_store, }; static struct platform_device thunderg_earsense_device = { .name = "lge-switch-gpio", .id = 1, .dev = { .platform_data = &thunderg_earsense_data, }, }; /*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ /*+++++++++++++++++++++++++++++++++++++++++++++++++++KGSL Device Support+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ static struct resource kgsl_3d0_resources[] = { { .name = KGSL_3D0_REG_MEMORY, .start = 0xA0000000, .end = 0xA001ffff, .flags = IORESOURCE_MEM, }, { .name = KGSL_3D0_IRQ, .start = INT_GRAPHICS, .end = INT_GRAPHICS, .flags = IORESOURCE_IRQ, }, }; static struct kgsl_device_platform_data kgsl_3d0_pdata = { /* bus_freq has been set to 160000 for power savings. * OEMs may modify the value at their discretion for performance * The appropriate maximum replacement for 160000 is: * msm7x2x_clock_data.max_axi_khz */ .pwrlevel = { { .gpu_freq = 0, .bus_freq = 160000000, }, }, .init_level = 0, .num_levels = 1, .set_grp_async = NULL, .idle_timeout = HZ/5, .clk_map = KGSL_CLK_CORE | KGSL_CLK_IFACE | KGSL_CLK_MEM, }; struct platform_device msm_kgsl_3d0 = { .name = "kgsl-3d0", .id = 0, .num_resources = ARRAY_SIZE(kgsl_3d0_resources), .resource = kgsl_3d0_resources, .dev = { .platform_data = &kgsl_3d0_pdata, }, }; /*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++Power Management Support+++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ static struct msm_pm_platform_data msm7x27_pm_data[MSM_PM_SLEEP_MODE_NR] = { [MSM_PM_MODE(0, MSM_PM_SLEEP_MODE_POWER_COLLAPSE)] = { .idle_supported = 1, .suspend_supported = 1, .idle_enabled = 1, .suspend_enabled = 1, .latency = 16000, .residency = 20000, }, [MSM_PM_MODE(0, MSM_PM_SLEEP_MODE_POWER_COLLAPSE_NO_XO_SHUTDOWN)] = { .idle_supported = 1, .suspend_supported = 1, .idle_enabled = 1, .suspend_enabled = 1, .latency = 12000, .residency = 20000, }, [MSM_PM_MODE(0, MSM_PM_SLEEP_MODE_RAMP_DOWN_AND_WAIT_FOR_INTERRUPT)] = { .idle_supported = 1, .suspend_supported = 1, .idle_enabled = 1, .suspend_enabled = 1, .latency = 2000, .residency = 0, }, }; static struct msm_pm_boot_platform_data msm_pm_boot_pdata __initdata = { .mode = MSM_PM_BOOT_CONFIG_RESET_VECTOR_PHYS, .p_addr = 0, }; int lcd_bl_power_state=0; int thunderg_pwrsink_suspend_noirq(struct device *dev) { printk(KERN_INFO"%s: configure gpio for suspend\n", __func__); camera_power_mutex_lock(); if(camera_power_state == CAM_POWER_ON) { camera_power_mutex_unlock(); return 0; } gpio_tlmm_config(GPIO_CFG(GPIO_LCD_BL_EN, 0, GPIO_CFG_INPUT, GPIO_CFG_PULL_DOWN, GPIO_CFG_2MA), GPIO_CFG_ENABLE); gpio_tlmm_config(GPIO_CFG(GPIO_BL_I2C_SCL, 0, GPIO_CFG_INPUT, GPIO_CFG_NO_PULL, GPIO_CFG_2MA), GPIO_CFG_ENABLE); gpio_tlmm_config(GPIO_CFG(GPIO_BL_I2C_SDA, 0, GPIO_CFG_INPUT, GPIO_CFG_NO_PULL, GPIO_CFG_2MA), GPIO_CFG_ENABLE); // gpio_tlmm_config(GPIO_CFG(GPIO_LCD_VSYNC_O, 0, GPIO_CFG_INPUT, GPIO_CFG_PULL_DOWN, GPIO_CFG_2MA), GPIO_CFG_ENABLE); gpio_tlmm_config(GPIO_CFG(GPIO_LCD_MAKER_LOW, 0, GPIO_CFG_OUTPUT, GPIO_CFG_PULL_DOWN, GPIO_CFG_2MA), GPIO_CFG_ENABLE); gpio_direction_output(GPIO_LCD_MAKER_LOW, 0); gpio_tlmm_config(GPIO_CFG(GPIO_LCD_RESET_N, 0, GPIO_CFG_OUTPUT, GPIO_CFG_PULL_DOWN, GPIO_CFG_2MA), GPIO_CFG_ENABLE); gpio_direction_output(GPIO_LCD_RESET_N, 0); lcd_bl_power_state = BL_POWER_SUSPEND; camera_power_mutex_unlock(); return 0; } int thunderg_pwrsink_resume_noirq(struct device *dev) { printk(KERN_INFO"%s: configure gpio for resume\n", __func__); camera_power_mutex_lock(); if(camera_power_state == CAM_POWER_ON || lcd_bl_power_state == BL_POWER_RESUME) { camera_power_mutex_unlock(); return 0; } gpio_tlmm_config(GPIO_CFG(GPIO_LCD_BL_EN, 0, GPIO_CFG_OUTPUT, GPIO_CFG_NO_PULL, GPIO_CFG_2MA), GPIO_CFG_ENABLE); gpio_direction_output(GPIO_LCD_BL_EN, 1); gpio_tlmm_config(GPIO_CFG(GPIO_BL_I2C_SCL, 0, GPIO_CFG_OUTPUT, GPIO_CFG_NO_PULL, GPIO_CFG_2MA), GPIO_CFG_ENABLE); gpio_direction_output(GPIO_BL_I2C_SCL, 1); gpio_tlmm_config(GPIO_CFG(GPIO_BL_I2C_SDA, 0, GPIO_CFG_OUTPUT, GPIO_CFG_NO_PULL, GPIO_CFG_2MA), GPIO_CFG_ENABLE); gpio_direction_output(GPIO_BL_I2C_SDA, 1); // gpio_tlmm_config(GPIO_CFG(GPIO_LCD_VSYNC_O, 0, GPIO_CFG_INPUT, GPIO_CFG_PULL_DOWN, GPIO_CFG_2MA), GPIO_CFG_ENABLE); gpio_tlmm_config(GPIO_CFG(GPIO_LCD_MAKER_LOW, 0, GPIO_CFG_INPUT, GPIO_CFG_PULL_UP, GPIO_CFG_2MA), GPIO_CFG_ENABLE); gpio_tlmm_config(GPIO_CFG(GPIO_LCD_RESET_N, 0, GPIO_CFG_OUTPUT, GPIO_CFG_PULL_DOWN, GPIO_CFG_2MA), GPIO_CFG_ENABLE); gpio_direction_output(GPIO_LCD_RESET_N, 0); lcd_bl_power_state = BL_POWER_RESUME; camera_power_mutex_unlock(); return 0; } void thunderg_pwrsink_resume() { gpio_tlmm_config(GPIO_CFG(GPIO_LCD_BL_EN, 0, GPIO_CFG_OUTPUT, GPIO_CFG_NO_PULL, GPIO_CFG_2MA), GPIO_CFG_ENABLE); gpio_direction_output(GPIO_LCD_BL_EN, 1); gpio_tlmm_config(GPIO_CFG(GPIO_BL_I2C_SCL, 0, GPIO_CFG_OUTPUT, GPIO_CFG_NO_PULL, GPIO_CFG_2MA), GPIO_CFG_ENABLE); gpio_direction_output(GPIO_BL_I2C_SCL, 1); gpio_tlmm_config(GPIO_CFG(GPIO_BL_I2C_SDA, 0, GPIO_CFG_OUTPUT, GPIO_CFG_NO_PULL, GPIO_CFG_2MA), GPIO_CFG_ENABLE); gpio_direction_output(GPIO_BL_I2C_SDA, 1); // gpio_tlmm_config(GPIO_CFG(GPIO_LCD_VSYNC_O, 0, GPIO_CFG_INPUT, GPIO_CFG_PULL_DOWN, GPIO_CFG_2MA), GPIO_CFG_ENABLE); gpio_tlmm_config(GPIO_CFG(GPIO_LCD_MAKER_LOW, 0, GPIO_CFG_INPUT, GPIO_CFG_PULL_UP, GPIO_CFG_2MA), GPIO_CFG_ENABLE); gpio_tlmm_config(GPIO_CFG(GPIO_LCD_RESET_N, 0, GPIO_CFG_OUTPUT, GPIO_CFG_NO_PULL, GPIO_CFG_2MA), GPIO_CFG_ENABLE); gpio_direction_output(GPIO_LCD_RESET_N, 0); lcd_bl_power_state = BL_POWER_RESUME; } static struct dev_pm_ops thunderg_pwrsink_data = { .suspend_noirq = thunderg_pwrsink_suspend_noirq, .resume_noirq = thunderg_pwrsink_resume_noirq, }; static struct platform_device thunderg_pwrsink_device = { .name = "lge-pwrsink", .id = -1, .dev = { .platform_data = &thunderg_pwrsink_data, }, }; /*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++ATCMD Virtual Device Support+++++++++++++++++++++++++++++++++++++++++++++++++++++*/ static unsigned short atcmd_virtual_keycode[ATCMD_VIRTUAL_KEYPAD_ROW][ATCMD_VIRTUAL_KEYPAD_COL] = { {KEY_1, KEY_8, KEY_Q, KEY_I, KEY_D, KEY_HOME, KEY_B, KEY_UP}, {KEY_2, KEY_9, KEY_W, KEY_O, KEY_F, KEY_RIGHTSHIFT, KEY_N, KEY_DOWN}, {KEY_3, KEY_0, KEY_E, KEY_P, KEY_G, KEY_Z, KEY_M, KEY_UNKNOWN}, {KEY_4, KEY_BACK, KEY_R, KEY_SEARCH, KEY_H, KEY_X, KEY_LEFTSHIFT, KEY_UNKNOWN}, {KEY_5, KEY_BACKSPACE, KEY_T, KEY_LEFTALT, KEY_J, KEY_C, KEY_REPLY, KEY_CAMERA}, {KEY_6, KEY_ENTER, KEY_Y, KEY_A, KEY_K, KEY_V, KEY_RIGHT, KEY_CAMERAFOCUS}, {KEY_7, KEY_MENU, KEY_U, KEY_S, KEY_L, KEY_SPACE, KEY_LEFT, KEY_SEND}, {KEY_UNKNOWN, KEY_UNKNOWN, KEY_UNKNOWN, KEY_UNKNOWN, KEY_UNKNOWN, KEY_UNKNOWN, KEY_FOLDER_MENU, KEY_FOLDER_HOME}, }; static struct atcmd_virtual_platform_data atcmd_virtual_pdata = { .keypad_row = ATCMD_VIRTUAL_KEYPAD_ROW, .keypad_col = ATCMD_VIRTUAL_KEYPAD_COL, .keycode = (unsigned char *)atcmd_virtual_keycode, }; static struct platform_device atcmd_virtual_device = { .name = "atcmd_virtual_kbd", .id = -1, .dev = { .platform_data = &atcmd_virtual_pdata, }, }; /*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ /*+++++++++++++++++++++++++++++++++++++++++++++++++++++Hardware Keys Support+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ static unsigned int keypad_row_gpios[] = {32, 33, 36}; static unsigned int keypad_col_gpios[] = {37, 38}; #define KEYMAP_INDEX(row, col) ((row)*ARRAY_SIZE(keypad_col_gpios) + (col)) static const unsigned short keypad_keymap_thunder[][8] = { [LGE_REV_B] = { [KEYMAP_INDEX(0, 0)] = KEY_MENU, [KEYMAP_INDEX(0, 1)] = KEY_SEARCH, [KEYMAP_INDEX(1, 0)] = KEY_HOME, [KEYMAP_INDEX(1, 1)] = KEY_BACK, [KEYMAP_INDEX(2, 0)] = KEY_VOLUMEDOWN, [KEYMAP_INDEX(2, 1)] = KEY_VOLUMEUP, }, [LGE_REV_C] = { [KEYMAP_INDEX(0, 0)] = KEY_HOME, [KEYMAP_INDEX(0, 1)] = KEY_SEARCH, [KEYMAP_INDEX(1, 0)] = KEY_BACK, [KEYMAP_INDEX(1, 1)] = KEY_MENU, [KEYMAP_INDEX(2, 0)] = KEY_VOLUMEDOWN, [KEYMAP_INDEX(2, 1)] = KEY_VOLUMEUP, }, [LGE_REV_D] = { [KEYMAP_INDEX(0, 0)] = KEY_HOME, [KEYMAP_INDEX(0, 1)] = KEY_SEARCH, [KEYMAP_INDEX(1, 0)] = KEY_BACK, [KEYMAP_INDEX(1, 1)] = KEY_MENU, [KEYMAP_INDEX(2, 0)] = KEY_VOLUMEDOWN, [KEYMAP_INDEX(2, 1)] = KEY_VOLUMEUP, }, [LGE_REV_E] = { [KEYMAP_INDEX(0, 0)] = KEY_HOME, [KEYMAP_INDEX(0, 1)] = KEY_SEARCH, [KEYMAP_INDEX(1, 0)] = KEY_BACK, [KEYMAP_INDEX(1, 1)] = KEY_MENU, [KEYMAP_INDEX(2, 0)] = KEY_VOLUMEDOWN, [KEYMAP_INDEX(2, 1)] = KEY_VOLUMEUP, }, [LGE_REV_F] = { [KEYMAP_INDEX(0, 0)] = KEY_HOME, [KEYMAP_INDEX(0, 1)] = KEY_SEARCH, [KEYMAP_INDEX(1, 0)] = KEY_BACK, [KEYMAP_INDEX(1, 1)] = KEY_MENU, [KEYMAP_INDEX(2, 0)] = KEY_VOLUMEDOWN, [KEYMAP_INDEX(2, 1)] = KEY_VOLUMEUP, }, [LGE_REV_10] = { [KEYMAP_INDEX(0, 0)] = KEY_HOME, [KEYMAP_INDEX(0, 1)] = KEY_SEARCH, [KEYMAP_INDEX(1, 0)] = KEY_BACK, [KEYMAP_INDEX(1, 1)] = KEY_MENU, [KEYMAP_INDEX(2, 0)] = KEY_VOLUMEDOWN, [KEYMAP_INDEX(2, 1)] = KEY_VOLUMEUP, }, [LGE_REV_11] = { [KEYMAP_INDEX(0, 0)] = KEY_HOME, [KEYMAP_INDEX(0, 1)] = KEY_SEARCH, [KEYMAP_INDEX(1, 0)] = KEY_BACK, [KEYMAP_INDEX(1, 1)] = KEY_MENU, [KEYMAP_INDEX(2, 0)] = KEY_VOLUMEDOWN, [KEYMAP_INDEX(2, 1)] = KEY_VOLUMEUP, }, }; int thunderg_matrix_info_wrapper(struct gpio_event_input_devs *input_dev, struct gpio_event_info *info, void **data, int func) { int ret ; if (func == GPIO_EVENT_FUNC_RESUME) { gpio_tlmm_config(GPIO_CFG(keypad_col_gpios[0], 0,GPIO_CFG_INPUT, GPIO_CFG_PULL_UP,GPIO_CFG_2MA), GPIO_CFG_ENABLE); gpio_tlmm_config(GPIO_CFG(keypad_col_gpios[1], 0,GPIO_CFG_INPUT, GPIO_CFG_PULL_UP,GPIO_CFG_2MA), GPIO_CFG_ENABLE); } ret = gpio_event_matrix_func(input_dev, info, data, func); return ret ; } static int thunderg_gpio_matrix_power( const struct gpio_event_platform_data *pdata, bool on) { /* this is dummy function to make gpio_event driver register suspend function*/ return 0; } static struct gpio_event_matrix_info thunder_keypad_matrix_info = { .info.func = thunderg_matrix_info_wrapper, .keymap = NULL, .output_gpios = keypad_row_gpios, .input_gpios = keypad_col_gpios, .noutputs = ARRAY_SIZE(keypad_row_gpios), .ninputs = ARRAY_SIZE(keypad_col_gpios), .settle_time.tv.nsec = 40 * NSEC_PER_USEC, .poll_time.tv.nsec = 20 * NSEC_PER_MSEC, .flags = GPIOKPF_LEVEL_TRIGGERED_IRQ | GPIOKPF_PRINT_UNMAPPED_KEYS | GPIOKPF_DRIVE_INACTIVE }; static void __init thunder_select_keymap(void) { thunder_keypad_matrix_info.keymap = keypad_keymap_thunder[lge_bd_rev]; return; } static struct gpio_event_info *thunder_keypad_info[] = { &thunder_keypad_matrix_info.info }; static struct gpio_event_platform_data thunder_keypad_data = { .name = "thunder_keypad", .info = thunder_keypad_info, .info_count = ARRAY_SIZE(thunder_keypad_info), .power = thunderg_gpio_matrix_power, }; struct platform_device keypad_device_thunder= { .name = GPIO_EVENT_DEV_NAME, .id = -1, .dev = { .platform_data = &thunder_keypad_data, }, }; /*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ /*++++++++++++++++++++++++++++++++++++++++++++++++++++++KeyReset Platform Device Support+++++++++++++++++++++++++++++++++++++++++++++++++++*/ static int thunderg_reset_keys_up[] = { KEY_HOME, 0 }; static struct keyreset_platform_data thunderg_reset_keys_pdata = { .keys_up = thunderg_reset_keys_up, .keys_down = { //KEY_BACK, KEY_VOLUMEDOWN, KEY_SEARCH, 0 }, }; struct platform_device thunderg_reset_keys_device = { .name = KEYRESET_NAME, .dev.platform_data = &thunderg_reset_keys_pdata, }; /*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++mcs6000 Touchscreen Support++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ static struct gpio_i2c_pin ts_i2c_pin[] = { [0] = { .sda_pin = TS_GPIO_I2C_SDA, .scl_pin = TS_GPIO_I2C_SCL, .reset_pin = 0, .irq_pin = TS_GPIO_IRQ, }, }; static struct i2c_gpio_platform_data ts_i2c_pdata = { .sda_is_open_drain = 0, .scl_is_open_drain = 0, .udelay = 2, }; static struct platform_device ts_i2c_device = { .id = i2c_bus_num, .name = "i2c-gpio", .dev.platform_data = &ts_i2c_pdata, }; static int ts_set_vreg_pulldown(int onoff) { struct vreg *vreg_touch; int rc; unsigned id; printk("[Touch] %s() pulldown:%d\n",__FUNCTION__, onoff); vreg_touch = vreg_get(0, "synt"); if(IS_ERR(vreg_touch)) { printk("[Touch] vreg_get fail : touch\n"); return -1; } id = PM_VREG_PDOWN_SYNT_ID; rc = msm_proc_comm(PCOM_VREG_PULLDOWN, &onoff, &id); if (rc != 0) { printk("[Touch] vreg_set_pulldown failed\n"); return -1; } vreg_disable(vreg_touch); return 0; } static int ts_set_vreg(unsigned char onoff) { struct vreg *vreg_touch; int rc; printk("[Touch] %s() onoff:%d\n",__FUNCTION__, onoff); vreg_touch = vreg_get(0, "synt"); if(IS_ERR(vreg_touch)) { printk("[Touch] vreg_get fail : touch\n"); return -1; } if (onoff) { rc = vreg_set_level(vreg_touch, 3050); if (rc != 0) { printk("[Touch] vreg_set_level failed\n"); return -1; } vreg_enable(vreg_touch); } else { vreg_disable(vreg_touch); } return 0; } static struct touch_platform_data ts_pdata = { .ts_x_min = TS_X_MIN, .ts_x_max = TS_X_MAX, .ts_y_min = TS_Y_MIN, .ts_y_max = TS_Y_MAX, .power = ts_set_vreg, .pulldown = ts_set_vreg_pulldown, .irq = TS_GPIO_IRQ, .scl = TS_GPIO_I2C_SCL, .sda = TS_GPIO_I2C_SDA, }; static struct i2c_board_info ts_i2c_bdinfo[] = { [0] = { I2C_BOARD_INFO("touch_mcs6000", TS_I2C_SLAVE_ADDR), .type = "touch_mcs6000", .platform_data = &ts_pdata, }, }; static void __init thunderg_init_i2c_touch() { ts_i2c_pdata.sda_pin = ts_i2c_pin[0].sda_pin; ts_i2c_pdata.scl_pin = ts_i2c_pin[0].scl_pin; gpio_tlmm_config(GPIO_CFG(ts_i2c_pin[0].sda_pin, 0, GPIO_CFG_OUTPUT,GPIO_CFG_NO_PULL, GPIO_CFG_2MA), GPIO_CFG_ENABLE); gpio_tlmm_config(GPIO_CFG(ts_i2c_pin[0].scl_pin, 0, GPIO_CFG_OUTPUT,GPIO_CFG_NO_PULL, GPIO_CFG_2MA), GPIO_CFG_ENABLE); gpio_set_value(ts_i2c_pin[0].sda_pin, 1); gpio_set_value(ts_i2c_pin[0].scl_pin, 1); if (ts_i2c_pin[0].reset_pin) { gpio_tlmm_config(GPIO_CFG(ts_i2c_pin[0].reset_pin, 0, GPIO_CFG_OUTPUT,GPIO_CFG_NO_PULL, GPIO_CFG_2MA), GPIO_CFG_ENABLE); gpio_set_value(ts_i2c_pin[0].reset_pin, 1); } if (ts_i2c_pin[0].irq_pin) { gpio_tlmm_config(GPIO_CFG(ts_i2c_pin[0].irq_pin, 0, GPIO_CFG_INPUT,GPIO_CFG_PULL_UP, GPIO_CFG_2MA), GPIO_CFG_ENABLE); ts_i2c_bdinfo[0].irq = MSM_GPIO_TO_INT(ts_i2c_pin[0].irq_pin); } i2c_register_board_info(ts_i2c_device.id, &ts_i2c_bdinfo[0], 1); platform_device_register(&ts_i2c_device); } i2c_bus_num++; /*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ /*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++Accelerometer Support+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ static int kr3dh_config_gpio(int config) { if (config) { /* for wake state */ gpio_tlmm_config(GPIO_CFG(ACCEL_GPIO_I2C_SCL, 0, GPIO_CFG_OUTPUT, GPIO_CFG_NO_PULL, GPIO_CFG_2MA), GPIO_CFG_ENABLE); gpio_tlmm_config(GPIO_CFG(ACCEL_GPIO_I2C_SDA, 0, GPIO_CFG_OUTPUT, GPIO_CFG_NO_PULL, GPIO_CFG_2MA), GPIO_CFG_ENABLE); } else { /* for sleep state */ gpio_tlmm_config(GPIO_CFG(ACCEL_GPIO_I2C_SCL, 0, GPIO_CFG_INPUT, GPIO_CFG_NO_PULL, GPIO_CFG_2MA), GPIO_CFG_ENABLE); gpio_tlmm_config(GPIO_CFG(ACCEL_GPIO_I2C_SDA, 0, GPIO_CFG_INPUT, GPIO_CFG_NO_PULL, GPIO_CFG_2MA), GPIO_CFG_ENABLE); } return 0; } static int kr_init(void) { return 0; } static void kr_exit(void) { } static int accel_power_on(void) { int ret = 0; struct vreg *gp3_vreg = vreg_get(0, "gp3"); printk("[Accelerometer] %s() : Power On\n",__FUNCTION__); vreg_set_level(gp3_vreg, 3000); vreg_enable(gp3_vreg); return ret; } static int accel_power_off(void) { int ret = 0; struct vreg *gp3_vreg = vreg_get(0, "gp3"); printk("[Accelerometer] %s() : Power Off\n",__FUNCTION__); vreg_disable(gp3_vreg); return ret; } struct kr3dh_platform_data kr3dh_data = { .poll_interval = 100, .min_interval = 0, .g_range = 0x00, .axis_map_x = 0, .axis_map_y = 1, .axis_map_z = 2, .negate_x = 0, .negate_y = 0, .negate_z = 0, .power_on = accel_power_on, .power_off = accel_power_off, .kr_init = kr_init, .kr_exit = kr_exit, .gpio_config = kr3dh_config_gpio, }; static struct gpio_i2c_pin accel_i2c_pin[] = { [0] = { .sda_pin = ACCEL_GPIO_I2C_SDA, .scl_pin = ACCEL_GPIO_I2C_SCL, .reset_pin = 0, .irq_pin = ACCEL_GPIO_INT, }, }; static struct i2c_gpio_platform_data accel_i2c_pdata = { .sda_is_open_drain = 0, .scl_is_open_drain = 0, .udelay = 2, }; static struct platform_device accel_i2c_device = { .id = i2c_bus_num, .name = "i2c-gpio", .dev.platform_data = &accel_i2c_pdata, }; static struct i2c_board_info accel_i2c_bdinfo[] = { [1] = { I2C_BOARD_INFO("KR3DH", ACCEL_I2C_ADDRESS_H), .type = "KR3DH", .platform_data = &kr3dh_data, }, [0] = { I2C_BOARD_INFO("KR3DM", ACCEL_I2C_ADDRESS), .type = "KR3DM", .platform_data = &kr3dh_data, }, }; static void __init thunderg_init_i2c_acceleration() { accel_i2c_pdata.sda_pin = accel_i2c_pin[0].sda_pin; accel_i2c_pdata.scl_pin = accel_i2c_pin[0].scl_pin; gpio_tlmm_config(GPIO_CFG(accel_i2c_pin[0].sda_pin, 0, GPIO_CFG_OUTPUT,GPIO_CFG_NO_PULL, GPIO_CFG_2MA), GPIO_CFG_ENABLE); gpio_tlmm_config(GPIO_CFG(accel_i2c_pin[0].scl_pin, 0, GPIO_CFG_OUTPUT,GPIO_CFG_NO_PULL, GPIO_CFG_2MA), GPIO_CFG_ENABLE); gpio_set_value(accel_i2c_pin[0].sda_pin, 1); gpio_set_value(accel_i2c_pin[0].scl_pin, 1); if (accel_i2c_pin[0].reset_pin) { gpio_tlmm_config(GPIO_CFG(accel_i2c_pin[0].reset_pin, 0, GPIO_CFG_OUTPUT,GPIO_CFG_NO_PULL, GPIO_CFG_2MA), GPIO_CFG_ENABLE); gpio_set_value(accel_i2c_pin[0].reset_pin, 1); } if (accel_i2c_pin[0].irq_pin) { gpio_tlmm_config(GPIO_CFG(accel_i2c_pin[0].irq_pin, 0, GPIO_CFG_INPUT,GPIO_CFG_PULL_UP, GPIO_CFG_2MA), GPIO_CFG_ENABLE); accel_i2c_bdinfo[0].irq = MSM_GPIO_TO_INT(accel_i2c_pin[0].irq_pin); } if(lge_bd_rev >= LGE_REV_11) i2c_register_board_info(accel_i2c_device.id, &accel_i2c_bdinfo[1], 1); /* KR3DH */ else i2c_register_board_info(accel_i2c_device.id, &accel_i2c_bdinfo[0], 1); /* KR3DM */ platform_device_register(&accel_i2c_device); } i2c_bus_num++; /*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ /*+++++++++++++++++++++++++++++++++++++++++++++++++ECompass & Proximity Sensor Support+++++++++++++++++++++++++++++++++++++++++++++++++++++*/ static int ecom_power_set(unsigned char onoff) { int ret = 0; struct vreg *gp3_vreg = vreg_get(0, "gp3"); struct vreg *gp6_vreg = vreg_get(0, "gp6"); printk("[Ecompass] %s() : Power %s\n",__FUNCTION__, onoff ? "On" : "Off"); if (onoff) { vreg_set_level(gp3_vreg, 3000); vreg_enable(gp3_vreg); /* proximity power on , when we turn off I2C line be set to low caues sensor H/W characteristic */ vreg_set_level(gp6_vreg, 2800); vreg_enable(gp6_vreg); } else { vreg_disable(gp3_vreg); /* proximity power off */ vreg_disable(gp6_vreg); } return ret; } static struct ecom_platform_data ecom_pdata = { .pin_int = ECOM_GPIO_INT, .pin_rst = 0, .power = ecom_power_set, }; static int prox_power_set(unsigned char onoff) { int ret = 0; struct vreg *gp6_vreg = vreg_get(0, "gp6"); printk("[Proximity] %s() : Power %s\n",__FUNCTION__, onoff ? "On" : "Off"); if (onoff) { vreg_set_level(gp6_vreg, 2800); vreg_enable(gp6_vreg); } else { vreg_disable(gp6_vreg); } return ret; } static struct proximity_platform_data proxi_pdata = { .irq_num = PROXI_GPIO_DOUT, .power = prox_power_set, .methods = 0, .operation_mode = 2, .debounce = 0, .cycle = 2, }; static struct i2c_board_info prox_ecom_i2c_bdinfo[] = { [0] = { I2C_BOARD_INFO("proximity_gp2ap", PROXI_I2C_ADDRESS), .type = "proximity_gp2ap", .platform_data = &proxi_pdata, }, [1] = { I2C_BOARD_INFO("ami304_sensor", ECOM_I2C_ADDRESS), .type = "ami304_sensor", .platform_data = &ecom_pdata, }, }; static struct gpio_i2c_pin proxi_ecom_i2c_pin[] = { [0] = { .sda_pin = PROXI_GPIO_I2C_SDA, .scl_pin = PROXI_GPIO_I2C_SCL, .reset_pin = 0, .irq_pin = PROXI_GPIO_DOUT, }, [1] = { .sda_pin = ECOM_GPIO_I2C_SDA, .scl_pin = ECOM_GPIO_I2C_SCL, .reset_pin = 0, .irq_pin = ECOM_GPIO_INT, }, }; static struct i2c_gpio_platform_data proxi_ecom_i2c_pdata = { .sda_is_open_drain = 0, .scl_is_open_drain = 0, .udelay = 2, }; static struct platform_device proxi_ecom_i2c_device = { .id = i2c_bus_num, .name = "i2c-gpio", .dev.platform_data = &proxi_ecom_i2c_pdata, }; static void __init thunderg_init_i2c_prox_ecom(int bus_num) { int index; for(index=0;index<2;index++) { proxi_ecom_i2c_pdata.sda_pin = proxi_ecom_i2c_pin[index].sda_pin; proxi_ecom_i2c_pdata.scl_pin = proxi_ecom_i2c_pin[index].scl_pin; gpio_tlmm_config(GPIO_CFG(proxi_ecom_i2c_pin[index].sda_pin,0,GPIO_CFG_OUTPUT,GPIO_CFG_NO_PULL,GPIO_CFG_2MA), GPIO_CFG_ENABLE); gpio_tlmm_config(GPIO_CFG(proxi_ecom_i2c_pin[index].scl_pin, 0, GPIO_CFG_OUTPUT,GPIO_CFG_NO_PULL, GPIO_CFG_2MA), GPIO_CFG_ENABLE); gpio_set_value(proxi_ecom_i2c_pin[index].sda_pin, 1); gpio_set_value(proxi_ecom_i2c_pin[index].scl_pin, 1); if (proxi_ecom_i2c_pin[index].reset_pin) { gpio_tlmm_config(GPIO_CFG(proxi_ecom_i2c_pin[index].reset_pin, 0,GPIO_CFG_OUTPUT,GPIO_CFG_NO_PULL,GPIO_CFG_2MA), GPIO_CFG_ENABLE); gpio_set_value(proxi_ecom_i2c_pin[index].reset_pin, 1); } if (proxi_ecom_i2c_pin[index].irq_pin) { gpio_tlmm_config(GPIO_CFG(proxi_ecom_i2c_pin[index].irq_pin, 0, GPIO_CFG_INPUT,GPIO_CFG_PULL_UP, GPIO_CFG_2MA), GPIO_CFG_ENABLE); prox_ecom_i2c_bdinfo[index].irq =MSM_GPIO_TO_INT(proxi_ecom_i2c_pin[index].irq_pin); } i2c_register_board_info(proxi_ecom_i2c_device.id, &prox_ecom_i2c_bdinfo[0], 2); platform_device_register(&proxi_ecom_i2c_device); } i2c_bus_num++; /*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ struct platform_device asoc_msm_pcm = { .name = "msm-dsp-audio", .id = 0, }; struct platform_device asoc_msm_dai0 = { .name = "msm-codec-dai", .id = 0, }; struct platform_device asoc_msm_dai1 = { .name = "msm-cpu-dai", .id = 0, }; /*++++++++++++++++++++++++++++++++++++++++++++++++++++++Devices being added to system++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ static struct platform_device *devices[] __initdata = { &asoc_msm_pcm, &asoc_msm_dai0, &asoc_msm_dai1, &msm_device_smd, # &msm_device_dmov, # &msm_device_nand, # #ifdef CONFIG_USB_MSM_OTG_72K &msm_device_otg, # #ifdef CONFIG_USB_GADGET &msm_device_gadget_peripheral, # #endif #endif #ifdef CONFIG_USB_ANDROID &usb_mass_storage_device, # &rndis_device, # #ifdef CONFIG_USB_ANDROID_CDC_ECM &ecm_device, # #endif #ifdef CONFIG_USB_ANDROID_ACM &acm_device, # #endif #ifdef CONFIG_USB_ANDROID_DIAG &usb_diag_device, # #endif #ifdef CONFIG_USB_SUPPORT_LGE_ANDROID_AUTORUN &usb_cdrom_storage_device, # #endif &android_usb_device, # #endif #ifdef CONFIG_USB_G_ANDROID &android_usb_device, # #endif &msm_device_i2c, # &msm_device_tssc, &android_pmem_device, # &android_pmem_adsp_device, # &android_pmem_audio_device, # &msm_fb_device, # &mddi_hitachi_panel_device # &msm_device_uart_dm1, # #ifdef CONFIG_BT &msm_bt_power_device, # #endif &msm_device_pmic_leds, # &msm_device_snd, # &msm_device_adspdec, # #if defined (CONFIG_ISX005) &msm_camera_sensor_isx005, # #endif &msm_bluesleep_device, # #ifdef CONFIG_ARCH_MSM7X27 &msm_kgsl_3d0, # #endif #if defined(CONFIG_TSIF) || defined(CONFIG_TSIF_MODULE) &msm_device_tsif, # #endif &hs_device, # &keypad_device_thunder, # &thunderg_reset_keys_device, # &atcmd_virtual_device, # &msm_batt_device, # &android_vibrator_device, # &thunderg_carkit_device, # &thunderg_earsense_device, # &thunderg_pwrsink_device, # }; /*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++MMC Support++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ #if (defined(CONFIG_MMC_MSM_SDC1_SUPPORT)\ || defined(CONFIG_MMC_MSM_SDC2_SUPPORT)\ || defined(CONFIG_MMC_MSM_SDC3_SUPPORT)\ || defined(CONFIG_MMC_MSM_SDC4_SUPPORT)) static unsigned long vreg_sts, gpio_sts; static struct vreg *vreg_mmc; static unsigned mpp_mmc = 2; struct sdcc_gpio { struct msm_gpio *cfg_data; uint32_t size; struct msm_gpio *sleep_cfg_data; }; static struct msm_gpio sdc1_cfg_data[] = { #ifdef CONFIG_MMC_MSM_CARD_HW_DETECTION {GPIO_CFG(GPIO_SD_DATA_3, 1, GPIO_CFG_OUTPUT, GPIO_CFG_PULL_UP, GPIO_CFG_8MA), "sdc1_dat_3"}, {GPIO_CFG(GPIO_SD_DATA_2, 1, GPIO_CFG_OUTPUT, GPIO_CFG_PULL_UP, GPIO_CFG_8MA), "sdc1_dat_2"}, {GPIO_CFG(GPIO_SD_DATA_1, 1, GPIO_CFG_OUTPUT, GPIO_CFG_PULL_UP, GPIO_CFG_8MA), "sdc1_dat_1"}, {GPIO_CFG(GPIO_SD_DATA_0, 1, GPIO_CFG_OUTPUT, GPIO_CFG_PULL_UP, GPIO_CFG_8MA), "sdc1_dat_0"}, {GPIO_CFG(GPIO_SD_CMD, 1, GPIO_CFG_OUTPUT, GPIO_CFG_PULL_UP, GPIO_CFG_8MA), "sdc1_cmd"}, {GPIO_CFG(GPIO_SD_CLK, 1, GPIO_CFG_OUTPUT, GPIO_CFG_NO_PULL, GPIO_CFG_8MA), "sdc1_clk"}, #else {GPIO_CFG(51, 1, GPIO_CFG_OUTPUT, GPIO_CFG_PULL_UP, GPIO_CFG_8MA), "sdc1_dat_3"}, {GPIO_CFG(52, 1, GPIO_CFG_OUTPUT, GPIO_CFG_PULL_UP, GPIO_CFG_8MA), "sdc1_dat_2"}, {GPIO_CFG(53, 1, GPIO_CFG_OUTPUT, GPIO_CFG_PULL_UP, GPIO_CFG_8MA), "sdc1_dat_1"}, {GPIO_CFG(54, 1, GPIO_CFG_OUTPUT, GPIO_CFG_PULL_UP, GPIO_CFG_8MA), "sdc1_dat_0"}, {GPIO_CFG(55, 1, GPIO_CFG_OUTPUT, GPIO_CFG_PULL_UP, GPIO_CFG_8MA), "sdc1_cmd"}, {GPIO_CFG(56, 1, GPIO_CFG_OUTPUT, GPIO_CFG_NO_PULL, GPIO_CFG_8MA), "sdc1_clk"}, #endif }; static struct msm_gpio sdc2_cfg_data[] = { {GPIO_CFG(62, 2, GPIO_CFG_OUTPUT, GPIO_CFG_NO_PULL, GPIO_CFG_8MA), "sdc2_clk"}, {GPIO_CFG(63, 2, GPIO_CFG_OUTPUT, GPIO_CFG_PULL_UP, GPIO_CFG_8MA), "sdc2_cmd"}, {GPIO_CFG(64, 2, GPIO_CFG_OUTPUT, GPIO_CFG_PULL_UP, GPIO_CFG_8MA), "sdc2_dat_3"}, {GPIO_CFG(65, 2, GPIO_CFG_OUTPUT, GPIO_CFG_PULL_UP, GPIO_CFG_8MA), "sdc2_dat_2"}, {GPIO_CFG(66, 2, GPIO_CFG_OUTPUT, GPIO_CFG_PULL_UP, GPIO_CFG_8MA), "sdc2_dat_1"}, {GPIO_CFG(67, 2, GPIO_CFG_OUTPUT, GPIO_CFG_PULL_UP, GPIO_CFG_8MA), "sdc2_dat_0"}, }; static struct msm_gpio sdc2_sleep_cfg_data[] = { {GPIO_CFG(62, 0, GPIO_CFG_INPUT, GPIO_CFG_PULL_DOWN, GPIO_CFG_2MA), "sdc2_clk"}, {GPIO_CFG(63, 0, GPIO_CFG_INPUT, GPIO_CFG_PULL_DOWN, GPIO_CFG_2MA), "sdc2_cmd"}, {GPIO_CFG(64, 0, GPIO_CFG_INPUT, GPIO_CFG_PULL_DOWN, GPIO_CFG_2MA), "sdc2_dat_3"}, {GPIO_CFG(65, 0, GPIO_CFG_INPUT, GPIO_CFG_PULL_DOWN, GPIO_CFG_2MA), "sdc2_dat_2"}, {GPIO_CFG(66, 0, GPIO_CFG_INPUT, GPIO_CFG_PULL_DOWN, GPIO_CFG_2MA), "sdc2_dat_1"}, {GPIO_CFG(67, 0, GPIO_CFG_INPUT, GPIO_CFG_PULL_DOWN, GPIO_CFG_2MA), "sdc2_dat_0"}, }; static struct msm_gpio sdc3_cfg_data[] = { {GPIO_CFG(88, 1, GPIO_CFG_OUTPUT, GPIO_CFG_NO_PULL, GPIO_CFG_8MA), "sdc3_clk"}, {GPIO_CFG(89, 1, GPIO_CFG_OUTPUT, GPIO_CFG_PULL_UP, GPIO_CFG_8MA), "sdc3_cmd"}, {GPIO_CFG(90, 1, GPIO_CFG_OUTPUT, GPIO_CFG_PULL_UP, GPIO_CFG_8MA), "sdc3_dat_3"}, {GPIO_CFG(91, 1, GPIO_CFG_OUTPUT, GPIO_CFG_PULL_UP, GPIO_CFG_8MA), "sdc3_dat_2"}, {GPIO_CFG(92, 1, GPIO_CFG_OUTPUT, GPIO_CFG_PULL_UP, GPIO_CFG_8MA), "sdc3_dat_1"}, {GPIO_CFG(93, 1, GPIO_CFG_OUTPUT, GPIO_CFG_PULL_UP, GPIO_CFG_8MA), "sdc3_dat_0"}, }; static struct msm_gpio sdc4_cfg_data[] = { {GPIO_CFG(19, 3, GPIO_CFG_OUTPUT, GPIO_CFG_PULL_UP, GPIO_CFG_8MA), "sdc4_dat_3"}, {GPIO_CFG(20, 3, GPIO_CFG_OUTPUT, GPIO_CFG_PULL_UP, GPIO_CFG_8MA), "sdc4_dat_2"}, {GPIO_CFG(21, 4, GPIO_CFG_OUTPUT, GPIO_CFG_PULL_UP, GPIO_CFG_8MA), "sdc4_dat_1"}, {GPIO_CFG(107, 1, GPIO_CFG_OUTPUT, GPIO_CFG_PULL_UP, GPIO_CFG_8MA), "sdc4_cmd"}, {GPIO_CFG(108, 1, GPIO_CFG_OUTPUT, GPIO_CFG_PULL_UP, GPIO_CFG_8MA), "sdc4_dat_0"}, {GPIO_CFG(109, 1, GPIO_CFG_OUTPUT, GPIO_CFG_NO_PULL, GPIO_CFG_8MA), "sdc4_clk"}, }; static struct sdcc_gpio sdcc_cfg_data[] = { { .cfg_data = sdc1_cfg_data, .size = ARRAY_SIZE(sdc1_cfg_data), .sleep_cfg_data = NULL, }, { .cfg_data = sdc2_cfg_data, .size = ARRAY_SIZE(sdc2_cfg_data), .sleep_cfg_data = sdc2_sleep_cfg_data, }, { .cfg_data = sdc3_cfg_data, .size = ARRAY_SIZE(sdc3_cfg_data), .sleep_cfg_data = NULL, }, { .cfg_data = sdc4_cfg_data, .size = ARRAY_SIZE(sdc4_cfg_data), .sleep_cfg_data = NULL, }, }; static void msm_sdcc_setup_gpio(int dev_id, unsigned int enable) { int rc = 0; struct sdcc_gpio *curr; curr = &sdcc_cfg_data[dev_id - 1]; if (!(test_bit(dev_id, &gpio_sts)^enable)) return; if (enable) { set_bit(dev_id, &gpio_sts); rc = msm_gpios_request_enable(curr->cfg_data, curr->size); if (rc) printk(KERN_ERR "%s: Failed to turn on GPIOs for slot %d\n", __func__, dev_id); } else { clear_bit(dev_id, &gpio_sts); if (curr->sleep_cfg_data) { msm_gpios_enable(curr->sleep_cfg_data, curr->size); msm_gpios_free(curr->sleep_cfg_data, curr->size); return; } msm_gpios_disable_free(curr->cfg_data, curr->size); } } static uint32_t msm_sdcc_setup_power(struct device *dv, unsigned int vdd) { int rc = 0; struct platform_device *pdev; pdev = container_of(dv, struct platform_device, dev); msm_sdcc_setup_gpio(pdev->id, !!vdd); if (vdd == 0) { if (!vreg_sts) return 0; clear_bit(pdev->id, &vreg_sts); if (!vreg_sts) { if (machine_is_msm7x25_ffa() || machine_is_msm7x27_ffa()) { rc = mpp_config_digital_out(mpp_mmc, MPP_CFG(MPP_DLOGIC_LVL_MSMP, MPP_DLOGIC_OUT_CTRL_LOW)); } else rc = regulator_disable(vreg_mmc); if (rc) { pr_err("%s: return val: %d\n", __func__, rc); } } return 0; } if (!vreg_sts) { if (machine_is_msm7x25_ffa() || machine_is_msm7x27_ffa()) { rc = mpp_config_digital_out(mpp_mmc, MPP_CFG(MPP_DLOGIC_LVL_MSMP, MPP_DLOGIC_OUT_CTRL_HIGH)); } else { #ifdef CONFIG_MMC_MSM_CARD_HW_DETECTION rc = vreg_set_level(vreg_mmc, VREG_SD_LEVEL); #else rc = vreg_set_level(vreg_mmc, 2850); #endif if (!rc) rc = regulator_enable(vreg_mmc); } if (rc) { pr_err("%s: return val: %d\n", __func__, rc); } } set_bit(pdev->id, &vreg_sts); return 0; } #ifdef CONFIG_MMC_MSM_CARD_HW_DETECTION static unsigned int thunderg_sdcc_slot_status(struct device *dev) { return !(gpio_get_value(GPIO_MMC_COVER_DETECT)||gpio_get_value(GPIO_SD_DETECT_N)); } #endif static struct mmc_platform_data msm7x2x_sdcc_data = { #ifdef CONFIG_MMC_MSM_CARD_HW_DETECTION .ocr_mask = MMC_VDD_30_31, .translate_vdd = msm_sdcc_setup_power, .status = thunderg_sdcc_slot_status, .status_irq = MSM_GPIO_TO_INT(GPIO_MMC_COVER_DETECT), .irq_flags = IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING, .mmc_bus_width = MMC_CAP_4_BIT_DATA, #else .ocr_mask = MMC_VDD_28_29, .translate_vdd = msm_sdcc_setup_power, .mmc_bus_width = MMC_CAP_4_BIT_DATA, #endif .msmsdcc_fmin = 144000, .msmsdcc_fmid = 24576000, .msmsdcc_fmax = 49152000, .nonremovable = 0, }; #if defined(CONFIG_LGE_BCM432X_PATCH) static unsigned int bcm432x_sdcc_wlan_slot_status(struct device *dev) { printk(KERN_ERR "%s: %d %d\n", __func__, CONFIG_BCM4325_GPIO_WL_RESET, gpio_get_value(CONFIG_BCM4325_GPIO_WL_RESET)); return gpio_get_value(CONFIG_BCM4325_GPIO_WL_RESET); } static struct mmc_platform_data bcm432x_sdcc_wlan_data = { .ocr_mask = MMC_VDD_30_31, .translate_vdd = msm_sdcc_setup_power, .status = bcm432x_sdcc_wlan_slot_status, .status_irq = MSM_GPIO_TO_INT(CONFIG_BCM4325_GPIO_WL_RESET), .irq_flags = IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING, .mmc_bus_width = MMC_CAP_4_BIT_DATA, .msmsdcc_fmin = 144000, .msmsdcc_fmid = 24576000, .msmsdcc_fmax = 49152000, .nonremovable = 1, }; #endif static void __init msm7x2x_init_mmc(void) { if (!machine_is_msm7x25_ffa() && !machine_is_msm7x27_ffa()) { vreg_mmc = vreg_get(NULL, "wlan"); if (IS_ERR(vreg_mmc)) { pr_err("%s: could not get regulator: %ld\n", __func__, PTR_ERR(vreg_mmc)); } } #ifdef CONFIG_MMC_MSM_CARD_HW_DETECTION int rc = 0; if (gpio_request(GPIO_SD_DETECT_N, "sdc1_status_pin_irq")) pr_err("failed to request gpio sdc1_status_irq\n"); rc = gpio_tlmm_config(GPIO_CFG(GPIO_SD_DETECT_N, 0, GPIO_CFG_INPUT, GPIO_CFG_PULL_UP, GPIO_CFG_2MA), GPIO_CFG_ENABLE); if (rc) printk(KERN_ERR "%s: Failed to configure GPIO %d\n", __func__, rc); if (gpio_request(GPIO_MMC_COVER_DETECT, "sdc1_status_socket_irq")) pr_err("failed to request gpio sdc1_status_irq\n"); rc = gpio_tlmm_config(GPIO_CFG(GPIO_MMC_COVER_DETECT, 0, GPIO_CFG_INPUT, GPIO_CFG_PULL_UP, GPIO_CFG_2MA), GPIO_CFG_ENABLE); if (rc) printk(KERN_ERR "%s: Failed to configure GPIO %d\n", __func__, rc); #endif msm_add_sdcc(1, &msm7x2x_sdcc_data); #if defined(CONFIG_LGE_BCM432X_PATCH) /* GPIO config */ gpio_tlmm_config(GPIO_CFG(CONFIG_BCM4325_GPIO_WL_REGON, 0, GPIO_OUTPUT, GPIO_PULL_UP, GPIO_2MA), GPIO_ENABLE); gpio_configure(CONFIG_BCM4325_GPIO_WL_REGON, GPIOF_DRIVE_OUTPUT); gpio_set_value(CONFIG_BCM4325_GPIO_WL_REGON, 0); gpio_tlmm_config(GPIO_CFG(CONFIG_BCM4325_GPIO_WL_RESET, 0, GPIO_OUTPUT, GPIO_PULL_UP, GPIO_2MA), GPIO_ENABLE); gpio_configure(CONFIG_BCM4325_GPIO_WL_RESET, GPIOF_DRIVE_OUTPUT); gpio_set_value(CONFIG_BCM4325_GPIO_WL_RESET, 0); gpio_tlmm_config(GPIO_CFG(CONFIG_BCM4325_GPIO_WL_HOSTWAKEUP, 0, GPIO_OUTPUT, GPIO_PULL_UP, GPIO_2MA), GPIO_ENABLE); gpio_configure(CONFIG_BCM4325_GPIO_WL_HOSTWAKEUP, GPIOF_INPUT); /* Register platform device */ msm_add_sdcc(2, &bcm432x_sdcc_wlan_data); /* Enable RESET IRQ for wlan card detect */ enable_irq(gpio_to_irq(CONFIG_BCM4325_GPIO_WL_RESET)); #endif } #else #define msm7x2x_init_mmc() do {} while (0) #endif /*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ extern struct sys_timer msm_timer; static void __init msm7x2x_init_irq(void) { msm_init_irq(); } void msm_serial_debug_init(unsigned int base, int irq, struct device *clk_device, int signal_irq); static void msm_i2c_gpio_config(int iface, int config_type) { int gpio_scl; int gpio_sda; if (iface) { gpio_scl = 95; gpio_sda = 96; } else { gpio_scl = 60; gpio_sda = 61; } if (config_type) { gpio_tlmm_config(GPIO_CFG(gpio_scl, 1, GPIO_CFG_INPUT, GPIO_CFG_NO_PULL, GPIO_CFG_16MA), GPIO_CFG_ENABLE); gpio_tlmm_config(GPIO_CFG(gpio_sda, 1, GPIO_CFG_INPUT, GPIO_CFG_NO_PULL, GPIO_CFG_16MA), GPIO_CFG_ENABLE); } else { gpio_tlmm_config(GPIO_CFG(gpio_scl, 0, GPIO_CFG_OUTPUT, GPIO_CFG_NO_PULL, GPIO_CFG_16MA), GPIO_CFG_ENABLE); gpio_tlmm_config(GPIO_CFG(gpio_sda, 0, GPIO_CFG_OUTPUT, GPIO_CFG_NO_PULL, GPIO_CFG_16MA), GPIO_CFG_ENABLE); } } static struct msm_i2c_platform_data msm_i2c_pdata = { .clk_freq = 100000, .rmutex = 0, .pri_clk = 60, .pri_dat = 61, .aux_clk = 95, .aux_dat = 96, .msm_i2c_config_gpio = msm_i2c_gpio_config, }; static void __init msm_device_i2c_init(void) { if (gpio_request(60, "i2c_pri_clk")) pr_err("failed to request gpio i2c_pri_clk\n"); if (gpio_request(61, "i2c_pri_dat")) pr_err("failed to request gpio i2c_pri_dat\n"); if (gpio_request(95, "i2c_sec_clk")) pr_err("failed to request gpio i2c_sec_clk\n"); if (gpio_request(96, "i2c_sec_dat")) pr_err("failed to request gpio i2c_sec_dat\n"); msm_i2c_pdata.pm_lat = msm7x27_pm_data[MSM_PM_SLEEP_MODE_POWER_COLLAPSE_NO_XO_SHUTDOWN] .latency; msm_device_i2c.dev.platform_data = &msm_i2c_pdata; } static void usb_mpp_init(void) { /*TODO*/ } static void msm7x27_wlan_init(void) { /*TODO*/ } static void msm_adsp_add_pdev(void) { int rc = 0; struct rpc_board_dev *rpc_adsp_pdev; rpc_adsp_pdev = kzalloc(sizeof(struct rpc_board_dev), GFP_KERNEL); if (rpc_adsp_pdev == NULL) { pr_err("%s: Memory Allocation failure\n", __func__); return; } rpc_adsp_pdev->prog = ADSP_RPC_PROG; rpc_adsp_pdev->pdev = msm_adsp_device; rc = msm_rpc_add_board_dev(rpc_adsp_pdev, 1); if (rc < 0) { pr_err("%s: return val: %d\n", __func__, rc); kfree(rpc_adsp_pdev); } } /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++Main Init Rountine+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ static void __init msm7x2x_init(void) { msm_clock_init(&msm7x27_clock_init_data); #if defined(CONFIG_MSM_SERIAL_DEBUGGER) msm_serial_debug_init(MSM_UART3_PHYS, INT_UART3, &msm_device_uart3.dev, 1); #endif acpuclk_init(&acpuclk_7x27_soc_data); usb_mpp_init(); #ifdef CONFIG_USB_MSM_OTG_72K msm_device_otg.dev.platform_data = &msm_otg_pdata; if (machine_is_msm7x25_surf() || machine_is_msm7x25_ffa()) { msm_otg_pdata.pemp_level = PRE_EMPHASIS_WITH_20_PERCENT; msm_otg_pdata.drv_ampl = HS_DRV_AMPLITUDE_5_PERCENT; msm_otg_pdata.cdr_autoreset = CDR_AUTO_RESET_ENABLE; msm_otg_pdata.phy_reset = msm_otg_rpc_phy_reset; } if (machine_is_msm7x27_surf() || machine_is_msm7x27_ffa()) { msm_otg_pdata.pemp_level = PRE_EMPHASIS_WITH_10_PERCENT; msm_otg_pdata.drv_ampl = HS_DRV_AMPLITUDE_5_PERCENT; msm_otg_pdata.cdr_autoreset = CDR_AUTO_RESET_DISABLE; msm_otg_pdata.phy_reset_sig_inverted = 1; } #ifdef CONFIG_USB_GADGET msm_otg_pdata.swfi_latency = msm7x27_pm_data [MSM_PM_SLEEP_MODE_RAMP_DOWN_AND_WAIT_FOR_INTERRUPT].latency; msm_device_gadget_peripheral.dev.platform_data = &msm_gadget_pdata; msm_gadget_pdata.is_phy_status_timer_on = 1; #endif #endif #if defined(CONFIG_TSIF) || defined(CONFIG_TSIF_MODULE) msm_device_tsif.dev.platform_data = &tsif_platform_data; #endif thunder_select_keymap(); lcd_bl_power_state = BL_POWER_RESUME; platform_add_devices(devices, ARRAY_SIZE(devices)); #if !defined(CONFIG_MSM_SERIAL_DEBUGGER) if (lge_get_uart_mode()) platform_device_register(&msm_device_uart3); #endif #ifdef CONFIG_MSM_CAMERA config_camera_off_gpios(); /* might not be necessary */ #endif msm_adsp_add_pdev(); msm_device_i2c_init(); i2c_register_board_info(0, i2c_devices, ARRAY_SIZE(i2c_devices)); lcdc_gordon_gpio_init(); msm_fb_add_devices(); #ifdef CONFIG_USB_EHCI_MSM_72K msm7x2x_init_host(); #endif msm7x2x_init_mmc(); bt_power_init(); #ifdef CONFIG_ANDROID_RAM_CONSOLE lge_add_ramconsole_devices(); lge_add_ers_devices(); lge_add_panic_handler_devices(); #endif thunderg_init_i2c_backlight(); lge_add_gpio_i2c_device(thunderg_init_i2c_touch); lge_add_gpio_i2c_device(thunderg_init_i2c_prox_ecom); lge_add_gpio_i2c_device(thunderg_init_i2c_acceleration); if (cpu_is_msm7x27()) msm_pm_set_platform_data(msm7x27_pm_data, ARRAY_SIZE(msm7x27_pm_data)); else msm_pm_set_platform_data(msm7x25_pm_data, ARRAY_SIZE(msm7x25_pm_data)); BUG_ON(msm_pm_boot_init(&msm_pm_boot_pdata)); msm7x27_wlan_init(); } /*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ static unsigned pmem_kernel_ebi1_size = PMEM_KERNEL_EBI1_SIZE; static int __init pmem_kernel_ebi1_size_setup(char *p) { pmem_kernel_ebi1_size = memparse(p, NULL); return 0; } early_param("pmem_kernel_ebi1_size", pmem_kernel_ebi1_size_setup); static unsigned pmem_mdp_size = MSM_PMEM_MDP_SIZE; static int __init pmem_mdp_size_setup(char *p) { pmem_mdp_size = memparse(p, NULL); return 0; } early_param("pmem_mdp_size", pmem_mdp_size_setup); static unsigned pmem_adsp_size = MSM_PMEM_ADSP_SIZE; static int __init pmem_adsp_size_setup(char *p) { pmem_adsp_size = memparse(p, NULL); return 0; } early_param("pmem_adsp_size", pmem_adsp_size_setup); static unsigned pmem_audio_size = MSM_PMEM_AUDIO_SIZE; static int __init pmem_audio_size_setup(char *p) { pmem_audio_size = memparse(p, NULL); return 0; } early_param("pmem_audio_size", pmem_audio_size_setup); static unsigned fb_size = MSM_FB_SIZE; static int __init fb_size_setup(char *p) { fb_size = memparse(p, NULL); return 0; } early_param("fb_size", fb_size_setup); static void __init msm_msm7x2x_allocate_memory_regions(void) { void *addr; unsigned long size; size = fb_size ? : MSM_FB_SIZE; addr = alloc_bootmem_align(size, 0x1000); msm_fb_resources[0].start = __pa(addr); msm_fb_resources[0].end = msm_fb_resources[0].start + size - 1; pr_info("allocating %lu bytes at %p (%lx physical) for fb\n", size, addr, __pa(addr)); } static struct memtype_reserve msm7x27_reserve_table[] __initdata = { [MEMTYPE_SMI] = { }, [MEMTYPE_EBI0] = { .flags = MEMTYPE_FLAGS_1M_ALIGN, }, [MEMTYPE_EBI1] = { .flags = MEMTYPE_FLAGS_1M_ALIGN, }, }; static void __init size_pmem_devices(void) { #ifdef CONFIG_ANDROID_PMEM android_pmem_adsp_pdata.size = pmem_adsp_size; android_pmem_pdata.size = pmem_mdp_size; android_pmem_audio_pdata.size = pmem_audio_size; #endif } static void __init reserve_memory_for(struct android_pmem_platform_data *p) { msm7x27_reserve_table[p->memory_type].size += p->size; } static void __init reserve_pmem_memory(void) { #ifdef CONFIG_ANDROID_PMEM reserve_memory_for(&android_pmem_adsp_pdata); reserve_memory_for(&android_pmem_pdata); reserve_memory_for(&android_pmem_audio_pdata); msm7x27_reserve_table[MEMTYPE_EBI1].size += pmem_kernel_ebi1_size; #endif } static void __init msm7x27_calculate_reserve_sizes(void) { size_pmem_devices(); reserve_pmem_memory(); } static int msm7x27_paddr_to_memtype(unsigned int paddr) { return MEMTYPE_EBI1; } static struct reserve_info msm7x27_reserve_info __initdata = { .memtype_reserve_table = msm7x27_reserve_table, .calculate_reserve_sizes = msm7x27_calculate_reserve_sizes, .paddr_to_memtype = msm7x27_paddr_to_memtype, }; static void __init msm7x27_reserve(void) { reserve_info = &msm7x27_reserve_info; msm_reserve(); } static void __init msm7x27_init_early(void) { msm_msm7x2x_allocate_memory_regions(); } static void __init msm7x2x_map_io(void) { msm_map_common_io(); if (socinfo_init() < 0) BUG(); #ifdef CONFIG_CACHE_L2X0 /* 7x27 has 256KB L2 cache: 64Kb/Way and 4-Way Associativity; R/W latency: 3 cycles; evmon/parity/share disabled. */ l2x0_init(MSM_L2CC_BASE, 0x00068012, 0xfe000000); #endif } MACHINE_START(MSM7X27_THUNDERG, "THUNDER Global board (LGE LGP500)") .boot_params = PLAT_PHYS_OFFSET + 0x100, .map_io = msm7x2x_map_io, .reserve = msm7x27_reserve, .init_irq = msm7x2x_init_irq, .init_machine = msm7x2x_init, .timer = &msm_timer, .init_early = msm7x27_init_early, .handle_irq = vic_handle_irq, MACHINE_END