diff options
author | Gary King <gking@nvidia.com> | 2010-05-27 20:54:58 -0700 |
---|---|---|
committer | Gary King <gking@nvidia.com> | 2010-05-27 21:41:04 -0700 |
commit | a05cde61f3f9426805ec691ffd13e815b2cdc408 (patch) | |
tree | 4160edf02a2922087a09b21babb6add91c11088b | |
parent | 6b72a2f24eb2dfecb1115659bd17e3c3c29b70ff (diff) |
[ARM/tegra] board-nvodm: add registration helper function for SPI
gcc auto-inlining seems to breakdown with this file now that there are
so many registration functions; mark all of the setup helpers as noinline
to prevent the optimizer from producing non-working kernels
Change-Id: Id29df6111aa50c02099fe96ebd60c119e6dcdd44
-rw-r--r-- | arch/arm/mach-tegra/board-generic.c | 4 | ||||
-rw-r--r-- | arch/arm/mach-tegra/board-nvodm.c | 125 |
2 files changed, 123 insertions, 6 deletions
diff --git a/arch/arm/mach-tegra/board-generic.c b/arch/arm/mach-tegra/board-generic.c index e9c51661884c..8f513260d2eb 100644 --- a/arch/arm/mach-tegra/board-generic.c +++ b/arch/arm/mach-tegra/board-generic.c @@ -97,13 +97,13 @@ static struct platform_device *platform_devices[] = { #endif }; -extern void __init tegra_setup_nvodm(bool standard_i2c); +extern void __init tegra_setup_nvodm(bool standard_i2c, bool standard_spi); extern void __init tegra_register_socdev(void); static void __init tegra_generic_init(void) { tegra_common_init(); - tegra_setup_nvodm(true); + tegra_setup_nvodm(true, true); tegra_register_socdev(); tegra_android_platform.product_name = harmony_dev; platform_add_devices(platform_devices, ARRAY_SIZE(platform_devices)); diff --git a/arch/arm/mach-tegra/board-nvodm.c b/arch/arm/mach-tegra/board-nvodm.c index a37c4cbe77d7..43ff10b83146 100644 --- a/arch/arm/mach-tegra/board-nvodm.c +++ b/arch/arm/mach-tegra/board-nvodm.c @@ -41,6 +41,7 @@ #include <mach/regulator.h> #include <mach/kbc.h> #include <mach/i2c.h> +#include <mach/spi.h> #include <mach/nvrm_linux.h> @@ -645,7 +646,7 @@ static inline void tegra_setup_hcd(void) { } #ifdef CONFIG_KEYBOARD_TEGRA struct tegra_kbc_plat tegra_kbc_platform; -static void tegra_setup_kbc(void) +static noinline void __init tegra_setup_kbc(void) { struct tegra_kbc_plat *pdata = &tegra_kbc_platform; const NvOdmPeripheralConnectivity *conn; @@ -822,7 +823,7 @@ static struct platform_device lbee9qmb_device = { .platform_data = &lbee9qmb_platform, }, }; -static void tegra_setup_rfkill(void) +static noinline void __init tegra_setup_rfkill(void) { const NvOdmPeripheralConnectivity *con; unsigned int i; @@ -861,6 +862,120 @@ static struct platform_device *nvodm_devices[] __initdata = { #endif }; +#ifdef CONFIG_SPI_TEGRA +static struct tegra_spi_platform_data tegra_spi_platform[] = { + [0] = { + .is_slink = true, + }, + [1] = { + .is_slink = true, + }, + [2] = { + .is_slink = true, + }, + [3] = { + .is_slink = true, + }, + [4] = { + .is_slink = false, + }, +}; +static struct platform_device tegra_spi_devices[] = { + [0] = { + .name = "tegra_spi", + .id = 0, + .dev = { + .platform_data = &tegra_spi_platform[0], + }, + }, + [1] = { + .name = "tegra_spi", + .id = 1, + .dev = { + .platform_data = &tegra_spi_platform[1], + }, + }, + [2] = { + .name = "tegra_spi", + .id = 2, + .dev = { + .platform_data = &tegra_spi_platform[2], + }, + }, + [3] = { + .name = "tegra_spi", + .id = 3, + .dev = { + .platform_data = &tegra_spi_platform[3], + }, + }, + [4] = { + .name = "tegra_spi", + .id = 4, + .dev = { + .platform_data = &tegra_spi_platform[4], + }, + }, +}; +static noinline void __init tegra_setup_spi(void) +{ + const NvU32 *spi_mux; + const NvU32 *sflash_mux; + NvU32 spi_mux_nr; + NvU32 sflash_mux_nr; + int i; + + NvOdmQueryPinMux(NvOdmIoModule_Spi, &spi_mux, &spi_mux_nr); + NvOdmQueryPinMux(NvOdmIoModule_Sflash, &sflash_mux, &sflash_mux_nr); + + for (i=0; i<ARRAY_SIZE(tegra_spi_devices); i++) { + struct platform_device *pdev = &tegra_spi_devices[i]; + struct tegra_spi_platform_data *plat = &tegra_spi_platform[i]; + + const NvOdmQuerySpiDeviceInfo *info = NULL; + NvU32 mux = 0; + int rc; + + if (plat->is_slink && pdev->id<spi_mux_nr) + mux = spi_mux[pdev->id]; + else if (!plat->is_slink) + mux = sflash_mux[0]; + + if (!mux) + continue; + + if (mux == NVODM_QUERY_PINMAP_MULTIPLEXED) { + pr_err("%s: not registering multiplexed SPI master " + "%s.%d\n", __func__, pdev->name, pdev->id); + WARN_ON(1); + continue; + } + + if (plat->is_slink) { + info = NvOdmQuerySpiGetDeviceInfo(NvOdmIoModule_Spi, + pdev->id, 0); + } else { + info = NvOdmQuerySpiGetDeviceInfo(NvOdmIoModule_Sflash, + 0, 0); + } + + if (info && info->IsSlave) { + pr_info("%s: not registering SPI slave %s.%d\n", + __func__, pdev->name, pdev->id); + continue; + } + + rc = platform_device_register(pdev); + if (rc) { + pr_err("%s: registration of %s.%d failed\n", + __func__, pdev->name, pdev->id); + } + } +} +#else +static void tegra_setup_spi(void) { } +#endif + #ifdef CONFIG_I2C_TEGRA static struct tegra_i2c_plat_parms tegra_i2c_platform[] = { [0] = { @@ -922,7 +1037,7 @@ static struct platform_device tegra_i2c_devices[] = { }, }, }; -static void tegra_setup_i2c(void) +static noinline void __init tegra_setup_i2c(void) { const NvOdmPeripheralConnectivity *smbus; const NvOdmIoAddress *smbus_addr = NULL; @@ -1120,7 +1235,7 @@ do_register: tegra_init_suspend(plat); } -void __init tegra_setup_nvodm(bool standard_i2c) +void __init tegra_setup_nvodm(bool standard_i2c, bool standard_spi) { NvRmGpioOpen(s_hRmGlobal, &s_hGpioGlobal); tegra_setup_debug_uart(); @@ -1131,6 +1246,8 @@ void __init tegra_setup_nvodm(bool standard_i2c) tegra_setup_kbc(); if (standard_i2c) tegra_setup_i2c(); + if (standard_spi) + tegra_setup_spi(); platform_add_devices(nvodm_devices, ARRAY_SIZE(nvodm_devices)); pm_power_off = tegra_system_power_off; tegra_setup_suspend(); |