/* * arch/arm/mach-tegra/board-generic.c * * Copyright (C) 2010 Google, Inc. * Copyright (C) 2010 NVIDIA Corporation * * 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 "gpio-names.h" #include #include #include #include #include #include "nvodm_query.h" #include "nvodm_query_discovery.h" #include "board.h" #ifdef CONFIG_USB_ANDROID static char *tegra_android_functions_ums[] = { #ifdef CONFIG_USB_ANDROID_MASS_STORAGE "usb_mass_storage", #endif }; static char *tegra_android_functions_ums_adb[] = { #ifdef CONFIG_USB_ANDROID_MASS_STORAGE "usb_mass_storage", #endif #ifdef CONFIG_USB_ANDROID_ADB "adb", #endif }; static char *tegra_android_functions_rndis[] = { #ifdef CONFIG_USB_ANDROID_RNDIS "rndis", #endif }; static char *tegra_android_functions_rndis_adb[] = { #ifdef CONFIG_USB_ANDROID_RNDIS "rndis", #endif #ifdef CONFIG_USB_ANDROID_ADB "adb", #endif }; static char *tegra_android_functions_all[] = { #ifdef CONFIG_USB_ANDROID_RNDIS "rndis", #endif #ifdef CONFIG_USB_ANDROID_MASS_STORAGE "usb_mass_storage", #endif #ifdef CONFIG_USB_ANDROID_ADB "adb", #endif }; static struct android_usb_product tegra_android_products[] = { [0] = { .product_id = 0x7100, .num_functions = ARRAY_SIZE(tegra_android_functions_ums), .functions = tegra_android_functions_ums, }, [1] = { .product_id = 0x7100, .num_functions = ARRAY_SIZE(tegra_android_functions_ums_adb), .functions = tegra_android_functions_ums_adb, }, [2] = { .product_id = 0x7102, .num_functions = ARRAY_SIZE(tegra_android_functions_rndis), .functions = tegra_android_functions_rndis, }, [3] = { .product_id = 0x7103, .num_functions = ARRAY_SIZE(tegra_android_functions_rndis_adb), .functions = tegra_android_functions_rndis_adb, }, }; static char *harmony_dev = "NVIDIA Harmony"; static char *ventana_dev = "NVIDIA Ventana"; static char *generic_dev = "NVIDIA Tegra 2"; static struct android_usb_platform_data tegra_android_platform = { .vendor_id = 0x955, .product_id = 0x7100, .manufacturer_name = "NVIDIA", .num_products = ARRAY_SIZE(tegra_android_products), .products = tegra_android_products, .num_functions = ARRAY_SIZE(tegra_android_functions_all), .functions = tegra_android_functions_all, }; static struct platform_device tegra_android_device = { .name = "android_usb", .id = -1, .dev = { .platform_data = &tegra_android_platform, }, }; #ifdef CONFIG_USB_ANDROID_MASS_STORAGE static struct usb_mass_storage_platform_data tegra_usb_fsg_platform = { .vendor = "NVIDIA", .product = "Tegra 2", .nluns = 1, .bulk_size = 16384, }; static struct platform_device tegra_usb_fsg_device = { .name = "usb_mass_storage", .id = -1, .dev = { .platform_data = &tegra_usb_fsg_platform, }, }; #endif #ifdef CONFIG_USB_ANDROID_RNDIS static struct usb_ether_platform_data tegra_usb_rndis_platform = { .ethaddr = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, .vendorID = 0x7100, .vendorDescr = "Tegra 2 RNDIS", }; static struct platform_device tegra_usb_rndis_device = { .name = "rndis", .id = -1, .dev = { .platform_data = &tegra_usb_rndis_platform, }, }; #endif #endif static struct platform_device *platform_devices[] = { #ifdef CONFIG_USB_ANDROID #ifdef CONFIG_USB_ANDROID_RNDIS &tegra_usb_rndis_device, #endif #ifdef CONFIG_USB_ANDROID_MASS_STORAGE &tegra_usb_fsg_device, #endif &tegra_android_device, #endif }; static struct i2c_board_info bus0_i2c_devices[] = { #ifdef CONFIG_SENSORS_ISL29018 { I2C_BOARD_INFO("isl29018", 0x44), .irq = (INT_GPIO_BASE + TEGRA_GPIO_PZ2), }, #endif }; static struct i2c_board_info bus3_i2c_devices[] = { #ifdef CONFIG_SENSORS_AK8975 { I2C_BOARD_INFO("mm_ak8975", 0x0C), .irq = (INT_GPIO_BASE + TEGRA_GPIO_PN5), }, #endif #ifdef CONFIG_SENSORS_LM90 { I2C_BOARD_INFO("nct1008", 0x4C), }, #endif }; void __init i2c_device_setup(void) { if (ARRAY_SIZE(bus0_i2c_devices)) i2c_register_board_info(0, bus0_i2c_devices, ARRAY_SIZE(bus0_i2c_devices)); if (ARRAY_SIZE(bus3_i2c_devices)) i2c_register_board_info(3, bus3_i2c_devices, ARRAY_SIZE(bus3_i2c_devices)); } // enable 32Khz clock used by bcm4329 wifi, bluetooth and gps static void __init tegra_setup_32khz_clock(void) { int RequestedPeriod, ReturnedPeriod; NvOdmServicesPwmHandle hOdmPwm = NULL; hOdmPwm = NvOdmPwmOpen(); if (!hOdmPwm) { pr_err("%s: failed to open NvOdmPwmOpen\n", __func__); return; } RequestedPeriod = 0; NvOdmPwmConfig(hOdmPwm, NvOdmPwmOutputId_Blink, NvOdmPwmMode_Blink_32KHzClockOutput, 0, &RequestedPeriod, &ReturnedPeriod); NvOdmPwmClose(hOdmPwm); } extern void __init tegra_setup_nvodm(bool standard_i2c, bool standard_spi); extern void __init tegra_register_socdev(void); static struct spi_board_info tegra_spi_ipc_devices[] __initdata = { { .modalias = "spi_ipc", .bus_num = 0, .chip_select = 0, .mode = SPI_MODE_1, .max_speed_hz = 12000000, .platform_data = NULL, .irq = 0, }, }; static void __init register_spi_ipc_devices(void) { unsigned long instance = 0xFFFF; unsigned long cs = 0xFFFF; const NvOdmPeripheralConnectivity *pConnectivity = NULL; int i; pConnectivity = NvOdmPeripheralGetGuid(NV_ODM_GUID('s','p','i',' ','_','i','p','c')); if (!pConnectivity) return; for (i = 0; i < pConnectivity->NumAddress; i++) { switch (pConnectivity->AddressList[i].Interface) { case NvOdmIoModule_Spi: instance = pConnectivity->AddressList[i].Instance; cs = pConnectivity->AddressList[i].Address; break; default: break; } } if (instance == 0xffff || cs == 0xffff) { pr_err("%s: SPI IPC Protocol driver: Instance and CS are Invalid\n", __func__); return; } tegra_spi_ipc_devices[0].bus_num = instance; tegra_spi_ipc_devices[0].chip_select = cs; if (spi_register_board_info(tegra_spi_ipc_devices, ARRAY_SIZE(tegra_spi_ipc_devices)) != 0) { pr_err("%s: spi_register_board_info returned error\n", __func__); } } static void __init do_system_init(bool standard_i2c, bool standard_spi) { unsigned int chip_id[2]; char serial[17]; tegra_common_init(); tegra_setup_nvodm(true, true); tegra_register_socdev(); NvRmQueryChipUniqueId(s_hRmGlobal, sizeof(chip_id), (void*)chip_id); snprintf(serial, sizeof(serial), "%08x%08x", chip_id[1], chip_id[0]); #ifdef CONFIG_USB_ANDROID tegra_android_platform.serial_number = kstrdup(serial, GFP_KERNEL); #endif platform_add_devices(platform_devices, ARRAY_SIZE(platform_devices)); } static void __init tegra_harmony_init(void) { #ifdef CONFIG_USB_ANDROID tegra_android_platform.product_name = harmony_dev; #endif do_system_init(true, true); } static void __init tegra_ventana_init(void) { #ifdef CONFIG_USB_ANDROID tegra_android_platform.product_name = ventana_dev; #endif do_system_init(false, true); i2c_device_setup(); tegra_setup_32khz_clock(); } static void __init tegra_generic_init(void) { #ifdef CONFIG_USB_ANDROID tegra_android_platform.product_name = generic_dev; #endif do_system_init(true, true); register_spi_ipc_devices(); } MACHINE_START(VENTANA, "NVIDIA Ventana Development System") .boot_params = 0x00000100, .phys_io = IO_APB_PHYS, .io_pg_offst = ((IO_APB_VIRT) >> 18) & 0xfffc, .init_irq = tegra_init_irq, .init_machine = tegra_ventana_init, .map_io = tegra_map_common_io, .timer = &tegra_timer, MACHINE_END MACHINE_START(HARMONY, "NVIDIA Harmony Development System") .boot_params = 0x00000100, .phys_io = IO_APB_PHYS, .io_pg_offst = ((IO_APB_VIRT) >> 18) & 0xfffc, .init_irq = tegra_init_irq, .init_machine = tegra_harmony_init, .map_io = tegra_map_common_io, .timer = &tegra_timer, MACHINE_END MACHINE_START(TEGRA_GENERIC, "Tegra 2 Development System") .boot_params = 0x00000100, .phys_io = IO_APB_PHYS, .io_pg_offst = ((IO_APB_VIRT) >> 18) & 0xfffc, .init_irq = tegra_init_irq, .init_machine = tegra_generic_init, .map_io = tegra_map_common_io, .timer = &tegra_timer, MACHINE_END