From 37440f3ed07a6f588b05b8f98d0b3025c1949371 Mon Sep 17 00:00:00 2001 From: Marcel Ziswiler Date: Fri, 8 Jun 2012 20:36:31 +0200 Subject: Initial Toradex Colibri T20 L4T R15 support. --- arch/arm/mach-tegra/Kconfig | 6 + arch/arm/mach-tegra/Makefile | 8 + arch/arm/mach-tegra/board-colibri_t20-panel.c | 493 +++++++++++++ arch/arm/mach-tegra/board-colibri_t20-pinmux.c | 286 ++++++++ arch/arm/mach-tegra/board-colibri_t20-power.c | 279 +++++++ arch/arm/mach-tegra/board-colibri_t20.c | 977 +++++++++++++++++++++++++ arch/arm/mach-tegra/board-colibri_t20.h | 49 ++ arch/arm/mach-tegra/common.c | 4 +- arch/arm/mach-tegra/devices.c | 25 + arch/arm/mach-tegra/devices.h | 1 + arch/arm/mach-tegra/include/mach/ac97.h | 87 +++ arch/arm/mach-tegra/include/mach/usb_phy.h | 1 + arch/arm/mach-tegra/tegra2_clocks.c | 3 +- arch/arm/mach-tegra/usb_phy.c | 35 +- 14 files changed, 2246 insertions(+), 8 deletions(-) create mode 100644 arch/arm/mach-tegra/board-colibri_t20-panel.c create mode 100644 arch/arm/mach-tegra/board-colibri_t20-pinmux.c create mode 100644 arch/arm/mach-tegra/board-colibri_t20-power.c create mode 100644 arch/arm/mach-tegra/board-colibri_t20.c create mode 100644 arch/arm/mach-tegra/board-colibri_t20.h create mode 100644 arch/arm/mach-tegra/include/mach/ac97.h (limited to 'arch/arm/mach-tegra') diff --git a/arch/arm/mach-tegra/Kconfig b/arch/arm/mach-tegra/Kconfig index c0bf9340483e..0684e13f7e9c 100644 --- a/arch/arm/mach-tegra/Kconfig +++ b/arch/arm/mach-tegra/Kconfig @@ -71,6 +71,12 @@ config TEGRA_PCI comment "Tegra board type" +config MACH_COLIBRI_T20 + bool "Toradex Colibri T20 module" + depends on ARCH_TEGRA_2x_SOC + help + Support for Toradex Colibri T20 module on Iris carrier board + config MACH_HARMONY bool "Harmony board" depends on ARCH_TEGRA_2x_SOC diff --git a/arch/arm/mach-tegra/Makefile b/arch/arm/mach-tegra/Makefile index 96d4667a51be..cc0bb6bc00fd 100644 --- a/arch/arm/mach-tegra/Makefile +++ b/arch/arm/mach-tegra/Makefile @@ -101,6 +101,14 @@ obj-$(CONFIG_SENSORS_TEGRA_TSENSOR) += tegra3_tsensor.o obj-$(CONFIG_TEGRA_DYNAMIC_PWRDET) += powerdetect.o obj-$(CONFIG_TEGRA_USB_MODEM_POWER) += tegra_usb_modem_power.o obj-$(CONFIG_TEGRA_PCI) += pcie.o + +obj-${CONFIG_MACH_COLIBRI_T20} += board-colibri_t20.o +#memory +obj-${CONFIG_MACH_COLIBRI_T20} += board-colibri_t20-panel.o +obj-${CONFIG_MACH_COLIBRI_T20} += board-colibri_t20-pinmux.o +obj-${CONFIG_MACH_COLIBRI_T20} += board-colibri_t20-power.o +#sensors + obj-${CONFIG_MACH_HARMONY} += board-harmony.o obj-${CONFIG_MACH_HARMONY} += board-harmony-kbc.o obj-${CONFIG_MACH_HARMONY} += board-harmony-panel.o diff --git a/arch/arm/mach-tegra/board-colibri_t20-panel.c b/arch/arm/mach-tegra/board-colibri_t20-panel.c new file mode 100644 index 000000000000..86a331648ede --- /dev/null +++ b/arch/arm/mach-tegra/board-colibri_t20-panel.c @@ -0,0 +1,493 @@ +/* + * arch/arm/mach-tegra/board-colibri_t20-panel.c + * + * Copyright (c) 2012, Toradex, Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * 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. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include "board.h" +#include "devices.h" +#include "gpio-names.h" + +#ifndef CAMERA_INTERFACE +#define colibri_t20_bl_enb TEGRA_GPIO_PT4 /* BL_ON */ +#endif +#define colibri_t20_hdmi_hpd TEGRA_GPIO_PN7 /* HOTPLUG_DETECT */ + +#ifdef CONFIG_TEGRA_DC +static struct regulator *colibri_t20_hdmi_reg = NULL; +static struct regulator *colibri_t20_hdmi_pll = NULL; +#endif + +#ifndef CAMERA_INTERFACE +static int colibri_t20_backlight_init(struct device *dev) { + int ret; + + ret = gpio_request(colibri_t20_bl_enb, "BL_ON"); + if (ret < 0) + return ret; + + ret = gpio_direction_output(colibri_t20_bl_enb, 1); + if (ret < 0) + gpio_free(colibri_t20_bl_enb); + else + tegra_gpio_enable(colibri_t20_bl_enb); + + return ret; +}; + +static void colibri_t20_backlight_exit(struct device *dev) { + gpio_set_value(colibri_t20_bl_enb, 0); + gpio_free(colibri_t20_bl_enb); + tegra_gpio_disable(colibri_t20_bl_enb); +} + +static int colibri_t20_backlight_notify(struct device *unused, int brightness) +{ + gpio_set_value(colibri_t20_bl_enb, !!brightness); + return brightness; +} + +static int colibri_t20_disp1_check_fb(struct device *dev, struct fb_info *info); + +static struct platform_pwm_backlight_data colibri_t20_backlight_data = { + .pwm_id = 2, /* PWM (PMFM_PWM2) */ + .max_brightness = 255, + .dft_brightness = 127, + .pwm_period_ns = 5000000, + .init = colibri_t20_backlight_init, + .exit = colibri_t20_backlight_exit, + .notify = colibri_t20_backlight_notify, + /* Only toggle backlight on fb blank notifications for disp1 */ + .check_fb = colibri_t20_disp1_check_fb, +}; + +static struct platform_device colibri_t20_backlight_device = { + .name = "pwm-backlight", + .id = -1, + .dev = { + .platform_data = &colibri_t20_backlight_data, + }, +}; +#endif /* !CAMERA_INTERFACE */ + +#ifdef CONFIG_TEGRA_DC +static int colibri_t20_panel_enable(void) +{ + struct regulator *reg = regulator_get(NULL, "vdd_ldo4"); + + if (!reg) { + regulator_enable(reg); + regulator_put(reg); + } + + reg = regulator_get(NULL, "avdd_vdac"); + pr_info("LDO6: %d\n", regulator_get_voltage(reg)); + regulator_set_voltage(reg, 2850000, 2850000); + pr_info("LDO6: %d\n", regulator_get_voltage(reg)); + regulator_enable(reg); + + reg = regulator_get(NULL, "avdd_hdmi"); + pr_info("LDO7: %d\n", regulator_get_voltage(reg)); + regulator_set_voltage(reg, 3300000, 3300000); + pr_info("LDO7: %d\n", regulator_get_voltage(reg)); + regulator_enable(reg); + + reg = regulator_get(NULL, "avdd_hdmi_pll"); + pr_info("LDO8: %d\n", regulator_get_voltage(reg)); + regulator_set_voltage(reg, 1800000, 1800000); + pr_info("LDO8: %d\n", regulator_get_voltage(reg)); + regulator_enable(reg); + + return 0; +} + +static int colibri_t20_panel_disable(void) +{ + return 0; +} + +static int colibri_t20_hdmi_enable(void) +{ + if (!colibri_t20_hdmi_reg) { + colibri_t20_hdmi_reg = regulator_get(NULL, "avdd_hdmi"); /* LD07 */ + if (IS_ERR_OR_NULL(colibri_t20_hdmi_reg)) { + pr_err("hdmi: couldn't get regulator avdd_hdmi\n"); + colibri_t20_hdmi_reg = NULL; + return PTR_ERR(colibri_t20_hdmi_reg); + } + } + regulator_enable(colibri_t20_hdmi_reg); + + if (!colibri_t20_hdmi_pll) { + colibri_t20_hdmi_pll = regulator_get(NULL, "avdd_hdmi_pll"); /* LD08 */ + if (IS_ERR_OR_NULL(colibri_t20_hdmi_pll)) { + pr_err("hdmi: couldn't get regulator avdd_hdmi_pll\n"); + colibri_t20_hdmi_pll = NULL; + regulator_disable(colibri_t20_hdmi_reg); + colibri_t20_hdmi_reg = NULL; + return PTR_ERR(colibri_t20_hdmi_pll); + } + } + regulator_enable(colibri_t20_hdmi_pll); + return 0; +} + +static int colibri_t20_hdmi_disable(void) +{ + regulator_disable(colibri_t20_hdmi_reg); + regulator_disable(colibri_t20_hdmi_pll); + return 0; +} + +static struct resource colibri_t20_disp1_resources[] = { + { + .name = "irq", + .start = INT_DISPLAY_GENERAL, + .end = INT_DISPLAY_GENERAL, + .flags = IORESOURCE_IRQ, + }, + { + .name = "regs", + .start = TEGRA_DISPLAY_BASE, + .end = TEGRA_DISPLAY_BASE + TEGRA_DISPLAY_SIZE-1, + .flags = IORESOURCE_MEM, + }, + { + .name = "fbmem", + .flags = IORESOURCE_MEM, + }, +}; + +static struct resource colibri_t20_disp2_resources[] = { + { + .name = "irq", + .start = INT_DISPLAY_B_GENERAL, + .end = INT_DISPLAY_B_GENERAL, + .flags = IORESOURCE_IRQ, + }, + { + .name = "regs", + .start = TEGRA_DISPLAY2_BASE, + .end = TEGRA_DISPLAY2_BASE + TEGRA_DISPLAY2_SIZE - 1, + .flags = IORESOURCE_MEM, + }, + { + .name = "fbmem", + .flags = IORESOURCE_MEM, + }, + { + .name = "hdmi_regs", + .start = TEGRA_HDMI_BASE, + .end = TEGRA_HDMI_BASE + TEGRA_HDMI_SIZE - 1, + .flags = IORESOURCE_MEM, + }, +}; + +static struct tegra_dc_mode colibri_t20_panel_modes[] = { + { + .pclk = 72072000, + .h_ref_to_sync = 11, + .v_ref_to_sync = 1, + .h_sync_width = 58, + .v_sync_width = 4, + .h_back_porch = 58, + .v_back_porch = 4, + .h_active = 1366, + .v_active = 768, + .h_front_porch = 58, + .v_front_porch = 4, +#if 0 + .pclk = 25175000, + .h_ref_to_sync = 8, + .v_ref_to_sync = 2, + .h_sync_width = 96, + .v_sync_width = 2, + .h_back_porch = 48, + .v_back_porch = 33, + .h_active = 640, + .v_active = 480, + .h_front_porch = 16, + .v_front_porch = 10, +//#else + .pclk = 74250000, + .h_ref_to_sync = 1, + .v_ref_to_sync = 1, + .h_sync_width = 40, + .v_sync_width = 5, + .h_back_porch = 220, + .v_back_porch = 20, + .h_active = 1280, + .v_active = 720, + .h_front_porch = 110, + .v_front_porch = 5, +#endif + }, +}; + +static struct tegra_fb_data colibri_t20_fb_data = { + .win = 0, + .xres = 1366, + .yres = 768, +#if 0 + .xres = 640, + .yres = 480, +//#else + .xres = 1280, + .yres = 720, +#endif + .bits_per_pixel = 32, + .flags = TEGRA_FB_FLIP_ON_PROBE, +}; + +static struct tegra_fb_data colibri_t20_hdmi_fb_data = { + .win = 0, + .xres = 640, + .yres = 480, + .bits_per_pixel = 32, + .flags = TEGRA_FB_FLIP_ON_PROBE, +}; + +static struct tegra_dc_out colibri_t20_disp1_out = { + .type = TEGRA_DC_OUT_RGB, + + .align = TEGRA_DC_ALIGN_MSB, + .order = TEGRA_DC_ORDER_RED_BLUE, + .depth = 18, + .dither = TEGRA_DC_ORDERED_DITHER, + + .modes = colibri_t20_panel_modes, + .n_modes = ARRAY_SIZE(colibri_t20_panel_modes), + + .enable = colibri_t20_panel_enable, + .disable = colibri_t20_panel_disable, +}; + +static struct tegra_dc_out colibri_t20_disp2_out = { + .type = TEGRA_DC_OUT_HDMI, + .flags = TEGRA_DC_OUT_HOTPLUG_HIGH, + + .dcc_bus = 1, + .hotplug_gpio = colibri_t20_hdmi_hpd, + + .max_pixclock = KHZ2PICOS(148500), + + .align = TEGRA_DC_ALIGN_MSB, + .order = TEGRA_DC_ORDER_RED_BLUE, + + .enable = colibri_t20_hdmi_enable, + .disable = colibri_t20_hdmi_disable, + +// .dither = TEGRA_DC_ORDERED_DITHER, +}; + +static struct tegra_dc_platform_data colibri_t20_disp1_pdata = { + .flags = TEGRA_DC_FLAG_ENABLED, + .default_out = &colibri_t20_disp1_out, + .fb = &colibri_t20_fb_data, +}; + +static struct tegra_dc_platform_data colibri_t20_disp2_pdata = { + .flags = 0, + .default_out = &colibri_t20_disp2_out, + .fb = &colibri_t20_hdmi_fb_data, +}; + +static struct nvhost_device colibri_t20_disp1_device = { + .name = "tegradc", + .id = 0, + .resource = colibri_t20_disp1_resources, + .num_resources = ARRAY_SIZE(colibri_t20_disp1_resources), + .dev = { + .platform_data = &colibri_t20_disp1_pdata, + }, +}; + +static int colibri_t20_disp1_check_fb(struct device *dev, struct fb_info *info) +{ + return info->device == &colibri_t20_disp1_device.dev; +} + +static struct nvhost_device colibri_t20_disp2_device = { + .name = "tegradc", + .id = 1, + .resource = colibri_t20_disp2_resources, + .num_resources = ARRAY_SIZE(colibri_t20_disp2_resources), + .dev = { + .platform_data = &colibri_t20_disp2_pdata, + }, +}; +#else +static int colibri_t20_disp1_check_fb(struct device *dev, struct fb_info *info) +{ + return 0; +} +#endif + +#if defined(CONFIG_TEGRA_NVMAP) +static struct nvmap_platform_carveout colibri_t20_carveouts[] = { + [0] = NVMAP_HEAP_CARVEOUT_IRAM_INIT, + [1] = { + .name = "generic-0", + .usage_mask = NVMAP_HEAP_CARVEOUT_GENERIC, + .buddy_size = SZ_32K, + }, +}; + +static struct nvmap_platform_data colibri_t20_nvmap_data = { + .carveouts = colibri_t20_carveouts, + .nr_carveouts = ARRAY_SIZE(colibri_t20_carveouts), +}; + +static struct platform_device colibri_t20_nvmap_device = { + .name = "tegra-nvmap", + .id = -1, + .dev = { + .platform_data = &colibri_t20_nvmap_data, + }, +}; +#endif /* CONFIG_TEGRA_NVMAP */ + +static struct platform_device *colibri_t20_gfx_devices[] __initdata = { +#if defined(CONFIG_TEGRA_NVMAP) + &colibri_t20_nvmap_device, +#endif +#ifndef CAMERA_INTERFACE + &tegra_pwfm2_device, + &colibri_t20_backlight_device, +#endif /* !CAMERA_INTERFACE */ +}; + +#ifdef CONFIG_HAS_EARLYSUSPEND +/* put early_suspend/late_resume handlers here for the display in order + * to keep the code out of the display driver, keeping it closer to upstream + */ +struct early_suspend colibri_t20_panel_early_suspender; + +static void colibri_t20_panel_early_suspend(struct early_suspend *h) +{ + /* power down LCD, add use a black screen for HDMI */ + if (num_registered_fb > 0) + fb_blank(registered_fb[0], FB_BLANK_POWERDOWN); + if (num_registered_fb > 1) + fb_blank(registered_fb[1], FB_BLANK_NORMAL); +#ifdef CONFIG_TEGRA_CONVSERVATIVE_GOV_ON_EARLYSUPSEND + cpufreq_save_default_governor(); + cpufreq_set_conservative_governor(); + cpufreq_set_conservative_governor_param("up_threshold", + SET_CONSERVATIVE_GOVERNOR_UP_THRESHOLD); + + cpufreq_set_conservative_governor_param("down_threshold", + SET_CONSERVATIVE_GOVERNOR_DOWN_THRESHOLD); + + cpufreq_set_conservative_governor_param("freq_step", + SET_CONSERVATIVE_GOVERNOR_FREQ_STEP); +#endif +} + +static void colibri_t20_panel_late_resume(struct early_suspend *h) +{ + unsigned i; +#ifdef CONFIG_TEGRA_CONVSERVATIVE_GOV_ON_EARLYSUPSEND + cpufreq_restore_default_governor(); +#endif + for (i = 0; i < num_registered_fb; i++) + fb_blank(registered_fb[i], FB_BLANK_UNBLANK); +} +#endif + +int __init colibri_t20_panel_init(void) +{ + int err; + struct resource __maybe_unused *res; + + /* enable hdmi hotplug gpio for hotplug detection */ + tegra_gpio_enable(colibri_t20_hdmi_hpd); + gpio_request(colibri_t20_hdmi_hpd, "hdmi_hpd"); + gpio_direction_input(colibri_t20_hdmi_hpd); + +#ifdef CONFIG_HAS_EARLYSUSPEND + colibri_t20_panel_early_suspender.suspend = colibri_t20_panel_early_suspend; + colibri_t20_panel_early_suspender.resume = colibri_t20_panel_late_resume; + colibri_t20_panel_early_suspender.level = EARLY_SUSPEND_LEVEL_DISABLE_FB; + register_early_suspend(&colibri_t20_panel_early_suspender); +#endif + +#if defined(CONFIG_TEGRA_NVMAP) + colibri_t20_carveouts[1].base = tegra_carveout_start; +printk("tegra_carveout_start=0x%08x\n", tegra_carveout_start); + colibri_t20_carveouts[1].size = tegra_carveout_size; +printk("tegra_carveout_size=0x%08x\n", tegra_carveout_size); +#endif /* CONFIG_TEGRA_NVMAP */ + +#ifdef CONFIG_TEGRA_GRHOST + err = nvhost_device_register(&tegra_grhost_device); + if (err) + return err; +#endif + + err = platform_add_devices(colibri_t20_gfx_devices, + ARRAY_SIZE(colibri_t20_gfx_devices)); +//return 0; +//<3>tegra_grhost tegra_grhost: missing required platform resources +#if defined(CONFIG_TEGRA_GRHOST) && defined(CONFIG_TEGRA_DC) + res = nvhost_get_resource_byname(&colibri_t20_disp1_device, + IORESOURCE_MEM, "fbmem"); + res->start = tegra_fb_start; + res->end = tegra_fb_start + tegra_fb_size - 1; + + res = nvhost_get_resource_byname(&colibri_t20_disp2_device, + IORESOURCE_MEM, "fbmem"); + res->start = tegra_fb2_start; + res->end = tegra_fb2_start + tegra_fb2_size - 1; +#endif + + /* Copy the bootloader fb to the fb. */ + tegra_move_framebuffer(tegra_fb_start, tegra_bootloader_fb_start, + min(tegra_fb_size, tegra_bootloader_fb_size)); + + /* Copy the bootloader fb to the fb2. */ + tegra_move_framebuffer(tegra_fb2_start, tegra_bootloader_fb_start, + min(tegra_fb2_size, tegra_bootloader_fb_size)); + + +#if defined(CONFIG_TEGRA_GRHOST) && defined(CONFIG_TEGRA_DC) + if (!err) + err = nvhost_device_register(&colibri_t20_disp1_device); + + if (!err) + err = nvhost_device_register(&colibri_t20_disp2_device); +#endif + + return err; +} diff --git a/arch/arm/mach-tegra/board-colibri_t20-pinmux.c b/arch/arm/mach-tegra/board-colibri_t20-pinmux.c new file mode 100644 index 000000000000..94e0dd446a7f --- /dev/null +++ b/arch/arm/mach-tegra/board-colibri_t20-pinmux.c @@ -0,0 +1,286 @@ +/* + * arch/arm/mach-tegra/board-colibri_t20-pinmux.c + * + * Copyright (C) 2011 Toradex, Inc. + * + * 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 "board-colibri_t20.h" +#include "gpio-names.h" + +#define DEFAULT_DRIVE(_name) \ + { \ + .pingroup = TEGRA_DRIVE_PINGROUP_##_name, \ + .hsm = TEGRA_HSM_DISABLE, \ + .schmitt = TEGRA_SCHMITT_ENABLE, \ + .drive = TEGRA_DRIVE_DIV_1, \ + .pull_down = TEGRA_PULL_31, \ + .pull_up = TEGRA_PULL_31, \ + .slew_rising = TEGRA_SLEW_SLOWEST, \ + .slew_falling = TEGRA_SLEW_SLOWEST, \ + } + +#define SET_DRIVE(_name, _hsm, _schmitt, _drive, _pulldn_drive, _pullup_drive, _pulldn_slew, _pullup_slew) \ + { \ + .pingroup = TEGRA_DRIVE_PINGROUP_##_name, \ + .hsm = TEGRA_HSM_##_hsm, \ + .schmitt = TEGRA_SCHMITT_##_schmitt, \ + .drive = TEGRA_DRIVE_##_drive, \ + .pull_down = TEGRA_PULL_##_pulldn_drive, \ + .pull_up = TEGRA_PULL_##_pullup_drive, \ + .slew_rising = TEGRA_SLEW_##_pulldn_slew, \ + .slew_falling = TEGRA_SLEW_##_pullup_slew, \ + } + +static __initdata struct tegra_drive_pingroup_config colibri_t20_drive_pinmux[] = { + DEFAULT_DRIVE(DDC), + DEFAULT_DRIVE(SDIO1), + DEFAULT_DRIVE(VI1), + + SET_DRIVE(AO1, DISABLE, ENABLE, DIV_1, 31, 31, FASTEST, FASTEST), + SET_DRIVE(AT1, DISABLE, ENABLE, DIV_1, 31, 31, FASTEST, FASTEST), + SET_DRIVE(DBG, DISABLE, ENABLE, DIV_1, 31, 31, FASTEST, FASTEST), + SET_DRIVE(VI2, DISABLE, ENABLE, DIV_1, 31, 31, FASTEST, FASTEST), +}; + +static __initdata struct tegra_pingroup_config colibri_t20_pinmux[] = { +/* tegra_pingroup tegra_mux_func tegra_pullupdown tegra_tristate */ + /* nRESET_OUT, GPIO I3, I4 and I6 */ + {TEGRA_PINGROUP_ATA, TEGRA_MUX_GMI, TEGRA_PUPD_PULL_UP, TEGRA_TRI_NORMAL}, + {TEGRA_PINGROUP_ATB, TEGRA_MUX_SDIO4, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL}, + /* nCSx, AD0, AD1, AD2, AD3, AD4, AD5, AD6 and AD7, nWR, nOE, GPIO K0, K1, K2, K3 and K4 */ + {TEGRA_PINGROUP_ATC, TEGRA_MUX_GMI, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL}, + /* AD8, AD9, AD10 and AD11 */ + {TEGRA_PINGROUP_ATD, TEGRA_MUX_GMI, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL}, + /* AD12, AD13, AD14 and AD15 */ + {TEGRA_PINGROUP_ATE, TEGRA_MUX_GMI, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL}, + /* WM9715L XTL_IN */ +//audio sync clk could be either AC97 or PLLA_OUT0 +//SYNC_CLK_DOUBLER_ENB: Enable audio sync clk doubler. +// {TEGRA_PINGROUP_CDEV1, TEGRA_MUX_AUDIO_SYNC, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL}, + {TEGRA_PINGROUP_CDEV1, TEGRA_MUX_PLLA_OUT, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL}, + /* USB3340 REFCLK */ + {TEGRA_PINGROUP_CDEV2, TEGRA_MUX_PLLP_OUT4, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL}, + {TEGRA_PINGROUP_CK32, TEGRA_MUX_NONE, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL}, + {TEGRA_PINGROUP_CRTP, TEGRA_MUX_CRT, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL}, + {TEGRA_PINGROUP_CSUS, TEGRA_MUX_VI_SENSOR_CLK,TEGRA_PUPD_PULL_DOWN, TEGRA_TRI_NORMAL}, + /* GPIO N0, N1, N2, N3 and USBC_DET */ + {TEGRA_PINGROUP_DAP1, TEGRA_MUX_RSVD, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL}, + /* GPIO A2 and A3 */ + {TEGRA_PINGROUP_DAP2, TEGRA_MUX_RSVD, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL}, + {TEGRA_PINGROUP_DAP3, TEGRA_MUX_DAP3, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL}, + /* A13, A14, A15 and A16, GPIO P4, P5, P6 and P7 */ + {TEGRA_PINGROUP_DAP4, TEGRA_MUX_GMI, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL}, + {TEGRA_PINGROUP_DDC, TEGRA_MUX_I2C2, TEGRA_PUPD_PULL_UP, TEGRA_TRI_NORMAL}, + {TEGRA_PINGROUP_DDRC, TEGRA_MUX_NONE, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL}, + /* GPIO D5 */ + {TEGRA_PINGROUP_DTA, TEGRA_MUX_VI, TEGRA_PUPD_PULL_DOWN, TEGRA_TRI_NORMAL}, + /* GPIO T2 and T3 */ + {TEGRA_PINGROUP_DTB, TEGRA_MUX_VI, TEGRA_PUPD_PULL_DOWN, TEGRA_TRI_NORMAL}, + {TEGRA_PINGROUP_DTC, TEGRA_MUX_VI, TEGRA_PUPD_PULL_DOWN, TEGRA_TRI_NORMAL}, + /* GPIO L0, L1, L2, L3, L6 and L7 */ + {TEGRA_PINGROUP_DTD, TEGRA_MUX_VI, TEGRA_PUPD_PULL_DOWN, TEGRA_TRI_NORMAL}, + /* AX88772B V_BUS, WM9715L PENDOWN, GPIO A0 and BB4 */ +// {TEGRA_PINGROUP_DTE, TEGRA_MUX_RSVD, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL}, + {TEGRA_PINGROUP_DTE, TEGRA_MUX_VI, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL}, + /* GPIO BB2 and BB3 */ + {TEGRA_PINGROUP_DTF, TEGRA_MUX_I2C3, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL}, + {TEGRA_PINGROUP_GMA, TEGRA_MUX_SDIO4, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL}, + /* MM_CD */ + {TEGRA_PINGROUP_GMB, TEGRA_MUX_GMI_INT, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL}, + /* BT_TXD, BT_RXD, BT_CTS and BT_RTS, GPIO K7 */ + {TEGRA_PINGROUP_GMC, TEGRA_MUX_UARTD, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL}, + {TEGRA_PINGROUP_GMD, TEGRA_MUX_RSVD, TEGRA_PUPD_PULL_UP, TEGRA_TRI_NORMAL}, + /* GPIO AA4, AA5, AA6 and AA7 */ +#ifndef SDHCI_8BIT + {TEGRA_PINGROUP_GME, TEGRA_MUX_RSVD, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL}, +#else + {TEGRA_PINGROUP_GME, TEGRA_MUX_SDIO4, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL}, +#endif + /* A6, A7, A8, A9, A10, A11 and A12, GPIO U6 */ + {TEGRA_PINGROUP_GPU, TEGRA_MUX_GMI, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL}, + {TEGRA_PINGROUP_GPU7, TEGRA_MUX_RSVD, TEGRA_PUPD_NORMAL, TEGRA_TRI_TRISTATE}, + /* AX88772B RESET_N and EXTWAKEUP_N */ + {TEGRA_PINGROUP_GPV, TEGRA_MUX_RSVD, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL}, + /* HDMI HOTPLUG_DETECT */ + {TEGRA_PINGROUP_HDINT, TEGRA_MUX_HDMI, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL}, + {TEGRA_PINGROUP_I2CP, TEGRA_MUX_I2C, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL}, + /* A0 */ + {TEGRA_PINGROUP_IRRX, TEGRA_MUX_GMI, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL}, + /* A1 */ + {TEGRA_PINGROUP_IRTX, TEGRA_MUX_GMI, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL}, + {TEGRA_PINGROUP_KBCA, TEGRA_MUX_NAND, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL}, + {TEGRA_PINGROUP_KBCB, TEGRA_MUX_NAND, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL}, + {TEGRA_PINGROUP_KBCC, TEGRA_MUX_NAND, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL}, + {TEGRA_PINGROUP_KBCD, TEGRA_MUX_NAND, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL}, + {TEGRA_PINGROUP_KBCE, TEGRA_MUX_NAND, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL}, + {TEGRA_PINGROUP_KBCF, TEGRA_MUX_NAND, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL}, + /* GPIO N4 */ + {TEGRA_PINGROUP_LCSN, TEGRA_MUX_RSVD, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL}, + {TEGRA_PINGROUP_LD0, TEGRA_MUX_DISPLAYA, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL}, + {TEGRA_PINGROUP_LD1, TEGRA_MUX_DISPLAYA, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL}, + {TEGRA_PINGROUP_LD10, TEGRA_MUX_DISPLAYA, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL}, + {TEGRA_PINGROUP_LD11, TEGRA_MUX_DISPLAYA, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL}, + {TEGRA_PINGROUP_LD12, TEGRA_MUX_DISPLAYA, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL}, + {TEGRA_PINGROUP_LD13, TEGRA_MUX_DISPLAYA, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL}, + {TEGRA_PINGROUP_LD14, TEGRA_MUX_DISPLAYA, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL}, + {TEGRA_PINGROUP_LD15, TEGRA_MUX_DISPLAYA, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL}, + {TEGRA_PINGROUP_LD16, TEGRA_MUX_DISPLAYA, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL}, + {TEGRA_PINGROUP_LD17, TEGRA_MUX_DISPLAYA, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL}, + {TEGRA_PINGROUP_LD2, TEGRA_MUX_DISPLAYA, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL}, + {TEGRA_PINGROUP_LD3, TEGRA_MUX_DISPLAYA, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL}, + {TEGRA_PINGROUP_LD4, TEGRA_MUX_DISPLAYA, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL}, + {TEGRA_PINGROUP_LD5, TEGRA_MUX_DISPLAYA, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL}, + {TEGRA_PINGROUP_LD6, TEGRA_MUX_DISPLAYA, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL}, + {TEGRA_PINGROUP_LD7, TEGRA_MUX_DISPLAYA, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL}, + {TEGRA_PINGROUP_LD8, TEGRA_MUX_DISPLAYA, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL}, + {TEGRA_PINGROUP_LD9, TEGRA_MUX_DISPLAYA, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL}, + /* GPIO N6 */ + {TEGRA_PINGROUP_LDC, TEGRA_MUX_RSVD, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL}, + {TEGRA_PINGROUP_LDI, TEGRA_MUX_RSVD, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL}, + {TEGRA_PINGROUP_LHP0, TEGRA_MUX_RSVD, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL}, + {TEGRA_PINGROUP_LHP1, TEGRA_MUX_RSVD, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL}, + {TEGRA_PINGROUP_LHP2, TEGRA_MUX_RSVD, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL}, + {TEGRA_PINGROUP_LHS, TEGRA_MUX_DISPLAYA, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL}, + /* Multiplexed RDnWR */ + {TEGRA_PINGROUP_LM0, TEGRA_MUX_RSVD, TEGRA_PUPD_NORMAL, TEGRA_TRI_TRISTATE}, + {TEGRA_PINGROUP_LM1, TEGRA_MUX_RSVD, TEGRA_PUPD_NORMAL, TEGRA_TRI_TRISTATE}, + {TEGRA_PINGROUP_LPP, TEGRA_MUX_RSVD, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL}, + /* GPIO B2 */ +// {TEGRA_PINGROUP_LPW0, TEGRA_MUX_RSVD, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL}, + {TEGRA_PINGROUP_LPW0, TEGRA_MUX_DISPLAYA, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL}, + {TEGRA_PINGROUP_LPW1, TEGRA_MUX_RSVD, TEGRA_PUPD_NORMAL, TEGRA_TRI_TRISTATE}, +// {TEGRA_PINGROUP_LPW2, TEGRA_MUX_RSVD, TEGRA_PUPD_NORMAL, TEGRA_TRI_TRISTATE}, + {TEGRA_PINGROUP_LPW2, TEGRA_MUX_DISPLAYA, TEGRA_PUPD_NORMAL, TEGRA_TRI_TRISTATE}, + {TEGRA_PINGROUP_LSC0, TEGRA_MUX_DISPLAYA, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL}, + /* Multiplexed nPWE */ +// {TEGRA_PINGROUP_LSC1, TEGRA_MUX_RSVD, TEGRA_PUPD_NORMAL, TEGRA_TRI_TRISTATE}, + {TEGRA_PINGROUP_LSC1, TEGRA_MUX_DISPLAYA, TEGRA_PUPD_NORMAL, TEGRA_TRI_TRISTATE}, + /* GPIO Z4 */ +// {TEGRA_PINGROUP_LSCK, TEGRA_MUX_RSVD, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL}, + {TEGRA_PINGROUP_LSCK, TEGRA_MUX_DISPLAYA, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL}, + /* GPIO N5 */ +// {TEGRA_PINGROUP_LSDA, TEGRA_MUX_RSVD, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL}, + {TEGRA_PINGROUP_LSDA, TEGRA_MUX_DISPLAYA, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL}, + /* GPIO Z2 */ + {TEGRA_PINGROUP_LSDI, TEGRA_MUX_RSVD, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL}, + {TEGRA_PINGROUP_LSPI, TEGRA_MUX_DISPLAYA, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL}, + {TEGRA_PINGROUP_LVP0, TEGRA_MUX_RSVD, TEGRA_PUPD_NORMAL, TEGRA_TRI_TRISTATE}, + {TEGRA_PINGROUP_LVP1, TEGRA_MUX_RSVD, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL}, + {TEGRA_PINGROUP_LVS, TEGRA_MUX_DISPLAYA, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL}, + {TEGRA_PINGROUP_OWC, TEGRA_MUX_OWR, TEGRA_PUPD_PULL_UP, TEGRA_TRI_NORMAL}, +//Todo: Tri-state for now due to 5K/s spurious interrupts. +// {TEGRA_PINGROUP_PMC, TEGRA_MUX_PWR_ON, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL}, + {TEGRA_PINGROUP_PMC, TEGRA_MUX_PWR_ON, TEGRA_PUPD_NORMAL, TEGRA_TRI_TRISTATE}, + {TEGRA_PINGROUP_PMCA, TEGRA_MUX_NONE, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL}, + {TEGRA_PINGROUP_PMCB, TEGRA_MUX_NONE, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL}, + {TEGRA_PINGROUP_PMCC, TEGRA_MUX_NONE, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL}, + {TEGRA_PINGROUP_PMCD, TEGRA_MUX_NONE, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL}, +//Todo: What exactly is PMCE? Why would it need pull-up? +// {TEGRA_PINGROUP_PMCE, TEGRA_MUX_NONE, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL}, + {TEGRA_PINGROUP_PMCE, TEGRA_MUX_NONE, TEGRA_PUPD_PULL_UP, TEGRA_TRI_NORMAL}, + /* Not tri-stating RDnWR, nPWE */ + {TEGRA_PINGROUP_PTA, TEGRA_MUX_RSVD, TEGRA_PUPD_PULL_DOWN, TEGRA_TRI_NORMAL}, + {TEGRA_PINGROUP_RM, TEGRA_MUX_I2C, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL}, + /* PWM3 */ +#ifdef CAMERA_INTERFACE + /* PWM multiplexed with CIF_DD<6> */ + {TEGRA_PINGROUP_SDB, TEGRA_MUX_PWM, TEGRA_PUPD_NORMAL, TEGRA_TRI_TRISTATE}, +#else + {TEGRA_PINGROUP_SDB, TEGRA_MUX_PWM, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL}, +#endif + /* GPIO B6 and B7, PWM0 and PWM1 */ +#ifdef CAMERA_INTERFACE + /* PWM multiplexed with CIF_DD<7> */ + {TEGRA_PINGROUP_SDC, TEGRA_MUX_PWM, TEGRA_PUPD_NORMAL, TEGRA_TRI_TRISTATE}, +#else + {TEGRA_PINGROUP_SDC, TEGRA_MUX_PWM, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL}, +#endif + /* PWM2 */ + {TEGRA_PINGROUP_SDD, TEGRA_MUX_PWM, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL}, + {TEGRA_PINGROUP_SDIO1, TEGRA_MUX_UARTA, TEGRA_PUPD_PULL_UP, TEGRA_TRI_NORMAL}, + + /* SPI4 */ + {TEGRA_PINGROUP_SLXA, TEGRA_MUX_SPI4, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL}, + {TEGRA_PINGROUP_SLXC, TEGRA_MUX_SPI4, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL}, + {TEGRA_PINGROUP_SLXD, TEGRA_MUX_SPI4, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL}, + {TEGRA_PINGROUP_SLXK, TEGRA_MUX_SPI4, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL}, + + {TEGRA_PINGROUP_SPDI, TEGRA_MUX_RSVD, TEGRA_PUPD_NORMAL, TEGRA_TRI_TRISTATE}, + {TEGRA_PINGROUP_SPDO, TEGRA_MUX_RSVD, TEGRA_PUPD_NORMAL, TEGRA_TRI_TRISTATE}, + + /* X0, X1, X2, X3, X4, X5, X6 and X7 */ +// {TEGRA_PINGROUP_SPIA, TEGRA_MUX_RSVD, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL}, + {TEGRA_PINGROUP_SPIA, TEGRA_MUX_GMI, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL}, +// {TEGRA_PINGROUP_SPIB, TEGRA_MUX_RSVD, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL}, + {TEGRA_PINGROUP_SPIB, TEGRA_MUX_GMI, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL}, +// {TEGRA_PINGROUP_SPIC, TEGRA_MUX_RSVD, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL}, + {TEGRA_PINGROUP_SPIC, TEGRA_MUX_GMI, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL}, +// {TEGRA_PINGROUP_SPID, TEGRA_MUX_RSVD, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL}, + {TEGRA_PINGROUP_SPID, TEGRA_MUX_SPI1, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL}, +// {TEGRA_PINGROUP_SPIE, TEGRA_MUX_RSVD, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL}, + {TEGRA_PINGROUP_SPIE, TEGRA_MUX_SPI1, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL}, + {TEGRA_PINGROUP_SPIF, TEGRA_MUX_RSVD, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL}, + + /* USBH_PEN */ +// {TEGRA_PINGROUP_SPIG, TEGRA_MUX_RSVD, TEGRA_PUPD_PULL_UP, TEGRA_TRI_NORMAL}, + {TEGRA_PINGROUP_SPIG, TEGRA_MUX_SPI2_ALT, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL}, + /* USBH_OC */ +// {TEGRA_PINGROUP_SPIH, TEGRA_MUX_RSVD, TEGRA_PUPD_PULL_UP, TEGRA_TRI_NORMAL}, + {TEGRA_PINGROUP_SPIH, TEGRA_MUX_SPI2_ALT, TEGRA_PUPD_PULL_UP, TEGRA_TRI_NORMAL}, + {TEGRA_PINGROUP_UAA, TEGRA_MUX_ULPI, TEGRA_PUPD_PULL_UP, TEGRA_TRI_NORMAL}, + {TEGRA_PINGROUP_UAB, TEGRA_MUX_ULPI, TEGRA_PUPD_PULL_UP, TEGRA_TRI_NORMAL}, + /* WM9715L RESET#, USB3340 RESETB, WM9715L GENIRQ and GPIO V3 */ + {TEGRA_PINGROUP_UAC, TEGRA_MUX_RSVD, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL}, + /* STD_TXD and STD_RXD */ + {TEGRA_PINGROUP_UAD, TEGRA_MUX_IRDA, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL}, + /* A2 and A3 */ + {TEGRA_PINGROUP_UCA, TEGRA_MUX_GMI, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL}, + /* A4 and A5 */ + {TEGRA_PINGROUP_UCB, TEGRA_MUX_GMI, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL}, + {TEGRA_PINGROUP_UDA, TEGRA_MUX_ULPI, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL}, + {TEGRA_PINGROUP_XM2C, TEGRA_MUX_NONE, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL}, + {TEGRA_PINGROUP_XM2D, TEGRA_MUX_NONE, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL}, +}; + +#if 0 +/* 32-bit wide data and 28-bit wide address bus, more chip selects */ +static __initdata struct tegra_pingroup_config colibri_t20_widebus_pinmux[] = { + /* D28, D29, D30 and D31 */ + {TEGRA_PINGROUP_DAP1, TEGRA_MUX_GMI, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL}, + /* AD20, AD21, AD22 and AD23 */ + {TEGRA_PINGROUP_GMA, TEGRA_MUX_GMI, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL}, + /* AD16, AD17, AD18 and AD19 */ + {TEGRA_PINGROUP_GMC, TEGRA_MUX_GMI, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL}, + /* nCS0 and nCS1 */ + {TEGRA_PINGROUP_GMD, TEGRA_MUX_GMI, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL}, +#ifndef SDHCI_8BIT + /* AD24, AD25, AD26 and AD27 */ + {TEGRA_PINGROUP_GME, TEGRA_MUX_GMI, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL}, +#endif +}; +#endif + +int __init colibri_t20_pinmux_init(void) +{ + tegra_pinmux_config_table(colibri_t20_pinmux, ARRAY_SIZE(colibri_t20_pinmux)); + tegra_drive_pinmux_config_table(colibri_t20_drive_pinmux, + ARRAY_SIZE(colibri_t20_drive_pinmux)); + + return 0; +} diff --git a/arch/arm/mach-tegra/board-colibri_t20-power.c b/arch/arm/mach-tegra/board-colibri_t20-power.c new file mode 100644 index 000000000000..e5c1d9bf5716 --- /dev/null +++ b/arch/arm/mach-tegra/board-colibri_t20-power.c @@ -0,0 +1,279 @@ +/* + * Copyright (C) 2011 Toradex, Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * 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. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + * 02111-1307, USA + */ + +#include +#include +#include +#include +// +#include +// +#include +#include +// +#include +// + +#include +#include + +#include + +#include "gpio-names.h" +#include "fuse.h" +#include "pm.h" +#include "wakeups-t2.h" +#include "board.h" +#include "board-colibri_t20.h" + +#define PMC_CTRL 0x0 +#define PMC_CTRL_INTR_LOW (1 << 17) + +static struct regulator_consumer_supply tps658621_sm0_supply[] = { + REGULATOR_SUPPLY("vdd_core", NULL), +}; + +static struct regulator_consumer_supply tps658621_sm1_supply[] = { + REGULATOR_SUPPLY("vdd_cpu", NULL), +}; + +static struct regulator_consumer_supply tps658621_sm2_supply[] = { + REGULATOR_SUPPLY("vdd_sm2", NULL), +}; + +static struct regulator_consumer_supply tps658621_ldo0_supply[] = { + REGULATOR_SUPPLY("vdd_ldo0", NULL), + REGULATOR_SUPPLY("p_cam_avdd", NULL), +}; + +static struct regulator_consumer_supply tps658621_ldo1_supply[] = { + REGULATOR_SUPPLY("vdd_ldo1", NULL), + REGULATOR_SUPPLY("avdd_pll", NULL), +}; + +static struct regulator_consumer_supply tps658621_ldo2_supply[] = { + REGULATOR_SUPPLY("vdd_ldo2", NULL), + REGULATOR_SUPPLY("vdd_rtc", NULL), + REGULATOR_SUPPLY("vdd_aon", NULL), +}; + +static struct regulator_consumer_supply tps658621_ldo3_supply[] = { + /* unused */ + REGULATOR_SUPPLY("vdd_ldo3", NULL), + REGULATOR_SUPPLY("avdd_lvds", NULL), +}; + +static struct regulator_consumer_supply tps658621_ldo4_supply[] = { + REGULATOR_SUPPLY("vdd_ldo4", NULL), + REGULATOR_SUPPLY("avdd_osc", NULL), + REGULATOR_SUPPLY("vddio_sys", "panjit_touch"), +}; + +static struct regulator_consumer_supply tps658621_ldo5_supply[] = { + REGULATOR_SUPPLY("vdd_ldo5", NULL), + REGULATOR_SUPPLY("avdd_usb", NULL), + REGULATOR_SUPPLY("avdd_usb_pll", NULL), +// REGULATOR_SUPPLY("vcore_mmc", "sdhci-tegra.1"), + REGULATOR_SUPPLY("vmmc", "sdhci-tegra.3"), + /* fuse via separate GPIO FET (FUSE_ENABLE_N) */ + REGULATOR_SUPPLY("vdd_fuse", NULL), +}; + +static struct regulator_consumer_supply tps658621_ldo6_supply[] = { + /* Off after boot, needs to be explicitly turned on! */ + REGULATOR_SUPPLY("vdd_ldo6", NULL), + REGULATOR_SUPPLY("avdd_vdac", NULL), +}; + +static struct regulator_consumer_supply tps658621_ldo7_supply[] = { + REGULATOR_SUPPLY("vdd_ldo7", NULL), + REGULATOR_SUPPLY("avdd_hdmi", NULL), +}; + +static struct regulator_consumer_supply tps658621_ldo8_supply[] = { + REGULATOR_SUPPLY("vdd_ldo8", NULL), + REGULATOR_SUPPLY("avdd_hdmi_pll", NULL), +}; + +static struct regulator_consumer_supply tps658621_ldo9_supply[] = { + REGULATOR_SUPPLY("vdd_ldo9", NULL), + REGULATOR_SUPPLY("avdd_2v85", NULL), + REGULATOR_SUPPLY("vdd_ddr_rx", NULL), +// REGULATOR_SUPPLY("avdd_amp", NULL), +}; + +static struct tps6586x_settings sm0_config = { + .sm_pwm_mode = PWM_DEFAULT_VALUE, + .slew_rate = SLEW_RATE_3520UV_PER_SEC, +}; + +static struct tps6586x_settings sm1_config = { + /* + * Current TPS6586x is known for having a voltage glitch if current load + * changes from low to high in auto PWM/PFM mode for CPU's Vdd line. + */ + .sm_pwm_mode = PWM_ONLY, + .slew_rate = SLEW_RATE_3520UV_PER_SEC, +}; + +#define REGULATOR_INIT(_id, _minmv, _maxmv, on, config) \ + { \ + .constraints = { \ + .min_uV = (_minmv)*1000, \ + .max_uV = (_maxmv)*1000, \ + .valid_modes_mask = (REGULATOR_MODE_NORMAL | \ + REGULATOR_MODE_STANDBY), \ + .valid_ops_mask = (REGULATOR_CHANGE_MODE | \ + REGULATOR_CHANGE_STATUS | \ + REGULATOR_CHANGE_VOLTAGE), \ + .always_on = on, \ + .apply_uV = 1, \ + }, \ + .num_consumer_supplies = ARRAY_SIZE(tps658621_##_id##_supply),\ + .consumer_supplies = tps658621_##_id##_supply, \ + .driver_data = config, \ + } + +#define ON 1 +#define OFF 0 + +static struct regulator_init_data sm0_data = REGULATOR_INIT(sm0, 725, 1500, ON, &sm0_config); +static struct regulator_init_data sm1_data = REGULATOR_INIT(sm1, 725, 1500, ON, &sm1_config); +static struct regulator_init_data sm2_data = REGULATOR_INIT(sm2, 1700, 2475, ON, NULL); +static struct regulator_init_data ldo0_data = REGULATOR_INIT(ldo0, 1200, 3300, OFF, NULL); +static struct regulator_init_data ldo1_data = REGULATOR_INIT(ldo1, 725, 1500, ON, NULL); +static struct regulator_init_data ldo2_data = REGULATOR_INIT(ldo2, 725, 1500, OFF, NULL); +static struct regulator_init_data ldo3_data = REGULATOR_INIT(ldo3, 1250, 3300, OFF, NULL); +static struct regulator_init_data ldo4_data = REGULATOR_INIT(ldo4, 1700, 2475, ON, NULL); +static struct regulator_init_data ldo5_data = REGULATOR_INIT(ldo5, 1250, 3300, ON, NULL); +static struct regulator_init_data ldo6_data = REGULATOR_INIT(ldo6, 1250, 3300, OFF, NULL); +static struct regulator_init_data ldo7_data = REGULATOR_INIT(ldo7, 1250, 3300, OFF, NULL); +static struct regulator_init_data ldo8_data = REGULATOR_INIT(ldo8, 1250, 3300, OFF, NULL); +static struct regulator_init_data ldo9_data = REGULATOR_INIT(ldo9, 1250, 3300, OFF, NULL); + +static struct tps6586x_rtc_platform_data rtc_data = { + .irq = TEGRA_NR_IRQS + TPS6586X_INT_RTC_ALM1, + .start = { + .year = 2009, + .month = 1, + .day = 1, + }, + .cl_sel = TPS6586X_RTC_CL_SEL_1_5PF /* use lowest (external 20pF cap) */ +}; + +#define TPS_REG(_id, _data) \ + { \ + .id = TPS6586X_ID_##_id, \ + .name = "tps6586x-regulator", \ + .platform_data = _data, \ + } + +static struct tps6586x_subdev_info tps_devs[] = { + TPS_REG(SM_0, &sm0_data), + TPS_REG(SM_1, &sm1_data), + TPS_REG(SM_2, &sm2_data), + TPS_REG(LDO_0, &ldo0_data), + TPS_REG(LDO_1, &ldo1_data), + TPS_REG(LDO_2, &ldo2_data), + TPS_REG(LDO_3, &ldo3_data), + TPS_REG(LDO_4, &ldo4_data), + TPS_REG(LDO_5, &ldo5_data), + TPS_REG(LDO_6, &ldo6_data), + TPS_REG(LDO_7, &ldo7_data), + TPS_REG(LDO_8, &ldo8_data), + TPS_REG(LDO_9, &ldo9_data), + { + .id = 0, + .name = "tps6586x-rtc", + .platform_data = &rtc_data, + }, +}; + +static struct tps6586x_platform_data tps_platform = { + .irq_base = TPS6586X_INT_BASE, + .num_subdevs = ARRAY_SIZE(tps_devs), + .subdevs = tps_devs, + .gpio_base = TPS6586X_GPIO_BASE, +}; + +static struct i2c_board_info __initdata colibri_t20_regulators[] = { + { + I2C_BOARD_INFO("tps6586x", 0x34), + .irq = INT_EXTERNAL_PMU, + .platform_data = &tps_platform, + }, + { + /* LM95245 temperature sensor on PWR_I2C_SCL/SDA */ + I2C_BOARD_INFO("lm95241", 0x4c), + .type = "lm95241", + }, +}; + +static void colibri_t20_board_suspend(int lp_state, enum suspend_stage stg) +{ + if ((lp_state == TEGRA_SUSPEND_LP1) && (stg == TEGRA_SUSPEND_BEFORE_CPU)) + tegra_console_uart_suspend(); +} + +static void colibri_t20_board_resume(int lp_state, enum resume_stage stg) +{ + if ((lp_state == TEGRA_SUSPEND_LP1) && (stg == TEGRA_RESUME_AFTER_CPU)) + tegra_console_uart_resume(); +} + +static struct tegra_suspend_platform_data colibri_t20_suspend_data = { + /* + * Check power on time and crystal oscillator start time + * for appropriate settings. + */ + .cpu_timer = 2000, + .cpu_off_timer = 100, + .suspend_mode = TEGRA_SUSPEND_LP0, + .core_timer = 0x7e7e, + .core_off_timer = 0xf, + .corereq_high = false, + .sysclkreq_high = true, + .board_suspend = colibri_t20_board_suspend, + .board_resume = colibri_t20_board_resume, +}; + +int __init colibri_t20_regulator_init(void) +{ + void __iomem *pmc = IO_ADDRESS(TEGRA_PMC_BASE); + void __iomem *chip_id = IO_ADDRESS(TEGRA_APB_MISC_BASE) + 0x804; + u32 pmc_ctrl; + u32 minor; + + minor = (readl(chip_id) >> 16) & 0xf; + /* A03 (but not A03p) chips do not support LP0 */ + if (minor == 3 && !(tegra_spare_fuse(18) || tegra_spare_fuse(19))) + colibri_t20_suspend_data.suspend_mode = TEGRA_SUSPEND_LP1; + + /* configure the power management controller to trigger PMU + * interrupts when low */ + pmc_ctrl = readl(pmc + PMC_CTRL); + writel(pmc_ctrl | PMC_CTRL_INTR_LOW, pmc + PMC_CTRL); + + i2c_register_board_info(4, colibri_t20_regulators, ARRAY_SIZE(colibri_t20_regulators)); + +// regulator_has_full_constraints(); + + tegra_init_suspend(&colibri_t20_suspend_data); + + return 0; +} diff --git a/arch/arm/mach-tegra/board-colibri_t20.c b/arch/arm/mach-tegra/board-colibri_t20.c new file mode 100644 index 000000000000..2caafbbad76e --- /dev/null +++ b/arch/arm/mach-tegra/board-colibri_t20.c @@ -0,0 +1,977 @@ +/* + * arch/arm/mach-tegra/board-colibri_t20.c + * + * Copyright (C) 2011 Toradex, Inc. + * + * 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 +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "board-colibri_t20.h" +#include "board.h" +#include "clock.h" +#include "devices.h" +#include "gpio-names.h" +//move to board-colibri_t20-power.c? +#include "pm.h" + +#ifdef CONFIG_TEGRA_OSC_CRYSTAL_FREQ_12MHZ +#define OSC_CTL_FREQ 12000000 +#else +#ifdef CONFIG_TEGRA_OSC_CRYSTAL_FREQ_13MHZ +#define OSC_CTL_FREQ 13000000 +#else +#error choose either TEGRA_OSC_CRYSTAL_FREQ_12MHZ or \ +TEGRA_OSC_CRYSTAL_FREQ_13MHZ +#endif +#endif + +/* ADC */ + +static struct wm97xx_batt_pdata colibri_t20_adc_pdata = { + .batt_aux = WM97XX_AUX_ID1, /* AD0 - ANALOG_IN0 */ + .temp_aux = WM97XX_AUX_ID2, /* AD1 - ANALOG_IN1 */ + .charge_gpio = -1, + .batt_div = 1, + .batt_mult = 1, + .temp_div = 1, + .temp_mult = 1, + .batt_name = "colibri_t20-analog_inputs", +}; + +static struct wm97xx_pdata colibri_t20_wm97xx_pdata = { + .batt_pdata = &colibri_t20_adc_pdata, +}; + +/* Audio */ + +static struct platform_device colibri_t20_audio_device = { + .name = "colibri_t20-snd-wm9715l", + .id = 0, +// .dev = { +// .platform_data = &colibri_t20_audio_pdata, +// }, +}; + +#ifdef CAMERA_INTERFACE +/* Camera */ +static struct platform_device tegra_camera = { + .name = "tegra_camera", + .id = -1, +}; +#endif /* CAMERA_INTERFACE */ + +/* Clock */ +static __initdata struct tegra_clk_init_table colibri_t20_clk_init_table[] = { + /* name parent rate enabled */ +#if 1 + {"blink", "clk_32k", 32768, false}, + /* SMSC3340 REFCLK 24 MHz */ + {"pll_p_out4", "pll_p", 24000000, true}, + {"pwm", "clk_32k", 32768, false}, + {"i2s1", "pll_a_out0", 0, false}, + {"i2s2", "pll_a_out0", 0, false}, + {"spdif_out", "pll_a_out0", 0, false}, + +//required otherwise getting disabled by "Disabling clocks left on by bootloader" stage + {"uarta", "pll_p", 216000000, true}, + +//required otherwise uses pll_p_out4 as parent and changing its rate to 72 MHz + {"sclk", "pll_p_out3", 108000000, true }, + + {"ac97", "pll_a_out0", 24576000, true}, + /* WM9715L XTL_IN 24.576 MHz */ +//[ 0.372722] Unable to set parent pll_a_out0 of clock cdev1: -38 +// {"cdev1", "pll_a_out0", 24576000, true}, +// {"pll_a_out0", "pll_a", 24576000, true}, + + {NULL, NULL, 0, 0}, +#else + {"2d", "pll_c", 300000000, true}, + {"3d", "pll_c", 300000000, true}, + {"ac97", "pll_a_out0", 24576000, true}, + /* afi ? */ + {"audio", "pll_a_out0", 24576000, true}, + {"audio_2x", "audio", 49152000, false}, + /* bit stream engine for audio applications */ + {"bsea", "clk_m", OSC_CTL_FREQ, false}, + /* encryption/security ? */ + {"bsev", "clk_m", OSC_CTL_FREQ, false}, + {"clk_32k", NULL, 32768, true}, + {"clk_d", "clk_m", OSC_CTL_FREQ*2, true}, + {"clk_dev1", NULL, 26000000, true}, + {"clk_m", NULL, OSC_CTL_FREQ, true}, + {"csi", "pll_p_out3", 72000000, false}, + /* coresight debug registers */ + {"csite", "pll_p", 144000000, true}, + /* required for vi_sensor ? */ + {"csus", "clk_m", OSC_CTL_FREQ, true}, + /* Zoran TV encoder */ + {"cve", "clk_m", OSC_CTL_FREQ, false}, + {"disp1", "pll_p", 216000000, true}, + {"disp2", "clk_m", OSC_CTL_FREQ, true}, + {"dsi", "pll_d", 594000000, false}, + /* dynamic voltage controller module */ + {"dvc", "clk_m", 3000000, false}, + {"dvc_i2c", "pll_p_out3", 72000000, true}, + /* video encoder pre-processor */ + {"epp", "pll_m", 111000000, true}, + {"hclk", "sclk", 240000000, true}, + {"hdmi", "clk_m", OSC_CTL_FREQ, false}, + {"host1x", "pll_p", 166000000, true}, + {"i2c1", "clk_m", 3000000, false}, + {"i2c1_i2c", "pll_p_out3", 72000000, true}, + {"i2c2", "clk_m", 3000000, false}, + {"i2c2_i2c", "pll_p_out3", 72000000, true}, + {"i2c3", "clk_m", 3000000, false}, + {"i2c3_i2c", "pll_p_out3", 72000000, true}, + {"i2s1", "pll_a_out0", 11289600, true}, + {"i2s2", "clk_m", 11289600, false}, + {"ide", "clk_m", OSC_CTL_FREQ, false}, + /* image signal processor */ + {"isp", "clk_m", OSC_CTL_FREQ, true}, + {"kbc", "clk_32k", 32768, true}, + /* ? */ + {"la", "clk_m", OSC_CTL_FREQ, false}, + {"mipi", "clk_m", OSC_CTL_FREQ, false}, + /* video encoder */ + {"mpe", "pll_m", 111000000, true}, + {"ndflash", "pll_p", 108000000, true}, +// {"ndflash", "pll_p", 144000000, true}, +// {"ndflash", "pll_c", 150000000, true}, +// {"ndflash", "pll_m", 160333333, true}, +// {"ndflash", "clk_m", 162500000, true}, + {"nor", "pll_p", 86500000, true}, + /* one wire controller */ + {"owr", "clk_m", OSC_CTL_FREQ, false}, + {"pclk", "hclk", 120000000, true}, + {"pll_a", "pll_p_out1", 73728000, true}, + /* WM9715L XTL_IN 24.576 MHz */ + {"pll_a_out0", "pll_a", 24576000, true}, + {"pll_c", "clk_m", 600000000, true}, + {"pll_c_out1", "pll_c", 240000000, true}, + {"pll_d", "clk_m", 594000000, false}, + {"pll_d_out0", "pll_d", 297000000, false}, + {"pll_m", "clk_m", 721500000, true}, + {"pll_p", "clk_m", 216000000, true}, + {"pll_p_out1", "pll_p", 28800000, true}, + {"pll_p_out2", "pll_p", 48000000, true}, + {"pll_p_out3", "pll_p", 72000000, true}, + /* SMSC3340 REFCLK 24 MHz */ + {"pll_p_out4", "pll_p", 24000000, true}, + {"pll_s", "clk_32k", 32768, false}, + {"pll_u", "clk_m", OSC_CTL_FREQ*40,true}, + {"pwm", "clk_32k", 32768, false}, + {"rtc", "clk_32k", 32768, true}, + {"sbc1", "clk_m", OSC_CTL_FREQ, false}, + {"sbc2", "clk_m", OSC_CTL_FREQ, false}, + {"sbc3", "clk_m", OSC_CTL_FREQ, false}, + {"sbc4", "clk_m", OSC_CTL_FREQ, false}, + {"sclk", "pll_c_out1", 240000000, true}, + {"sdmmc1", "pll_p", 48000000, false}, + {"sdmmc2", "pll_p", 48000000, false}, + {"sdmmc3", "pll_p", 48000000, false}, + {"sdmmc4", "pll_p", 48000000, false}, + {"spdif_in", "pll_m", 22579000, true}, + {"spdif_out", "pll_a_out0", 5644800, true}, + {"spi", "clk_m", OSC_CTL_FREQ, false}, + {"timer", "clk_m", OSC_CTL_FREQ, true}, + {"tvdac", "clk_m", OSC_CTL_FREQ, true}, + {"tvo", "clk_m", OSC_CTL_FREQ, false}, + /* three-wire controller */ + {"twc", "clk_m", OSC_CTL_FREQ, false}, + {"uarta", "pll_p", 216000000, true}, + {"uartb", "clk_m", OSC_CTL_FREQ, false}, + {"uartc", "pll_p", 216000000, false}, + {"uartd", "clk_m", OSC_CTL_FREQ, false}, + {"uarte", "clk_m", OSC_CTL_FREQ, false}, + {"usb2", "clk_m", OSC_CTL_FREQ, true}, + {"usb3", "clk_m", OSC_CTL_FREQ, true}, + {"usbd", "clk_m", OSC_CTL_FREQ, false}, + /* vector co-processor (vcp) */ + /* video decoder engine */ + {"vde", "pll_c", 240000000, false}, + {"vfir", "clk_m", OSC_CTL_FREQ, false}, + /* video input block */ + {"vi", "pll_m", 111000000, true}, + /* CIF_MCLK 27 MHz */ + {"vi_sensor", "pll_m", 27000000, true}, + /* misc I/O */ + {"xio", "clk_m", OSC_CTL_FREQ, false}, +#endif + {NULL, NULL, 0, 0}, +}; + +/* GPIO */ + +static struct gpio colibri_t20_gpios[] = { +//conflicts with CAN interrupt on Colibri Evaluation Board and MECS Tellurium xPOD1 CAN + {TEGRA_GPIO_PA0, GPIOF_OUT_INIT_LOW, "SODIMM pin 73"}, + {TEGRA_GPIO_PA2, GPIOF_OUT_INIT_LOW, "SODIMM pin 186"}, + {TEGRA_GPIO_PA3, GPIOF_OUT_INIT_LOW, "SODIMM pin 184"}, + {TEGRA_GPIO_PB2, GPIOF_OUT_INIT_LOW, "SODIMM pin 154"}, +//conflicts with MECS Tellurium xPOD2 SSPCLK2 + {TEGRA_GPIO_PB6, GPIOF_OUT_INIT_LOW, "SODIMM pin 55"}, +//conflicts with MECS Tellurium xPOD2 SSPFRM2 + {TEGRA_GPIO_PB7, GPIOF_OUT_INIT_LOW, "SODIMM pin 63"}, +#ifndef CAMERA_INTERFACE + {TEGRA_GPIO_PD5, GPIOF_OUT_INIT_LOW, "SODI-98, Iris X16-13"}, + {TEGRA_GPIO_PD6, GPIOF_OUT_INIT_LOW, "SODIMM pin 81"}, + {TEGRA_GPIO_PD7, GPIOF_OUT_INIT_LOW, "SODIMM pin 94"}, +#endif + {TEGRA_GPIO_PI3, GPIOF_OUT_INIT_LOW, "SODIMM pin 130"}, + {TEGRA_GPIO_PI4, GPIOF_OUT_INIT_LOW, "SODIMM pin 87"}, + {TEGRA_GPIO_PI6, GPIOF_OUT_INIT_LOW, "SODIMM pin 132"}, + {TEGRA_GPIO_PK0, GPIOF_OUT_INIT_LOW, "SODIMM pin 150"}, + {TEGRA_GPIO_PK1, GPIOF_OUT_INIT_LOW, "SODIMM pin 152"}, +//conflicts with CAN reset on MECS Tellurium xPOD1 CAN + {TEGRA_GPIO_PK4, GPIOF_OUT_INIT_LOW, "SODIMM pin 106"}, +// {TEGRA_GPIO_PK5, GPIOF_OUT_INIT_LOW, "USBC_DET"}, +#ifndef CAMERA_INTERFACE + {TEGRA_GPIO_PL0, GPIOF_OUT_INIT_LOW, "SOD-101, Iris X16-16"}, + {TEGRA_GPIO_PL1, GPIOF_OUT_INIT_LOW, "SOD-103, Iris X16-15"}, +//conflicts with Ethernet interrupt on Protea + {TEGRA_GPIO_PL2, GPIOF_OUT_INIT_LOW, "SODI-79, Iris X16-19"}, + {TEGRA_GPIO_PL3, GPIOF_OUT_INIT_LOW, "SODI-97, Iris X16-17"}, + {TEGRA_GPIO_PL4, GPIOF_OUT_INIT_LOW, "SODIMM pin 67"}, + {TEGRA_GPIO_PL5, GPIOF_OUT_INIT_LOW, "SODIMM pin 59"}, + {TEGRA_GPIO_PL6, GPIOF_OUT_INIT_LOW, "SODI-85, Iris X16-18"}, + {TEGRA_GPIO_PL7, GPIOF_OUT_INIT_LOW, "SODIMM pin 65"}, +#endif + {TEGRA_GPIO_PN0, GPIOF_OUT_INIT_LOW, "SODIMM pin 174"}, + {TEGRA_GPIO_PN1, GPIOF_OUT_INIT_LOW, "SODIMM pin 176"}, + {TEGRA_GPIO_PN2, GPIOF_OUT_INIT_LOW, "SODIMM pin 178"}, + {TEGRA_GPIO_PN3, GPIOF_OUT_INIT_LOW, "SODIMM pin 180"}, + {TEGRA_GPIO_PN4, GPIOF_OUT_INIT_LOW, "SODIMM pin 160"}, + {TEGRA_GPIO_PN5, GPIOF_OUT_INIT_LOW, "SODIMM pin 158"}, + {TEGRA_GPIO_PN6, GPIOF_OUT_INIT_LOW, "SODIMM pin 162"}, +//conflicts with ADDRESS13 + {TEGRA_GPIO_PP4, GPIOF_OUT_INIT_LOW, "SODIMM pin 120"}, +//conflicts with ADDRESS14 + {TEGRA_GPIO_PP5, GPIOF_OUT_INIT_LOW, "SODIMM pin 122"}, +//conflicts with ADDRESS15 + {TEGRA_GPIO_PP6, GPIOF_OUT_INIT_LOW, "SODIMM pin 124"}, + {TEGRA_GPIO_PP7, GPIOF_OUT_INIT_LOW, "SODIMM pin 188"}, +#ifndef CAMERA_INTERFACE + {TEGRA_GPIO_PT0, GPIOF_OUT_INIT_LOW, "SODIMM pin 96"}, + {TEGRA_GPIO_PT1, GPIOF_OUT_INIT_LOW, "SODIMM pin 75"}, + {TEGRA_GPIO_PT2, GPIOF_OUT_INIT_LOW, "SODIMM pin 69"}, + {TEGRA_GPIO_PT3, GPIOF_OUT_INIT_LOW, "SODIMM pin 77"}, +//conflicts with BL_ON +// {TEGRA_GPIO_PT4, GPIOF_OUT_INIT_LOW, "SODIMM pin 71"}, +#endif +//conflicts with ADDRESS12 + {TEGRA_GPIO_PU6, GPIOF_OUT_INIT_LOW, "SODIMM pin 118"}, +//conflicts with power key (WAKE1) + {TEGRA_GPIO_PV3, GPIOF_OUT_INIT_LOW, "SODI-45, Iris X16-20"}, + {TEGRA_GPIO_PX0, GPIOF_OUT_INIT_LOW, "SODIMM pin 142"}, + {TEGRA_GPIO_PX1, GPIOF_OUT_INIT_LOW, "SODIMM pin 140"}, + {TEGRA_GPIO_PX2, GPIOF_OUT_INIT_LOW, "SODIMM pin 138"}, + {TEGRA_GPIO_PX3, GPIOF_OUT_INIT_LOW, "SODIMM pin 136"}, + {TEGRA_GPIO_PX4, GPIOF_OUT_INIT_LOW, "SODIMM pin 134"}, + {TEGRA_GPIO_PX6, GPIOF_OUT_INIT_LOW, "102, I X13 ForceOFF#"}, + {TEGRA_GPIO_PX7, GPIOF_OUT_INIT_LOW, "104, I X14 ForceOFF#"}, + {TEGRA_GPIO_PZ2, GPIOF_OUT_INIT_LOW, "SODIMM pin 156"}, + {TEGRA_GPIO_PZ4, GPIOF_OUT_INIT_LOW, "SODIMM pin 164"}, +#ifndef SDHCI_8BIT + {TEGRA_GPIO_PAA4, GPIOF_OUT_INIT_LOW, "SODIMM pin 166"}, + {TEGRA_GPIO_PAA5, GPIOF_OUT_INIT_LOW, "SODIMM pin 168"}, + {TEGRA_GPIO_PAA6, GPIOF_OUT_INIT_LOW, "SODIMM pin 170"}, + {TEGRA_GPIO_PAA7, GPIOF_OUT_INIT_LOW, "SODIMM pin 172"}, +#endif + {TEGRA_GPIO_PBB2, GPIOF_OUT_INIT_LOW, "SOD-133, Iris X16-14"}, + {TEGRA_GPIO_PBB3, GPIOF_OUT_INIT_LOW, "SODIMM pin 127"}, + {TEGRA_GPIO_PBB4, GPIOF_OUT_INIT_LOW, "SODIMM pin 22"}, + {TEGRA_GPIO_PBB5, GPIOF_OUT_INIT_LOW, "SODIMM pin 24"}, +}; + +static void colibri_t20_gpio_init(void) +{ + int i = 0; + int length = sizeof(colibri_t20_gpios) / sizeof(struct gpio); + int err = 0; + + for (i = 0; i < length; i++) { + err = gpio_request_one(colibri_t20_gpios[i].gpio, + colibri_t20_gpios[i].flags, + colibri_t20_gpios[i].label); + + if (err) { + pr_warning("gpio_request(%s)failed, err = %d", + colibri_t20_gpios[i].label, err); + } else { + tegra_gpio_enable(colibri_t20_gpios[i].gpio); + gpio_export(colibri_t20_gpios[i].gpio, true); + /* gpio direction was always out when exported so + explicitly making it in */ + gpio_direction_input(colibri_t20_gpios[i].gpio); + } + } +} + +/* I2C*/ + +/* GEN1_I2C: I2C_SDA/SCL on SODIMM pin 194/196 (e.g. RTC on carrier board) */ +static struct i2c_board_info colibri_t20_i2c_bus1_board_info[] = { + { + /* M41T0M6 real time clock on Iris carrier board */ + I2C_BOARD_INFO("rtc-ds1307", 0x68), + .type = "m41t00", + }, +#if 0 +//#ifdef CAMERA_INTERFACE + { + I2C_BOARD_INFO("adv7180", 0x21), + }, + { + I2C_BOARD_INFO("mt9v111", 0x5c), + .platform_data = (void *)&camera_mt9v111_data, + }, +#endif /* CAMERA_INTERFACE */ +}; + +static struct tegra_i2c_platform_data colibri_t20_i2c1_platform_data = { + .adapter_nr = 0, + .bus_count = 1, + .bus_clk_rate = {400000, 0}, + .slave_addr = 0x00FC, + .scl_gpio = {TEGRA_GPIO_PC4, 0}, /* I2C_SDA */ + .sda_gpio = {TEGRA_GPIO_PC5, 0}, /* I2C_SCL */ + .arb_recovery = arb_lost_recovery, +}; + +static const struct tegra_pingroup_config i2c2_ddc = { + .pingroup = TEGRA_PINGROUP_DDC, + .func = TEGRA_MUX_I2C2, +}; + +/* GEN2_I2C: SODIMM pin 93/99 */ +static const struct tegra_pingroup_config i2c2_gen2 = { + .pingroup = TEGRA_PINGROUP_PTA, + .func = TEGRA_MUX_I2C2, +}; + +static struct tegra_i2c_platform_data colibri_t20_i2c2_platform_data = { + .adapter_nr = 1, + .bus_count = 2, + .bus_clk_rate = {10000, 10000}, + .bus_mux = {&i2c2_ddc, &i2c2_gen2}, + .bus_mux_len = {1, 1}, + .slave_addr = 0x00FC, + .scl_gpio = {0, TEGRA_GPIO_PT5}, + .sda_gpio = {0, TEGRA_GPIO_PT6}, + .arb_recovery = arb_lost_recovery, +}; + +/* CAM_I2C SODIMM pin 127/133 */ +static struct tegra_i2c_platform_data colibri_t20_i2c3_platform_data = { + .adapter_nr = 3, + .bus_count = 1, + .bus_clk_rate = {400000, 0}, + .slave_addr = 0x00FC, + .scl_gpio = {TEGRA_GPIO_PBB2, 0}, + .sda_gpio = {TEGRA_GPIO_PBB3, 0}, + .arb_recovery = arb_lost_recovery, +}; + +/* PWR_I2C: power I2C to PMIC and temperature sensor */ +static struct tegra_i2c_platform_data colibri_t20_dvc_platform_data = { + .adapter_nr = 4, + .bus_count = 1, + .bus_clk_rate = {400000, 0}, + .is_dvc = true, + .scl_gpio = {TEGRA_GPIO_PZ6, 0}, + .sda_gpio = {TEGRA_GPIO_PZ7, 0}, + .arb_recovery = arb_lost_recovery, +}; + +static void colibri_t20_i2c_init(void) +{ + tegra_i2c_device1.dev.platform_data = &colibri_t20_i2c1_platform_data; + tegra_i2c_device2.dev.platform_data = &colibri_t20_i2c2_platform_data; + tegra_i2c_device3.dev.platform_data = &colibri_t20_i2c3_platform_data; + tegra_i2c_device4.dev.platform_data = &colibri_t20_dvc_platform_data; + + platform_device_register(&tegra_i2c_device1); + platform_device_register(&tegra_i2c_device2); + platform_device_register(&tegra_i2c_device3); + platform_device_register(&tegra_i2c_device4); + + i2c_register_board_info(0, colibri_t20_i2c_bus1_board_info, ARRAY_SIZE(colibri_t20_i2c_bus1_board_info)); +} + +/* Keys */ + +/* MMC/SD */ + +static struct tegra_sdhci_platform_data colibri_t20_sdhci_platform_data = { + .cd_gpio = TEGRA_GPIO_PC7, /* MM_CD */ +#ifndef SDHCI_8BIT + .is_8bit = 0, +#else + .is_8bit = 1, +#endif + .power_gpio = -1, + .wp_gpio = -1, +}; + +int __init colibri_t20_sdhci_init(void) +{ + tegra_gpio_enable(colibri_t20_sdhci_platform_data.cd_gpio); + + tegra_sdhci_device4.dev.platform_data = + &colibri_t20_sdhci_platform_data; + platform_device_register(&tegra_sdhci_device4); + + return 0; +} + +/* NAND */ + +static struct tegra_nand_chip_parms nand_chip_parms[] = { + /* Micron MT29F4G08ABBDAH4 */ + [0] = { + .vendor_id = 0x2C, + .device_id = 0xAC, + .read_id_fourth_byte = 0x15, + .capacity = 512, + .timing = { + .trp = 12, + .trh = 10, /* tREH */ + .twp = 12, + .twh = 10, + .tcs = 20, /* Max(tCS, tCH, tALS, tALH) */ + .twhr = 80, + .tcr_tar_trr = 20, /* Max(tCR, tAR, tRR) */ + .twb = 100, + .trp_resp = 12, /* tRP */ + .tadl = 70, + }, + }, + /* Micron MT29F4G08ABBEAH4 */ + [1] = { + .vendor_id = 0x2C, + .device_id = 0xAC, + .read_id_fourth_byte = 0x26, + .capacity = 512, + .timing = { + .trp = 15, + .trh = 10, /* tREH */ + .twp = 15, + .twh = 10, + .tcs = 25, /* Max(tCS, tCH, tALS, tALH) */ + .twhr = 80, + .tcr_tar_trr = 20, /* Max(tCR, tAR, tRR) */ + .twb = 100, + .trp_resp = 15, /* tRP */ + .tadl = 100, + }, + }, + /* Micron MT29F8G08ABCBB on Colibri T20 before V1.2 */ + [2] = { + .vendor_id = 0x2C, + .device_id = 0x38, + .read_id_fourth_byte = 0x26, + .capacity = 1024, + .timing = { + /* timing mode 4 */ + .trp = 12, + .trh = 10, /* tREH */ + .twp = 12, + .twh = 10, + .tcs = 20, /* Max(tCS, tCH, tALS, tALH) */ + .twhr = 60, + .tcr_tar_trr = 20, /* Max(tCR, tAR, tRR) */ + .twb = 100, + .trp_resp = 12, /* tRP */ + .tadl = 70, + }, + }, + /* Micron MT29F8G08ADBDAH4 */ + [3] = { + .vendor_id = 0x2C, + .device_id = 0xA3, + .read_id_fourth_byte = 0x15, + .capacity = 1024, + .timing = { + .trp = 12, + .trh = 10, /* tREH */ + .twp = 12, + .twh = 10, + .tcs = 20, /* Max(tCS, tCH, tALS, tALH) */ + .twhr = 80, + .tcr_tar_trr = 20, /* Max(tCR, tAR, tRR) */ + .twb = 100, + .trp_resp = 12, /* tRP */ + .tadl = 70, + }, + }, + /* Micron MT29F8G08ABBCA */ + [4] = { + .vendor_id = 0x2C, + .device_id = 0xA3, + .read_id_fourth_byte = 0x26, + .capacity = 1024, + .timing = { + .trp = 15, + .trh = 10, /* tREH */ + .twp = 15, + .twh = 10, + .tcs = 25, /* Max(tCS, tCH, tALS, tALH) */ + .twhr = 80, + .tcr_tar_trr = 20, /* Max(tCR, tAR, tRR) */ + .twb = 100, + .trp_resp = 15, /* tRP */ + .tadl = 100, + }, + }, +}; + +struct tegra_nand_platform colibri_t20_nand_data = { + .max_chips = 8, + .chip_parms = nand_chip_parms, + .nr_chip_parms = ARRAY_SIZE(nand_chip_parms), + .wp_gpio = TEGRA_GPIO_PS0, +}; + +static struct resource resources_nand[] = { + [0] = { + .start = INT_NANDFLASH, + .end = INT_NANDFLASH, + .flags = IORESOURCE_IRQ, + }, +}; + +static struct platform_device tegra_nand_device = { + .name = "tegra_nand", + .id = -1, + .num_resources = ARRAY_SIZE(resources_nand), + .resource = resources_nand, + .dev = { + .platform_data = &colibri_t20_nand_data, + }, +}; + +/* RTC */ +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), +}; + +/* SPI */ + +static struct spi_board_info tegra_spi_devices[] __initdata = { + { + .bus_num = 3, + .chip_select = 0, + .irq = 0, + .max_speed_hz = 50000000, + .modalias = "spidev", + .mode = SPI_MODE_0, + .platform_data = NULL, + }, +}; + +static void __init colibri_t20_register_spidev(void) +{ + spi_register_board_info(tegra_spi_devices, + ARRAY_SIZE(tegra_spi_devices)); +} + +/* UART */ + +static struct platform_device *colibri_t20_uart_devices[] __initdata = { + &tegra_uarta_device, + &tegra_uartb_device, + &tegra_uartd_device, +}; + +static struct uart_clk_parent uart_parent_clk[] = { +#if 1 + [0] = {.name = "pll_m"}, + [1] = {.name = "pll_p"}, + [2] = {.name = "clk_m"}, +#else + [0] = {.name = "clk_m"}, + [1] = {.name = "pll_m"}, + [2] = {.name = "pll_p"}, +#endif +}; + +static struct tegra_uart_platform_data colibri_t20_uart_pdata; + +static void __init uart_debug_init(void) +{ + unsigned long rate; + struct clk *c; + + /* UARTA is the debug port. */ + pr_info("Selecting UARTA as the debug console\n"); + colibri_t20_uart_devices[0] = &debug_uarta_device; + debug_uart_port_base = ((struct plat_serial8250_port *)( + debug_uarta_device.dev.platform_data))->mapbase; + debug_uart_clk = clk_get_sys("serial8250.0", "uarta"); + + /* Clock enable for the debug channel */ + if (!IS_ERR_OR_NULL(debug_uart_clk)) { + rate = ((struct plat_serial8250_port *)( + debug_uarta_device.dev.platform_data))->uartclk; + pr_info("The debug console clock name is %s\n", + debug_uart_clk->name); + c = tegra_get_clock_by_name("pll_p"); + if (IS_ERR_OR_NULL(c)) + pr_err("Not getting the parent clock pll_p\n"); + else + clk_set_parent(debug_uart_clk, c); + + clk_enable(debug_uart_clk); + clk_set_rate(debug_uart_clk, rate); + } else { + pr_err("Not getting the clock %s for debug console\n", + debug_uart_clk->name); + } +} + +static void __init colibri_t20_uart_init(void) +{ + int i; + struct clk *c; + + for (i = 0; i < ARRAY_SIZE(uart_parent_clk); ++i) { + c = tegra_get_clock_by_name(uart_parent_clk[i].name); + if (IS_ERR_OR_NULL(c)) { + pr_err("Not able to get the clock for %s\n", + uart_parent_clk[i].name); + continue; + } + uart_parent_clk[i].parent_clk = c; + uart_parent_clk[i].fixed_clk_rate = clk_get_rate(c); + } + colibri_t20_uart_pdata.parent_clk_list = uart_parent_clk; + colibri_t20_uart_pdata.parent_clk_count = ARRAY_SIZE(uart_parent_clk); + tegra_uarta_device.dev.platform_data = &colibri_t20_uart_pdata; + tegra_uartb_device.dev.platform_data = &colibri_t20_uart_pdata; + tegra_uartd_device.dev.platform_data = &colibri_t20_uart_pdata; + + /* Register low speed only if it is selected */ + if (!is_tegra_debug_uartport_hs()) + uart_debug_init(); + + platform_add_devices(colibri_t20_uart_devices, + ARRAY_SIZE(colibri_t20_uart_devices)); +} + +/* USB */ + +static struct tegra_utmip_config utmi_phy_config[] = { + [0] = { + .hssync_start_delay = 9, + .idle_wait_delay = 17, + .elastic_limit = 16, + .term_range_adj = 6, + .xcvr_setup = 15, + .xcvr_setup_offset = 0, + .xcvr_use_fuses = 1, + .xcvr_lsfslew = 2, + .xcvr_lsrslew = 2, + }, + [1] = { + .hssync_start_delay = 9, + .idle_wait_delay = 17, + .elastic_limit = 16, + .term_range_adj = 6, + .xcvr_setup = 8, + .xcvr_setup_offset = 0, + .xcvr_use_fuses = 1, + .xcvr_lsfslew = 2, + .xcvr_lsrslew = 2, + }, +}; + +static struct tegra_ulpi_config colibri_t20_ehci2_ulpi_phy_config = { + .clk = "cdev2", + .reset_gpio = TEGRA_GPIO_PV1, /* USB3340 RESETB */ +}; + +static struct tegra_ehci_platform_data colibri_t20_ehci2_ulpi_platform_data = { + .operating_mode = TEGRA_USB_HOST, + .power_down_on_bus_suspend = 1, + .phy_config = &colibri_t20_ehci2_ulpi_phy_config, + .phy_type = TEGRA_USB_PHY_TYPE_LINK_ULPI, +}; + +static struct usb_phy_plat_data tegra_usb_phy_pdata[] = { + [0] = { + .instance = 0, +//[ 4.309032] Failed to register IRQ +//tegra_gpio_enable required? +// .vbus_irq = TEGRA_GPIO_PK5, /* USBC_DET */ + .vbus_gpio = -1, + }, + [1] = { + .instance = 1, + .vbus_gpio = -1, +// .vbus_gpio = TEGRA_GPIO_PBB1, /* ETHERNET_VBUS_GPIO */ + }, + [2] = { + .instance = 2, + .vbus_gpio = TEGRA_GPIO_PW2, /* USBH_PEN */ + .vbus_gpio_inverted = 1, + }, +}; + +static struct tegra_ehci_platform_data tegra_ehci_pdata[] = { + [0] = { + .phy_config = &utmi_phy_config[0], + .operating_mode = TEGRA_USB_HOST, + .power_down_on_bus_suspend = 1, + }, + [1] = { + .phy_config = &colibri_t20_ehci2_ulpi_phy_config, + .operating_mode = TEGRA_USB_HOST, + .power_down_on_bus_suspend = 1, + .phy_type = TEGRA_USB_PHY_TYPE_LINK_ULPI, + }, + [2] = { + .phy_config = &utmi_phy_config[1], + .operating_mode = TEGRA_USB_HOST, + .power_down_on_bus_suspend = 1, + .hotplug = 1, + }, +}; + +static struct tegra_otg_platform_data tegra_otg_pdata = { + .ehci_device = &tegra_ehci1_device, + .ehci_pdata = &tegra_ehci_pdata[0], +}; + +static void colibri_t20_usb_init(void) +{ +//no improvement +// tegra_gpio_enable(TEGRA_GPIO_PK5); +#ifdef CONFIG_USB_SUPPORT + tegra_usb_phy_init(tegra_usb_phy_pdata, ARRAY_SIZE(tegra_usb_phy_pdata)); +#endif + + /* OTG should be the first to be registered + EHCI instance 0: USB1_DP/N -> USBOTG_P/N */ + tegra_otg_device.dev.platform_data = &tegra_otg_pdata; + platform_device_register(&tegra_otg_device); + platform_device_register(&tegra_udc_device); + +// + tegra_ehci2_device.dev.platform_data=&tegra_ehci_pdata[1]; +// + platform_device_register(&tegra_ehci2_device); + + /* EHCI instance 2: USB3_DP/N -> USBH1_P/N */ + tegra_ehci3_device.dev.platform_data=&tegra_ehci_pdata[2]; + platform_device_register(&tegra_ehci3_device); + +#ifdef MECS_TELLURIUM +//SD card multiplexing: pull GPIO_PT2 and GPIO_PBB2 low +//working even without any modifications + { + int gpio_status; + unsigned int i2c_scl = TEGRA_GPIO_PC5; + unsigned int i2c_sda = TEGRA_GPIO_PC4; + unsigned int tellurium_usb_hub_reset = TEGRA_GPIO_PBB3; + + printk("MECS Tellurium USB Hub Initialisation\n"); + + /* configure USB hub reset line as output and pull low into reset */ + gpio_status = gpio_request(tellurium_usb_hub_reset, "USB_HUB_RESET"); + if (gpio_status < 0) + pr_warning("USB_HUB_RESET request GPIO FAILED\n"); + tegra_gpio_enable(tellurium_usb_hub_reset); + gpio_status = gpio_direction_output(tellurium_usb_hub_reset, 0); + if (gpio_status < 0) + pr_warning("USB_HUB_RESET request GPIO DIRECTION FAILED\n"); + + /* configure I2C pins as outputs and pull low */ + tegra_gpio_enable(i2c_scl); + gpio_status = gpio_direction_output(i2c_scl, 0); + if (gpio_status < 0) + pr_warning("I2C_SCL request GPIO DIRECTION FAILED\n"); + tegra_gpio_enable(i2c_sda); + gpio_status = gpio_direction_output(i2c_sda, 0); + if (gpio_status < 0) + pr_warning("I2C_SDA request GPIO DIRECTION FAILED\n"); + + /* pull USB hub out of reset */ + gpio_set_value(tellurium_usb_hub_reset, 1); + + /* release I2C pins again */ + tegra_gpio_disable(i2c_scl); + tegra_gpio_disable(i2c_sda); + } +#endif /* MECS_TELLURIUM */ +} + +static struct platform_device *colibri_t20_devices[] __initdata = { + &tegra_rtc_device, + &tegra_nand_device, + + &tegra_pmu_device, + &tegra_gart_device, + &tegra_aes_device, +#ifdef CONFIG_KEYBOARD_GPIO +// &colibri_t20_keys_device, +#endif + &tegra_wdt_device, + &tegra_avp_device, +#ifdef CAMERA_INTERFACE + &tegra_camera, +#endif + &tegra_ac97_device, + &tegra_spdif_device, + &tegra_das_device, + &spdif_dit_device, +//bluetooth + &tegra_pcm_device, + &colibri_t20_audio_device, + + &tegra_spi_device4, +}; + +static void __init tegra_colibri_t20_init(void) +{ +#if 0 +tegra_clk_init_from_table(colibri_t20_clk_init_table); +colibri_t20_pinmux_init(); +colibri_t20_i2c_init(); +colibri_t20_uart_init(); +tegra_ehci2_device.dev.platform_data += &colibri_t20_ehci2_ulpi_platform_data; +platform_add_devices(colibri_t20_devices, +ARRAY_SIZE(colibri_t20_devices)); +colibri_t20_sdhci_init(); +colibri_t20_regulator_init(); + +//disabled for now: +//regulator +//panel +#else + tegra_clk_init_from_table(colibri_t20_clk_init_table); + colibri_t20_pinmux_init(); + colibri_t20_i2c_init(); + colibri_t20_uart_init(); +// + tegra_ac97_device.dev.platform_data = &colibri_t20_wm97xx_pdata; +// + tegra_ehci2_device.dev.platform_data + = &colibri_t20_ehci2_ulpi_platform_data; + platform_add_devices(colibri_t20_devices, + ARRAY_SIZE(colibri_t20_devices)); + tegra_ram_console_debug_init(); + colibri_t20_sdhci_init(); +//charge +// + colibri_t20_regulator_init(); +// +//charger + +// tegra_das_device.dev.platform_data = &tegra_das_pdata; +// tegra_ac97_device.dev.platform_data = &tegra_audio_pdata; +// tegra_spdif_input_device.name = "spdif"; +// tegra_spdif_input_device.dev.platform_data = &tegra_spdif_audio_pdata; + +#ifdef CONFIG_KEYBOARD_GPIO +//keys +#endif + + colibri_t20_usb_init(); + colibri_t20_panel_init(); +//sensors +//emc + + colibri_t20_gpio_init(); + colibri_t20_register_spidev(); + + tegra_release_bootloader_fb(); +#endif +} + +int __init tegra_colibri_t20_protected_aperture_init(void) +{ + if (!machine_is_colibri_t20()) + return 0; + + tegra_protected_aperture_init(tegra_grhost_aperture); + return 0; +} +late_initcall(tegra_colibri_t20_protected_aperture_init); + +void __init tegra_colibri_t20_reserve(void) +{ + if (memblock_reserve(0x0, 4096) < 0) + pr_warn("Cannot reserve first 4K of memory for safety\n"); + + tegra_reserve(SZ_256M, SZ_8M + SZ_1M, SZ_16M); +} + +MACHINE_START(COLIBRI_T20, "Toradex Colibri T20") + .boot_params = 0x00000100, + .init_early = tegra_init_early, + .init_irq = tegra_init_irq, + .init_machine = tegra_colibri_t20_init, + .map_io = tegra_map_common_io, + .reserve = tegra_colibri_t20_reserve, + .timer = &tegra_timer, +MACHINE_END diff --git a/arch/arm/mach-tegra/board-colibri_t20.h b/arch/arm/mach-tegra/board-colibri_t20.h new file mode 100644 index 000000000000..900be9363702 --- /dev/null +++ b/arch/arm/mach-tegra/board-colibri_t20.h @@ -0,0 +1,49 @@ +/* + * arch/arm/mach-tegra/board-colibri_t20.h + * + * Copyright (C) 2011 Toradex, Inc. + * + * 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. + * + */ + +#ifndef _MACH_TEGRA_BOARD_COLIBRI_T20_H +#define _MACH_TEGRA_BOARD_COLIBRI_T20_H + +#define CONFIG_TEGRA_OSC_CRYSTAL_FREQ_13MHZ + +/* TPS6586X gpios */ +#define TPS6586X_GPIO_BASE TEGRA_NR_GPIOS +#define AVDD_DSI_CSI_ENB_GPIO (TPS6586X_GPIO_BASE + 1) /* gpio2 */ + +/* Interrupt numbers from external peripherals */ +#define TPS6586X_INT_BASE TEGRA_NR_IRQS +#define TPS6586X_INT_END (TPS6586X_INT_BASE + 32) + +/* Uncomment for camera interface support on Colibri Evaluation carrier board */ +#define CAMERA_INTERFACE + +/* Uncomment to use OTG port as host only */ +//#define HOST_ONLY + +/* Uncomment for back light and USB hub support on MECS Tellurium carrier board */ +//#define MECS_TELLURIUM + +/* Uncomment for 8-bit SDHCI on HSMMC controller (requires custom carrier board) */ +//#define SDHCI_8BIT + +/* Run framebuffer in VGA mode */ +#define TEGRA_FB_VGA + +int colibri_t20_panel_init(void); +int colibri_t20_pinmux_init(void); +int colibri_t20_regulator_init(void); + +#endif diff --git a/arch/arm/mach-tegra/common.c b/arch/arm/mach-tegra/common.c index f0c0cb69896f..200604694508 100644 --- a/arch/arm/mach-tegra/common.c +++ b/arch/arm/mach-tegra/common.c @@ -168,7 +168,9 @@ static __initdata struct tegra_clk_init_table common_clk_init_table[] = { { "pll_p_out4", "pll_p", 108000000, false }, { "pll_m", "clk_m", 0, true }, { "pll_m_out1", "pll_m", 120000000, true }, - { "sclk", "pll_c_out1", 40000000, true }, +//[ 0.000000] Failed to set parent pll_c_out1 for sclk (violates clock limit 240000000) +//[ 0.000000] Unable to set parent pll_c_out1 of clock sclk: -22 + { "sclk", "pll_p_out3", 72000000, true }, { "hclk", "sclk", 40000000, true }, { "pclk", "hclk", 40000000, true }, { "mpe", "pll_c", 0, false }, diff --git a/arch/arm/mach-tegra/devices.c b/arch/arm/mach-tegra/devices.c index 202c767550e8..079d18e2339b 100644 --- a/arch/arm/mach-tegra/devices.c +++ b/arch/arm/mach-tegra/devices.c @@ -911,6 +911,31 @@ struct platform_device debug_uarte_device = { #endif #ifdef CONFIG_ARCH_TEGRA_2x_SOC +static struct resource tegra_ac97_resource[] = { + [0] = { + .start = INT_AC97, + .end = INT_AC97, + .flags = IORESOURCE_IRQ + }, + [1] = { + .start = TEGRA_DMA_REQ_SEL_AC97, + .end = TEGRA_DMA_REQ_SEL_AC97, + .flags = IORESOURCE_DMA + }, + [2] = { + .start = TEGRA_AC97_BASE, + .end = TEGRA_AC97_BASE + TEGRA_AC97_SIZE - 1, + .flags = IORESOURCE_MEM + } +}; + +struct platform_device tegra_ac97_device = { + .name = "tegra20-ac97", + .id = -1, + .resource = tegra_ac97_resource, + .num_resources = ARRAY_SIZE(tegra_ac97_resource), +}; + static struct resource i2s_resource1[] = { [0] = { .start = INT_I2S1, diff --git a/arch/arm/mach-tegra/devices.h b/arch/arm/mach-tegra/devices.h index 97a0c53ccfce..8b413d45d9b9 100644 --- a/arch/arm/mach-tegra/devices.h +++ b/arch/arm/mach-tegra/devices.h @@ -74,6 +74,7 @@ extern struct platform_device tegra_udc_device; extern struct platform_device tegra_ehci1_device; extern struct platform_device tegra_ehci2_device; extern struct platform_device tegra_ehci3_device; +extern struct platform_device tegra_ac97_device; extern struct platform_device tegra_i2s_device1; extern struct platform_device tegra_i2s_device2; #ifndef CONFIG_ARCH_TEGRA_2x_SOC diff --git a/arch/arm/mach-tegra/include/mach/ac97.h b/arch/arm/mach-tegra/include/mach/ac97.h new file mode 100644 index 000000000000..a62cb93123a9 --- /dev/null +++ b/arch/arm/mach-tegra/include/mach/ac97.h @@ -0,0 +1,87 @@ +/* + * arch/arm/mach-tegra/include/mach/ac97.h + * + * Copyright (C) 2011 Toradex, Inc. + * + * 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. + * + */ + +#ifndef __ARCH_ARM_MACH_TEGRA_AC97_H +#define __ARCH_ARM_MACH_TEGRA_AC97_H + +#include +#include + +/* Offsets from TEGRA_AC97_BASE */ +#define AC_AC_CTRL_0 0 +#define AC_AC_CMD_0 4 +#define AC_AC_STATUS1_0 8 +/* ... */ +#define AC_AC_FIFO1_SCR_0 0x1c +#define AC_AC_FIFO2_SCR_0 0x2c +/* ... */ +#define AC_AC_FIFO_OUT1_0 0x40 +#define AC_AC_FIFO_IN1_0 0x80 +#define AC_AC_FIFO_OUT2_0 0x140 +#define AC_AC_FIFO_IN2_0 0x180 + +/* AC_AC_CTRL_0 */ +#define AC_AC_CTRL_STM2_EN (1<<16) +#define AC_AC_CTRL_DOUBLE_SAMPLING_EN (1<<11) +#define AC_AC_CTRL_IO_CNTRL_EN (1<<10) +#define AC_AC_CTRL_HSET_DAC_EN (1<<9) +#define AC_AC_CTRL_LINE2_DAC_EN (1<<8) +#define AC_AC_CTRL_PCM_LFE_EN (1<<7) +#define AC_AC_CTRL_PCM_SUR_EN (1<<6) +#define AC_AC_CTRL_PCM_CEN_DAC_EN (1<<5) +#define AC_AC_CTRL_LINE1_DAC_EN (1<<4) +#define AC_AC_CTRL_PCM_DAC_EN (1<<3) +#define AC_AC_CTRL_COLD_RESET (1<<2) +#define AC_AC_CTRL_WARM_RESET (1<<1) +#define AC_AC_CTRL_STM_EN (1<<0) + +/* AC_AC_CMD_0 */ +#define AC_AC_CMD_CMD_ADDR_SHIFT (24) +#define AC_AC_CMD_CMD_ADDR_MASK (0xff< #include #include "fuse.h" +#include "gpio-names.h" #ifdef CONFIG_ARCH_TEGRA_2x_SOC @@ -718,9 +719,9 @@ static struct tegra_utmip_config utmip_default[] = { }; struct usb_phy_plat_data usb_phy_data[] = { - { 0, 0, -1, NULL}, - { 0, 0, -1, NULL}, - { 0, 0, -1, NULL}, + { 0, 0, -1, (int)NULL}, + { 0, 0, -1, (int)NULL}, + { 0, 0, -1, (int)NULL}, }; static int utmip_pad_open(struct tegra_usb_phy *phy) @@ -908,6 +909,7 @@ static void vbus_enable(struct tegra_usb_phy *phy) #ifdef CONFIG_ARCH_TEGRA_2x_SOC int gpio_status; int gpio = usb_phy_data[phy->instance].vbus_gpio; + int gpio_inverted = usb_phy_data[phy->instance].vbus_gpio_inverted; if (gpio == -1) return; @@ -919,13 +921,13 @@ static void vbus_enable(struct tegra_usb_phy *phy) return; } if (gpio < TEGRA_NR_GPIOS) tegra_gpio_enable(gpio); - gpio_status = gpio_direction_output(gpio, 1); + gpio_status = gpio_direction_output(gpio, !gpio_inverted); if (gpio_status < 0) { printk("VBUS_USB request GPIO DIRECTION FAILED \n"); WARN_ON(1); return; } - gpio_set_value_cansleep(gpio, 1); + gpio_set_value_cansleep(gpio, !gpio_inverted); #else if (phy->reg_vbus) regulator_enable(phy->reg_vbus); @@ -936,11 +938,12 @@ static void vbus_disable(struct tegra_usb_phy *phy) { #ifdef CONFIG_ARCH_TEGRA_2x_SOC int gpio = usb_phy_data[phy->instance].vbus_gpio; + int gpio_inverted = usb_phy_data[phy->instance].vbus_gpio_inverted; if (gpio == -1) return; - gpio_set_value_cansleep(gpio, 0); + gpio_set_value_cansleep(gpio, gpio_inverted); gpio_free(gpio); #else if (phy->reg_vbus) @@ -2002,6 +2005,25 @@ static int ulpi_phy_power_on(struct tegra_usb_phy *phy, bool is_dpd) val |= USB_PORTSC1_WKOC | USB_PORTSC1_WKDS | USB_PORTSC1_WKCN; writel(val, base + USB_PORTSC1); +//should really all be done in some board specific enable_vbus() +#ifdef CONFIG_MACH_COLIBRI_T20 + /* Fix Ethernet detection faults */ + mdelay(100); + +#define ETHERNET_VBUS_GPIO TEGRA_GPIO_PBB1 +#define ETHERNET_RESET_GPIO TEGRA_GPIO_PV4 + + tegra_gpio_enable(ETHERNET_VBUS_GPIO); + gpio_request(ETHERNET_VBUS_GPIO, "ethernet_vbus"); + gpio_direction_output(ETHERNET_VBUS_GPIO, 1); + gpio_export(ETHERNET_VBUS_GPIO, false); + + tegra_gpio_enable(ETHERNET_RESET_GPIO); + gpio_request(ETHERNET_RESET_GPIO, "ethernet_reset"); + gpio_direction_output(ETHERNET_RESET_GPIO, 1); + gpio_export(ETHERNET_RESET_GPIO, false); +#endif /* CONFIG_MACH_COLIBRI_T20 */ + return 0; } @@ -3182,6 +3204,7 @@ int __init tegra_usb_phy_init(struct usb_phy_plat_data *pdata, int size) usb_phy_data[pdata->instance].instance = pdata->instance; usb_phy_data[pdata->instance].vbus_irq = pdata->vbus_irq; usb_phy_data[pdata->instance].vbus_gpio = pdata->vbus_gpio; + usb_phy_data[pdata->instance].vbus_gpio_inverted = pdata->vbus_gpio_inverted; usb_phy_data[pdata->instance].vbus_reg_supply = pdata->vbus_reg_supply; } } -- cgit v1.2.3