diff options
Diffstat (limited to 'arch/arm/mach-tegra/board-colibri_t20.c')
-rw-r--r-- | arch/arm/mach-tegra/board-colibri_t20.c | 977 |
1 files changed, 977 insertions, 0 deletions
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 <asm/mach-types.h> +#include <asm/mach/arch.h> +#include <asm/setup.h> + +#include <linux/clk.h> +#include <linux/dma-mapping.h> +#include <linux/gpio_keys.h> +#include <linux/i2c.h> +#include <linux/i2c-tegra.h> +#include <linux/init.h> +#include <linux/input.h> +#include <linux/io.h> +#include <linux/kernel.h> +#include <linux/memblock.h> +#include <linux/mfd/tps6586x.h> +#include <linux/platform_data/tegra_usb.h> +#include <linux/platform_device.h> +#include <linux/serial_8250.h> +#include <linux/slab.h> +#include <linux/spi/spi.h> +#include <linux/suspend.h> +#include <linux/tegra_uart.h> +#include <linux/wm97xx.h> + +#include <mach/audio.h> +#include <mach/clk.h> +#include <mach/gpio.h> +#include <mach/iomap.h> +#include <mach/irqs.h> +#include <mach/nand.h> +#include <mach/sdhci.h> +#include <mach/spdif.h> +#include <mach/usb_phy.h> + +#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 |