summaryrefslogtreecommitdiff
path: root/arch
diff options
context:
space:
mode:
authorGary King <gking@nvidia.com>2010-05-27 19:11:59 -0700
committerGary King <gking@nvidia.com>2010-05-27 21:41:01 -0700
commitf6caae835d7b2aaec4bdae6075049fd432bebdb1 (patch)
treea44c3361479e1feff6c55eddb927d807ac9e342d /arch
parentcc97da113940c13a6b9d06a42b5f238014ccb95e (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.c15
-rw-r--r--arch/arm/mach-tegra/board-nvodm.c147
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();