| /* |
| * arch/arm/mach-tegra/board-curacao.c |
| * |
| * Copyright (c) 2011-2013, NVIDIA Corporation. |
| * |
| * 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 <linux/kernel.h> |
| #include <linux/init.h> |
| #include <linux/slab.h> |
| #include <linux/ctype.h> |
| #include <linux/platform_device.h> |
| #include <linux/clk.h> |
| #include <linux/serial_8250.h> |
| #include <linux/i2c.h> |
| #include <linux/i2c/panjit_ts.h> |
| #include <linux/dma-mapping.h> |
| #include <linux/delay.h> |
| #include <linux/i2c-tegra.h> |
| #include <linux/gpio.h> |
| #include <linux/gpio_keys.h> |
| #include <linux/input.h> |
| #include <linux/platform_data/tegra_usb.h> |
| #include <linux/of_platform.h> |
| #include <linux/usb/tegra_usb_phy.h> |
| #include <linux/clk/tegra.h> |
| |
| #include <mach/gpio-tegra.h> |
| #include <mach/iomap.h> |
| #include <mach/io_dpd.h> |
| #include <mach/irqs.h> |
| #include <mach/pinmux.h> |
| #include <mach/iomap.h> |
| #include <mach/i2s.h> |
| #include <mach/audio.h> |
| #include <mach/nand.h> |
| #include <mach/hardware.h> |
| |
| #include <asm/mach-types.h> |
| #include <asm/mach/arch.h> |
| |
| #include "board.h" |
| #include "board-curacao.h" |
| #include "clock.h" |
| #include "common.h" |
| #include "devices.h" |
| #include "fuse.h" |
| #include "gpio-names.h" |
| #include <mach/i2s.h> |
| #include <sound/tegra_wm8903.h> |
| #include <sound/wm8903.h> |
| |
| #define ENABLE_OTG 0 |
| |
| static struct plat_serial8250_port debug_uart_platform_data[] = { |
| { |
| .membase = IO_ADDRESS(TEGRA_UARTA_BASE), |
| .mapbase = TEGRA_UARTA_BASE, |
| .irq = INT_UARTA, |
| .flags = UPF_BOOT_AUTOCONF | UPF_FIXED_TYPE, |
| .type = PORT_TEGRA, |
| .iotype = UPIO_MEM, |
| .regshift = 2, |
| .uartclk = 13000000, |
| }, { |
| .flags = 0, |
| } |
| }; |
| |
| static struct platform_device debug_uart = { |
| .name = "serial8250", |
| .id = PLAT8250_DEV_PLATFORM, |
| .dev = { |
| .platform_data = debug_uart_platform_data, |
| }, |
| }; |
| |
| |
| #ifdef CONFIG_BCM4329_RFKILL |
| |
| static struct resource curacao_bcm4329_rfkill_resources[] = { |
| { |
| .name = "bcm4329_nreset_gpio", |
| .start = TEGRA_GPIO_PU0, |
| .end = TEGRA_GPIO_PU0, |
| .flags = IORESOURCE_IO, |
| }, |
| { |
| .name = "bcm4329_nshutdown_gpio", |
| .start = TEGRA_GPIO_PK2, |
| .end = TEGRA_GPIO_PK2, |
| .flags = IORESOURCE_IO, |
| }, |
| }; |
| |
| static struct platform_device curacao_bcm4329_rfkill_device = { |
| .name = "bcm4329_rfkill", |
| .id = -1, |
| .num_resources = ARRAY_SIZE(curacao_bcm4329_rfkill_resources), |
| .resource = curacao_bcm4329_rfkill_resources, |
| }; |
| |
| static noinline void __init curacao_bt_rfkill(void) |
| { |
| /*Add Clock Resource*/ |
| clk_add_alias("bcm4329_32k_clk", curacao_bcm4329_rfkill_device.name, \ |
| "blink", NULL); |
| |
| platform_device_register(&curacao_bcm4329_rfkill_device); |
| |
| return; |
| } |
| #else |
| static inline void curacao_bt_rfkill(void) { } |
| #endif |
| |
| static __initdata struct tegra_clk_init_table curacao_clk_init_table[] = { |
| /* name parent rate enabled */ |
| { "uarta_dbg", "clk_m", 13000000, true}, |
| { "uartb_dbg", "clk_m", 13000000, true}, |
| { "uartc_dbg", "clk_m", 13000000, true}, |
| { "uartd_dbg", "clk_m", 13000000, true}, |
| { "uarte_dbg", "clk_m", 13000000, true}, |
| { "sdmmc1", "clk_m", 13000000, false}, |
| { "sdmmc3", "clk_m", 13000000, false}, |
| { "sdmmc4", "clk_m", 13000000, false}, |
| { "blink", "clk_32k", 32768, false}, |
| { "pwm", "clk_32k", 32768, false}, |
| { "blink", "clk_32k", 32768, false}, |
| { "pll_a", NULL, 282240000, true}, |
| { "pll_a_out0", NULL, 11289600, true}, |
| { "i2s0", "clk_m", 13000000, true}, |
| { "i2s1", "pll_a_out0", 11289600, true}, |
| { "i2s2", "pll_a_out0", 11289600, true}, |
| { "d_audio", "pll_a_out0", 11289600, false}, |
| { "audio", "pll_a_out0", 11289600, false}, |
| { "audio_2x", "audio", 22579200, true}, |
| { NULL, NULL, 0, 0}, |
| }; |
| |
| |
| static struct tegra_i2c_platform_data curacao_i2c1_platform_data = { |
| .bus_clk_rate = 100000, |
| .scl_gpio = -1, |
| .sda_gpio = -1, |
| }; |
| |
| static struct tegra_i2c_platform_data curacao_i2c2_platform_data = { |
| .bus_clk_rate = 100000, |
| .scl_gpio = -1, |
| .sda_gpio = -1, |
| }; |
| |
| static struct tegra_i2c_platform_data curacao_i2c3_platform_data = { |
| .bus_clk_rate = 100000, |
| .scl_gpio = -1, |
| .sda_gpio = -1, |
| }; |
| |
| static struct tegra_i2c_platform_data curacao_i2c4_platform_data = { |
| .bus_clk_rate = 100000, |
| .scl_gpio = -1, |
| .sda_gpio = -1, |
| }; |
| |
| static struct tegra_i2c_platform_data curacao_i2c5_platform_data = { |
| .bus_clk_rate = 100000, |
| .scl_gpio = -1, |
| .sda_gpio = -1, |
| }; |
| |
| static struct wm8903_platform_data curacao_wm8903_pdata = { |
| .irq_active_low = 0, |
| .micdet_cfg = 0, |
| .micdet_delay = 100, |
| }; |
| |
| static struct i2c_board_info __initdata wm8903_board_info = { |
| I2C_BOARD_INFO("wm8903", 0x1a), |
| .platform_data = &curacao_wm8903_pdata, |
| }; |
| |
| static void curacao_i2c_init(void) |
| { |
| tegra11_i2c_device1.dev.platform_data = &curacao_i2c1_platform_data; |
| tegra11_i2c_device2.dev.platform_data = &curacao_i2c2_platform_data; |
| tegra11_i2c_device3.dev.platform_data = &curacao_i2c3_platform_data; |
| tegra11_i2c_device4.dev.platform_data = &curacao_i2c4_platform_data; |
| tegra11_i2c_device5.dev.platform_data = &curacao_i2c5_platform_data; |
| |
| i2c_register_board_info(0, &wm8903_board_info, 1); |
| |
| platform_device_register(&tegra11_i2c_device5); |
| platform_device_register(&tegra11_i2c_device4); |
| platform_device_register(&tegra11_i2c_device3); |
| platform_device_register(&tegra11_i2c_device2); |
| platform_device_register(&tegra11_i2c_device1); |
| } |
| |
| #define GPIO_KEY(_id, _gpio, _iswake) \ |
| { \ |
| .code = _id, \ |
| .gpio = TEGRA_GPIO_##_gpio, \ |
| .active_low = 1, \ |
| .desc = #_id, \ |
| .type = EV_KEY, \ |
| .wakeup = _iswake, \ |
| .debounce_interval = 10, \ |
| } |
| |
| /* !!!FIXME!!! */ |
| static struct gpio_keys_button curacao_keys[] = { |
| [0] = GPIO_KEY(KEY_MENU, PQ0, 0), |
| [1] = GPIO_KEY(KEY_HOME, PQ1, 0), |
| [2] = GPIO_KEY(KEY_BACK, PQ2, 0), |
| [3] = GPIO_KEY(KEY_VOLUMEUP, PQ3, 0), |
| [4] = GPIO_KEY(KEY_VOLUMEDOWN, PQ4, 0), |
| [5] = GPIO_KEY(KEY_POWER, PV2, 1), |
| }; |
| |
| static struct gpio_keys_platform_data curacao_keys_platform_data = { |
| .buttons = curacao_keys, |
| .nbuttons = ARRAY_SIZE(curacao_keys), |
| }; |
| |
| static struct platform_device curacao_keys_device = { |
| .name = "gpio-keys", |
| .id = 0, |
| .dev = { |
| .platform_data = &curacao_keys_platform_data, |
| }, |
| }; |
| |
| static struct platform_device tegra_camera = { |
| .name = "tegra_camera", |
| .id = -1, |
| }; |
| |
| 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), |
| }; |
| |
| #if defined(CONFIG_MTD_NAND_TEGRA) |
| static struct resource nand_resources[] = { |
| [0] = { |
| .start = INT_NANDFLASH, |
| .end = INT_NANDFLASH, |
| .flags = IORESOURCE_IRQ |
| }, |
| [1] = { |
| .start = TEGRA_NAND_BASE, |
| .end = TEGRA_NAND_BASE + TEGRA_NAND_SIZE - 1, |
| .flags = IORESOURCE_MEM |
| } |
| }; |
| |
| static struct tegra_nand_chip_parms nand_chip_parms[] = { |
| /* Samsung K5E2G1GACM */ |
| [0] = { |
| .vendor_id = 0xEC, |
| .device_id = 0xAA, |
| .capacity = 256, |
| .timing = { |
| .trp = 21, |
| .trh = 15, |
| .twp = 21, |
| .twh = 15, |
| .tcs = 31, |
| .twhr = 60, |
| .tcr_tar_trr = 20, |
| .twb = 100, |
| .trp_resp = 30, |
| .tadl = 100, |
| }, |
| }, |
| /* Hynix H5PS1GB3EFR */ |
| [1] = { |
| .vendor_id = 0xAD, |
| .device_id = 0xDC, |
| .capacity = 512, |
| .timing = { |
| .trp = 12, |
| .trh = 10, |
| .twp = 12, |
| .twh = 10, |
| .tcs = 20, |
| .twhr = 80, |
| .tcr_tar_trr = 20, |
| .twb = 100, |
| .trp_resp = 20, |
| .tadl = 70, |
| }, |
| }, |
| }; |
| |
| struct tegra_nand_platform nand_data = { |
| .max_chips = 8, |
| .chip_parms = nand_chip_parms, |
| .nr_chip_parms = ARRAY_SIZE(nand_chip_parms), |
| }; |
| |
| struct platform_device tegra_nand_device = { |
| .name = "tegra_nand", |
| .id = -1, |
| .resource = nand_resources, |
| .num_resources = ARRAY_SIZE(nand_resources), |
| .dev = { |
| .platform_data = &nand_data, |
| }, |
| }; |
| #endif |
| |
| static struct tegra_wm8903_platform_data curacao_audio_pdata = { |
| .gpio_spkr_en = -1, |
| .gpio_hp_det = -1, |
| .gpio_hp_mute = -1, |
| .gpio_int_mic_en = -1, |
| .gpio_ext_mic_en = -1, |
| }; |
| |
| static struct platform_device curacao_audio_device = { |
| .name = "tegra-snd-wm8903", |
| .id = 0, |
| .dev = { |
| .platform_data = &curacao_audio_pdata, |
| }, |
| }; |
| |
| static struct platform_device *curacao_devices[] __initdata = { |
| #if ENABLE_OTG |
| &tegra_otg_device, |
| #endif |
| &debug_uart, |
| &tegra_pmu_device, |
| &tegra_rtc_device, |
| &tegra_udc_device, |
| &curacao_keys_device, |
| #if defined(CONFIG_SND_HDA_TEGRA) |
| &tegra_hda_device, |
| #endif |
| &tegra_avp_device, |
| &tegra_camera, |
| #if defined(CONFIG_CRYPTO_DEV_TEGRA_SE) |
| &tegra11_se_device, |
| #endif |
| &tegra_ahub_device, |
| &tegra_dam_device0, |
| &tegra_i2s_device0, |
| &curacao_audio_device, |
| #if defined(CONFIG_MTD_NAND_TEGRA) |
| &tegra_nand_device, |
| #endif |
| }; |
| |
| static int __init curacao_touch_init(void) |
| { |
| return 0; |
| } |
| |
| |
| #if defined(USB_HOST_ONLY) |
| static struct tegra_usb_platform_data tegra_ehci1_utmi_pdata = { |
| .port_otg = true, |
| .has_hostpc = true, |
| .unaligned_dma_buf_supported = true, |
| .phy_intf = TEGRA_USB_PHY_INTF_UTMI, |
| .op_mode = TEGRA_USB_OPMODE_HOST, |
| .u_data.host = { |
| .vbus_gpio = -1, |
| .hot_plug = true, |
| .remote_wakeup_supported = true, |
| .power_off_on_suspend = true, |
| }, |
| .u_cfg.utmi = { |
| .hssync_start_delay = 0, |
| .elastic_limit = 16, |
| .idle_wait_delay = 17, |
| .term_range_adj = 6, |
| .xcvr_setup = 15, |
| .xcvr_lsfslew = 2, |
| .xcvr_lsrslew = 2, |
| .xcvr_setup_offset = 0, |
| .xcvr_use_fuses = 1, |
| }, |
| }; |
| |
| |
| static void ulpi_link_platform_open(void) |
| { |
| int reset_gpio = TEGRA_GPIO_PV1; |
| |
| gpio_request(reset_gpio, "ulpi_phy_reset"); |
| gpio_direction_output(reset_gpio, 0); |
| msleep(5); |
| gpio_direction_output(reset_gpio, 1); |
| } |
| |
| static struct tegra_usb_phy_platform_ops ulpi_link_plat_ops = { |
| .open = ulpi_link_platform_open, |
| }; |
| |
| static struct tegra_usb_platform_data tegra_ehci2_ulpi_link_pdata = { |
| .port_otg = false, |
| .has_hostpc = true, |
| .unaligned_dma_buf_supported = true, |
| .phy_intf = TEGRA_USB_PHY_INTF_ULPI_LINK, |
| .op_mode = TEGRA_USB_OPMODE_HOST, |
| .u_data.host = { |
| .vbus_gpio = -1, |
| .hot_plug = false, |
| .remote_wakeup_supported = false, |
| .power_off_on_suspend = true, |
| }, |
| .u_cfg.ulpi = { |
| .shadow_clk_delay = 10, |
| .clock_out_delay = 1, |
| .data_trimmer = 4, |
| .stpdirnxt_trimmer = 4, |
| .dir_trimmer = 4, |
| .clk = "cdev2", |
| }, |
| .ops = &ulpi_link_plat_ops, |
| }; |
| #else |
| |
| static struct tegra_usb_platform_data tegra_udc_pdata = { |
| .port_otg = true, |
| .has_hostpc = true, |
| .phy_intf = TEGRA_USB_PHY_INTF_UTMI, |
| .op_mode = TEGRA_USB_OPMODE_DEVICE, |
| .u_data.dev = { |
| .vbus_pmu_irq = 0, |
| .vbus_gpio = -1, |
| .charging_supported = false, |
| .remote_wakeup_supported = false, |
| }, |
| .u_cfg.utmi = { |
| .hssync_start_delay = 0, |
| .elastic_limit = 16, |
| .idle_wait_delay = 17, |
| .term_range_adj = 6, |
| .xcvr_setup = 8, |
| .xcvr_lsfslew = 2, |
| .xcvr_lsrslew = 2, |
| .xcvr_setup_offset = 0, |
| .xcvr_use_fuses = 1, |
| }, |
| }; |
| |
| #endif |
| |
| static void curacao_usb_init(void) |
| { |
| #if defined(USB_HOST_ONLY) |
| tegra_ehci1_device.dev.platform_data = &tegra_ehci1_utmi_pdata; |
| platform_device_register(&tegra_ehci1_device); |
| |
| tegra_ehci2_device.dev.platform_data = &tegra_ehci2_ulpi_link_pdata; |
| platform_device_register(&tegra_ehci2_device); |
| #else |
| /* setup the udc platform data */ |
| tegra_udc_device.dev.platform_data = &tegra_udc_pdata; |
| |
| #endif |
| } |
| |
| static struct platform_device *curacao_hs_uart_devices[] __initdata = { |
| &tegra_uartb_device, |
| &tegra_uartc_device, |
| &tegra_uartd_device, |
| &tegra_uarte_device, |
| }; |
| |
| static void __init curacao_hs_uart_init(void) |
| { |
| platform_add_devices(curacao_hs_uart_devices, |
| ARRAY_SIZE(curacao_hs_uart_devices)); |
| } |
| |
| static void __init tegra_curacao_init(void) |
| { |
| tegra_clk_init_from_table(curacao_clk_init_table); |
| tegra_enable_pinmux(); |
| curacao_pinmux_init(); |
| tegra_soc_device_init("curacao"); |
| |
| if (tegra_platform_is_qt()) |
| debug_uart_platform_data[0].uartclk = tegra_clk_measure_input_freq(); |
| |
| platform_add_devices(curacao_devices, ARRAY_SIZE(curacao_devices)); |
| |
| tegra_io_dpd_init(); |
| curacao_sdhci_init(); |
| curacao_i2c_init(); |
| curacao_regulator_init(); |
| curacao_emc_init(); |
| curacao_suspend_init(); |
| curacao_touch_init(); |
| curacao_usb_init(); |
| curacao_panel_init(); |
| curacao_hs_uart_init(); |
| curacao_bt_rfkill(); |
| curacao_sensors_init(); |
| } |
| |
| #ifdef CONFIG_USE_OF |
| struct of_dev_auxdata curacao_auxdata_lookup[] __initdata = { |
| OF_DEV_AUXDATA("nvidia,tegra114-host1x", TEGRA_HOST1X_BASE, "host1x", |
| NULL), |
| OF_DEV_AUXDATA("nvidia,tegra114-gr3d", TEGRA_GR3D_BASE, "gr3d", NULL), |
| OF_DEV_AUXDATA("nvidia,tegra114-gr2d", TEGRA_GR2D_BASE, "gr2d", NULL), |
| OF_DEV_AUXDATA("nvidia,tegra114-msenc", TEGRA_MSENC_BASE, "msenc", |
| NULL), |
| OF_DEV_AUXDATA("nvidia,tegra114-vi", TEGRA_VI_BASE, "vi", NULL), |
| OF_DEV_AUXDATA("nvidia,tegra114-isp", TEGRA_ISP_BASE, "isp", NULL), |
| OF_DEV_AUXDATA("nvidia,tegra114-tsec", TEGRA_TSEC_BASE, "tsec", NULL), |
| {} |
| }; |
| #endif |
| |
| static void __init tegra_curacao_dt_init(void) |
| { |
| of_platform_populate(NULL, |
| of_default_bus_match_table, curacao_auxdata_lookup, |
| &platform_bus); |
| |
| tegra_curacao_init(); |
| } |
| |
| static void __init tegra_curacao_reserve(void) |
| { |
| #if defined(CONFIG_NVMAP_CONVERT_CARVEOUT_TO_IOVMM) |
| tegra_reserve(0, SZ_4M, 0); |
| #else |
| tegra_reserve(SZ_32M, SZ_4M, 0); |
| #endif |
| } |
| |
| static const char * const curacao_dt_board_compat[] = { |
| "nvidia,curacao", |
| NULL |
| }; |
| |
| MACHINE_START(CURACAO, CURACAO_BOARD_NAME) |
| .atag_offset = 0x80000100, |
| .smp = smp_ops(tegra_smp_ops), |
| .map_io = tegra_map_common_io, |
| .reserve = tegra_curacao_reserve, |
| .init_early = tegra11x_init_early, |
| .init_irq = tegra_dt_init_irq, |
| .init_time = tegra_init_timer, |
| .init_machine = tegra_curacao_dt_init, |
| .dt_compat = curacao_dt_board_compat, |
| MACHINE_END |