/* * arch/arm/mach-tegra/board-e1853.c * * Copyright (c) 2012, NVIDIA CORPORATION. All rights reserved. * * This program is free software; you can redistribute it and/or modify it * under the terms and conditions of the GNU General Public License, * version 2, as published by the Free Software Foundation. * * This program is distributed in the hope it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for * more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #if defined(CONFIG_TOUCHSCREEN_ATMEL_MXT) #include #endif #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "board.h" #include "clock.h" #include "board-e1853.h" #include "devices.h" #include "gpio-names.h" #include "fuse.h" #include "common.h" #include "pm.h" #define IO_EXPANDER_ADDR (0x75) #define BT_RESET_BIT_POS (IO_EXP_PIN_0) #define BT_ENABLE_BIT_POS (IO_EXP_PIN_5) #define BT_WAKEUP_BIT_POS (IO_EXP_PIN_7) static __initdata struct tegra_clk_init_table e1853_clk_init_table[] = { /* name parent rate enabled */ { "pll_m", NULL, 0, true}, { "hda", "pll_p", 108000000, false}, { "hda2codec_2x", "pll_p", 48000000, false}, { "pwm", "clk_32k", 32768, false}, { "blink", "clk_32k", 32768, true}, { "pll_a", NULL, 552960000, false}, /* audio cif clock should be faster than i2s */ { "pll_a_out0", NULL, 24576000, false}, { "d_audio", "pll_a_out0", 24576000, false}, { "nor", "pll_p", 86500000, true}, { "uarta", "pll_p", 480000000, true}, { "uartb", "pll_p", 480000000, true}, { "uartc", "pll_p", 480000000, true}, { "uartd", "pll_p", 480000000, true}, { "sdmmc2", "pll_p", 52000000, true}, { "sbc2", "pll_m", 100000000, true}, { "sbc3", "pll_m", 100000000, true}, { "sbc4", "pll_m", 100000000, true}, { "sbc5", "pll_m", 100000000, true}, { "sbc6", "pll_m", 100000000, true}, { "cpu_g", "cclk_g", 900000000, true}, { "i2s0", "pll_a_out0", 24576000, false}, { "i2s1", "pll_a_out0", 24576000, false}, { "i2s2", "pll_a_out0", 24576000, false}, { "i2s3", "pll_a_out0", 24576000, false}, { "i2s4", "pll_a_out0", 24576000, false}, { "audio0", "i2s0_sync", 12288000, false}, { "audio1", "i2s1_sync", 12288000, false}, { "audio2", "i2s2_sync", 12288000, false}, { "audio3", "i2s3_sync", 12288000, false}, { "audio4", "i2s4_sync", 12288000, false}, { "apbif", "clk_m", 12000000, false}, { "dam0", "clk_m", 12000000, true}, { "dam1", "clk_m", 12000000, true}, { "dam2", "clk_m", 12000000, true}, { "vi", "pll_p", 470000000, false}, { "vi_sensor", "pll_p", 150000000, false}, { "vde", "pll_c", 484000000, true}, { "host1x", "pll_c", 242000000, true}, { "mpe", "pll_c", 484000000, true}, { "se", "pll_m", 625000000, true}, { "i2c1", "pll_p", 3200000, true}, { "i2c2", "pll_p", 3200000, true}, { "i2c3", "pll_p", 3200000, true}, { "i2c4", "pll_p", 3200000, true}, { "i2c5", "pll_p", 3200000, true}, { "sdmmc2", "pll_p", 104000000, false}, {"wake.sclk", NULL, 334000000, true }, { NULL, NULL, 0, 0}, }; static struct tegra_i2c_platform_data e1853_i2c1_platform_data = { .adapter_nr = 0, .bus_count = 1, .bus_clk_rate = { 100000, 0 }, }; static struct tegra_i2c_platform_data e1853_i2c2_platform_data = { .adapter_nr = 1, .bus_count = 1, .bus_clk_rate = { 100000, 0 }, .is_clkon_always = true, }; static struct tegra_i2c_platform_data e1853_i2c4_platform_data = { .adapter_nr = 3, .bus_count = 1, .bus_clk_rate = { 100000, 0 }, }; static struct tegra_i2c_platform_data e1853_i2c5_platform_data = { .adapter_nr = 4, .bus_count = 1, .bus_clk_rate = { 100000, 0 }, }; static struct tegra_pci_platform_data e1853_pci_platform_data = { .port_status[0] = 1, .port_status[1] = 1, .port_status[2] = 1, .use_dock_detect = 0, .gpio = 0, }; static void e1853_pcie_init(void) { tegra_pci_device.dev.platform_data = &e1853_pci_platform_data; platform_device_register(&tegra_pci_device); } static void e1853_i2c_init(void) { tegra_i2c_device1.dev.platform_data = &e1853_i2c1_platform_data; tegra_i2c_device2.dev.platform_data = &e1853_i2c2_platform_data; tegra_i2c_device4.dev.platform_data = &e1853_i2c4_platform_data; tegra_i2c_device5.dev.platform_data = &e1853_i2c5_platform_data; platform_device_register(&tegra_i2c_device5); platform_device_register(&tegra_i2c_device4); platform_device_register(&tegra_i2c_device2); platform_device_register(&tegra_i2c_device1); } static struct platform_device *e1853_uart_devices[] __initdata = { &tegra_uarta_device, &tegra_uartb_device, &tegra_uartc_device, &tegra_uartd_device, }; static void __init uart_debug_init(void) { /* UARTA is the debug port. */ pr_info("Selecting UARTA as the debug console\n"); e1853_uart_devices[0] = &debug_uarta_device; debug_uart_clk = clk_get_sys("serial8250.0", "uarta"); debug_uart_port_base = ((struct plat_serial8250_port *)( debug_uarta_device.dev.platform_data))->mapbase; } static void __init e1853_uart_init(void) { /* Register low speed only if it is selected */ if (!is_tegra_debug_uartport_hs()) { uart_debug_init(); /* Clock enable for the debug channel */ if (!IS_ERR_OR_NULL(debug_uart_clk)) { pr_info("The debug console clock name is %s\n", debug_uart_clk->name); clk_enable(debug_uart_clk); clk_set_rate(debug_uart_clk, 408000000); } else { pr_err("Not getting the clock %s for debug console\n", debug_uart_clk->name); } } platform_add_devices(e1853_uart_devices, ARRAY_SIZE(e1853_uart_devices)); } #if defined(CONFIG_RTC_DRV_TEGRA) static struct resource tegra_rtc_resources[] = { [0] = { .start = TEGRA_RTC_BASE, .end = TEGRA_RTC_BASE + TEGRA_RTC_SIZE - 1, .flags = IORESOURCE_MEM, }, [1] = { .start = INT_RTC, .end = INT_RTC, .flags = IORESOURCE_IRQ, }, }; static struct platform_device tegra_rtc_device = { .name = "tegra_rtc", .id = -1, .resource = tegra_rtc_resources, .num_resources = ARRAY_SIZE(tegra_rtc_resources), }; #endif static struct tegra_asoc_vcm_platform_data jetson_audio_pdata = { .codec_info[0] = { .codec_dai_name = "dit-hifi", .cpu_dai_name = "tegra30-i2s.0", .codec_name = "spdif-dit.0", .name = "tegra-i2s-1", .pcm_driver = "tegra-pcm-audio", .i2s_format = format_i2s, /* Audio Codec is Master */ .master = 1, }, .codec_info[1] = { .codec_dai_name = "dit-hifi", .cpu_dai_name = "tegra30-i2s.3", .codec_name = "spdif-dit.1", .name = "tegra-i2s-2", .pcm_driver = "tegra-tdm-pcm-audio", .i2s_format = format_tdm, /* Audio Codec is Master */ .master = 1, .num_slots = 8, .slot_width = 32, .tx_mask = 0xff, .rx_mask = 0xff, }, }; static struct platform_device generic_codec_1 = { .name = "spdif-dit", .id = 0, }; static struct platform_device generic_codec_2 = { .name = "spdif-dit", .id = 1, }; static struct platform_device tegra_snd_e1853 = { .name = "tegra-snd-e1853", .id = 0, .dev = { .platform_data = &jetson_audio_pdata, }, }; static void e1853_i2s_audio_init(void) { platform_device_register(&tegra_pcm_device); platform_device_register(&tegra_tdm_pcm_device); platform_device_register(&generic_codec_1); platform_device_register(&generic_codec_2); platform_device_register(&tegra_i2s_device0); platform_device_register(&tegra_i2s_device3); platform_device_register(&tegra_ahub_device); platform_device_register(&tegra_snd_e1853); } #if defined(CONFIG_SPI_TEGRA) && defined(CONFIG_SPI_SPIDEV) static struct spi_board_info tegra_spi_devices[] __initdata = { { .modalias = "spidev", .bus_num = 1, .chip_select = 1, .mode = SPI_MODE_0, .max_speed_hz = 18000000, .platform_data = NULL, .irq = 0, }, { .modalias = "spidev", .bus_num = 2, .chip_select = 1, .mode = SPI_MODE_0, .max_speed_hz = 18000000, .platform_data = NULL, .irq = 0, }, { .modalias = "spidev", .bus_num = 4, .chip_select = 2, .mode = SPI_MODE_0, .max_speed_hz = 18000000, .platform_data = NULL, .irq = 0, }, }; static void __init e1853_register_spidev(void) { spi_register_board_info(tegra_spi_devices, ARRAY_SIZE(tegra_spi_devices)); } #else #define e1853_register_spidev() do {} while (0) #endif static void e1853_spi_init(void) { tegra_spi_device3.name = "spi_slave_tegra"; platform_device_register(&tegra_spi_device2); platform_device_register(&tegra_spi_device3); platform_device_register(&tegra_spi_device5); e1853_register_spidev(); } static struct platform_device tegra_camera = { .name = "tegra_camera", .id = -1, }; static struct platform_device *e1853_devices[] __initdata = { #if defined(CONFIG_TEGRA_AVP) &tegra_avp_device, #endif #if defined(CONFIG_RTC_DRV_TEGRA) &tegra_rtc_device, #endif &tegra_camera, &tegra_wdt0_device }; #ifdef CONFIG_TOUCHSCREEN_ATMEL_MXT #define MXT_CONFIG_CRC 0xD62DE8 static const u8 config[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x32, 0x0A, 0x00, 0x14, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x8B, 0x00, 0x00, 0x1B, 0x2A, 0x00, 0x20, 0x3C, 0x04, 0x05, 0x00, 0x02, 0x01, 0x00, 0x0A, 0x0A, 0x0A, 0x0A, 0xFF, 0x02, 0x55, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x64, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x23, 0x00, 0x00, 0x00, 0x05, 0x0A, 0x15, 0x1E, 0x00, 0x00, 0x04, 0xFF, 0x03, 0x3F, 0x64, 0x64, 0x01, 0x0A, 0x14, 0x28, 0x4B, 0x00, 0x02, 0x00, 0x64, 0x00, 0x19, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x10, 0x3C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; #define MXT_CONFIG_CRC_SKU2000 0xA24D9A static const u8 config_sku2000[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x32, 0x0A, 0x00, 0x14, 0x14, 0x19, 0x00, 0x00, 0x00, 0x00, 0x00, 0x8B, 0x00, 0x00, 0x1B, 0x2A, 0x00, 0x20, 0x3A, 0x04, 0x05, 0x00, /* 23=thr 2 di */ 0x04, 0x04, 0x41, 0x0A, 0x0A, 0x0A, 0x0A, 0xFF, 0x02, 0x55, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0A, 0x00, 0x00, 0x00, 0x00, /* 0A=limit */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x23, 0x00, 0x00, 0x00, 0x05, 0x0A, 0x15, 0x1E, 0x00, 0x00, 0x04, 0x00, 0x03, 0x3F, 0x64, 0x64, 0x01, 0x0A, 0x14, 0x28, 0x4B, 0x00, 0x02, 0x00, 0x64, 0x00, 0x19, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x10, 0x3C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; static struct mxt_platform_data atmel_mxt_info = { .x_line = 27, .y_line = 42, .x_size = 768, .y_size = 1366, .blen = 0x20, .threshold = 0x3C, .voltage = 3300000, /* 3.3V */ .orient = 5, .config = config, .config_length = 157, .config_crc = MXT_CONFIG_CRC, .irqflags = IRQF_TRIGGER_FALLING, .read_chg = NULL, }; static struct i2c_board_info __initdata atmel_i2c_info[] = { { I2C_BOARD_INFO("atmel_mxt_ts", 0x5A), .irq = TEGRA_GPIO_TO_IRQ(TOUCH_GPIO_IRQ_ATMEL_T9), .platform_data = &atmel_mxt_info, } }; static __initdata struct tegra_clk_init_table spi_clk_init_table[] = { /* name parent rate enabled */ { "sbc1", "pll_p", 52000000, true}, { NULL, NULL, 0, 0}, }; static int __init e1853_touch_init(void) { tegra_gpio_enable(TOUCH_GPIO_IRQ_ATMEL_T9); tegra_gpio_enable(TOUCH_GPIO_RST_ATMEL_T9); gpio_request(TOUCH_GPIO_IRQ_ATMEL_T9, "atmel-irq"); gpio_direction_input(TOUCH_GPIO_IRQ_ATMEL_T9); gpio_request(TOUCH_GPIO_RST_ATMEL_T9, "atmel-reset"); gpio_direction_output(TOUCH_GPIO_RST_ATMEL_T9, 0); usleep_range(1000, 2000); gpio_set_value(TOUCH_GPIO_RST_ATMEL_T9, 1); msleep(100); atmel_mxt_info.config = config_sku2000; atmel_mxt_info.config_crc = MXT_CONFIG_CRC_SKU2000; i2c_register_board_info(TOUCH_BUS_ATMEL_T9, atmel_i2c_info, 1); return 0; } #endif /* CONFIG_TOUCHSCREEN_ATMEL_MXT */ #if defined(CONFIG_USB_G_ANDROID) static struct tegra_usb_platform_data tegra_udc_pdata = { .port_otg = false, .has_hostpc = true, .phy_intf = TEGRA_USB_PHY_INTF_UTMI, .op_mode = TEGRA_USB_OPMODE_DEVICE, .u_data.dev = { .vbus_pmu_irq = 0, .vbus_gpio = -1, .charging_supported = false, .remote_wakeup_supported = false, }, .u_cfg.utmi = { .hssync_start_delay = 0, .idle_wait_delay = 17, .elastic_limit = 16, .term_range_adj = 6, .xcvr_setup = 63, .xcvr_setup_offset = 6, .xcvr_use_fuses = 1, .xcvr_lsfslew = 2, .xcvr_lsrslew = 2, .xcvr_use_lsb = 1, }, }; #else static struct tegra_usb_platform_data tegra_ehci1_utmi_pdata = { .port_otg = false, .has_hostpc = true, .phy_intf = TEGRA_USB_PHY_INTF_UTMI, .op_mode = TEGRA_USB_OPMODE_HOST, .u_data.host = { .vbus_gpio = -1, .hot_plug = true, .remote_wakeup_supported = true, .power_off_on_suspend = true, }, .u_cfg.utmi = { .hssync_start_delay = 0, .idle_wait_delay = 17, .elastic_limit = 16, .term_range_adj = 6, .xcvr_setup = 63, .xcvr_setup_offset = 6, .xcvr_use_fuses = 1, .xcvr_lsfslew = 2, .xcvr_lsrslew = 2, .xcvr_use_lsb = 1, }, }; #endif static struct tegra_usb_platform_data tegra_ehci2_utmi_pdata = { .port_otg = false, .has_hostpc = true, .phy_intf = TEGRA_USB_PHY_INTF_UTMI, .op_mode = TEGRA_USB_OPMODE_HOST, .u_data.host = { .vbus_gpio = -1, .hot_plug = true, .remote_wakeup_supported = true, .power_off_on_suspend = true, }, .u_cfg.utmi = { .hssync_start_delay = 0, .idle_wait_delay = 17, .elastic_limit = 16, .term_range_adj = 6, .xcvr_setup = 63, .xcvr_setup_offset = 6, .xcvr_use_fuses = 1, .xcvr_lsfslew = 2, .xcvr_lsrslew = 2, .xcvr_use_lsb = 1, }, }; static struct tegra_usb_platform_data tegra_ehci3_utmi_pdata = { .port_otg = false, .has_hostpc = true, .phy_intf = TEGRA_USB_PHY_INTF_UTMI, .op_mode = TEGRA_USB_OPMODE_HOST, .u_data.host = { .vbus_gpio = -1, .hot_plug = true, .remote_wakeup_supported = true, .power_off_on_suspend = true, }, .u_cfg.utmi = { .hssync_start_delay = 0, .idle_wait_delay = 17, .elastic_limit = 16, .term_range_adj = 6, .xcvr_setup = 63, .xcvr_setup_offset = 6, .xcvr_use_fuses = 1, .xcvr_lsfslew = 2, .xcvr_lsrslew = 2, .xcvr_use_lsb = 1, }, }; static void e1853_usb_init(void) { /* Need to parse sku info to decide host/device mode */ /* G_ANDROID require device mode */ #if defined(CONFIG_USB_G_ANDROID) tegra_udc_device.dev.platform_data = &tegra_udc_pdata; platform_device_register(&tegra_udc_device); #else tegra_ehci1_device.dev.platform_data = &tegra_ehci1_utmi_pdata; platform_device_register(&tegra_ehci1_device); #endif tegra_ehci2_device.dev.platform_data = &tegra_ehci2_utmi_pdata; platform_device_register(&tegra_ehci2_device); tegra_ehci3_device.dev.platform_data = &tegra_ehci3_utmi_pdata; platform_device_register(&tegra_ehci3_device); } static struct tegra_nor_platform_data e1853_nor_data = { .flash = { .map_name = "cfi_probe", .width = 2, }, .chip_parms = { .MuxMode = NorMuxMode_ADMux, .BurstLength = NorBurstLength_CntBurst, .ReadMode = NorReadMode_Async, .ReadyActive = NorReadyActive_BeforeData, /* FIXME: Need to use characterized value */ .timing_default = { .timing0 = 0xA0A05585, .timing1 = 0x200A0406, }, .timing_read = { .timing0 = 0xA0A05585, .timing1 = 0x00050406, }, }, }; static void e1853_nor_init(void) { tegra_nor_device.resource[2].end = TEGRA_NOR_FLASH_BASE + SZ_64M - 1; tegra_nor_device.dev.platform_data = &e1853_nor_data; platform_device_register(&tegra_nor_device); } static void __init tegra_e1853_init(void) { tegra_init_board_info(); tegra_clk_init_from_table(e1853_clk_init_table); tegra_enable_pinmux(); tegra_smmu_init(); tegra_soc_device_init("e1853"); e1853_pinmux_init(); e1853_i2c_init(); e1853_gpio_init(); /* e1853_regulator_init(); e1853_suspend_init(); */ e1853_i2s_audio_init(); e1853_uart_init(); e1853_usb_init(); tegra_io_dpd_init(); e1853_sdhci_init(); e1853_spi_init(); platform_add_devices(e1853_devices, ARRAY_SIZE(e1853_devices)); #ifdef CONFIG_TOUCHSCREEN_ATMEL_MXT e1853_touch_init(); #endif e1853_panel_init(); e1853_nor_init(); e1853_pcie_init(); } static void __init tegra_e1853_reserve(void) { #if defined(CONFIG_NVMAP_CONVERT_CARVEOUT_TO_IOVMM) tegra_reserve(0, SZ_8M, SZ_8M); #else tegra_reserve(SZ_128M, SZ_8M, SZ_8M); #endif } static int __init e1853_bt_init(void) { struct i2c_adapter *adapter; struct i2c_board_info info = { {0} }; struct i2c_client *client = NULL; struct i2c_msg msg; u8 cmd_buf[2]; int ret = 0; /* Program the IO Expander */ adapter = i2c_get_adapter(1); if (!adapter) { printk(KERN_WARNING "%s: adapter is null\n", __func__); ret = -ENXIO; goto i2c_done; } info.addr = IO_EXPANDER_ADDR; client = i2c_new_device(adapter, &info); i2c_put_adapter(adapter); if (!client) { printk(KERN_WARNING "%s: client is null\n", __func__); ret = -ENXIO; goto i2c_done; } /* Set output state for BT_RST, BT_EN and BT_WAKEUP */ /* Read register contents of OUTPUT_PORT_REG */ cmd_buf[0] = IO_EXP_OUTPUT_PORT_REG_0; msg.addr = IO_EXPANDER_ADDR; msg.flags = 0; msg.len = 1; msg.buf = &cmd_buf[0]; ret = i2c_transfer(client->adapter, &msg, 1); if (ret < 0) goto i2c_done; msg.addr = IO_EXPANDER_ADDR; msg.flags = I2C_M_RD; msg.len = 1; msg.buf = &cmd_buf[1]; ret = i2c_transfer(client->adapter, &msg, 1); if (ret < 0) goto i2c_done; /* Set required output values and write */ cmd_buf[0] = IO_EXP_OUTPUT_PORT_REG_0; cmd_buf[1] |= ((1 << BT_ENABLE_BIT_POS) | (1 << BT_WAKEUP_BIT_POS) | (1 << BT_RESET_BIT_POS)); msg.addr = IO_EXPANDER_ADDR; msg.flags = 0; msg.len = 2; msg.buf = &cmd_buf[0]; ret = i2c_transfer(client->adapter, &msg, 1); if (ret < 0) goto i2c_done; /* Set BT_RST, BT_EN and BT_WAKEUP as output pins */ /* Read register contents of CONFIG_REG */ cmd_buf[0] = IO_EXP_CONFIG_REG_0; msg.addr = IO_EXPANDER_ADDR; msg.flags = 0; msg.len = 1; msg.buf = &cmd_buf[0]; ret = i2c_transfer(client->adapter, &msg, 1); if (ret < 0) goto i2c_done; msg.addr = IO_EXPANDER_ADDR; msg.flags = I2C_M_RD; msg.len = 1; msg.buf = &cmd_buf[1]; ret = i2c_transfer(client->adapter, &msg, 1); if (ret < 0) goto i2c_done; /* Set required direction bits */ cmd_buf[0] = IO_EXP_CONFIG_REG_0; cmd_buf[1] &= (~((1 << BT_ENABLE_BIT_POS) | (1 << BT_WAKEUP_BIT_POS) | (1 << BT_RESET_BIT_POS))); msg.addr = IO_EXPANDER_ADDR; msg.flags = 0; msg.len = 2; msg.buf = &cmd_buf[0]; ret = i2c_transfer(client->adapter, &msg, 1); if (ret < 0) goto i2c_done; ret = 0; i2c_done: if (ret < 0) printk(KERN_ERR "%s: I2C transaction failed\n", __func__); if (client) i2c_unregister_device(client); return ret; } late_initcall(e1853_bt_init); MACHINE_START(E1853, "e1853") .atag_offset = 0x100, .soc = &tegra_soc_desc, .init_irq = tegra_init_irq, .init_early = tegra30_init_early, .init_machine = tegra_e1853_init, .map_io = tegra_map_common_io, .reserve = tegra_e1853_reserve, .timer = &tegra_timer, .handle_irq = gic_handle_irq, MACHINE_END