diff options
author | Gary King <gking@nvidia.com> | 2010-05-27 19:11:59 -0700 |
---|---|---|
committer | Gary King <gking@nvidia.com> | 2010-05-27 21:41:01 -0700 |
commit | f6caae835d7b2aaec4bdae6075049fd432bebdb1 (patch) | |
tree | a44c3361479e1feff6c55eddb927d807ac9e342d /arch | |
parent | cc97da113940c13a6b9d06a42b5f238014ccb95e (diff) |
[ARM/tegra] board-nvodm: register I2C devices for simple platforms
on platforms which have simple configurations (specifically no pinmux
multiplexing for I2C controllers), implement a helper function in
board-nvodm to register all of the I2C master controllers on the system
based on the ODM kit-specified values.
the code will skip registering I2C slave controllers, which are currently
detected by the SMBUS GUID.
also, since board-generic is really intended to be only for NVIDIA
development boards, make the terminology in the file more clearly
NVIDIA-specific.
Change-Id: I115fb6bf68d93f62a548d65fa5bfdd2d00c13fbc
Diffstat (limited to 'arch')
-rw-r--r-- | arch/arm/mach-tegra/board-generic.c | 15 | ||||
-rw-r--r-- | arch/arm/mach-tegra/board-nvodm.c | 147 |
2 files changed, 155 insertions, 7 deletions
diff --git a/arch/arm/mach-tegra/board-generic.c b/arch/arm/mach-tegra/board-generic.c index 7fc8d1c854f0..e9c51661884c 100644 --- a/arch/arm/mach-tegra/board-generic.c +++ b/arch/arm/mach-tegra/board-generic.c @@ -1,7 +1,8 @@ /* - * arch/arm/mach-tegra/board-harmony.c + * 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 @@ -51,11 +52,13 @@ static struct android_usb_product tegra_android_products[] = { .functions = tegra_android_functions, }, }; + +static char *harmony_dev = "Harmony ADB"; + static struct android_usb_platform_data tegra_android_platform = { .vendor_id = 0x955, .product_id = 0x7100, .manufacturer_name = "NVIDIA", - .product_name = "Harmony", .num_products = ARRAY_SIZE(tegra_android_products), .products = tegra_android_products, .num_functions = ARRAY_SIZE(tegra_android_functions), @@ -94,19 +97,19 @@ static struct platform_device *platform_devices[] = { #endif }; - -extern void __init tegra_setup_nvodm(void); +extern void __init tegra_setup_nvodm(bool standard_i2c); extern void __init tegra_register_socdev(void); static void __init tegra_generic_init(void) { tegra_common_init(); - tegra_setup_nvodm(); + tegra_setup_nvodm(true); tegra_register_socdev(); + tegra_android_platform.product_name = harmony_dev; platform_add_devices(platform_devices, ARRAY_SIZE(platform_devices)); } -MACHINE_START(TEGRA_GENERIC, "Tegra Generic") +MACHINE_START(TEGRA_GENERIC, "Tegra 2 Development System") .boot_params = 0x00000100, .phys_io = IO_APB_PHYS, .io_pg_offst = ((IO_APB_VIRT) >> 18) & 0xfffc, diff --git a/arch/arm/mach-tegra/board-nvodm.c b/arch/arm/mach-tegra/board-nvodm.c index f6ece6423a90..a37c4cbe77d7 100644 --- a/arch/arm/mach-tegra/board-nvodm.c +++ b/arch/arm/mach-tegra/board-nvodm.c @@ -40,6 +40,7 @@ #include <mach/nand.h> #include <mach/regulator.h> #include <mach/kbc.h> +#include <mach/i2c.h> #include <mach/nvrm_linux.h> @@ -860,6 +861,148 @@ static struct platform_device *nvodm_devices[] __initdata = { #endif }; +#ifdef CONFIG_I2C_TEGRA +static struct tegra_i2c_plat_parms tegra_i2c_platform[] = { + [0] = { + .adapter_nr = 0, + .bus_count = 1, + .bus_mux = { 0, 0 }, + .bus_clk = { 100000, 0 }, /* default to 100KHz */ + .is_dvc = false, + }, + [1] = { + .adapter_nr = 1, + .bus_count = 1, + .bus_mux = { 0, 0 }, + .bus_clk = { 100000, 0 }, + .is_dvc = false, + }, + [2] = { + .adapter_nr = 2, + .bus_count = 1, + .bus_mux = { 0, 0 }, + .bus_clk = { 100000, 0 }, + .is_dvc = false, + }, + [3] = { + .adapter_nr = 3, + .bus_count = 1, + .bus_mux = { 0, 0 }, + .bus_clk = { 100000, 0 }, + .is_dvc = true, + }, +}; +static struct platform_device tegra_i2c_devices[] = { + [0] = { + .name = "tegra_i2c", + .id = 0, + .dev = { + .platform_data = &tegra_i2c_platform[0], + }, + }, + [1] = { + .name = "tegra_i2c", + .id = 1, + .dev = { + .platform_data = &tegra_i2c_platform[1], + }, + }, + [2] = { + .name = "tegra_i2c", + .id = 2, + .dev = { + .platform_data = &tegra_i2c_platform[2], + }, + }, + [3] = { + .name = "tegra_i2c", + .id = 3, + .dev = { + .platform_data = &tegra_i2c_platform[3], + }, + }, +}; +static void tegra_setup_i2c(void) +{ + const NvOdmPeripheralConnectivity *smbus; + const NvOdmIoAddress *smbus_addr = NULL; + const NvU32 *odm_mux_i2c = NULL; + const NvU32 *odm_clk_i2c = NULL; + const NvU32 *odm_mux_i2cp = NULL; + const NvU32 *odm_clk_i2cp = NULL; + NvU32 odm_mux_i2c_nr; + NvU32 odm_clk_i2c_nr; + NvU32 odm_mux_i2cp_nr; + NvU32 odm_clk_i2cp_nr; + int i; + + smbus = NvOdmPeripheralGetGuid(NV_ODM_GUID('I','2','c','S','m','B','u','s')); + + if (smbus) { + unsigned int j; + smbus_addr = smbus->AddressList; + for (j=0; j<smbus->NumAddress; j++, smbus_addr++) { + if ((smbus_addr->Interface == NvOdmIoModule_I2c) || + (smbus_addr->Interface == NvOdmIoModule_I2c_Pmu)) + break; + } + if (j==smbus->NumAddress) + smbus_addr = NULL; + } + + NvOdmQueryPinMux(NvOdmIoModule_I2c, &odm_mux_i2c, &odm_mux_i2c_nr); + NvOdmQueryPinMux(NvOdmIoModule_I2c_Pmu, &odm_mux_i2cp, &odm_mux_i2cp_nr); + NvOdmQueryClockLimits(NvOdmIoModule_I2c, &odm_clk_i2c, &odm_clk_i2c_nr); + NvOdmQueryClockLimits(NvOdmIoModule_I2c_Pmu, &odm_clk_i2cp, &odm_clk_i2cp_nr); + + for (i=0; i<ARRAY_SIZE(tegra_i2c_devices); i++) { + + struct platform_device *dev = &tegra_i2c_devices[i]; + struct tegra_i2c_plat_parms *plat = &tegra_i2c_platform[i]; + NvU32 mux, clk; + + if (smbus_addr) { + if (smbus_addr->Interface == NvOdmIoModule_I2c && + smbus_addr->Instance == dev->id && !plat->is_dvc) { + pr_info("%s: skipping %s.%d (SMBUS)\n", + __func__, dev->name, dev->id); + continue; + } + } + + if (plat->is_dvc) { + mux = (odm_mux_i2cp_nr) ? odm_mux_i2cp[0] : 0; + clk = (odm_clk_i2cp_nr) ? odm_clk_i2cp[0] : 100; + } else if (dev->id < odm_mux_i2c_nr) { + mux = odm_mux_i2c[dev->id]; + clk = (dev->id < odm_clk_i2c_nr) ? odm_clk_i2c[0] : 100; + } else { + mux = 0; + clk = 0; + } + + if (!mux) + continue; + + if (mux == NVODM_QUERY_PINMAP_MULTIPLEXED) { + pr_err("%s: unable to register %s.%d (multiplexed)\n", + __func__, dev->name, dev->id); + WARN_ON(1); + continue; + } + + if (clk) + plat->bus_clk[0] = clk*1000; + + if (platform_device_register(dev)) + pr_err("%s: failed to register %s.%d\n", + __func__, dev->name, dev->id); + } +} +#else +static void tegra_setup_i2c(void) { } +#endif + #ifdef CONFIG_TEGRA_PCI extern void __init tegra_pcie_init(void); static int tegra_setup_pcie(void) @@ -977,7 +1120,7 @@ do_register: tegra_init_suspend(plat); } -void __init tegra_setup_nvodm(void) +void __init tegra_setup_nvodm(bool standard_i2c) { NvRmGpioOpen(s_hRmGlobal, &s_hGpioGlobal); tegra_setup_debug_uart(); @@ -986,6 +1129,8 @@ void __init tegra_setup_nvodm(void) tegra_setup_sdhci(); tegra_setup_rfkill(); tegra_setup_kbc(); + if (standard_i2c) + tegra_setup_i2c(); platform_add_devices(nvodm_devices, ARRAY_SIZE(nvodm_devices)); pm_power_off = tegra_system_power_off; tegra_setup_suspend(); |