/* Board support file for Samsung Tuna Board. * * Copyright (C) 2011 Google, Inc. * Copyright (C) 2010 Texas Instruments * * Based on mach-omap2/board-omap4panda.c * * 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 #include #include #include "timer-gp.h" #include "omap4-sar-layout.h" #include "hsmmc.h" #include "control.h" #include "mux.h" #include "board-tuna.h" #include "omap_ram_console.h" #include "resetreason.h" #include struct class *sec_class; EXPORT_SYMBOL(sec_class); /* For LTE(CMC221) */ #define OMAP_GPIO_LTE_ACTIVE 47 #define OMAP_GPIO_CMC2AP_INT1 61 #define GPIO_AUD_PWRON 127 #define GPIO_AUD_PWRON_TORO_V1 20 /* GPS GPIO Setting */ #define GPIO_AP_AGPS_TSYNC 18 #define GPIO_GPS_nRST 136 #define GPIO_GPS_PWR_EN 137 #define GPIO_GPS_UART_SEL 164 #define GPIO_MHL_SCL_18V 99 #define GPIO_MHL_SDA_18V 98 #define REBOOT_FLAG_RECOVERY 0x52564352 #define REBOOT_FLAG_FASTBOOT 0x54534146 #define REBOOT_FLAG_NORMAL 0x4D524F4E #define REBOOT_FLAG_POWER_OFF 0x46464F50 #define UART_NUM_FOR_GPS 0 static int tuna_hw_rev; static struct gpio tuna_hw_rev_gpios[] = { {76, GPIOF_IN, "hw_rev0"}, {75, GPIOF_IN, "hw_rev1"}, {74, GPIOF_IN, "hw_rev2"}, {73, GPIOF_IN, "hw_rev3"}, {170, GPIOF_IN, "hw_rev4"}, }; static const char const *omap4_tuna_hw_name_maguro[] = { [0x00] = "Toro Lunchbox #1", [0x01] = "Maguro 1st Sample", [0x02] = "Maguro 2nd Sample", [0x03] = "Maguro 4th Sample", [0x05] = "Maguro 5th Sample", [0x07] = "Maguro 6th Sample", [0x08] = "Maguro 7th Sample", [0x09] = "Maguro 8th Sample", }; static const char const *omap4_tuna_hw_name_toro[] = { [0x00] = "Toro Lunchbox #2", [0x01] = "Toro 1st Sample", [0x02] = "Toro 2nd Sample", [0x03] = "Toro 4th Sample", [0x05] = "Toro 5th Sample", [0x06] = "Toro 8th Sample", [0x08] = "Toro 8th Sample", [0x09] = "Toro 8-1th Sample", [0x0a] = "Toro 8-2th Sample", [0x0e] = "Toroplus 1st Sample", }; int omap4_tuna_get_revision(void) { return tuna_hw_rev & TUNA_REV_MASK; } int omap4_tuna_get_type(void) { return tuna_hw_rev & TUNA_TYPE_MASK; } static const char *omap4_tuna_hw_rev_name(void) { const char *ret; const char **names; int num; int rev; if (omap4_tuna_get_type() == TUNA_TYPE_MAGURO) { names = omap4_tuna_hw_name_maguro; num = ARRAY_SIZE(omap4_tuna_hw_name_maguro); ret = "Maguro unknown"; } else { names = omap4_tuna_hw_name_toro; num = ARRAY_SIZE(omap4_tuna_hw_name_toro); ret = "Toro unknown"; } rev = omap4_tuna_get_revision(); if (rev >= num || !names[rev]) return ret; return names[rev]; } /* * Store a handy board information string which we can use elsewhere like * like in panic situation */ static char omap4_tuna_bd_info_string[255]; static void omap4_tuna_init_hw_rev(void) { int ret; int i; u32 r; /* Disable weak driver pulldown on usbb2_hsic_strobe */ r = omap4_ctrl_pad_readl(OMAP4_CTRL_MODULE_PAD_CORE_CONTROL_USBB_HSIC); r &= ~OMAP4_USBB2_HSIC_STROBE_WD_MASK; omap4_ctrl_pad_writel(r, OMAP4_CTRL_MODULE_PAD_CORE_CONTROL_USBB_HSIC); ret = gpio_request_array(tuna_hw_rev_gpios, ARRAY_SIZE(tuna_hw_rev_gpios)); BUG_ON(ret); for (i = 0; i < ARRAY_SIZE(tuna_hw_rev_gpios); i++) tuna_hw_rev |= gpio_get_value(tuna_hw_rev_gpios[i].gpio) << i; snprintf(omap4_tuna_bd_info_string, ARRAY_SIZE(omap4_tuna_bd_info_string), "Tuna HW revision: %02x (%s), cpu %s ES%d.%d ", tuna_hw_rev, omap4_tuna_hw_rev_name(), cpu_is_omap443x() ? "OMAP4430" : "OMAP4460", (GET_OMAP_REVISION() >> 4) & 0xf, GET_OMAP_REVISION() & 0xf); pr_info("%s\n", omap4_tuna_bd_info_string); mach_panic_string = omap4_tuna_bd_info_string; } /* wl127x BT, FM, GPS connectivity chip */ static int wl1271_gpios[] = {46, -1, -1}; static struct platform_device wl1271_device = { .name = "kim", .id = -1, .dev = { .platform_data = &wl1271_gpios, }, }; static struct platform_device bcm4330_bluetooth_device = { .name = "bcm4330_bluetooth", .id = -1, }; static void __init tuna_bt_init(void) { /* BT_EN - GPIO 104 */ omap_mux_init_signal("gpmc_ncs6.gpio_103", OMAP_PIN_OUTPUT); /*BT_nRST - GPIO 42 */ omap_mux_init_signal("gpmc_a18.gpio_42", OMAP_PIN_OUTPUT); /* BT_WAKE - GPIO 27 */ omap_mux_init_signal("dpm_emu16.gpio_27", OMAP_PIN_OUTPUT); /* BT_HOST_WAKE - GPIO 177 */ omap_mux_init_signal("kpd_row5.gpio_177", OMAP_WAKEUP_EN | OMAP_PIN_INPUT_PULLDOWN); platform_device_register(&bcm4330_bluetooth_device); } static struct twl4030_madc_platform_data twl6030_madc = { .irq_line = -1, }; static struct platform_device twl6030_madc_device = { .name = "twl6030_madc", .id = -1, .dev = { .platform_data = &twl6030_madc, }, }; static struct i2c_gpio_platform_data tuna_gpio_i2c5_pdata = { .sda_pin = GPIO_MHL_SDA_18V, .scl_pin = GPIO_MHL_SCL_18V, .udelay = 3, .timeout = 0, }; static struct platform_device tuna_gpio_i2c5_device = { .name = "i2c-gpio", .id = 5, .dev = { .platform_data = &tuna_gpio_i2c5_pdata, } }; static struct platform_device tuna_spdif_dit_device = { .name = "spdif-dit", .id = 0, }; static struct platform_device *tuna_devices[] __initdata = { &wl1271_device, &twl6030_madc_device, &tuna_gpio_i2c5_device, &tuna_spdif_dit_device, }; /* * The UART1 is for GPS, and CSR GPS chip should control uart1 rts level * for gps firmware download. */ static int uart1_rts_ctrl_write(struct file *file, const char __user *buffer, size_t count, loff_t *offs) { char buf[10] = {0,}; if (omap4_tuna_get_revision() < TUNA_REV_SAMPLE_4) return -ENXIO; if (count > sizeof(buf) - 1) return -EINVAL; if (copy_from_user(buf, buffer, count)) return -EFAULT; if (!strncmp(buf, "1", 1)) { omap_rts_mux_write(OMAP_PIN_INPUT_PULLUP | OMAP_MUX_MODE7, UART_NUM_FOR_GPS); } else if (!strncmp(buf, "0", 1)) { omap_rts_mux_write(OMAP_PIN_OUTPUT | OMAP_MUX_MODE1, UART_NUM_FOR_GPS); } return count; } static const struct file_operations uart1_rts_ctrl_proc_fops = { .write = uart1_rts_ctrl_write, }; static int __init tuna_gps_rts_ctrl_init(void) { struct proc_dir_entry *p_entry; p_entry = proc_create("mcspi1_cs3_ctrl", 0666, NULL, &uart1_rts_ctrl_proc_fops); if (!p_entry) return -ENOMEM; return 0; } static void tuna_gsd4t_gps_gpio(void) { /* AP_AGPS_TSYNC - GPIO 18 */ omap_mux_init_signal("dpm_emu7.gpio_18", OMAP_PIN_OUTPUT); /* GPS_nRST - GPIO 136 */ omap_mux_init_signal("mcspi1_simo.gpio_136", OMAP_PIN_OUTPUT); /* GPS_PWR_EN - GPIO 137 */ omap_mux_init_signal("mcspi1_cs0.gpio_137", OMAP_PIN_OUTPUT); /* GPS_UART_SEL - GPIO 164 */ omap_mux_init_signal("usbb2_ulpitll_dat3.gpio_164", OMAP_PIN_OUTPUT); } static void tuna_gsd4t_gps_init(void) { struct device *gps_dev; gps_dev = device_create(sec_class, NULL, 0, NULL, "gps"); if (IS_ERR(gps_dev)) { pr_err("Failed to create device(gps)!\n"); goto err; } tuna_gsd4t_gps_gpio(); gpio_request(GPIO_AP_AGPS_TSYNC, "AP_AGPS_TSYNC"); gpio_direction_output(GPIO_AP_AGPS_TSYNC, 0); gpio_request(GPIO_GPS_nRST, "GPS_nRST"); gpio_direction_output(GPIO_GPS_nRST, 1); gpio_request(GPIO_GPS_PWR_EN, "GPS_PWR_EN"); gpio_direction_output(GPIO_GPS_PWR_EN, 0); gpio_request(GPIO_GPS_UART_SEL , "GPS_UART_SEL"); gpio_direction_output(GPIO_GPS_UART_SEL , 0); gpio_export(GPIO_GPS_nRST, 1); gpio_export(GPIO_GPS_PWR_EN, 1); gpio_export_link(gps_dev, "GPS_nRST", GPIO_GPS_nRST); gpio_export_link(gps_dev, "GPS_PWR_EN", GPIO_GPS_PWR_EN); tuna_gps_rts_ctrl_init(); err: return; } static int __init sec_common_init(void) { sec_class = class_create(THIS_MODULE, "sec"); if (IS_ERR(sec_class)) pr_err("Failed to create class(sec)!\n"); return 0; } static void __init tuna_init_early(void) { omap2_init_common_infrastructure(); omap2_init_common_devices(NULL, NULL); } static struct omap_musb_board_data musb_board_data = { .interface_type = MUSB_INTERFACE_UTMI, #ifdef CONFIG_USB_MUSB_OTG .mode = MUSB_OTG, #else .mode = MUSB_PERIPHERAL, #endif .power = 500, }; static struct omap2_hsmmc_info mmc[] = { { .mmc = 1, .nonremovable = true, .caps = MMC_CAP_4_BIT_DATA | MMC_CAP_8_BIT_DATA, .ocr_mask = MMC_VDD_165_195, .gpio_wp = -EINVAL, .gpio_cd = -EINVAL, }, { .name = "omap_wlan", .mmc = 5, .caps = MMC_CAP_4_BIT_DATA, .gpio_wp = -EINVAL, .gpio_cd = -EINVAL, .ocr_mask = MMC_VDD_165_195 | MMC_VDD_20_21, .nonremovable = false, .mmc_data = &tuna_wifi_data, }, {} /* Terminator */ }; static struct regulator_consumer_supply tuna_vmmc_supply[] = { { .supply = "vmmc", .dev_name = "omap_hsmmc.0", }, { .supply = "vmmc", .dev_name = "omap_hsmmc.1", }, }; static struct regulator_init_data tuna_vaux1 = { .constraints = { .min_uV = 3000000, .max_uV = 3000000, .apply_uV = true, .valid_modes_mask = REGULATOR_MODE_NORMAL | REGULATOR_MODE_STANDBY, .valid_ops_mask = REGULATOR_CHANGE_MODE | REGULATOR_CHANGE_STATUS, .always_on = true, .state_mem = { .disabled = true, }, }, }; static struct regulator_init_data tuna_vaux2 = { .constraints = { .min_uV = 1200000, .max_uV = 2800000, .apply_uV = true, .valid_modes_mask = REGULATOR_MODE_NORMAL | REGULATOR_MODE_STANDBY, .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE | REGULATOR_CHANGE_MODE | REGULATOR_CHANGE_STATUS, .state_mem = { .disabled = true, }, .initial_state = PM_SUSPEND_MEM, }, }; static struct regulator_consumer_supply tuna_vaux3_supplies[] = { { .supply = "vlcd", }, }; static struct regulator_init_data tuna_vaux3 = { .constraints = { .min_uV = 3100000, .max_uV = 3100000, .apply_uV = true, .valid_modes_mask = REGULATOR_MODE_NORMAL | REGULATOR_MODE_STANDBY, .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE | REGULATOR_CHANGE_MODE | REGULATOR_CHANGE_STATUS, .state_mem = { .disabled = true, }, }, .num_consumer_supplies = ARRAY_SIZE(tuna_vaux3_supplies), .consumer_supplies = tuna_vaux3_supplies, }; static struct regulator_init_data tuna_vmmc = { .constraints = { .min_uV = 1800000, .max_uV = 1800000, .apply_uV = true, .valid_modes_mask = REGULATOR_MODE_NORMAL | REGULATOR_MODE_STANDBY, .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE | REGULATOR_CHANGE_MODE | REGULATOR_CHANGE_STATUS, .state_mem = { .disabled = true, }, }, .num_consumer_supplies = 2, .consumer_supplies = tuna_vmmc_supply, }; static struct regulator_init_data tuna_vpp = { .constraints = { .min_uV = 1800000, .max_uV = 2500000, .apply_uV = true, .valid_modes_mask = REGULATOR_MODE_NORMAL | REGULATOR_MODE_STANDBY, .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE | REGULATOR_CHANGE_MODE | REGULATOR_CHANGE_STATUS, .state_mem = { .disabled = true, }, .initial_state = PM_SUSPEND_MEM, }, }; static struct regulator_consumer_supply tuna_vusim_supplies[] = { { .supply = "vlcd-iovcc", }, }; static struct regulator_init_data tuna_vusim = { .constraints = { .min_uV = 2200000, .max_uV = 2200000, .valid_modes_mask = REGULATOR_MODE_NORMAL | REGULATOR_MODE_STANDBY, .valid_ops_mask = REGULATOR_CHANGE_MODE | REGULATOR_CHANGE_STATUS, .state_mem = { .disabled = true, }, }, .num_consumer_supplies = ARRAY_SIZE(tuna_vusim_supplies), .consumer_supplies = tuna_vusim_supplies, }; static struct regulator_init_data tuna_vana = { .constraints = { .min_uV = 2100000, .max_uV = 2100000, .valid_modes_mask = REGULATOR_MODE_NORMAL | REGULATOR_MODE_STANDBY, .valid_ops_mask = REGULATOR_CHANGE_MODE | REGULATOR_CHANGE_STATUS, .always_on = true, .state_mem = { .disabled = true, }, }, }; static struct regulator_consumer_supply tuna_vcxio_supply[] = { REGULATOR_SUPPLY("vdds_dsi", "omapdss_dss"), REGULATOR_SUPPLY("vdds_dsi", "omapdss_dsi1"), }; static struct regulator_init_data tuna_vcxio = { .constraints = { .min_uV = 1800000, .max_uV = 1800000, .valid_modes_mask = REGULATOR_MODE_NORMAL | REGULATOR_MODE_STANDBY, .valid_ops_mask = REGULATOR_CHANGE_MODE | REGULATOR_CHANGE_STATUS, .state_mem = { .disabled = true, }, }, .num_consumer_supplies = ARRAY_SIZE(tuna_vcxio_supply), .consumer_supplies = tuna_vcxio_supply, }; static struct regulator_consumer_supply tuna_vdac_supply[] = { { .supply = "hdmi_vref", }, }; static struct regulator_init_data tuna_vdac = { .constraints = { .min_uV = 1800000, .max_uV = 1800000, .valid_modes_mask = REGULATOR_MODE_NORMAL | REGULATOR_MODE_STANDBY, .valid_ops_mask = REGULATOR_CHANGE_MODE | REGULATOR_CHANGE_STATUS, .state_mem = { .disabled = true, }, }, .num_consumer_supplies = ARRAY_SIZE(tuna_vdac_supply), .consumer_supplies = tuna_vdac_supply, }; static struct regulator_consumer_supply tuna_vusb_supply[] = { REGULATOR_SUPPLY("vusb", "tuna_otg"), }; static struct regulator_init_data tuna_vusb = { .constraints = { .min_uV = 3300000, .max_uV = 3300000, .valid_modes_mask = REGULATOR_MODE_NORMAL | REGULATOR_MODE_STANDBY, .valid_ops_mask = REGULATOR_CHANGE_MODE | REGULATOR_CHANGE_STATUS, .state_mem = { .disabled = true, }, .initial_state = PM_SUSPEND_MEM, }, .num_consumer_supplies = ARRAY_SIZE(tuna_vusb_supply), .consumer_supplies = tuna_vusb_supply, }; /* clk32kg is a twl6030 32khz clock modeled as a regulator, used by GPS */ static struct regulator_init_data tuna_clk32kg = { .constraints = { .valid_ops_mask = REGULATOR_CHANGE_STATUS, .always_on = true, }, }; static struct regulator_consumer_supply tuna_clk32kaudio_supply[] = { { .supply = "clk32kaudio", }, { .supply = "twl6040_clk32k", } }; static struct regulator_init_data tuna_clk32kaudio = { .constraints = { .valid_ops_mask = REGULATOR_CHANGE_STATUS, .boot_on = true, }, .num_consumer_supplies = ARRAY_SIZE(tuna_clk32kaudio_supply), .consumer_supplies = tuna_clk32kaudio_supply, }; static struct regulator_init_data tuna_vdd3 = { .constraints = { .valid_ops_mask = REGULATOR_CHANGE_STATUS, .state_mem = { .disabled = true, }, .initial_state = PM_SUSPEND_MEM, }, }; /* * VMEM is unused. Register it to regulator framework and let it * be in disabled state. */ static struct regulator_init_data tuna_vmem = { .constraints = { .valid_ops_mask = REGULATOR_CHANGE_STATUS, .state_mem = { .disabled = true, }, .initial_state = PM_SUSPEND_MEM, }, }; static struct regulator_init_data tuna_v2v1 = { .constraints = { .min_uV = 2100000, .max_uV = 2100000, .valid_modes_mask = REGULATOR_MODE_NORMAL | REGULATOR_MODE_STANDBY, .valid_ops_mask = REGULATOR_CHANGE_MODE | REGULATOR_CHANGE_STATUS, .always_on = true, .state_mem = { .disabled = true, }, }, }; static struct twl4030_codec_audio_data twl6040_audio = { /* single-step ramp for headset and handsfree */ .hs_left_step = 0x0f, .hs_right_step = 0x0f, .hf_left_step = 0x1d, .hf_right_step = 0x1d, .ep_step = 0x0f, }; static struct regulator *twl6040_clk32kreg; static int tuna_twl6040_get_ext_clk32k(void) { int ret = 0; twl6040_clk32kreg = regulator_get(NULL, "twl6040_clk32k"); if (IS_ERR(twl6040_clk32kreg)) { ret = PTR_ERR(twl6040_clk32kreg); pr_err("failed to get CLK32K %d\n", ret); } return ret; } static void tuna_twl6040_put_ext_clk32k(void) { regulator_put(twl6040_clk32kreg); } static int tuna_twl6040_set_ext_clk32k(bool on) { int ret; if (IS_ERR_OR_NULL(twl6040_clk32kreg)) return -EINVAL; if (on) ret = regulator_enable(twl6040_clk32kreg); else ret = regulator_disable(twl6040_clk32kreg); if (ret) pr_err("failed to enable TWL6040 CLK32K %d\n", ret); return ret; } static struct twl4030_codec_data twl6040_codec = { .audio = &twl6040_audio, .naudint_irq = OMAP44XX_IRQ_SYS_2N, .irq_base = TWL6040_CODEC_IRQ_BASE, .get_ext_clk32k = tuna_twl6040_get_ext_clk32k, .put_ext_clk32k = tuna_twl6040_put_ext_clk32k, .set_ext_clk32k = tuna_twl6040_set_ext_clk32k, }; static struct twl4030_platform_data tuna_twldata = { .irq_base = TWL6030_IRQ_BASE, .irq_end = TWL6030_IRQ_END, /* Regulators */ .vmmc = &tuna_vmmc, .vpp = &tuna_vpp, .vusim = &tuna_vusim, .vana = &tuna_vana, .vcxio = &tuna_vcxio, .vdac = &tuna_vdac, .vusb = &tuna_vusb, .vaux1 = &tuna_vaux1, .vaux2 = &tuna_vaux2, .vaux3 = &tuna_vaux3, .clk32kg = &tuna_clk32kg, .clk32kaudio = &tuna_clk32kaudio, /* children */ .codec = &twl6040_codec, .madc = &twl6030_madc, /* SMPS */ .vdd3 = &tuna_vdd3, .vmem = &tuna_vmem, .v2v1 = &tuna_v2v1, }; static void tuna_audio_init(void) { unsigned int aud_pwron; /* twl6040 naudint */ omap_mux_init_signal("sys_nirq2.sys_nirq2", \ OMAP_PIN_INPUT_PULLUP); /* aud_pwron */ if (omap4_tuna_get_type() == TUNA_TYPE_TORO && omap4_tuna_get_revision() >= 1) aud_pwron = GPIO_AUD_PWRON_TORO_V1; else aud_pwron = GPIO_AUD_PWRON; omap_mux_init_gpio(aud_pwron, OMAP_PIN_OUTPUT); twl6040_codec.audpwron_gpio = aud_pwron; omap_mux_init_signal("gpmc_a24.gpio_48", OMAP_PIN_OUTPUT | OMAP_MUX_MODE3); omap_mux_init_signal("kpd_col3.gpio_171", OMAP_PIN_OUTPUT | OMAP_MUX_MODE3); } static struct i2c_board_info __initdata tuna_i2c1_boardinfo[] = { { I2C_BOARD_INFO("twl6030", 0x48), .flags = I2C_CLIENT_WAKE, .irq = OMAP44XX_IRQ_SYS_1N, .platform_data = &tuna_twldata, }, }; static struct i2c_board_info __initdata tuna_i2c2_boardinfo[] = { { I2C_BOARD_INFO("ducati", 0x20), .irq = OMAP44XX_IRQ_I2C2, .ext_master = true, }, }; static struct i2c_board_info __initdata tuna_i2c4_boardinfo[] = { { I2C_BOARD_INFO("an30259a", 0x30), }, }; static void __init omap_i2c_hwspinlock_init(int bus_id, int spinlock_id, struct omap_i2c_bus_board_data *pdata) { /* spinlock_id should be -1 for a generic lock request */ if (spinlock_id < 0) pdata->handle = hwspin_lock_request(); else pdata->handle = hwspin_lock_request_specific(spinlock_id); if (pdata->handle != NULL) { pdata->hwspin_lock_timeout = hwspin_lock_timeout; pdata->hwspin_unlock = hwspin_unlock; } else { pr_err("I2C hwspinlock request failed for bus %d\n", \ bus_id); } } static struct omap_i2c_bus_board_data __initdata sdp4430_i2c_1_bus_pdata; static struct omap_i2c_bus_board_data __initdata sdp4430_i2c_2_bus_pdata; static struct omap_i2c_bus_board_data __initdata sdp4430_i2c_3_bus_pdata; static struct omap_i2c_bus_board_data __initdata sdp4430_i2c_4_bus_pdata; static int __init tuna_i2c_init(void) { u32 r; omap_i2c_hwspinlock_init(1, 0, &sdp4430_i2c_1_bus_pdata); omap_i2c_hwspinlock_init(2, 1, &sdp4430_i2c_2_bus_pdata); omap_i2c_hwspinlock_init(3, 2, &sdp4430_i2c_3_bus_pdata); omap_i2c_hwspinlock_init(4, 3, &sdp4430_i2c_4_bus_pdata); omap_register_i2c_bus_board_data(1, &sdp4430_i2c_1_bus_pdata); omap_register_i2c_bus_board_data(2, &sdp4430_i2c_2_bus_pdata); omap_register_i2c_bus_board_data(3, &sdp4430_i2c_3_bus_pdata); omap_register_i2c_bus_board_data(4, &sdp4430_i2c_4_bus_pdata); omap_mux_init_signal("sys_nirq1", OMAP_PIN_INPUT_PULLUP | OMAP_WAKEUP_EN); omap_mux_init_signal("i2c1_scl.i2c1_scl", OMAP_PIN_INPUT_PULLUP); omap_mux_init_signal("i2c1_sda.i2c1_sda", OMAP_PIN_INPUT_PULLUP); /* * This will allow unused regulator to be shutdown. This flag * should be set in the board file. Before regulators are registered. */ regulator_has_full_constraints(); /* * Phoenix Audio IC needs I2C1 to * start with 400 KHz or less */ omap_register_i2c_bus(1, 400, tuna_i2c1_boardinfo, ARRAY_SIZE(tuna_i2c1_boardinfo)); omap_register_i2c_bus(2, 400, tuna_i2c2_boardinfo, ARRAY_SIZE(tuna_i2c2_boardinfo)); omap_register_i2c_bus(3, 400, NULL, 0); /* Disable internal pullup on i2c.4 line: * as external 2.2K is already present */ r = omap4_ctrl_pad_readl(OMAP4_CTRL_MODULE_PAD_CORE_CONTROL_I2C_0); r |= (1 << OMAP4_I2C4_SDA_PULLUPRESX_SHIFT); omap4_ctrl_pad_writel(r, OMAP4_CTRL_MODULE_PAD_CORE_CONTROL_I2C_0); omap_register_i2c_bus(4, 400, NULL, 0); /* * Drive MSECURE high for TWL6030 write access. */ omap_mux_init_signal("fref_clk0_out.gpio_wk6", OMAP_PIN_OUTPUT); gpio_request(6, "msecure"); gpio_direction_output(6, 1); return 0; } #ifdef CONFIG_OMAP_MUX static struct omap_board_mux board_mux[] __initdata = { /* camera gpios */ OMAP4_MUX(MCSPI1_SOMI, OMAP_MUX_MODE3 | OMAP_PIN_INPUT_PULLDOWN), /* gpio_135 */ OMAP4_MUX(KPD_COL0, OMAP_MUX_MODE3 | OMAP_PIN_INPUT_PULLDOWN), /* gpio_173 */ OMAP4_MUX(GPMC_A19, OMAP_MUX_MODE3 | OMAP_PIN_INPUT_PULLDOWN), /* gpio_43 */ /* hwrev */ OMAP4_MUX(CSI21_DY4, OMAP_MUX_MODE3 | OMAP_PIN_INPUT), OMAP4_MUX(CSI21_DX4, OMAP_MUX_MODE3 | OMAP_PIN_INPUT), OMAP4_MUX(CSI21_DY3, OMAP_MUX_MODE3 | OMAP_PIN_INPUT), OMAP4_MUX(CSI21_DX3, OMAP_MUX_MODE3 | OMAP_PIN_INPUT), OMAP4_MUX(USBB2_HSIC_STROBE, OMAP_MUX_MODE3 | OMAP_PIN_INPUT), /* fRom */ OMAP4_MUX(USBB2_ULPITLL_DAT4, OMAP_MUX_MODE4 | OMAP_PIN_INPUT), /* mcpsi3_somi */ OMAP4_MUX(USBB2_ULPITLL_DAT5, OMAP_MUX_MODE4 | OMAP_PIN_INPUT_PULLDOWN), /* mcpsi3_cs0 */ OMAP4_MUX(USBB2_ULPITLL_DAT6, OMAP_MUX_MODE4 | OMAP_PIN_INPUT), /* mcpsi3_simo */ OMAP4_MUX(USBB2_ULPITLL_DAT7, OMAP_MUX_MODE4 | OMAP_PIN_INPUT), /* mcpsi3_clk */ { .reg_offset = OMAP_MUX_TERMINATOR }, }; static struct omap_board_mux board_wkup_mux[] __initdata = { /* power button */ OMAP4_MUX(SIM_CD, OMAP_MUX_MODE3 | OMAP_PIN_INPUT), { .reg_offset = OMAP_MUX_TERMINATOR }, }; #else #define board_mux NULL #define board_wkup_mux NULL #endif /* sample4+ adds gps rts/cts lines */ static struct omap_device_pad tuna_uart1_pads_sample4[] __initdata = { { .name = "mcspi1_cs3.uart1_rts", .enable = OMAP_PIN_OUTPUT | OMAP_MUX_MODE1, }, { .name = "mcspi1_cs2.uart1_cts", .enable = OMAP_PIN_INPUT_PULLUP | OMAP_MUX_MODE1, }, { .name = "uart3_cts_rctx.uart1_tx", .enable = OMAP_PIN_OUTPUT | OMAP_MUX_MODE1, }, { .name = "mcspi1_cs1.uart1_rx", .flags = OMAP_DEVICE_PAD_REMUX | OMAP_DEVICE_PAD_WAKEUP, .enable = OMAP_PIN_INPUT_PULLUP | OMAP_MUX_MODE1, .idle = OMAP_PIN_INPUT_PULLUP | OMAP_MUX_MODE1, }, }; static struct omap_device_pad tuna_uart1_pads[] __initdata = { { .name = "uart3_cts_rctx.uart1_tx", .enable = OMAP_PIN_OUTPUT | OMAP_MUX_MODE1, }, { .name = "mcspi1_cs1.uart1_rx", .flags = OMAP_DEVICE_PAD_REMUX | OMAP_DEVICE_PAD_WAKEUP, .enable = OMAP_PIN_INPUT_PULLUP | OMAP_MUX_MODE1, .idle = OMAP_PIN_INPUT_PULLUP | OMAP_MUX_MODE1, }, }; static struct omap_device_pad tuna_uart2_pads[] __initdata = { { .name = "uart2_cts.uart2_cts", .enable = OMAP_PIN_INPUT_PULLUP | OMAP_MUX_MODE0, }, { .name = "uart2_rts.uart2_rts", .enable = OMAP_PIN_OUTPUT | OMAP_MUX_MODE0, }, { .name = "uart2_tx.uart2_tx", .enable = OMAP_PIN_OUTPUT | OMAP_MUX_MODE0, }, { .name = "uart2_rx.uart2_rx", .enable = OMAP_PIN_INPUT_PULLUP | OMAP_MUX_MODE0, }, }; static struct omap_device_pad tuna_uart3_pads[] __initdata = { { .name = "uart3_tx_irtx.uart3_tx_irtx", .enable = OMAP_PIN_OUTPUT | OMAP_MUX_MODE0, }, { .name = "uart3_rx_irrx.uart3_rx_irrx", .flags = OMAP_DEVICE_PAD_REMUX | OMAP_DEVICE_PAD_WAKEUP, .enable = OMAP_PIN_INPUT | OMAP_MUX_MODE0, .idle = OMAP_PIN_INPUT | OMAP_MUX_MODE0, }, }; static struct omap_device_pad tuna_uart4_pads[] __initdata = { { .name = "uart4_tx.uart4_tx", .enable = OMAP_PIN_OUTPUT | OMAP_MUX_MODE0, }, { .name = "uart4_rx.uart4_rx", .enable = OMAP_PIN_INPUT | OMAP_MUX_MODE0, }, }; static struct omap_uart_port_info tuna_uart2_info __initdata = { .use_dma = 0, .dma_rx_buf_size = DEFAULT_RXDMA_BUFSIZE, .dma_rx_poll_rate = DEFAULT_RXDMA_POLLRATE, .dma_rx_timeout = DEFAULT_RXDMA_TIMEOUT, .auto_sus_timeout = 0, .wake_peer = bcm_bt_lpm_exit_lpm_locked, .rts_mux_driver_control = 1, }; static inline void __init board_serial_init(void) { struct omap_device_pad *uart1_pads; int uart1_pads_sz; if (omap4_tuna_get_revision() >= TUNA_REV_SAMPLE_4) { uart1_pads = tuna_uart1_pads_sample4; uart1_pads_sz = ARRAY_SIZE(tuna_uart1_pads_sample4); } else { uart1_pads = tuna_uart1_pads; uart1_pads_sz = ARRAY_SIZE(tuna_uart1_pads); } omap_serial_init_port_pads(0, uart1_pads, uart1_pads_sz, NULL); omap_serial_init_port_pads(1, tuna_uart2_pads, ARRAY_SIZE(tuna_uart2_pads), &tuna_uart2_info); omap_serial_init_port_pads(3, tuna_uart4_pads, ARRAY_SIZE(tuna_uart4_pads), NULL); } /* fiq_debugger initializes really early but OMAP resource mgmt * is not yet ready @ arch_init, so init the serial debugger later */ static int __init board_serial_debug_init(void) { return omap_serial_debug_init(2, false, true, tuna_uart3_pads, ARRAY_SIZE(tuna_uart3_pads)); } device_initcall(board_serial_debug_init); /* SPI flash memory in camera module */ #define F_ROM_SPI_BUS_NUM 3 #define F_ROM_SPI_CS 0 #define F_ROM_SPI_SPEED_HZ 24000000 static const struct flash_platform_data w25q80_pdata = { .name = "w25q80", .type = "w25q80", }; static struct omap2_mcspi_device_config f_rom_mcspi_config = { .turbo_mode = 0, .single_channel = 1, /* 0: slave, 1: master */ .swap_datalines = 1, }; static struct spi_board_info tuna_f_rom[] __initdata = { { .modalias = "m25p80", .controller_data = &f_rom_mcspi_config, .platform_data = &w25q80_pdata, .bus_num = F_ROM_SPI_BUS_NUM, .chip_select = F_ROM_SPI_CS, .max_speed_hz = F_ROM_SPI_SPEED_HZ, .mode = SPI_MODE_0, }, }; static void tuna_from_init(void) { int err; if (tuna_hw_rev >= 0x07) f_rom_mcspi_config.swap_datalines = 0; err = spi_register_board_info(tuna_f_rom, ARRAY_SIZE(tuna_f_rom)); if (err) pr_err("failed to register SPI F-ROM\n"); } /*SPI for LTE modem bootloader*/ #define LTE_MODEM_SPI_BUS_NUM 4 #define LTE_MODEM_SPI_CS 0 #define LTE_MODEM_SPI_MAX_HZ 1500000 struct lte_modem_bootloader_platform_data lte_modem_bootloader_pdata = { .name = "lte_modem_int", .gpio_lte2ap_status = OMAP_GPIO_CMC2AP_INT1, }; static struct omap2_mcspi_device_config lte_mcspi_config = { .turbo_mode = 0, .single_channel = 1, /* 0: slave, 1: master */ }; static struct spi_board_info tuna_lte_modem[] __initdata = { { .modalias = "lte_modem_spi", .controller_data = <e_mcspi_config, .platform_data = <e_modem_bootloader_pdata, .max_speed_hz = LTE_MODEM_SPI_MAX_HZ, .bus_num = LTE_MODEM_SPI_BUS_NUM, .chip_select = LTE_MODEM_SPI_CS, .mode = SPI_MODE_0, }, }; static int tuna_notifier_call(struct notifier_block *this, unsigned long code, void *_cmd) { void __iomem *sar_base; unsigned int flag = REBOOT_FLAG_NORMAL; sar_base = omap4_get_sar_ram_base(); if (!sar_base) return notifier_from_errno(-ENOMEM); if (code == SYS_RESTART) { if (_cmd) { if (!strcmp(_cmd, "recovery")) flag = REBOOT_FLAG_RECOVERY; else if (!strcmp(_cmd, "bootloader")) flag = REBOOT_FLAG_FASTBOOT; } } else if (code == SYS_POWER_OFF) { flag = REBOOT_FLAG_POWER_OFF; } /* The Samsung LOKE bootloader will look for the boot flag at a fixed * offset from the end of the 1st SAR bank. */ writel(flag, sar_base + SAR_BANK2_OFFSET - 0xC); return NOTIFY_DONE; } static struct notifier_block tuna_reboot_notifier = { .notifier_call = tuna_notifier_call, }; static ssize_t tuna_soc_family_show(struct kobject *kobj, struct kobj_attribute *attr, char *buf) { return sprintf(buf, "OMAP%04x\n", GET_OMAP_TYPE); } static ssize_t tuna_soc_revision_show(struct kobject *kobj, struct kobj_attribute *attr, char *buf) { return sprintf(buf, "ES%d.%d\n", (GET_OMAP_REVISION() >> 4) & 0xf, GET_OMAP_REVISION() & 0xf); } static ssize_t tuna_soc_die_id_show(struct kobject *kobj, struct kobj_attribute *attr, char *buf) { struct omap_die_id oid; omap_get_die_id(&oid); return sprintf(buf, "%08X-%08X-%08X-%08X\n", oid.id_3, oid.id_2, oid.id_1, oid.id_0); } static ssize_t tuna_soc_prod_id_show(struct kobject *kobj, struct kobj_attribute *attr, char *buf) { struct omap_die_id oid; omap_get_production_id(&oid); return sprintf(buf, "%08X-%08X\n", oid.id_1, oid.id_0); } static ssize_t tuna_soc_msv_show(struct kobject *kobj, struct kobj_attribute *attr, char *buf) { return sprintf(buf, "%08X\n", omap_ctrl_readl(0x013c)); } static const char *omap_types[] = { [OMAP2_DEVICE_TYPE_TEST] = "TST", [OMAP2_DEVICE_TYPE_EMU] = "EMU", [OMAP2_DEVICE_TYPE_SEC] = "HS", [OMAP2_DEVICE_TYPE_GP] = "GP", [OMAP2_DEVICE_TYPE_BAD] = "BAD", }; static ssize_t tuna_soc_type_show(struct kobject *kobj, struct kobj_attribute *attr, char *buf) { return sprintf(buf, "%s\n", omap_types[omap_type()]); } #define TUNA_ATTR_RO(_type, _name, _show) \ struct kobj_attribute tuna_##_type##_prop_attr_##_name = \ __ATTR(_name, S_IRUGO, _show, NULL) static TUNA_ATTR_RO(soc, family, tuna_soc_family_show); static TUNA_ATTR_RO(soc, revision, tuna_soc_revision_show); static TUNA_ATTR_RO(soc, type, tuna_soc_type_show); static TUNA_ATTR_RO(soc, die_id, tuna_soc_die_id_show); static TUNA_ATTR_RO(soc, production_id, tuna_soc_prod_id_show); static TUNA_ATTR_RO(soc, msv, tuna_soc_msv_show); static struct attribute *tuna_soc_prop_attrs[] = { &tuna_soc_prop_attr_family.attr, &tuna_soc_prop_attr_revision.attr, &tuna_soc_prop_attr_type.attr, &tuna_soc_prop_attr_die_id.attr, &tuna_soc_prop_attr_production_id.attr, &tuna_soc_prop_attr_msv.attr, NULL, }; static struct attribute_group tuna_soc_prop_attr_group = { .attrs = tuna_soc_prop_attrs, }; static ssize_t tuna_board_revision_show(struct kobject *kobj, struct kobj_attribute *attr, char *buf) { return sprintf(buf, "%s (0x%02x)\n", omap4_tuna_hw_rev_name(), tuna_hw_rev); } static TUNA_ATTR_RO(board, revision, tuna_board_revision_show); static struct attribute *tuna_board_prop_attrs[] = { &tuna_board_prop_attr_revision.attr, NULL, }; static struct attribute_group tuna_board_prop_attr_group = { .attrs = tuna_board_prop_attrs, }; static void __init omap4_tuna_create_board_props(void) { struct kobject *board_props_kobj; struct kobject *soc_kobj = NULL; int ret = 0; board_props_kobj = kobject_create_and_add("board_properties", NULL); if (!board_props_kobj) goto err_board_obj; soc_kobj = kobject_create_and_add("soc", board_props_kobj); if (!soc_kobj) goto err_soc_obj; ret = sysfs_create_group(board_props_kobj, &tuna_board_prop_attr_group); if (ret) goto err_board_sysfs_create; ret = sysfs_create_group(soc_kobj, &tuna_soc_prop_attr_group); if (ret) goto err_soc_sysfs_create; return; err_soc_sysfs_create: sysfs_remove_group(board_props_kobj, &tuna_board_prop_attr_group); err_board_sysfs_create: kobject_put(soc_kobj); err_soc_obj: kobject_put(board_props_kobj); err_board_obj: if (!board_props_kobj || !soc_kobj || ret) pr_err("failed to create board_properties\n"); } #define HSMMC2_MUX (OMAP_MUX_MODE1 | OMAP_PIN_INPUT_PULLUP) #define HSMMC1_MUX OMAP_PIN_INPUT_PULLUP static void __init omap4_tuna_led_init(void) { i2c_register_board_info(4, tuna_i2c4_boardinfo, ARRAY_SIZE(tuna_i2c4_boardinfo)); } /* always reboot into charger mode on "power-off". Let the bootloader * figure out if we should truly power-off or not. */ static void tuna_power_off(void) { printk(KERN_EMERG "Rebooting into bootloader for power-off.\n"); arm_pm_restart('c', NULL); } static void __init tuna_init(void) { int package = OMAP_PACKAGE_CBS; if (omap_rev() == OMAP4430_REV_ES1_0) package = OMAP_PACKAGE_CBL; omap4_mux_init(board_mux, board_wkup_mux, package); omap4_tuna_init_hw_rev(); omap4_tuna_emif_init(); pm_power_off = tuna_power_off; register_reboot_notifier(&tuna_reboot_notifier); /* hsmmc d0-d7 */ omap_mux_init_signal("sdmmc1_dat0.sdmmc1_dat0", HSMMC1_MUX); omap_mux_init_signal("sdmmc1_dat1.sdmmc1_dat1", HSMMC1_MUX); omap_mux_init_signal("sdmmc1_dat2.sdmmc1_dat2", HSMMC1_MUX); omap_mux_init_signal("sdmmc1_dat3.sdmmc1_dat3", HSMMC1_MUX); omap_mux_init_signal("sdmmc1_dat4.sdmmc1_dat4", HSMMC1_MUX); omap_mux_init_signal("sdmmc1_dat5.sdmmc1_dat5", HSMMC1_MUX); omap_mux_init_signal("sdmmc1_dat6.sdmmc1_dat6", HSMMC1_MUX); omap_mux_init_signal("sdmmc1_dat7.sdmmc1_dat7", HSMMC1_MUX); /* hsmmc cmd */ omap_mux_init_signal("sdmmc1_cmd.sdmmc1_cmd", HSMMC1_MUX); /* hsmmc clk */ omap_mux_init_signal("sdmmc1_clk.sdmmc1_clk", HSMMC1_MUX); gpio_request(158, "emmc_en"); gpio_direction_output(158, 1); omap_mux_init_gpio(158, OMAP_PIN_INPUT_PULLUP); omap_mux_init_gpio(GPIO_MHL_SDA_18V, OMAP_PIN_INPUT_PULLUP); omap_mux_init_gpio(GPIO_MHL_SCL_18V, OMAP_PIN_INPUT_PULLUP); sec_common_init(); if (TUNA_TYPE_TORO == omap4_tuna_get_type()) { omap_mux_init_signal("gpmc_wait0", OMAP_MUX_MODE3 | OMAP_PIN_INPUT_PULLDOWN); gpio_request(OMAP_GPIO_CMC2AP_INT1, "gpio_61"); gpio_direction_input(OMAP_GPIO_CMC2AP_INT1); omap_mux_init_signal("mcspi4_clk", OMAP_MUX_MODE0); omap_mux_init_signal("mcspi4_simo", OMAP_MUX_MODE0); omap_mux_init_signal("mcspi4_somi", OMAP_MUX_MODE0); omap_mux_init_signal("mcspi4_cs0", OMAP_MUX_MODE0); } tuna_wlan_init(); tuna_audio_init(); tuna_i2c_init(); tuna_gsd4t_gps_init(); platform_add_devices(tuna_devices, ARRAY_SIZE(tuna_devices)); board_serial_init(); tuna_bt_init(); omap2_hsmmc_init(mmc); usb_musb_init(&musb_board_data); omap4_tuna_create_board_props(); if (TUNA_TYPE_TORO == omap4_tuna_get_type()) { spi_register_board_info(tuna_lte_modem, ARRAY_SIZE(tuna_lte_modem)); } tuna_from_init(); omap_dmm_init(); omap4_register_ion(); omap4_tuna_display_init(); omap4_tuna_input_init(); omap4_tuna_nfc_init(); omap4_tuna_power_init(); omap4_tuna_jack_init(); omap4_tuna_sensors_init(); omap4_tuna_led_init(); omap4_tuna_connector_init(); omap4_tuna_pogo_init(); #ifdef CONFIG_OMAP_HSI_DEVICE if (TUNA_TYPE_MAGURO == omap4_tuna_get_type()) omap_hsi_init(); #endif #ifdef CONFIG_USB_EHCI_HCD_OMAP if (TUNA_TYPE_TORO == omap4_tuna_get_type()) { #ifdef CONFIG_SEC_MODEM modem_toro_init(); #endif omap4_ehci_init(); } #endif } static void __init tuna_map_io(void) { omap2_set_globals_443x(); omap44xx_map_common_io(); } static void __init tuna_reserve(void) { omap_init_ram_size(); #ifdef CONFIG_ION_OMAP tuna_android_display_setup(get_omap_ion_platform_data()); omap_ion_init(); #else tuna_android_display_setup(NULL); #endif omap_ram_console_init(OMAP_RAM_CONSOLE_START_DEFAULT, OMAP_RAM_CONSOLE_SIZE_DEFAULT); #ifndef CONFIG_CMA /* do the static reservations first */ memblock_remove(PHYS_ADDR_SMC_MEM, PHYS_ADDR_SMC_SIZE); memblock_remove(PHYS_ADDR_DUCATI_MEM, PHYS_ADDR_DUCATI_SIZE); #endif /* ipu needs to recognize secure input buffer area as well */ omap_ipu_set_static_mempool(PHYS_ADDR_DUCATI_MEM, PHYS_ADDR_DUCATI_SIZE + OMAP4_ION_HEAP_SECURE_INPUT_SIZE); omap_reserve(); } #define PHOENIX_LAST_TURNOFF_STS 0x22 static int __init tuna_print_last_turnon_sts(void) { u8 turnon_sts; int err; err = twl_i2c_read_u8(TWL6030_MODULE_ID0, &turnon_sts, PHOENIX_LAST_TURNOFF_STS); if (!err) { pr_info("PHOENIX_LAST_TURNOFF_STS: 0x%02x\n", turnon_sts); twl_i2c_write_u8(TWL6030_MODULE_ID0, turnon_sts, PHOENIX_LAST_TURNOFF_STS); } return 0; } device_initcall(tuna_print_last_turnon_sts); MACHINE_START(TUNA, "Tuna") /* Maintainer: Google, Inc */ .boot_params = 0x80000100, .reserve = tuna_reserve, .map_io = tuna_map_io, .init_early = tuna_init_early, .init_irq = gic_init_irq, .init_machine = tuna_init, .timer = &omap_timer, MACHINE_END