diff options
Diffstat (limited to 'arch/arm/mach-tegra')
53 files changed, 5360 insertions, 1056 deletions
diff --git a/arch/arm/mach-tegra/Kconfig b/arch/arm/mach-tegra/Kconfig index acd9552f8ada..3cdeffc97b44 100644 --- a/arch/arm/mach-tegra/Kconfig +++ b/arch/arm/mach-tegra/Kconfig | |||
@@ -10,6 +10,9 @@ config ARCH_TEGRA_2x_SOC | |||
10 | select CPU_V7 | 10 | select CPU_V7 |
11 | select ARM_GIC | 11 | select ARM_GIC |
12 | select ARCH_REQUIRE_GPIOLIB | 12 | select ARCH_REQUIRE_GPIOLIB |
13 | select USB_ARCH_HAS_EHCI if USB_SUPPORT | ||
14 | select USB_ULPI if USB_SUPPORT | ||
15 | select USB_ULPI_VIEWPORT if USB_SUPPORT | ||
13 | help | 16 | help |
14 | Support for NVIDIA Tegra AP20 and T20 processors, based on the | 17 | Support for NVIDIA Tegra AP20 and T20 processors, based on the |
15 | ARM CortexA9MP CPU and the ARM PL310 L2 cache controller | 18 | ARM CortexA9MP CPU and the ARM PL310 L2 cache controller |
@@ -27,6 +30,36 @@ config MACH_HARMONY | |||
27 | help | 30 | help |
28 | Support for nVidia Harmony development platform | 31 | Support for nVidia Harmony development platform |
29 | 32 | ||
33 | config MACH_KAEN | ||
34 | bool "Kaen board" | ||
35 | select MACH_SEABOARD | ||
36 | help | ||
37 | Support for the Kaen version of Seaboard | ||
38 | |||
39 | config MACH_PAZ00 | ||
40 | bool "Paz00 board" | ||
41 | help | ||
42 | Support for the Toshiba AC100/Dynabook AZ netbook | ||
43 | |||
44 | config MACH_SEABOARD | ||
45 | bool "Seaboard board" | ||
46 | help | ||
47 | Support for nVidia Seaboard development platform. It will | ||
48 | also be included for some of the derivative boards that | ||
49 | have large similarities with the seaboard design. | ||
50 | |||
51 | config MACH_TRIMSLICE | ||
52 | bool "TrimSlice board" | ||
53 | select TEGRA_PCI | ||
54 | help | ||
55 | Support for CompuLab TrimSlice platform | ||
56 | |||
57 | config MACH_WARIO | ||
58 | bool "Wario board" | ||
59 | select MACH_SEABOARD | ||
60 | help | ||
61 | Support for the Wario version of Seaboard | ||
62 | |||
30 | choice | 63 | choice |
31 | prompt "Low-level debug console UART" | 64 | prompt "Low-level debug console UART" |
32 | default TEGRA_DEBUG_UART_NONE | 65 | default TEGRA_DEBUG_UART_NONE |
@@ -58,4 +91,7 @@ config TEGRA_SYSTEM_DMA | |||
58 | Adds system DMA functionality for NVIDIA Tegra SoCs, used by | 91 | Adds system DMA functionality for NVIDIA Tegra SoCs, used by |
59 | several Tegra device drivers | 92 | several Tegra device drivers |
60 | 93 | ||
94 | config TEGRA_EMC_SCALING_ENABLE | ||
95 | bool "Enable scaling the memory frequency" | ||
96 | |||
61 | endif | 97 | endif |
diff --git a/arch/arm/mach-tegra/Makefile b/arch/arm/mach-tegra/Makefile index cdbc68e4c0ca..1afe05038c27 100644 --- a/arch/arm/mach-tegra/Makefile +++ b/arch/arm/mach-tegra/Makefile | |||
@@ -1,21 +1,34 @@ | |||
1 | obj-y += common.o | 1 | obj-y += common.o |
2 | obj-y += devices.o | ||
2 | obj-y += io.o | 3 | obj-y += io.o |
3 | obj-y += irq.o legacy_irq.o | 4 | obj-y += irq.o legacy_irq.o |
4 | obj-y += clock.o | 5 | obj-y += clock.o |
5 | obj-y += timer.o | 6 | obj-y += timer.o |
6 | obj-y += gpio.o | 7 | obj-y += gpio.o |
7 | obj-y += pinmux.o | 8 | obj-y += pinmux.o |
9 | obj-y += powergate.o | ||
8 | obj-y += fuse.o | 10 | obj-y += fuse.o |
9 | obj-$(CONFIG_ARCH_TEGRA_2x_SOC) += clock.o | 11 | obj-$(CONFIG_ARCH_TEGRA_2x_SOC) += clock.o |
10 | obj-$(CONFIG_ARCH_TEGRA_2x_SOC) += tegra2_clocks.o | 12 | obj-$(CONFIG_ARCH_TEGRA_2x_SOC) += tegra2_clocks.o |
11 | obj-$(CONFIG_ARCH_TEGRA_2x_SOC) += tegra2_dvfs.o | 13 | obj-$(CONFIG_ARCH_TEGRA_2x_SOC) += tegra2_emc.o |
12 | obj-$(CONFIG_ARCH_TEGRA_2x_SOC) += pinmux-t2-tables.o | 14 | obj-$(CONFIG_ARCH_TEGRA_2x_SOC) += pinmux-t2-tables.o |
13 | obj-$(CONFIG_SMP) += platsmp.o localtimer.o headsmp.o | 15 | obj-$(CONFIG_SMP) += platsmp.o localtimer.o headsmp.o |
14 | obj-$(CONFIG_HOTPLUG_CPU) += hotplug.o | 16 | obj-$(CONFIG_HOTPLUG_CPU) += hotplug.o |
15 | obj-$(CONFIG_TEGRA_SYSTEM_DMA) += dma.o | 17 | obj-$(CONFIG_TEGRA_SYSTEM_DMA) += dma.o |
16 | obj-$(CONFIG_CPU_FREQ) += cpu-tegra.o | 18 | obj-$(CONFIG_CPU_FREQ) += cpu-tegra.o |
17 | obj-$(CONFIG_TEGRA_PCI) += pcie.o | 19 | obj-$(CONFIG_TEGRA_PCI) += pcie.o |
20 | obj-$(CONFIG_USB_SUPPORT) += usb_phy.o | ||
18 | 21 | ||
19 | obj-${CONFIG_MACH_HARMONY} += board-harmony.o | 22 | obj-${CONFIG_MACH_HARMONY} += board-harmony.o |
20 | obj-${CONFIG_MACH_HARMONY} += board-harmony-pinmux.o | 23 | obj-${CONFIG_MACH_HARMONY} += board-harmony-pinmux.o |
21 | obj-${CONFIG_MACH_HARMONY} += board-harmony-pcie.o | 24 | obj-${CONFIG_MACH_HARMONY} += board-harmony-pcie.o |
25 | obj-${CONFIG_MACH_HARMONY} += board-harmony-power.o | ||
26 | |||
27 | obj-${CONFIG_MACH_PAZ00} += board-paz00.o | ||
28 | obj-${CONFIG_MACH_PAZ00} += board-paz00-pinmux.o | ||
29 | |||
30 | obj-${CONFIG_MACH_SEABOARD} += board-seaboard.o | ||
31 | obj-${CONFIG_MACH_SEABOARD} += board-seaboard-pinmux.o | ||
32 | |||
33 | obj-${CONFIG_MACH_TRIMSLICE} += board-trimslice.o | ||
34 | obj-${CONFIG_MACH_TRIMSLICE} += board-trimslice-pinmux.o | ||
diff --git a/arch/arm/mach-tegra/board-harmony-pcie.c b/arch/arm/mach-tegra/board-harmony-pcie.c index f7e7d4514b6a..9c27b95b8d86 100644 --- a/arch/arm/mach-tegra/board-harmony-pcie.c +++ b/arch/arm/mach-tegra/board-harmony-pcie.c | |||
@@ -27,13 +27,29 @@ | |||
27 | 27 | ||
28 | #ifdef CONFIG_TEGRA_PCI | 28 | #ifdef CONFIG_TEGRA_PCI |
29 | 29 | ||
30 | /* GPIO 3 of the PMIC */ | ||
31 | #define EN_VDD_1V05_GPIO (TEGRA_NR_GPIOS + 2) | ||
32 | |||
30 | static int __init harmony_pcie_init(void) | 33 | static int __init harmony_pcie_init(void) |
31 | { | 34 | { |
35 | struct regulator *regulator = NULL; | ||
32 | int err; | 36 | int err; |
33 | 37 | ||
34 | if (!machine_is_harmony()) | 38 | if (!machine_is_harmony()) |
35 | return 0; | 39 | return 0; |
36 | 40 | ||
41 | err = gpio_request(EN_VDD_1V05_GPIO, "EN_VDD_1V05"); | ||
42 | if (err) | ||
43 | return err; | ||
44 | |||
45 | gpio_direction_output(EN_VDD_1V05_GPIO, 1); | ||
46 | |||
47 | regulator = regulator_get(NULL, "pex_clk"); | ||
48 | if (IS_ERR_OR_NULL(regulator)) | ||
49 | goto err_reg; | ||
50 | |||
51 | regulator_enable(regulator); | ||
52 | |||
37 | tegra_pinmux_set_tristate(TEGRA_PINGROUP_GPV, TEGRA_TRI_NORMAL); | 53 | tegra_pinmux_set_tristate(TEGRA_PINGROUP_GPV, TEGRA_TRI_NORMAL); |
38 | tegra_pinmux_set_tristate(TEGRA_PINGROUP_SLXA, TEGRA_TRI_NORMAL); | 54 | tegra_pinmux_set_tristate(TEGRA_PINGROUP_SLXA, TEGRA_TRI_NORMAL); |
39 | tegra_pinmux_set_tristate(TEGRA_PINGROUP_SLXK, TEGRA_TRI_NORMAL); | 55 | tegra_pinmux_set_tristate(TEGRA_PINGROUP_SLXK, TEGRA_TRI_NORMAL); |
@@ -49,9 +65,15 @@ err_pcie: | |||
49 | tegra_pinmux_set_tristate(TEGRA_PINGROUP_SLXA, TEGRA_TRI_TRISTATE); | 65 | tegra_pinmux_set_tristate(TEGRA_PINGROUP_SLXA, TEGRA_TRI_TRISTATE); |
50 | tegra_pinmux_set_tristate(TEGRA_PINGROUP_SLXK, TEGRA_TRI_TRISTATE); | 66 | tegra_pinmux_set_tristate(TEGRA_PINGROUP_SLXK, TEGRA_TRI_TRISTATE); |
51 | 67 | ||
68 | regulator_disable(regulator); | ||
69 | regulator_put(regulator); | ||
70 | err_reg: | ||
71 | gpio_free(EN_VDD_1V05_GPIO); | ||
72 | |||
52 | return err; | 73 | return err; |
53 | } | 74 | } |
54 | 75 | ||
55 | subsys_initcall(harmony_pcie_init); | 76 | /* PCI should be initialized after I2C, mfd and regulators */ |
77 | subsys_initcall_sync(harmony_pcie_init); | ||
56 | 78 | ||
57 | #endif | 79 | #endif |
diff --git a/arch/arm/mach-tegra/board-harmony-pinmux.c b/arch/arm/mach-tegra/board-harmony-pinmux.c index 50b15d500cac..4d63e2e97a8d 100644 --- a/arch/arm/mach-tegra/board-harmony-pinmux.c +++ b/arch/arm/mach-tegra/board-harmony-pinmux.c | |||
@@ -15,8 +15,10 @@ | |||
15 | */ | 15 | */ |
16 | 16 | ||
17 | #include <linux/kernel.h> | 17 | #include <linux/kernel.h> |
18 | #include <linux/gpio.h> | ||
18 | #include <mach/pinmux.h> | 19 | #include <mach/pinmux.h> |
19 | 20 | ||
21 | #include "gpio-names.h" | ||
20 | #include "board-harmony.h" | 22 | #include "board-harmony.h" |
21 | 23 | ||
22 | static struct tegra_pingroup_config harmony_pinmux[] = { | 24 | static struct tegra_pingroup_config harmony_pinmux[] = { |
@@ -25,19 +27,19 @@ static struct tegra_pingroup_config harmony_pinmux[] = { | |||
25 | {TEGRA_PINGROUP_ATC, TEGRA_MUX_NAND, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL}, | 27 | {TEGRA_PINGROUP_ATC, TEGRA_MUX_NAND, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL}, |
26 | {TEGRA_PINGROUP_ATD, TEGRA_MUX_GMI, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL}, | 28 | {TEGRA_PINGROUP_ATD, TEGRA_MUX_GMI, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL}, |
27 | {TEGRA_PINGROUP_ATE, TEGRA_MUX_GMI, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL}, | 29 | {TEGRA_PINGROUP_ATE, TEGRA_MUX_GMI, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL}, |
28 | {TEGRA_PINGROUP_CDEV1, TEGRA_MUX_OSC, TEGRA_PUPD_PULL_DOWN, TEGRA_TRI_TRISTATE}, | 30 | {TEGRA_PINGROUP_CDEV1, TEGRA_MUX_PLLA_OUT, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL}, |
29 | {TEGRA_PINGROUP_CDEV2, TEGRA_MUX_PLLP_OUT4, TEGRA_PUPD_PULL_DOWN, TEGRA_TRI_TRISTATE}, | 31 | {TEGRA_PINGROUP_CDEV2, TEGRA_MUX_PLLP_OUT4, TEGRA_PUPD_PULL_DOWN, TEGRA_TRI_TRISTATE}, |
30 | {TEGRA_PINGROUP_CRTP, TEGRA_MUX_CRT, TEGRA_PUPD_NORMAL, TEGRA_TRI_TRISTATE}, | 32 | {TEGRA_PINGROUP_CRTP, TEGRA_MUX_CRT, TEGRA_PUPD_NORMAL, TEGRA_TRI_TRISTATE}, |
31 | {TEGRA_PINGROUP_CSUS, TEGRA_MUX_VI_SENSOR_CLK, TEGRA_PUPD_PULL_DOWN, TEGRA_TRI_TRISTATE}, | 33 | {TEGRA_PINGROUP_CSUS, TEGRA_MUX_VI_SENSOR_CLK, TEGRA_PUPD_PULL_DOWN, TEGRA_TRI_TRISTATE}, |
32 | {TEGRA_PINGROUP_DAP1, TEGRA_MUX_DAP1, TEGRA_PUPD_NORMAL, TEGRA_TRI_TRISTATE}, | 34 | {TEGRA_PINGROUP_DAP1, TEGRA_MUX_DAP1, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL}, |
33 | {TEGRA_PINGROUP_DAP2, TEGRA_MUX_DAP2, TEGRA_PUPD_NORMAL, TEGRA_TRI_TRISTATE}, | 35 | {TEGRA_PINGROUP_DAP2, TEGRA_MUX_DAP2, TEGRA_PUPD_NORMAL, TEGRA_TRI_TRISTATE}, |
34 | {TEGRA_PINGROUP_DAP3, TEGRA_MUX_DAP3, TEGRA_PUPD_NORMAL, TEGRA_TRI_TRISTATE}, | 36 | {TEGRA_PINGROUP_DAP3, TEGRA_MUX_DAP3, TEGRA_PUPD_NORMAL, TEGRA_TRI_TRISTATE}, |
35 | {TEGRA_PINGROUP_DAP4, TEGRA_MUX_DAP4, TEGRA_PUPD_NORMAL, TEGRA_TRI_TRISTATE}, | 37 | {TEGRA_PINGROUP_DAP4, TEGRA_MUX_DAP4, TEGRA_PUPD_NORMAL, TEGRA_TRI_TRISTATE}, |
36 | {TEGRA_PINGROUP_DDC, TEGRA_MUX_I2C2, TEGRA_PUPD_PULL_UP, TEGRA_TRI_NORMAL}, | 38 | {TEGRA_PINGROUP_DDC, TEGRA_MUX_I2C2, TEGRA_PUPD_PULL_UP, TEGRA_TRI_NORMAL}, |
37 | {TEGRA_PINGROUP_DTA, TEGRA_MUX_SDIO2, TEGRA_PUPD_PULL_UP, TEGRA_TRI_TRISTATE}, | 39 | {TEGRA_PINGROUP_DTA, TEGRA_MUX_SDIO2, TEGRA_PUPD_PULL_UP, TEGRA_TRI_NORMAL}, |
38 | {TEGRA_PINGROUP_DTB, TEGRA_MUX_RSVD1, TEGRA_PUPD_NORMAL, TEGRA_TRI_TRISTATE}, | 40 | {TEGRA_PINGROUP_DTB, TEGRA_MUX_RSVD1, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL}, |
39 | {TEGRA_PINGROUP_DTC, TEGRA_MUX_RSVD1, TEGRA_PUPD_NORMAL, TEGRA_TRI_TRISTATE}, | 41 | {TEGRA_PINGROUP_DTC, TEGRA_MUX_RSVD1, TEGRA_PUPD_NORMAL, TEGRA_TRI_TRISTATE}, |
40 | {TEGRA_PINGROUP_DTD, TEGRA_MUX_SDIO2, TEGRA_PUPD_PULL_UP, TEGRA_TRI_TRISTATE}, | 42 | {TEGRA_PINGROUP_DTD, TEGRA_MUX_SDIO2, TEGRA_PUPD_PULL_UP, TEGRA_TRI_NORMAL}, |
41 | {TEGRA_PINGROUP_DTE, TEGRA_MUX_RSVD1, TEGRA_PUPD_NORMAL, TEGRA_TRI_TRISTATE}, | 43 | {TEGRA_PINGROUP_DTE, TEGRA_MUX_RSVD1, TEGRA_PUPD_NORMAL, TEGRA_TRI_TRISTATE}, |
42 | {TEGRA_PINGROUP_DTF, TEGRA_MUX_I2C3, TEGRA_PUPD_NORMAL, TEGRA_TRI_TRISTATE}, | 44 | {TEGRA_PINGROUP_DTF, TEGRA_MUX_I2C3, TEGRA_PUPD_NORMAL, TEGRA_TRI_TRISTATE}, |
43 | {TEGRA_PINGROUP_GMA, TEGRA_MUX_SDIO4, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL}, | 45 | {TEGRA_PINGROUP_GMA, TEGRA_MUX_SDIO4, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL}, |
@@ -112,13 +114,13 @@ static struct tegra_pingroup_config harmony_pinmux[] = { | |||
112 | {TEGRA_PINGROUP_SLXK, TEGRA_MUX_PCIE, TEGRA_PUPD_NORMAL, TEGRA_TRI_TRISTATE}, | 114 | {TEGRA_PINGROUP_SLXK, TEGRA_MUX_PCIE, TEGRA_PUPD_NORMAL, TEGRA_TRI_TRISTATE}, |
113 | {TEGRA_PINGROUP_SPDI, TEGRA_MUX_RSVD2, TEGRA_PUPD_NORMAL, TEGRA_TRI_TRISTATE}, | 115 | {TEGRA_PINGROUP_SPDI, TEGRA_MUX_RSVD2, TEGRA_PUPD_NORMAL, TEGRA_TRI_TRISTATE}, |
114 | {TEGRA_PINGROUP_SPDO, TEGRA_MUX_RSVD2, TEGRA_PUPD_NORMAL, TEGRA_TRI_TRISTATE}, | 116 | {TEGRA_PINGROUP_SPDO, TEGRA_MUX_RSVD2, TEGRA_PUPD_NORMAL, TEGRA_TRI_TRISTATE}, |
115 | {TEGRA_PINGROUP_SPIA, TEGRA_MUX_GMI, TEGRA_PUPD_PULL_DOWN, TEGRA_TRI_TRISTATE}, | 117 | {TEGRA_PINGROUP_SPIA, TEGRA_MUX_GMI, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL}, |
116 | {TEGRA_PINGROUP_SPIB, TEGRA_MUX_GMI, TEGRA_PUPD_PULL_DOWN, TEGRA_TRI_TRISTATE}, | 118 | {TEGRA_PINGROUP_SPIB, TEGRA_MUX_GMI, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL}, |
117 | {TEGRA_PINGROUP_SPIC, TEGRA_MUX_GMI, TEGRA_PUPD_PULL_UP, TEGRA_TRI_NORMAL}, | 119 | {TEGRA_PINGROUP_SPIC, TEGRA_MUX_GMI, TEGRA_PUPD_PULL_UP, TEGRA_TRI_TRISTATE}, |
118 | {TEGRA_PINGROUP_SPID, TEGRA_MUX_SPI1, TEGRA_PUPD_PULL_DOWN, TEGRA_TRI_TRISTATE}, | 120 | {TEGRA_PINGROUP_SPID, TEGRA_MUX_SPI1, TEGRA_PUPD_PULL_DOWN, TEGRA_TRI_TRISTATE}, |
119 | {TEGRA_PINGROUP_SPIE, TEGRA_MUX_SPI1, TEGRA_PUPD_PULL_UP, TEGRA_TRI_TRISTATE}, | 121 | {TEGRA_PINGROUP_SPIE, TEGRA_MUX_SPI1, TEGRA_PUPD_PULL_UP, TEGRA_TRI_TRISTATE}, |
120 | {TEGRA_PINGROUP_SPIF, TEGRA_MUX_SPI1, TEGRA_PUPD_PULL_DOWN, TEGRA_TRI_TRISTATE}, | 122 | {TEGRA_PINGROUP_SPIF, TEGRA_MUX_SPI1, TEGRA_PUPD_PULL_DOWN, TEGRA_TRI_TRISTATE}, |
121 | {TEGRA_PINGROUP_SPIG, TEGRA_MUX_SPI2_ALT, TEGRA_PUPD_PULL_UP, TEGRA_TRI_TRISTATE}, | 123 | {TEGRA_PINGROUP_SPIG, TEGRA_MUX_SPI2_ALT, TEGRA_PUPD_NORMAL, TEGRA_TRI_TRISTATE}, |
122 | {TEGRA_PINGROUP_SPIH, TEGRA_MUX_SPI2_ALT, TEGRA_PUPD_PULL_UP, TEGRA_TRI_TRISTATE}, | 124 | {TEGRA_PINGROUP_SPIH, TEGRA_MUX_SPI2_ALT, TEGRA_PUPD_PULL_UP, TEGRA_TRI_TRISTATE}, |
123 | {TEGRA_PINGROUP_UAA, TEGRA_MUX_ULPI, TEGRA_PUPD_PULL_UP, TEGRA_TRI_TRISTATE}, | 125 | {TEGRA_PINGROUP_UAA, TEGRA_MUX_ULPI, TEGRA_PUPD_PULL_UP, TEGRA_TRI_TRISTATE}, |
124 | {TEGRA_PINGROUP_UAB, TEGRA_MUX_ULPI, TEGRA_PUPD_PULL_UP, TEGRA_TRI_TRISTATE}, | 126 | {TEGRA_PINGROUP_UAB, TEGRA_MUX_ULPI, TEGRA_PUPD_PULL_UP, TEGRA_TRI_TRISTATE}, |
@@ -138,7 +140,22 @@ static struct tegra_pingroup_config harmony_pinmux[] = { | |||
138 | {TEGRA_PINGROUP_XM2D, TEGRA_MUX_NONE, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL}, | 140 | {TEGRA_PINGROUP_XM2D, TEGRA_MUX_NONE, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL}, |
139 | }; | 141 | }; |
140 | 142 | ||
143 | static struct tegra_gpio_table gpio_table[] = { | ||
144 | { .gpio = TEGRA_GPIO_SD2_CD, .enable = true }, | ||
145 | { .gpio = TEGRA_GPIO_SD2_WP, .enable = true }, | ||
146 | { .gpio = TEGRA_GPIO_SD2_POWER, .enable = true }, | ||
147 | { .gpio = TEGRA_GPIO_SD4_CD, .enable = true }, | ||
148 | { .gpio = TEGRA_GPIO_SD4_WP, .enable = true }, | ||
149 | { .gpio = TEGRA_GPIO_SD4_POWER, .enable = true }, | ||
150 | { .gpio = TEGRA_GPIO_CDC_IRQ, .enable = true }, | ||
151 | { .gpio = TEGRA_GPIO_HP_DET, .enable = true }, | ||
152 | { .gpio = TEGRA_GPIO_INT_MIC_EN, .enable = true }, | ||
153 | { .gpio = TEGRA_GPIO_EXT_MIC_EN, .enable = true }, | ||
154 | }; | ||
155 | |||
141 | void harmony_pinmux_init(void) | 156 | void harmony_pinmux_init(void) |
142 | { | 157 | { |
143 | tegra_pinmux_config_table(harmony_pinmux, ARRAY_SIZE(harmony_pinmux)); | 158 | tegra_pinmux_config_table(harmony_pinmux, ARRAY_SIZE(harmony_pinmux)); |
159 | |||
160 | tegra_gpio_config(gpio_table, ARRAY_SIZE(gpio_table)); | ||
144 | } | 161 | } |
diff --git a/arch/arm/mach-tegra/board-harmony-power.c b/arch/arm/mach-tegra/board-harmony-power.c new file mode 100644 index 000000000000..c84442cabe07 --- /dev/null +++ b/arch/arm/mach-tegra/board-harmony-power.c | |||
@@ -0,0 +1,117 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2010 NVIDIA, Inc. | ||
3 | * | ||
4 | * This program is free software; you can redistribute it and/or modify | ||
5 | * it under the terms of the GNU General Public License version 2 as | ||
6 | * published by the Free Software Foundation. | ||
7 | * | ||
8 | * This program is distributed in the hope that it will be useful, | ||
9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
11 | * GNU General Public License for more details. | ||
12 | * | ||
13 | * You should have received a copy of the GNU General Public License | ||
14 | * along with this program; if not, write to the Free Software | ||
15 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA | ||
16 | * 02111-1307, USA | ||
17 | */ | ||
18 | #include <linux/i2c.h> | ||
19 | #include <linux/platform_device.h> | ||
20 | #include <linux/gpio.h> | ||
21 | |||
22 | #include <linux/regulator/machine.h> | ||
23 | #include <linux/mfd/tps6586x.h> | ||
24 | |||
25 | #include <mach/irqs.h> | ||
26 | |||
27 | #define PMC_CTRL 0x0 | ||
28 | #define PMC_CTRL_INTR_LOW (1 << 17) | ||
29 | |||
30 | static struct regulator_consumer_supply tps658621_ldo0_supply[] = { | ||
31 | REGULATOR_SUPPLY("pex_clk", NULL), | ||
32 | }; | ||
33 | |||
34 | static struct regulator_init_data ldo0_data = { | ||
35 | .constraints = { | ||
36 | .min_uV = 1250 * 1000, | ||
37 | .max_uV = 3300 * 1000, | ||
38 | .valid_modes_mask = (REGULATOR_MODE_NORMAL | | ||
39 | REGULATOR_MODE_STANDBY), | ||
40 | .valid_ops_mask = (REGULATOR_CHANGE_MODE | | ||
41 | REGULATOR_CHANGE_STATUS | | ||
42 | REGULATOR_CHANGE_VOLTAGE), | ||
43 | }, | ||
44 | .num_consumer_supplies = ARRAY_SIZE(tps658621_ldo0_supply), | ||
45 | .consumer_supplies = tps658621_ldo0_supply, | ||
46 | }; | ||
47 | |||
48 | #define HARMONY_REGULATOR_INIT(_id, _minmv, _maxmv) \ | ||
49 | static struct regulator_init_data _id##_data = { \ | ||
50 | .constraints = { \ | ||
51 | .min_uV = (_minmv)*1000, \ | ||
52 | .max_uV = (_maxmv)*1000, \ | ||
53 | .valid_modes_mask = (REGULATOR_MODE_NORMAL | \ | ||
54 | REGULATOR_MODE_STANDBY), \ | ||
55 | .valid_ops_mask = (REGULATOR_CHANGE_MODE | \ | ||
56 | REGULATOR_CHANGE_STATUS | \ | ||
57 | REGULATOR_CHANGE_VOLTAGE), \ | ||
58 | }, \ | ||
59 | } | ||
60 | |||
61 | HARMONY_REGULATOR_INIT(sm0, 725, 1500); | ||
62 | HARMONY_REGULATOR_INIT(sm1, 725, 1500); | ||
63 | HARMONY_REGULATOR_INIT(sm2, 3000, 4550); | ||
64 | HARMONY_REGULATOR_INIT(ldo1, 725, 1500); | ||
65 | HARMONY_REGULATOR_INIT(ldo2, 725, 1500); | ||
66 | HARMONY_REGULATOR_INIT(ldo3, 1250, 3300); | ||
67 | HARMONY_REGULATOR_INIT(ldo4, 1700, 2475); | ||
68 | HARMONY_REGULATOR_INIT(ldo5, 1250, 3300); | ||
69 | HARMONY_REGULATOR_INIT(ldo6, 1250, 3300); | ||
70 | HARMONY_REGULATOR_INIT(ldo7, 1250, 3300); | ||
71 | HARMONY_REGULATOR_INIT(ldo8, 1250, 3300); | ||
72 | HARMONY_REGULATOR_INIT(ldo9, 1250, 3300); | ||
73 | |||
74 | #define TPS_REG(_id, _data) \ | ||
75 | { \ | ||
76 | .id = TPS6586X_ID_##_id, \ | ||
77 | .name = "tps6586x-regulator", \ | ||
78 | .platform_data = _data, \ | ||
79 | } | ||
80 | |||
81 | static struct tps6586x_subdev_info tps_devs[] = { | ||
82 | TPS_REG(SM_0, &sm0_data), | ||
83 | TPS_REG(SM_1, &sm1_data), | ||
84 | TPS_REG(SM_2, &sm2_data), | ||
85 | TPS_REG(LDO_0, &ldo0_data), | ||
86 | TPS_REG(LDO_1, &ldo1_data), | ||
87 | TPS_REG(LDO_2, &ldo2_data), | ||
88 | TPS_REG(LDO_3, &ldo3_data), | ||
89 | TPS_REG(LDO_4, &ldo4_data), | ||
90 | TPS_REG(LDO_5, &ldo5_data), | ||
91 | TPS_REG(LDO_6, &ldo6_data), | ||
92 | TPS_REG(LDO_7, &ldo7_data), | ||
93 | TPS_REG(LDO_8, &ldo8_data), | ||
94 | TPS_REG(LDO_9, &ldo9_data), | ||
95 | }; | ||
96 | |||
97 | static struct tps6586x_platform_data tps_platform = { | ||
98 | .irq_base = TEGRA_NR_IRQS, | ||
99 | .num_subdevs = ARRAY_SIZE(tps_devs), | ||
100 | .subdevs = tps_devs, | ||
101 | .gpio_base = TEGRA_NR_GPIOS, | ||
102 | }; | ||
103 | |||
104 | static struct i2c_board_info __initdata harmony_regulators[] = { | ||
105 | { | ||
106 | I2C_BOARD_INFO("tps6586x", 0x34), | ||
107 | .irq = INT_EXTERNAL_PMU, | ||
108 | .platform_data = &tps_platform, | ||
109 | }, | ||
110 | }; | ||
111 | |||
112 | int __init harmony_regulator_init(void) | ||
113 | { | ||
114 | i2c_register_board_info(3, harmony_regulators, 1); | ||
115 | |||
116 | return 0; | ||
117 | } | ||
diff --git a/arch/arm/mach-tegra/board-harmony.c b/arch/arm/mach-tegra/board-harmony.c index b9dbdb1289d0..75c918a86a31 100644 --- a/arch/arm/mach-tegra/board-harmony.c +++ b/arch/arm/mach-tegra/board-harmony.c | |||
@@ -2,6 +2,7 @@ | |||
2 | * arch/arm/mach-tegra/board-harmony.c | 2 | * arch/arm/mach-tegra/board-harmony.c |
3 | * | 3 | * |
4 | * Copyright (C) 2010 Google, Inc. | 4 | * Copyright (C) 2010 Google, Inc. |
5 | * Copyright (C) 2011 NVIDIA, Inc. | ||
5 | * | 6 | * |
6 | * This software is licensed under the terms of the GNU General Public | 7 | * This software is licensed under the terms of the GNU General Public |
7 | * License version 2, as published by the Free Software Foundation, and | 8 | * License version 2, as published by the Free Software Foundation, and |
@@ -22,43 +23,27 @@ | |||
22 | #include <linux/dma-mapping.h> | 23 | #include <linux/dma-mapping.h> |
23 | #include <linux/pda_power.h> | 24 | #include <linux/pda_power.h> |
24 | #include <linux/io.h> | 25 | #include <linux/io.h> |
26 | #include <linux/gpio.h> | ||
27 | #include <linux/i2c.h> | ||
28 | #include <linux/i2c-tegra.h> | ||
29 | |||
30 | #include <sound/wm8903.h> | ||
25 | 31 | ||
26 | #include <asm/mach-types.h> | 32 | #include <asm/mach-types.h> |
27 | #include <asm/mach/arch.h> | 33 | #include <asm/mach/arch.h> |
28 | #include <asm/mach/time.h> | 34 | #include <asm/mach/time.h> |
29 | #include <asm/setup.h> | 35 | #include <asm/setup.h> |
30 | 36 | ||
37 | #include <mach/harmony_audio.h> | ||
31 | #include <mach/iomap.h> | 38 | #include <mach/iomap.h> |
32 | #include <mach/irqs.h> | 39 | #include <mach/irqs.h> |
40 | #include <mach/sdhci.h> | ||
33 | 41 | ||
34 | #include "board.h" | 42 | #include "board.h" |
35 | #include "board-harmony.h" | 43 | #include "board-harmony.h" |
36 | #include "clock.h" | 44 | #include "clock.h" |
37 | 45 | #include "devices.h" | |
38 | /* NVidia bootloader tags */ | 46 | #include "gpio-names.h" |
39 | #define ATAG_NVIDIA 0x41000801 | ||
40 | |||
41 | #define ATAG_NVIDIA_RM 0x1 | ||
42 | #define ATAG_NVIDIA_DISPLAY 0x2 | ||
43 | #define ATAG_NVIDIA_FRAMEBUFFER 0x3 | ||
44 | #define ATAG_NVIDIA_CHIPSHMOO 0x4 | ||
45 | #define ATAG_NVIDIA_CHIPSHMOOPHYS 0x5 | ||
46 | #define ATAG_NVIDIA_PRESERVED_MEM_0 0x10000 | ||
47 | #define ATAG_NVIDIA_PRESERVED_MEM_N 2 | ||
48 | #define ATAG_NVIDIA_FORCE_32 0x7fffffff | ||
49 | |||
50 | struct tag_tegra { | ||
51 | __u32 bootarg_key; | ||
52 | __u32 bootarg_len; | ||
53 | char bootarg[1]; | ||
54 | }; | ||
55 | |||
56 | static int __init parse_tag_nvidia(const struct tag *tag) | ||
57 | { | ||
58 | |||
59 | return 0; | ||
60 | } | ||
61 | __tagtable(ATAG_NVIDIA, parse_tag_nvidia); | ||
62 | 47 | ||
63 | static struct plat_serial8250_port debug_uart_platform_data[] = { | 48 | static struct plat_serial8250_port debug_uart_platform_data[] = { |
64 | { | 49 | { |
@@ -82,8 +67,81 @@ static struct platform_device debug_uart = { | |||
82 | }, | 67 | }, |
83 | }; | 68 | }; |
84 | 69 | ||
70 | static struct harmony_audio_platform_data harmony_audio_pdata = { | ||
71 | .gpio_spkr_en = TEGRA_GPIO_SPKR_EN, | ||
72 | .gpio_hp_det = TEGRA_GPIO_HP_DET, | ||
73 | .gpio_int_mic_en = TEGRA_GPIO_INT_MIC_EN, | ||
74 | .gpio_ext_mic_en = TEGRA_GPIO_EXT_MIC_EN, | ||
75 | }; | ||
76 | |||
77 | static struct platform_device harmony_audio_device = { | ||
78 | .name = "tegra-snd-harmony", | ||
79 | .id = 0, | ||
80 | .dev = { | ||
81 | .platform_data = &harmony_audio_pdata, | ||
82 | }, | ||
83 | }; | ||
84 | |||
85 | static struct tegra_i2c_platform_data harmony_i2c1_platform_data = { | ||
86 | .bus_clk_rate = 400000, | ||
87 | }; | ||
88 | |||
89 | static struct tegra_i2c_platform_data harmony_i2c2_platform_data = { | ||
90 | .bus_clk_rate = 400000, | ||
91 | }; | ||
92 | |||
93 | static struct tegra_i2c_platform_data harmony_i2c3_platform_data = { | ||
94 | .bus_clk_rate = 400000, | ||
95 | }; | ||
96 | |||
97 | static struct tegra_i2c_platform_data harmony_dvc_platform_data = { | ||
98 | .bus_clk_rate = 400000, | ||
99 | }; | ||
100 | |||
101 | static struct wm8903_platform_data harmony_wm8903_pdata = { | ||
102 | .irq_active_low = 0, | ||
103 | .micdet_cfg = 0, | ||
104 | .micdet_delay = 100, | ||
105 | .gpio_base = HARMONY_GPIO_WM8903(0), | ||
106 | .gpio_cfg = { | ||
107 | WM8903_GPIO_NO_CONFIG, | ||
108 | WM8903_GPIO_NO_CONFIG, | ||
109 | 0, | ||
110 | WM8903_GPIO_NO_CONFIG, | ||
111 | WM8903_GPIO_NO_CONFIG, | ||
112 | }, | ||
113 | }; | ||
114 | |||
115 | static struct i2c_board_info __initdata wm8903_board_info = { | ||
116 | I2C_BOARD_INFO("wm8903", 0x1a), | ||
117 | .platform_data = &harmony_wm8903_pdata, | ||
118 | .irq = TEGRA_GPIO_TO_IRQ(TEGRA_GPIO_CDC_IRQ), | ||
119 | }; | ||
120 | |||
121 | static void __init harmony_i2c_init(void) | ||
122 | { | ||
123 | tegra_i2c_device1.dev.platform_data = &harmony_i2c1_platform_data; | ||
124 | tegra_i2c_device2.dev.platform_data = &harmony_i2c2_platform_data; | ||
125 | tegra_i2c_device3.dev.platform_data = &harmony_i2c3_platform_data; | ||
126 | tegra_i2c_device4.dev.platform_data = &harmony_dvc_platform_data; | ||
127 | |||
128 | platform_device_register(&tegra_i2c_device1); | ||
129 | platform_device_register(&tegra_i2c_device2); | ||
130 | platform_device_register(&tegra_i2c_device3); | ||
131 | platform_device_register(&tegra_i2c_device4); | ||
132 | |||
133 | i2c_register_board_info(0, &wm8903_board_info, 1); | ||
134 | } | ||
135 | |||
85 | static struct platform_device *harmony_devices[] __initdata = { | 136 | static struct platform_device *harmony_devices[] __initdata = { |
86 | &debug_uart, | 137 | &debug_uart, |
138 | &tegra_sdhci_device1, | ||
139 | &tegra_sdhci_device2, | ||
140 | &tegra_sdhci_device4, | ||
141 | &tegra_i2s_device1, | ||
142 | &tegra_das_device, | ||
143 | &tegra_pcm_device, | ||
144 | &harmony_audio_device, | ||
87 | }; | 145 | }; |
88 | 146 | ||
89 | static void __init tegra_harmony_fixup(struct machine_desc *desc, | 147 | static void __init tegra_harmony_fixup(struct machine_desc *desc, |
@@ -99,25 +157,54 @@ static void __init tegra_harmony_fixup(struct machine_desc *desc, | |||
99 | static __initdata struct tegra_clk_init_table harmony_clk_init_table[] = { | 157 | static __initdata struct tegra_clk_init_table harmony_clk_init_table[] = { |
100 | /* name parent rate enabled */ | 158 | /* name parent rate enabled */ |
101 | { "uartd", "pll_p", 216000000, true }, | 159 | { "uartd", "pll_p", 216000000, true }, |
160 | { "pll_a", "pll_p_out1", 56448000, true }, | ||
161 | { "pll_a_out0", "pll_a", 11289600, true }, | ||
162 | { "cdev1", NULL, 0, true }, | ||
163 | { "i2s1", "pll_a_out0", 11289600, false}, | ||
102 | { NULL, NULL, 0, 0}, | 164 | { NULL, NULL, 0, 0}, |
103 | }; | 165 | }; |
104 | 166 | ||
167 | |||
168 | static struct tegra_sdhci_platform_data sdhci_pdata1 = { | ||
169 | .cd_gpio = -1, | ||
170 | .wp_gpio = -1, | ||
171 | .power_gpio = -1, | ||
172 | }; | ||
173 | |||
174 | static struct tegra_sdhci_platform_data sdhci_pdata2 = { | ||
175 | .cd_gpio = TEGRA_GPIO_SD2_CD, | ||
176 | .wp_gpio = TEGRA_GPIO_SD2_WP, | ||
177 | .power_gpio = TEGRA_GPIO_SD2_POWER, | ||
178 | }; | ||
179 | |||
180 | static struct tegra_sdhci_platform_data sdhci_pdata4 = { | ||
181 | .cd_gpio = TEGRA_GPIO_SD4_CD, | ||
182 | .wp_gpio = TEGRA_GPIO_SD4_WP, | ||
183 | .power_gpio = TEGRA_GPIO_SD4_POWER, | ||
184 | .is_8bit = 1, | ||
185 | }; | ||
186 | |||
105 | static void __init tegra_harmony_init(void) | 187 | static void __init tegra_harmony_init(void) |
106 | { | 188 | { |
107 | tegra_common_init(); | ||
108 | |||
109 | tegra_clk_init_from_table(harmony_clk_init_table); | 189 | tegra_clk_init_from_table(harmony_clk_init_table); |
110 | 190 | ||
111 | harmony_pinmux_init(); | 191 | harmony_pinmux_init(); |
112 | 192 | ||
193 | tegra_sdhci_device1.dev.platform_data = &sdhci_pdata1; | ||
194 | tegra_sdhci_device2.dev.platform_data = &sdhci_pdata2; | ||
195 | tegra_sdhci_device4.dev.platform_data = &sdhci_pdata4; | ||
196 | |||
113 | platform_add_devices(harmony_devices, ARRAY_SIZE(harmony_devices)); | 197 | platform_add_devices(harmony_devices, ARRAY_SIZE(harmony_devices)); |
198 | harmony_i2c_init(); | ||
199 | harmony_regulator_init(); | ||
114 | } | 200 | } |
115 | 201 | ||
116 | MACHINE_START(HARMONY, "harmony") | 202 | MACHINE_START(HARMONY, "harmony") |
117 | .boot_params = 0x00000100, | 203 | .boot_params = 0x00000100, |
118 | .fixup = tegra_harmony_fixup, | 204 | .fixup = tegra_harmony_fixup, |
119 | .init_irq = tegra_init_irq, | ||
120 | .init_machine = tegra_harmony_init, | ||
121 | .map_io = tegra_map_common_io, | 205 | .map_io = tegra_map_common_io, |
206 | .init_early = tegra_init_early, | ||
207 | .init_irq = tegra_init_irq, | ||
122 | .timer = &tegra_timer, | 208 | .timer = &tegra_timer, |
209 | .init_machine = tegra_harmony_init, | ||
123 | MACHINE_END | 210 | MACHINE_END |
diff --git a/arch/arm/mach-tegra/board-harmony.h b/arch/arm/mach-tegra/board-harmony.h index 09ca7755dd55..1e57b071f52d 100644 --- a/arch/arm/mach-tegra/board-harmony.h +++ b/arch/arm/mach-tegra/board-harmony.h | |||
@@ -17,6 +17,21 @@ | |||
17 | #ifndef _MACH_TEGRA_BOARD_HARMONY_H | 17 | #ifndef _MACH_TEGRA_BOARD_HARMONY_H |
18 | #define _MACH_TEGRA_BOARD_HARMONY_H | 18 | #define _MACH_TEGRA_BOARD_HARMONY_H |
19 | 19 | ||
20 | #define HARMONY_GPIO_WM8903(_x_) (TEGRA_NR_GPIOS + (_x_)) | ||
21 | |||
22 | #define TEGRA_GPIO_SD2_CD TEGRA_GPIO_PI5 | ||
23 | #define TEGRA_GPIO_SD2_WP TEGRA_GPIO_PH1 | ||
24 | #define TEGRA_GPIO_SD2_POWER TEGRA_GPIO_PT3 | ||
25 | #define TEGRA_GPIO_SD4_CD TEGRA_GPIO_PH2 | ||
26 | #define TEGRA_GPIO_SD4_WP TEGRA_GPIO_PH3 | ||
27 | #define TEGRA_GPIO_SD4_POWER TEGRA_GPIO_PI6 | ||
28 | #define TEGRA_GPIO_CDC_IRQ TEGRA_GPIO_PX3 | ||
29 | #define TEGRA_GPIO_SPKR_EN HARMONY_GPIO_WM8903(2) | ||
30 | #define TEGRA_GPIO_HP_DET TEGRA_GPIO_PW2 | ||
31 | #define TEGRA_GPIO_INT_MIC_EN TEGRA_GPIO_PX0 | ||
32 | #define TEGRA_GPIO_EXT_MIC_EN TEGRA_GPIO_PX1 | ||
33 | |||
20 | void harmony_pinmux_init(void); | 34 | void harmony_pinmux_init(void); |
35 | int harmony_regulator_init(void); | ||
21 | 36 | ||
22 | #endif | 37 | #endif |
diff --git a/arch/arm/mach-tegra/board-paz00-pinmux.c b/arch/arm/mach-tegra/board-paz00-pinmux.c new file mode 100644 index 000000000000..2643d1bd568b --- /dev/null +++ b/arch/arm/mach-tegra/board-paz00-pinmux.c | |||
@@ -0,0 +1,157 @@ | |||
1 | /* | ||
2 | * arch/arm/mach-tegra/board-paz00-pinmux.c | ||
3 | * | ||
4 | * Copyright (C) 2010 Marc Dietrich <marvin24@gmx.de> | ||
5 | * | ||
6 | * This software is licensed under the terms of the GNU General Public | ||
7 | * License version 2, as published by the Free Software Foundation, and | ||
8 | * may be copied, distributed, and modified under those terms. | ||
9 | * | ||
10 | * This program is distributed in the hope that it will be useful, | ||
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
13 | * GNU General Public License for more details. | ||
14 | * | ||
15 | */ | ||
16 | |||
17 | #include <linux/kernel.h> | ||
18 | #include <linux/gpio.h> | ||
19 | #include <mach/pinmux.h> | ||
20 | |||
21 | #include "gpio-names.h" | ||
22 | #include "board-paz00.h" | ||
23 | |||
24 | static struct tegra_pingroup_config paz00_pinmux[] = { | ||
25 | {TEGRA_PINGROUP_ATA, TEGRA_MUX_GMI, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL}, | ||
26 | {TEGRA_PINGROUP_ATB, TEGRA_MUX_SDIO4, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL}, | ||
27 | {TEGRA_PINGROUP_ATC, TEGRA_MUX_GMI, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL}, | ||
28 | {TEGRA_PINGROUP_ATD, TEGRA_MUX_GMI, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL}, | ||
29 | {TEGRA_PINGROUP_ATE, TEGRA_MUX_GMI, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL}, | ||
30 | {TEGRA_PINGROUP_CDEV1, TEGRA_MUX_PLLA_OUT, TEGRA_PUPD_PULL_DOWN, TEGRA_TRI_TRISTATE}, | ||
31 | {TEGRA_PINGROUP_CDEV2, TEGRA_MUX_PLLP_OUT4, TEGRA_PUPD_PULL_DOWN, TEGRA_TRI_NORMAL}, | ||
32 | {TEGRA_PINGROUP_CRTP, TEGRA_MUX_CRT, TEGRA_PUPD_NORMAL, TEGRA_TRI_TRISTATE}, | ||
33 | {TEGRA_PINGROUP_CSUS, TEGRA_MUX_PLLC_OUT1, TEGRA_PUPD_PULL_DOWN, TEGRA_TRI_TRISTATE}, | ||
34 | {TEGRA_PINGROUP_DAP1, TEGRA_MUX_DAP1, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL}, | ||
35 | {TEGRA_PINGROUP_DAP2, TEGRA_MUX_GMI, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL}, | ||
36 | {TEGRA_PINGROUP_DAP3, TEGRA_MUX_DAP3, TEGRA_PUPD_NORMAL, TEGRA_TRI_TRISTATE}, | ||
37 | {TEGRA_PINGROUP_DAP4, TEGRA_MUX_DAP4, TEGRA_PUPD_NORMAL, TEGRA_TRI_TRISTATE}, | ||
38 | {TEGRA_PINGROUP_DDC, TEGRA_MUX_I2C2, TEGRA_PUPD_PULL_UP, TEGRA_TRI_NORMAL}, | ||
39 | {TEGRA_PINGROUP_DTA, TEGRA_MUX_RSVD1, TEGRA_PUPD_PULL_UP, TEGRA_TRI_TRISTATE}, | ||
40 | {TEGRA_PINGROUP_DTB, TEGRA_MUX_RSVD1, TEGRA_PUPD_NORMAL, TEGRA_TRI_TRISTATE}, | ||
41 | {TEGRA_PINGROUP_DTC, TEGRA_MUX_RSVD1, TEGRA_PUPD_NORMAL, TEGRA_TRI_TRISTATE}, | ||
42 | {TEGRA_PINGROUP_DTD, TEGRA_MUX_RSVD1, TEGRA_PUPD_PULL_UP, TEGRA_TRI_TRISTATE}, | ||
43 | {TEGRA_PINGROUP_DTE, TEGRA_MUX_RSVD1, TEGRA_PUPD_NORMAL, TEGRA_TRI_TRISTATE}, | ||
44 | {TEGRA_PINGROUP_DTF, TEGRA_MUX_I2C3, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL}, | ||
45 | {TEGRA_PINGROUP_GMA, TEGRA_MUX_SDIO4, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL}, | ||
46 | {TEGRA_PINGROUP_GMB, TEGRA_MUX_GMI, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL}, | ||
47 | {TEGRA_PINGROUP_GMC, TEGRA_MUX_GMI, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL}, | ||
48 | {TEGRA_PINGROUP_GMD, TEGRA_MUX_GMI, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL}, | ||
49 | {TEGRA_PINGROUP_GME, TEGRA_MUX_SDIO4, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL}, | ||
50 | {TEGRA_PINGROUP_GPU, TEGRA_MUX_PWM, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL}, | ||
51 | {TEGRA_PINGROUP_GPU7, TEGRA_MUX_RTCK, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL}, | ||
52 | {TEGRA_PINGROUP_GPV, TEGRA_MUX_PCIE, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL}, | ||
53 | {TEGRA_PINGROUP_HDINT, TEGRA_MUX_HDMI, TEGRA_PUPD_PULL_UP, TEGRA_TRI_NORMAL}, | ||
54 | {TEGRA_PINGROUP_I2CP, TEGRA_MUX_I2C, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL}, | ||
55 | {TEGRA_PINGROUP_IRRX, TEGRA_MUX_UARTA, TEGRA_PUPD_PULL_UP, TEGRA_TRI_NORMAL}, | ||
56 | {TEGRA_PINGROUP_IRTX, TEGRA_MUX_UARTA, TEGRA_PUPD_PULL_UP, TEGRA_TRI_NORMAL}, | ||
57 | {TEGRA_PINGROUP_KBCA, TEGRA_MUX_KBC, TEGRA_PUPD_PULL_UP, TEGRA_TRI_NORMAL}, | ||
58 | {TEGRA_PINGROUP_KBCB, TEGRA_MUX_SDIO2, TEGRA_PUPD_PULL_UP, TEGRA_TRI_NORMAL}, | ||
59 | {TEGRA_PINGROUP_KBCC, TEGRA_MUX_KBC, TEGRA_PUPD_PULL_UP, TEGRA_TRI_NORMAL}, | ||
60 | {TEGRA_PINGROUP_KBCD, TEGRA_MUX_SDIO2, TEGRA_PUPD_PULL_UP, TEGRA_TRI_NORMAL}, | ||
61 | {TEGRA_PINGROUP_KBCE, TEGRA_MUX_KBC, TEGRA_PUPD_PULL_UP, TEGRA_TRI_NORMAL}, | ||
62 | {TEGRA_PINGROUP_KBCF, TEGRA_MUX_KBC, TEGRA_PUPD_PULL_UP, TEGRA_TRI_NORMAL}, | ||
63 | {TEGRA_PINGROUP_LCSN, TEGRA_MUX_DISPLAYA, TEGRA_PUPD_PULL_UP, TEGRA_TRI_TRISTATE}, | ||
64 | {TEGRA_PINGROUP_LD0, TEGRA_MUX_DISPLAYA, TEGRA_PUPD_PULL_DOWN, TEGRA_TRI_NORMAL}, | ||
65 | {TEGRA_PINGROUP_LD1, TEGRA_MUX_DISPLAYA, TEGRA_PUPD_PULL_DOWN, TEGRA_TRI_NORMAL}, | ||
66 | {TEGRA_PINGROUP_LD10, TEGRA_MUX_DISPLAYA, TEGRA_PUPD_PULL_DOWN, TEGRA_TRI_NORMAL}, | ||
67 | {TEGRA_PINGROUP_LD11, TEGRA_MUX_DISPLAYA, TEGRA_PUPD_PULL_DOWN, TEGRA_TRI_NORMAL}, | ||
68 | {TEGRA_PINGROUP_LD12, TEGRA_MUX_DISPLAYA, TEGRA_PUPD_PULL_DOWN, TEGRA_TRI_NORMAL}, | ||
69 | {TEGRA_PINGROUP_LD13, TEGRA_MUX_DISPLAYA, TEGRA_PUPD_PULL_DOWN, TEGRA_TRI_NORMAL}, | ||
70 | {TEGRA_PINGROUP_LD14, TEGRA_MUX_DISPLAYA, TEGRA_PUPD_PULL_DOWN, TEGRA_TRI_NORMAL}, | ||
71 | {TEGRA_PINGROUP_LD15, TEGRA_MUX_DISPLAYA, TEGRA_PUPD_PULL_DOWN, TEGRA_TRI_NORMAL}, | ||
72 | {TEGRA_PINGROUP_LD16, TEGRA_MUX_DISPLAYA, TEGRA_PUPD_PULL_DOWN, TEGRA_TRI_NORMAL}, | ||
73 | {TEGRA_PINGROUP_LD17, TEGRA_MUX_DISPLAYA, TEGRA_PUPD_PULL_DOWN, TEGRA_TRI_NORMAL}, | ||
74 | {TEGRA_PINGROUP_LD2, TEGRA_MUX_DISPLAYA, TEGRA_PUPD_PULL_DOWN, TEGRA_TRI_NORMAL}, | ||
75 | {TEGRA_PINGROUP_LD3, TEGRA_MUX_DISPLAYA, TEGRA_PUPD_PULL_DOWN, TEGRA_TRI_NORMAL}, | ||
76 | {TEGRA_PINGROUP_LD4, TEGRA_MUX_DISPLAYA, TEGRA_PUPD_PULL_DOWN, TEGRA_TRI_NORMAL}, | ||
77 | {TEGRA_PINGROUP_LD5, TEGRA_MUX_DISPLAYA, TEGRA_PUPD_PULL_DOWN, TEGRA_TRI_NORMAL}, | ||
78 | {TEGRA_PINGROUP_LD6, TEGRA_MUX_DISPLAYA, TEGRA_PUPD_PULL_DOWN, TEGRA_TRI_NORMAL}, | ||
79 | {TEGRA_PINGROUP_LD7, TEGRA_MUX_DISPLAYA, TEGRA_PUPD_PULL_DOWN, TEGRA_TRI_NORMAL}, | ||
80 | {TEGRA_PINGROUP_LD8, TEGRA_MUX_DISPLAYA, TEGRA_PUPD_PULL_DOWN, TEGRA_TRI_NORMAL}, | ||
81 | {TEGRA_PINGROUP_LD9, TEGRA_MUX_DISPLAYA, TEGRA_PUPD_PULL_DOWN, TEGRA_TRI_NORMAL}, | ||
82 | {TEGRA_PINGROUP_LDC, TEGRA_MUX_DISPLAYA, TEGRA_PUPD_PULL_UP, TEGRA_TRI_NORMAL}, | ||
83 | {TEGRA_PINGROUP_LDI, TEGRA_MUX_DISPLAYA, TEGRA_PUPD_PULL_DOWN, TEGRA_TRI_NORMAL}, | ||
84 | {TEGRA_PINGROUP_LHP0, TEGRA_MUX_DISPLAYA, TEGRA_PUPD_PULL_DOWN, TEGRA_TRI_TRISTATE}, | ||
85 | {TEGRA_PINGROUP_LHP1, TEGRA_MUX_DISPLAYA, TEGRA_PUPD_PULL_DOWN, TEGRA_TRI_TRISTATE}, | ||
86 | {TEGRA_PINGROUP_LHP2, TEGRA_MUX_DISPLAYA, TEGRA_PUPD_PULL_DOWN, TEGRA_TRI_TRISTATE}, | ||
87 | {TEGRA_PINGROUP_LHS, TEGRA_MUX_DISPLAYA, TEGRA_PUPD_PULL_UP, TEGRA_TRI_NORMAL}, | ||
88 | {TEGRA_PINGROUP_LM0, TEGRA_MUX_DISPLAYA, TEGRA_PUPD_PULL_UP, TEGRA_TRI_TRISTATE}, | ||
89 | {TEGRA_PINGROUP_LM1, TEGRA_MUX_DISPLAYA, TEGRA_PUPD_PULL_UP, TEGRA_TRI_TRISTATE}, | ||
90 | {TEGRA_PINGROUP_LPP, TEGRA_MUX_DISPLAYA, TEGRA_PUPD_PULL_DOWN, TEGRA_TRI_TRISTATE}, | ||
91 | {TEGRA_PINGROUP_LPW0, TEGRA_MUX_DISPLAYA, TEGRA_PUPD_PULL_UP, TEGRA_TRI_TRISTATE}, | ||
92 | {TEGRA_PINGROUP_LPW1, TEGRA_MUX_DISPLAYA, TEGRA_PUPD_PULL_UP, TEGRA_TRI_TRISTATE}, | ||
93 | {TEGRA_PINGROUP_LPW2, TEGRA_MUX_DISPLAYA, TEGRA_PUPD_PULL_UP, TEGRA_TRI_TRISTATE}, | ||
94 | {TEGRA_PINGROUP_LSC0, TEGRA_MUX_DISPLAYA, TEGRA_PUPD_PULL_UP, TEGRA_TRI_NORMAL}, | ||
95 | {TEGRA_PINGROUP_LSC1, TEGRA_MUX_DISPLAYA, TEGRA_PUPD_PULL_UP, TEGRA_TRI_TRISTATE}, | ||
96 | {TEGRA_PINGROUP_LSCK, TEGRA_MUX_DISPLAYA, TEGRA_PUPD_PULL_UP, TEGRA_TRI_TRISTATE}, | ||
97 | {TEGRA_PINGROUP_LSDA, TEGRA_MUX_DISPLAYA, TEGRA_PUPD_PULL_UP, TEGRA_TRI_TRISTATE}, | ||
98 | {TEGRA_PINGROUP_LSDI, TEGRA_MUX_DISPLAYA, TEGRA_PUPD_PULL_UP, TEGRA_TRI_TRISTATE}, | ||
99 | {TEGRA_PINGROUP_LSPI, TEGRA_MUX_DISPLAYA, TEGRA_PUPD_PULL_UP, TEGRA_TRI_NORMAL}, | ||
100 | {TEGRA_PINGROUP_LVP0, TEGRA_MUX_DISPLAYA, TEGRA_PUPD_PULL_UP, TEGRA_TRI_TRISTATE}, | ||
101 | {TEGRA_PINGROUP_LVP1, TEGRA_MUX_DISPLAYA, TEGRA_PUPD_PULL_DOWN, TEGRA_TRI_TRISTATE}, | ||
102 | {TEGRA_PINGROUP_LVS, TEGRA_MUX_DISPLAYA, TEGRA_PUPD_PULL_UP, TEGRA_TRI_NORMAL}, | ||
103 | {TEGRA_PINGROUP_OWC, TEGRA_MUX_OWR, TEGRA_PUPD_PULL_UP, TEGRA_TRI_TRISTATE}, | ||
104 | {TEGRA_PINGROUP_PMC, TEGRA_MUX_PWR_ON, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL}, | ||
105 | {TEGRA_PINGROUP_PTA, TEGRA_MUX_HDMI, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL}, | ||
106 | {TEGRA_PINGROUP_RM, TEGRA_MUX_I2C, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL}, | ||
107 | {TEGRA_PINGROUP_SDB, TEGRA_MUX_PWM, TEGRA_PUPD_NORMAL, TEGRA_TRI_TRISTATE}, | ||
108 | {TEGRA_PINGROUP_SDC, TEGRA_MUX_TWC, TEGRA_PUPD_PULL_UP, TEGRA_TRI_TRISTATE}, | ||
109 | {TEGRA_PINGROUP_SDD, TEGRA_MUX_PWM, TEGRA_PUPD_PULL_UP, TEGRA_TRI_TRISTATE}, | ||
110 | {TEGRA_PINGROUP_SDIO1, TEGRA_MUX_SDIO1, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL}, | ||
111 | {TEGRA_PINGROUP_SLXA, TEGRA_MUX_PCIE, TEGRA_PUPD_NORMAL, TEGRA_TRI_TRISTATE}, | ||
112 | {TEGRA_PINGROUP_SLXC, TEGRA_MUX_SPI4, TEGRA_PUPD_NORMAL, TEGRA_TRI_TRISTATE}, | ||
113 | {TEGRA_PINGROUP_SLXD, TEGRA_MUX_SPI4, TEGRA_PUPD_NORMAL, TEGRA_TRI_TRISTATE}, | ||
114 | {TEGRA_PINGROUP_SLXK, TEGRA_MUX_PCIE, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL}, | ||
115 | {TEGRA_PINGROUP_SPDI, TEGRA_MUX_RSVD2, TEGRA_PUPD_NORMAL, TEGRA_TRI_TRISTATE}, | ||
116 | {TEGRA_PINGROUP_SPDO, TEGRA_MUX_RSVD2, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL}, | ||
117 | {TEGRA_PINGROUP_SPIA, TEGRA_MUX_GMI, TEGRA_PUPD_PULL_DOWN, TEGRA_TRI_TRISTATE}, | ||
118 | {TEGRA_PINGROUP_SPIB, TEGRA_MUX_GMI, TEGRA_PUPD_PULL_DOWN, TEGRA_TRI_TRISTATE}, | ||
119 | {TEGRA_PINGROUP_SPIC, TEGRA_MUX_GMI, TEGRA_PUPD_PULL_UP, TEGRA_TRI_NORMAL}, | ||
120 | {TEGRA_PINGROUP_SPID, TEGRA_MUX_GMI, TEGRA_PUPD_PULL_DOWN, TEGRA_TRI_TRISTATE}, | ||
121 | {TEGRA_PINGROUP_SPIE, TEGRA_MUX_GMI, TEGRA_PUPD_PULL_UP, TEGRA_TRI_TRISTATE}, | ||
122 | {TEGRA_PINGROUP_SPIF, TEGRA_MUX_RSVD4, TEGRA_PUPD_PULL_DOWN, TEGRA_TRI_TRISTATE}, | ||
123 | {TEGRA_PINGROUP_SPIG, TEGRA_MUX_SPI2_ALT, TEGRA_PUPD_PULL_UP, TEGRA_TRI_NORMAL}, | ||
124 | {TEGRA_PINGROUP_SPIH, TEGRA_MUX_SPI2_ALT, TEGRA_PUPD_PULL_UP, TEGRA_TRI_TRISTATE}, | ||
125 | {TEGRA_PINGROUP_UAA, TEGRA_MUX_ULPI, TEGRA_PUPD_PULL_UP, TEGRA_TRI_NORMAL}, | ||
126 | {TEGRA_PINGROUP_UAB, TEGRA_MUX_ULPI, TEGRA_PUPD_PULL_UP, TEGRA_TRI_NORMAL}, | ||
127 | {TEGRA_PINGROUP_UAC, TEGRA_MUX_RSVD4, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL}, | ||
128 | {TEGRA_PINGROUP_UAD, TEGRA_MUX_SPDIF, TEGRA_PUPD_PULL_UP, TEGRA_TRI_TRISTATE}, | ||
129 | {TEGRA_PINGROUP_UCA, TEGRA_MUX_UARTC, TEGRA_PUPD_PULL_UP, TEGRA_TRI_TRISTATE}, | ||
130 | {TEGRA_PINGROUP_UCB, TEGRA_MUX_UARTC, TEGRA_PUPD_PULL_UP, TEGRA_TRI_TRISTATE}, | ||
131 | {TEGRA_PINGROUP_UDA, TEGRA_MUX_ULPI, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL}, | ||
132 | {TEGRA_PINGROUP_CK32, TEGRA_MUX_NONE, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL}, | ||
133 | {TEGRA_PINGROUP_DDRC, TEGRA_MUX_NONE, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL}, | ||
134 | {TEGRA_PINGROUP_PMCA, TEGRA_MUX_NONE, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL}, | ||
135 | {TEGRA_PINGROUP_PMCB, TEGRA_MUX_NONE, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL}, | ||
136 | {TEGRA_PINGROUP_PMCC, TEGRA_MUX_NONE, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL}, | ||
137 | {TEGRA_PINGROUP_PMCD, TEGRA_MUX_NONE, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL}, | ||
138 | {TEGRA_PINGROUP_PMCE, TEGRA_MUX_NONE, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL}, | ||
139 | {TEGRA_PINGROUP_XM2C, TEGRA_MUX_NONE, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL}, | ||
140 | {TEGRA_PINGROUP_XM2D, TEGRA_MUX_NONE, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL}, | ||
141 | }; | ||
142 | |||
143 | static struct tegra_gpio_table gpio_table[] = { | ||
144 | { .gpio = TEGRA_GPIO_SD1_CD, .enable = true }, | ||
145 | { .gpio = TEGRA_GPIO_SD1_WP, .enable = true }, | ||
146 | { .gpio = TEGRA_GPIO_SD1_POWER, .enable = true }, | ||
147 | { .gpio = TEGRA_GPIO_SD4_CD, .enable = true }, | ||
148 | { .gpio = TEGRA_GPIO_SD4_WP, .enable = true }, | ||
149 | { .gpio = TEGRA_GPIO_SD4_POWER, .enable = true }, | ||
150 | }; | ||
151 | |||
152 | void paz00_pinmux_init(void) | ||
153 | { | ||
154 | tegra_pinmux_config_table(paz00_pinmux, ARRAY_SIZE(paz00_pinmux)); | ||
155 | |||
156 | tegra_gpio_config(gpio_table, ARRAY_SIZE(gpio_table)); | ||
157 | } | ||
diff --git a/arch/arm/mach-tegra/board-paz00.c b/arch/arm/mach-tegra/board-paz00.c new file mode 100644 index 000000000000..57e50a823eec --- /dev/null +++ b/arch/arm/mach-tegra/board-paz00.c | |||
@@ -0,0 +1,128 @@ | |||
1 | /* | ||
2 | * arch/arm/mach-tegra/board-paz00.c | ||
3 | * | ||
4 | * Copyright (C) 2011 Marc Dietrich <marvin24@gmx.de> | ||
5 | * | ||
6 | * Based on board-harmony.c | ||
7 | * Copyright (C) 2010 Google, Inc. | ||
8 | * | ||
9 | * This software is licensed under the terms of the GNU General Public | ||
10 | * License version 2, as published by the Free Software Foundation, and | ||
11 | * may be copied, distributed, and modified under those terms. | ||
12 | * | ||
13 | * This program is distributed in the hope that it will be useful, | ||
14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
16 | * GNU General Public License for more details. | ||
17 | * | ||
18 | */ | ||
19 | |||
20 | #include <linux/kernel.h> | ||
21 | #include <linux/init.h> | ||
22 | #include <linux/platform_device.h> | ||
23 | #include <linux/serial_8250.h> | ||
24 | #include <linux/clk.h> | ||
25 | #include <linux/dma-mapping.h> | ||
26 | #include <linux/pda_power.h> | ||
27 | #include <linux/io.h> | ||
28 | |||
29 | #include <asm/mach-types.h> | ||
30 | #include <asm/mach/arch.h> | ||
31 | #include <asm/mach/time.h> | ||
32 | #include <asm/setup.h> | ||
33 | |||
34 | #include <mach/iomap.h> | ||
35 | #include <mach/irqs.h> | ||
36 | #include <mach/sdhci.h> | ||
37 | |||
38 | #include "board.h" | ||
39 | #include "board-paz00.h" | ||
40 | #include "clock.h" | ||
41 | #include "devices.h" | ||
42 | #include "gpio-names.h" | ||
43 | |||
44 | static struct plat_serial8250_port debug_uart_platform_data[] = { | ||
45 | { | ||
46 | .membase = IO_ADDRESS(TEGRA_UARTD_BASE), | ||
47 | .mapbase = TEGRA_UARTD_BASE, | ||
48 | .irq = INT_UARTD, | ||
49 | .flags = UPF_BOOT_AUTOCONF, | ||
50 | .iotype = UPIO_MEM, | ||
51 | .regshift = 2, | ||
52 | .uartclk = 216000000, | ||
53 | }, { | ||
54 | .flags = 0 | ||
55 | } | ||
56 | }; | ||
57 | |||
58 | static struct platform_device debug_uart = { | ||
59 | .name = "serial8250", | ||
60 | .id = PLAT8250_DEV_PLATFORM, | ||
61 | .dev = { | ||
62 | .platform_data = debug_uart_platform_data, | ||
63 | }, | ||
64 | }; | ||
65 | |||
66 | static struct platform_device *paz00_devices[] __initdata = { | ||
67 | &debug_uart, | ||
68 | &tegra_sdhci_device1, | ||
69 | &tegra_sdhci_device2, | ||
70 | &tegra_sdhci_device4, | ||
71 | }; | ||
72 | |||
73 | static void __init tegra_paz00_fixup(struct machine_desc *desc, | ||
74 | struct tag *tags, char **cmdline, struct meminfo *mi) | ||
75 | { | ||
76 | mi->nr_banks = 1; | ||
77 | mi->bank[0].start = PHYS_OFFSET; | ||
78 | mi->bank[0].size = 448 * SZ_1M; | ||
79 | } | ||
80 | |||
81 | static __initdata struct tegra_clk_init_table paz00_clk_init_table[] = { | ||
82 | /* name parent rate enabled */ | ||
83 | { "uartd", "pll_p", 216000000, true }, | ||
84 | { NULL, NULL, 0, 0}, | ||
85 | }; | ||
86 | |||
87 | |||
88 | static struct tegra_sdhci_platform_data sdhci_pdata1 = { | ||
89 | .cd_gpio = TEGRA_GPIO_SD1_CD, | ||
90 | .wp_gpio = TEGRA_GPIO_SD1_WP, | ||
91 | .power_gpio = TEGRA_GPIO_SD1_POWER, | ||
92 | }; | ||
93 | |||
94 | static struct tegra_sdhci_platform_data sdhci_pdata2 = { | ||
95 | .cd_gpio = -1, | ||
96 | .wp_gpio = -1, | ||
97 | .power_gpio = -1, | ||
98 | }; | ||
99 | |||
100 | static struct tegra_sdhci_platform_data sdhci_pdata4 = { | ||
101 | .cd_gpio = TEGRA_GPIO_SD4_CD, | ||
102 | .wp_gpio = TEGRA_GPIO_SD4_WP, | ||
103 | .power_gpio = TEGRA_GPIO_SD4_POWER, | ||
104 | .is_8bit = 1, | ||
105 | }; | ||
106 | |||
107 | static void __init tegra_paz00_init(void) | ||
108 | { | ||
109 | tegra_clk_init_from_table(paz00_clk_init_table); | ||
110 | |||
111 | paz00_pinmux_init(); | ||
112 | |||
113 | tegra_sdhci_device1.dev.platform_data = &sdhci_pdata1; | ||
114 | tegra_sdhci_device2.dev.platform_data = &sdhci_pdata2; | ||
115 | tegra_sdhci_device4.dev.platform_data = &sdhci_pdata4; | ||
116 | |||
117 | platform_add_devices(paz00_devices, ARRAY_SIZE(paz00_devices)); | ||
118 | } | ||
119 | |||
120 | MACHINE_START(PAZ00, "paz00") | ||
121 | .boot_params = 0x00000100, | ||
122 | .fixup = tegra_paz00_fixup, | ||
123 | .map_io = tegra_map_common_io, | ||
124 | .init_early = tegra_init_early, | ||
125 | .init_irq = tegra_init_irq, | ||
126 | .timer = &tegra_timer, | ||
127 | .init_machine = tegra_paz00_init, | ||
128 | MACHINE_END | ||
diff --git a/arch/arm/mach-tegra/board-paz00.h b/arch/arm/mach-tegra/board-paz00.h new file mode 100644 index 000000000000..da193ca76d3b --- /dev/null +++ b/arch/arm/mach-tegra/board-paz00.h | |||
@@ -0,0 +1,29 @@ | |||
1 | /* | ||
2 | * arch/arm/mach-tegra/board-paz00.h | ||
3 | * | ||
4 | * Copyright (C) 2010 Marc Dietrich <marvin24@gmx.de> | ||
5 | * | ||
6 | * This software is licensed under the terms of the GNU General Public | ||
7 | * License version 2, as published by the Free Software Foundation, and | ||
8 | * may be copied, distributed, and modified under those terms. | ||
9 | * | ||
10 | * This program is distributed in the hope that it will be useful, | ||
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
13 | * GNU General Public License for more details. | ||
14 | * | ||
15 | */ | ||
16 | |||
17 | #ifndef _MACH_TEGRA_BOARD_PAZ00_H | ||
18 | #define _MACH_TEGRA_BOARD_PAZ00_H | ||
19 | |||
20 | #define TEGRA_GPIO_SD1_CD TEGRA_GPIO_PV5 | ||
21 | #define TEGRA_GPIO_SD1_WP TEGRA_GPIO_PH1 | ||
22 | #define TEGRA_GPIO_SD1_POWER TEGRA_GPIO_PT3 | ||
23 | #define TEGRA_GPIO_SD4_CD TEGRA_GPIO_PH2 | ||
24 | #define TEGRA_GPIO_SD4_WP TEGRA_GPIO_PH3 | ||
25 | #define TEGRA_GPIO_SD4_POWER TEGRA_GPIO_PI6 | ||
26 | |||
27 | void paz00_pinmux_init(void); | ||
28 | |||
29 | #endif | ||
diff --git a/arch/arm/mach-tegra/board-seaboard-pinmux.c b/arch/arm/mach-tegra/board-seaboard-pinmux.c new file mode 100644 index 000000000000..0bda495e9742 --- /dev/null +++ b/arch/arm/mach-tegra/board-seaboard-pinmux.c | |||
@@ -0,0 +1,180 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2010 NVIDIA Corporation | ||
3 | * | ||
4 | * This software is licensed under the terms of the GNU General Public | ||
5 | * License version 2, as published by the Free Software Foundation, and | ||
6 | * may be copied, distributed, and modified under those terms. | ||
7 | * | ||
8 | * This program is distributed in the hope that it will be useful, | ||
9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
11 | * GNU General Public License for more details. | ||
12 | * | ||
13 | */ | ||
14 | |||
15 | #include <linux/kernel.h> | ||
16 | #include <linux/init.h> | ||
17 | #include <linux/gpio.h> | ||
18 | |||
19 | #include <mach/pinmux.h> | ||
20 | #include <mach/pinmux-t2.h> | ||
21 | |||
22 | #include "gpio-names.h" | ||
23 | #include "board-seaboard.h" | ||
24 | |||
25 | #define DEFAULT_DRIVE(_name) \ | ||
26 | { \ | ||
27 | .pingroup = TEGRA_DRIVE_PINGROUP_##_name, \ | ||
28 | .hsm = TEGRA_HSM_DISABLE, \ | ||
29 | .schmitt = TEGRA_SCHMITT_ENABLE, \ | ||
30 | .drive = TEGRA_DRIVE_DIV_1, \ | ||
31 | .pull_down = TEGRA_PULL_31, \ | ||
32 | .pull_up = TEGRA_PULL_31, \ | ||
33 | .slew_rising = TEGRA_SLEW_SLOWEST, \ | ||
34 | .slew_falling = TEGRA_SLEW_SLOWEST, \ | ||
35 | } | ||
36 | |||
37 | static __initdata struct tegra_drive_pingroup_config seaboard_drive_pinmux[] = { | ||
38 | DEFAULT_DRIVE(SDIO1), | ||
39 | }; | ||
40 | |||
41 | static __initdata struct tegra_pingroup_config seaboard_pinmux[] = { | ||
42 | {TEGRA_PINGROUP_ATA, TEGRA_MUX_IDE, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL}, | ||
43 | {TEGRA_PINGROUP_ATB, TEGRA_MUX_SDIO4, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL}, | ||
44 | {TEGRA_PINGROUP_ATC, TEGRA_MUX_NAND, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL}, | ||
45 | {TEGRA_PINGROUP_ATD, TEGRA_MUX_GMI, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL}, | ||
46 | {TEGRA_PINGROUP_ATE, TEGRA_MUX_GMI, TEGRA_PUPD_NORMAL, TEGRA_TRI_TRISTATE}, | ||
47 | {TEGRA_PINGROUP_CDEV1, TEGRA_MUX_PLLA_OUT, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL}, | ||
48 | {TEGRA_PINGROUP_CDEV2, TEGRA_MUX_PLLP_OUT4, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL}, | ||
49 | {TEGRA_PINGROUP_CRTP, TEGRA_MUX_CRT, TEGRA_PUPD_PULL_UP, TEGRA_TRI_TRISTATE}, | ||
50 | {TEGRA_PINGROUP_CSUS, TEGRA_MUX_VI_SENSOR_CLK, TEGRA_PUPD_NORMAL, TEGRA_TRI_TRISTATE}, | ||
51 | {TEGRA_PINGROUP_DAP1, TEGRA_MUX_DAP1, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL}, | ||
52 | {TEGRA_PINGROUP_DAP2, TEGRA_MUX_DAP2, TEGRA_PUPD_NORMAL, TEGRA_TRI_TRISTATE}, | ||
53 | {TEGRA_PINGROUP_DAP3, TEGRA_MUX_DAP3, TEGRA_PUPD_NORMAL, TEGRA_TRI_TRISTATE}, | ||
54 | {TEGRA_PINGROUP_DAP4, TEGRA_MUX_DAP4, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL}, | ||
55 | {TEGRA_PINGROUP_DDC, TEGRA_MUX_RSVD2, TEGRA_PUPD_NORMAL, TEGRA_TRI_TRISTATE}, | ||
56 | {TEGRA_PINGROUP_DTA, TEGRA_MUX_VI, TEGRA_PUPD_PULL_DOWN, TEGRA_TRI_NORMAL}, | ||
57 | {TEGRA_PINGROUP_DTB, TEGRA_MUX_VI, TEGRA_PUPD_PULL_DOWN, TEGRA_TRI_NORMAL}, | ||
58 | {TEGRA_PINGROUP_DTC, TEGRA_MUX_VI, TEGRA_PUPD_PULL_DOWN, TEGRA_TRI_NORMAL}, | ||
59 | {TEGRA_PINGROUP_DTD, TEGRA_MUX_VI, TEGRA_PUPD_PULL_DOWN, TEGRA_TRI_NORMAL}, | ||
60 | {TEGRA_PINGROUP_DTE, TEGRA_MUX_VI, TEGRA_PUPD_PULL_DOWN, TEGRA_TRI_TRISTATE}, | ||
61 | {TEGRA_PINGROUP_DTF, TEGRA_MUX_I2C3, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL}, | ||
62 | {TEGRA_PINGROUP_GMA, TEGRA_MUX_SDIO4, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL}, | ||
63 | {TEGRA_PINGROUP_GMB, TEGRA_MUX_GMI, TEGRA_PUPD_PULL_UP, TEGRA_TRI_TRISTATE}, | ||
64 | {TEGRA_PINGROUP_GMC, TEGRA_MUX_UARTD, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL}, | ||
65 | {TEGRA_PINGROUP_GMD, TEGRA_MUX_SFLASH, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL}, | ||
66 | {TEGRA_PINGROUP_GME, TEGRA_MUX_SDIO4, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL}, | ||
67 | {TEGRA_PINGROUP_GPU, TEGRA_MUX_PWM, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL}, | ||
68 | {TEGRA_PINGROUP_GPU7, TEGRA_MUX_RTCK, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL}, | ||
69 | {TEGRA_PINGROUP_GPV, TEGRA_MUX_PCIE, TEGRA_PUPD_NORMAL, TEGRA_TRI_TRISTATE}, | ||
70 | {TEGRA_PINGROUP_HDINT, TEGRA_MUX_HDMI, TEGRA_PUPD_NORMAL, TEGRA_TRI_TRISTATE}, | ||
71 | {TEGRA_PINGROUP_I2CP, TEGRA_MUX_I2C, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL}, | ||
72 | {TEGRA_PINGROUP_IRRX, TEGRA_MUX_UARTB, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL}, | ||
73 | {TEGRA_PINGROUP_IRTX, TEGRA_MUX_UARTB, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL}, | ||
74 | {TEGRA_PINGROUP_KBCA, TEGRA_MUX_KBC, TEGRA_PUPD_PULL_UP, TEGRA_TRI_NORMAL}, | ||
75 | {TEGRA_PINGROUP_KBCB, TEGRA_MUX_KBC, TEGRA_PUPD_PULL_UP, TEGRA_TRI_NORMAL}, | ||
76 | {TEGRA_PINGROUP_KBCC, TEGRA_MUX_KBC, TEGRA_PUPD_PULL_UP, TEGRA_TRI_NORMAL}, | ||
77 | {TEGRA_PINGROUP_KBCD, TEGRA_MUX_KBC, TEGRA_PUPD_PULL_UP, TEGRA_TRI_NORMAL}, | ||
78 | {TEGRA_PINGROUP_KBCE, TEGRA_MUX_KBC, TEGRA_PUPD_PULL_UP, TEGRA_TRI_NORMAL}, | ||
79 | {TEGRA_PINGROUP_KBCF, TEGRA_MUX_KBC, TEGRA_PUPD_PULL_UP, TEGRA_TRI_NORMAL}, | ||
80 | {TEGRA_PINGROUP_LCSN, TEGRA_MUX_RSVD4, TEGRA_PUPD_NORMAL, TEGRA_TRI_TRISTATE}, | ||
81 | {TEGRA_PINGROUP_LD0, TEGRA_MUX_DISPLAYA, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL}, | ||
82 | {TEGRA_PINGROUP_LD1, TEGRA_MUX_DISPLAYA, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL}, | ||
83 | {TEGRA_PINGROUP_LD10, TEGRA_MUX_DISPLAYA, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL}, | ||
84 | {TEGRA_PINGROUP_LD11, TEGRA_MUX_DISPLAYA, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL}, | ||
85 | {TEGRA_PINGROUP_LD12, TEGRA_MUX_DISPLAYA, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL}, | ||
86 | {TEGRA_PINGROUP_LD13, TEGRA_MUX_DISPLAYA, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL}, | ||
87 | {TEGRA_PINGROUP_LD14, TEGRA_MUX_DISPLAYA, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL}, | ||
88 | {TEGRA_PINGROUP_LD15, TEGRA_MUX_DISPLAYA, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL}, | ||
89 | {TEGRA_PINGROUP_LD16, TEGRA_MUX_DISPLAYA, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL}, | ||
90 | {TEGRA_PINGROUP_LD17, TEGRA_MUX_DISPLAYA, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL}, | ||
91 | {TEGRA_PINGROUP_LD2, TEGRA_MUX_DISPLAYA, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL}, | ||
92 | {TEGRA_PINGROUP_LD3, TEGRA_MUX_DISPLAYA, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL}, | ||
93 | {TEGRA_PINGROUP_LD4, TEGRA_MUX_DISPLAYA, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL}, | ||
94 | {TEGRA_PINGROUP_LD5, TEGRA_MUX_DISPLAYA, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL}, | ||
95 | {TEGRA_PINGROUP_LD6, TEGRA_MUX_DISPLAYA, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL}, | ||
96 | {TEGRA_PINGROUP_LD7, TEGRA_MUX_DISPLAYA, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL}, | ||
97 | {TEGRA_PINGROUP_LD8, TEGRA_MUX_DISPLAYA, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL}, | ||
98 | {TEGRA_PINGROUP_LD9, TEGRA_MUX_DISPLAYA, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL}, | ||
99 | {TEGRA_PINGROUP_LDC, TEGRA_MUX_RSVD4, TEGRA_PUPD_NORMAL, TEGRA_TRI_TRISTATE}, | ||
100 | {TEGRA_PINGROUP_LDI, TEGRA_MUX_DISPLAYA, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL}, | ||
101 | {TEGRA_PINGROUP_LHP0, TEGRA_MUX_DISPLAYA, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL}, | ||
102 | {TEGRA_PINGROUP_LHP1, TEGRA_MUX_DISPLAYA, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL}, | ||
103 | {TEGRA_PINGROUP_LHP2, TEGRA_MUX_DISPLAYA, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL}, | ||
104 | {TEGRA_PINGROUP_LHS, TEGRA_MUX_DISPLAYA, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL}, | ||
105 | {TEGRA_PINGROUP_LM0, TEGRA_MUX_RSVD4, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL}, | ||
106 | {TEGRA_PINGROUP_LM1, TEGRA_MUX_CRT, TEGRA_PUPD_NORMAL, TEGRA_TRI_TRISTATE}, | ||
107 | {TEGRA_PINGROUP_LPP, TEGRA_MUX_DISPLAYA, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL}, | ||
108 | {TEGRA_PINGROUP_LPW0, TEGRA_MUX_HDMI, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL}, | ||
109 | {TEGRA_PINGROUP_LPW1, TEGRA_MUX_RSVD4, TEGRA_PUPD_NORMAL, TEGRA_TRI_TRISTATE}, | ||
110 | {TEGRA_PINGROUP_LPW2, TEGRA_MUX_HDMI, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL}, | ||
111 | {TEGRA_PINGROUP_LSC0, TEGRA_MUX_DISPLAYA, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL}, | ||
112 | {TEGRA_PINGROUP_LSC1, TEGRA_MUX_HDMI, TEGRA_PUPD_NORMAL, TEGRA_TRI_TRISTATE}, | ||
113 | {TEGRA_PINGROUP_LSCK, TEGRA_MUX_HDMI, TEGRA_PUPD_NORMAL, TEGRA_TRI_TRISTATE}, | ||
114 | {TEGRA_PINGROUP_LSDA, TEGRA_MUX_HDMI, TEGRA_PUPD_NORMAL, TEGRA_TRI_TRISTATE}, | ||
115 | {TEGRA_PINGROUP_LSDI, TEGRA_MUX_RSVD4, TEGRA_PUPD_NORMAL, TEGRA_TRI_TRISTATE}, | ||
116 | {TEGRA_PINGROUP_LSPI, TEGRA_MUX_DISPLAYA, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL}, | ||
117 | {TEGRA_PINGROUP_LVP0, TEGRA_MUX_RSVD4, TEGRA_PUPD_NORMAL, TEGRA_TRI_TRISTATE}, | ||
118 | {TEGRA_PINGROUP_LVP1, TEGRA_MUX_DISPLAYA, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL}, | ||
119 | {TEGRA_PINGROUP_LVS, TEGRA_MUX_DISPLAYA, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL}, | ||
120 | {TEGRA_PINGROUP_OWC, TEGRA_MUX_RSVD2, TEGRA_PUPD_NORMAL, TEGRA_TRI_TRISTATE}, | ||
121 | {TEGRA_PINGROUP_PMC, TEGRA_MUX_PWR_ON, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL}, | ||
122 | {TEGRA_PINGROUP_PTA, TEGRA_MUX_HDMI, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL}, | ||
123 | {TEGRA_PINGROUP_RM, TEGRA_MUX_I2C, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL}, | ||
124 | {TEGRA_PINGROUP_SDB, TEGRA_MUX_SDIO3, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL}, | ||
125 | {TEGRA_PINGROUP_SDC, TEGRA_MUX_SDIO3, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL}, | ||
126 | {TEGRA_PINGROUP_SDD, TEGRA_MUX_SDIO3, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL}, | ||
127 | {TEGRA_PINGROUP_SDIO1, TEGRA_MUX_SDIO1, TEGRA_PUPD_PULL_UP, TEGRA_TRI_NORMAL}, | ||
128 | {TEGRA_PINGROUP_SLXA, TEGRA_MUX_PCIE, TEGRA_PUPD_PULL_UP, TEGRA_TRI_TRISTATE}, | ||
129 | {TEGRA_PINGROUP_SLXC, TEGRA_MUX_SPDIF, TEGRA_PUPD_NORMAL, TEGRA_TRI_TRISTATE}, | ||
130 | {TEGRA_PINGROUP_SLXD, TEGRA_MUX_SPDIF, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL}, | ||
131 | {TEGRA_PINGROUP_SLXK, TEGRA_MUX_PCIE, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL}, | ||
132 | {TEGRA_PINGROUP_SPDI, TEGRA_MUX_RSVD2, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL}, | ||
133 | {TEGRA_PINGROUP_SPDO, TEGRA_MUX_RSVD2, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL}, | ||
134 | {TEGRA_PINGROUP_SPIA, TEGRA_MUX_GMI, TEGRA_PUPD_PULL_UP, TEGRA_TRI_TRISTATE}, | ||
135 | {TEGRA_PINGROUP_SPIB, TEGRA_MUX_GMI, TEGRA_PUPD_NORMAL, TEGRA_TRI_TRISTATE}, | ||
136 | {TEGRA_PINGROUP_SPIC, TEGRA_MUX_GMI, TEGRA_PUPD_NORMAL, TEGRA_TRI_TRISTATE}, | ||
137 | {TEGRA_PINGROUP_SPID, TEGRA_MUX_SPI1, TEGRA_PUPD_NORMAL, TEGRA_TRI_TRISTATE}, | ||
138 | {TEGRA_PINGROUP_SPIE, TEGRA_MUX_SPI1, TEGRA_PUPD_NORMAL, TEGRA_TRI_TRISTATE}, | ||
139 | {TEGRA_PINGROUP_SPIF, TEGRA_MUX_SPI1, TEGRA_PUPD_PULL_DOWN, TEGRA_TRI_TRISTATE}, | ||
140 | {TEGRA_PINGROUP_SPIG, TEGRA_MUX_SPI2_ALT, TEGRA_PUPD_PULL_UP, TEGRA_TRI_TRISTATE}, | ||
141 | {TEGRA_PINGROUP_SPIH, TEGRA_MUX_SPI2_ALT, TEGRA_PUPD_PULL_UP, TEGRA_TRI_TRISTATE}, | ||
142 | {TEGRA_PINGROUP_UAA, TEGRA_MUX_ULPI, TEGRA_PUPD_PULL_UP, TEGRA_TRI_NORMAL}, | ||
143 | {TEGRA_PINGROUP_UAB, TEGRA_MUX_ULPI, TEGRA_PUPD_PULL_UP, TEGRA_TRI_NORMAL}, | ||
144 | {TEGRA_PINGROUP_UAC, TEGRA_MUX_RSVD2, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL}, | ||
145 | {TEGRA_PINGROUP_UAD, TEGRA_MUX_IRDA, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL}, | ||
146 | {TEGRA_PINGROUP_UCA, TEGRA_MUX_UARTC, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL}, | ||
147 | {TEGRA_PINGROUP_UCB, TEGRA_MUX_UARTC, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL}, | ||
148 | {TEGRA_PINGROUP_UDA, TEGRA_MUX_ULPI, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL}, | ||
149 | {TEGRA_PINGROUP_CK32, TEGRA_MUX_NONE, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL}, | ||
150 | {TEGRA_PINGROUP_DDRC, TEGRA_MUX_NONE, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL}, | ||
151 | {TEGRA_PINGROUP_PMCA, TEGRA_MUX_NONE, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL}, | ||
152 | {TEGRA_PINGROUP_PMCB, TEGRA_MUX_NONE, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL}, | ||
153 | {TEGRA_PINGROUP_PMCC, TEGRA_MUX_NONE, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL}, | ||
154 | {TEGRA_PINGROUP_PMCD, TEGRA_MUX_NONE, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL}, | ||
155 | {TEGRA_PINGROUP_PMCE, TEGRA_MUX_NONE, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL}, | ||
156 | {TEGRA_PINGROUP_XM2C, TEGRA_MUX_NONE, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL}, | ||
157 | {TEGRA_PINGROUP_XM2D, TEGRA_MUX_NONE, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL}, | ||
158 | }; | ||
159 | |||
160 | |||
161 | |||
162 | |||
163 | static struct tegra_gpio_table gpio_table[] = { | ||
164 | { .gpio = TEGRA_GPIO_SD2_CD, .enable = true }, | ||
165 | { .gpio = TEGRA_GPIO_SD2_WP, .enable = true }, | ||
166 | { .gpio = TEGRA_GPIO_SD2_POWER, .enable = true }, | ||
167 | { .gpio = TEGRA_GPIO_LIDSWITCH, .enable = true }, | ||
168 | { .gpio = TEGRA_GPIO_POWERKEY, .enable = true }, | ||
169 | { .gpio = TEGRA_GPIO_ISL29018_IRQ, .enable = true }, | ||
170 | }; | ||
171 | |||
172 | void __init seaboard_pinmux_init(void) | ||
173 | { | ||
174 | tegra_pinmux_config_table(seaboard_pinmux, ARRAY_SIZE(seaboard_pinmux)); | ||
175 | |||
176 | tegra_drive_pinmux_config_table(seaboard_drive_pinmux, | ||
177 | ARRAY_SIZE(seaboard_drive_pinmux)); | ||
178 | |||
179 | tegra_gpio_config(gpio_table, ARRAY_SIZE(gpio_table)); | ||
180 | } | ||
diff --git a/arch/arm/mach-tegra/board-seaboard.c b/arch/arm/mach-tegra/board-seaboard.c new file mode 100644 index 000000000000..a8d7ace9f958 --- /dev/null +++ b/arch/arm/mach-tegra/board-seaboard.c | |||
@@ -0,0 +1,250 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2010, 2011 NVIDIA Corporation. | ||
3 | * Copyright (C) 2010, 2011 Google, Inc. | ||
4 | * | ||
5 | * This program is free software; you can redistribute it and/or modify | ||
6 | * it under the terms of the GNU General Public License as published by | ||
7 | * the Free Software Foundation; either version 2 of the License, or | ||
8 | * (at your option) any later version. | ||
9 | * | ||
10 | * This program is distributed in the hope that it will be useful, but WITHOUT | ||
11 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||
12 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | ||
13 | * more details. | ||
14 | * | ||
15 | */ | ||
16 | |||
17 | #include <linux/kernel.h> | ||
18 | #include <linux/init.h> | ||
19 | #include <linux/platform_device.h> | ||
20 | #include <linux/serial_8250.h> | ||
21 | #include <linux/i2c.h> | ||
22 | #include <linux/i2c-tegra.h> | ||
23 | #include <linux/delay.h> | ||
24 | #include <linux/input.h> | ||
25 | #include <linux/io.h> | ||
26 | #include <linux/gpio.h> | ||
27 | #include <linux/gpio_keys.h> | ||
28 | |||
29 | #include <mach/iomap.h> | ||
30 | #include <mach/irqs.h> | ||
31 | #include <mach/sdhci.h> | ||
32 | |||
33 | #include <asm/mach-types.h> | ||
34 | #include <asm/mach/arch.h> | ||
35 | |||
36 | #include "board.h" | ||
37 | #include "board-seaboard.h" | ||
38 | #include "clock.h" | ||
39 | #include "devices.h" | ||
40 | #include "gpio-names.h" | ||
41 | |||
42 | static struct plat_serial8250_port debug_uart_platform_data[] = { | ||
43 | { | ||
44 | /* Memory and IRQ filled in before registration */ | ||
45 | .flags = UPF_BOOT_AUTOCONF, | ||
46 | .iotype = UPIO_MEM, | ||
47 | .regshift = 2, | ||
48 | .uartclk = 216000000, | ||
49 | }, { | ||
50 | .flags = 0, | ||
51 | } | ||
52 | }; | ||
53 | |||
54 | static struct platform_device debug_uart = { | ||
55 | .name = "serial8250", | ||
56 | .id = PLAT8250_DEV_PLATFORM, | ||
57 | .dev = { | ||
58 | .platform_data = debug_uart_platform_data, | ||
59 | }, | ||
60 | }; | ||
61 | |||
62 | static __initdata struct tegra_clk_init_table seaboard_clk_init_table[] = { | ||
63 | /* name parent rate enabled */ | ||
64 | { "uartb", "pll_p", 216000000, true}, | ||
65 | { "uartd", "pll_p", 216000000, true}, | ||
66 | { NULL, NULL, 0, 0}, | ||
67 | }; | ||
68 | |||
69 | static struct tegra_i2c_platform_data seaboard_i2c1_platform_data = { | ||
70 | .bus_clk_rate = 400000. | ||
71 | }; | ||
72 | |||
73 | static struct tegra_i2c_platform_data seaboard_i2c2_platform_data = { | ||
74 | .bus_clk_rate = 400000, | ||
75 | }; | ||
76 | |||
77 | static struct tegra_i2c_platform_data seaboard_i2c3_platform_data = { | ||
78 | .bus_clk_rate = 400000, | ||
79 | }; | ||
80 | |||
81 | static struct tegra_i2c_platform_data seaboard_dvc_platform_data = { | ||
82 | .bus_clk_rate = 400000, | ||
83 | }; | ||
84 | |||
85 | static struct gpio_keys_button seaboard_gpio_keys_buttons[] = { | ||
86 | { | ||
87 | .code = SW_LID, | ||
88 | .gpio = TEGRA_GPIO_LIDSWITCH, | ||
89 | .active_low = 0, | ||
90 | .desc = "Lid", | ||
91 | .type = EV_SW, | ||
92 | .wakeup = 1, | ||
93 | .debounce_interval = 1, | ||
94 | }, | ||
95 | { | ||
96 | .code = KEY_POWER, | ||
97 | .gpio = TEGRA_GPIO_POWERKEY, | ||
98 | .active_low = 1, | ||
99 | .desc = "Power", | ||
100 | .type = EV_KEY, | ||
101 | .wakeup = 1, | ||
102 | }, | ||
103 | }; | ||
104 | |||
105 | static struct gpio_keys_platform_data seaboard_gpio_keys = { | ||
106 | .buttons = seaboard_gpio_keys_buttons, | ||
107 | .nbuttons = ARRAY_SIZE(seaboard_gpio_keys_buttons), | ||
108 | }; | ||
109 | |||
110 | static struct platform_device seaboard_gpio_keys_device = { | ||
111 | .name = "gpio-keys", | ||
112 | .id = -1, | ||
113 | .dev = { | ||
114 | .platform_data = &seaboard_gpio_keys, | ||
115 | } | ||
116 | }; | ||
117 | |||
118 | static struct tegra_sdhci_platform_data sdhci_pdata1 = { | ||
119 | .cd_gpio = -1, | ||
120 | .wp_gpio = -1, | ||
121 | .power_gpio = -1, | ||
122 | }; | ||
123 | |||
124 | static struct tegra_sdhci_platform_data sdhci_pdata3 = { | ||
125 | .cd_gpio = TEGRA_GPIO_SD2_CD, | ||
126 | .wp_gpio = TEGRA_GPIO_SD2_WP, | ||
127 | .power_gpio = TEGRA_GPIO_SD2_POWER, | ||
128 | }; | ||
129 | |||
130 | static struct tegra_sdhci_platform_data sdhci_pdata4 = { | ||
131 | .cd_gpio = -1, | ||
132 | .wp_gpio = -1, | ||
133 | .power_gpio = -1, | ||
134 | .is_8bit = 1, | ||
135 | }; | ||
136 | |||
137 | static struct platform_device *seaboard_devices[] __initdata = { | ||
138 | &debug_uart, | ||
139 | &tegra_pmu_device, | ||
140 | &tegra_sdhci_device1, | ||
141 | &tegra_sdhci_device3, | ||
142 | &tegra_sdhci_device4, | ||
143 | &seaboard_gpio_keys_device, | ||
144 | }; | ||
145 | |||
146 | static struct i2c_board_info __initdata isl29018_device = { | ||
147 | I2C_BOARD_INFO("isl29018", 0x44), | ||
148 | .irq = TEGRA_GPIO_TO_IRQ(TEGRA_GPIO_ISL29018_IRQ), | ||
149 | }; | ||
150 | |||
151 | static struct i2c_board_info __initdata adt7461_device = { | ||
152 | I2C_BOARD_INFO("adt7461", 0x4c), | ||
153 | }; | ||
154 | |||
155 | static void __init seaboard_i2c_init(void) | ||
156 | { | ||
157 | gpio_request(TEGRA_GPIO_ISL29018_IRQ, "isl29018"); | ||
158 | gpio_direction_input(TEGRA_GPIO_ISL29018_IRQ); | ||
159 | |||
160 | i2c_register_board_info(0, &isl29018_device, 1); | ||
161 | |||
162 | i2c_register_board_info(4, &adt7461_device, 1); | ||
163 | |||
164 | tegra_i2c_device1.dev.platform_data = &seaboard_i2c1_platform_data; | ||
165 | tegra_i2c_device2.dev.platform_data = &seaboard_i2c2_platform_data; | ||
166 | tegra_i2c_device3.dev.platform_data = &seaboard_i2c3_platform_data; | ||
167 | tegra_i2c_device4.dev.platform_data = &seaboard_dvc_platform_data; | ||
168 | |||
169 | platform_device_register(&tegra_i2c_device1); | ||
170 | platform_device_register(&tegra_i2c_device2); | ||
171 | platform_device_register(&tegra_i2c_device3); | ||
172 | platform_device_register(&tegra_i2c_device4); | ||
173 | } | ||
174 | |||
175 | static void __init seaboard_common_init(void) | ||
176 | { | ||
177 | seaboard_pinmux_init(); | ||
178 | |||
179 | tegra_clk_init_from_table(seaboard_clk_init_table); | ||
180 | |||
181 | tegra_sdhci_device1.dev.platform_data = &sdhci_pdata1; | ||
182 | tegra_sdhci_device3.dev.platform_data = &sdhci_pdata3; | ||
183 | tegra_sdhci_device4.dev.platform_data = &sdhci_pdata4; | ||
184 | |||
185 | platform_add_devices(seaboard_devices, ARRAY_SIZE(seaboard_devices)); | ||
186 | } | ||
187 | |||
188 | static void __init tegra_seaboard_init(void) | ||
189 | { | ||
190 | /* Seaboard uses UARTD for the debug port. */ | ||
191 | debug_uart_platform_data[0].membase = IO_ADDRESS(TEGRA_UARTD_BASE); | ||
192 | debug_uart_platform_data[0].mapbase = TEGRA_UARTD_BASE; | ||
193 | debug_uart_platform_data[0].irq = INT_UARTD; | ||
194 | |||
195 | seaboard_common_init(); | ||
196 | |||
197 | seaboard_i2c_init(); | ||
198 | } | ||
199 | |||
200 | static void __init tegra_kaen_init(void) | ||
201 | { | ||
202 | /* Kaen uses UARTB for the debug port. */ | ||
203 | debug_uart_platform_data[0].membase = IO_ADDRESS(TEGRA_UARTB_BASE); | ||
204 | debug_uart_platform_data[0].mapbase = TEGRA_UARTB_BASE; | ||
205 | debug_uart_platform_data[0].irq = INT_UARTB; | ||
206 | |||
207 | seaboard_common_init(); | ||
208 | |||
209 | seaboard_i2c_init(); | ||
210 | } | ||
211 | |||
212 | static void __init tegra_wario_init(void) | ||
213 | { | ||
214 | /* Wario uses UARTB for the debug port. */ | ||
215 | debug_uart_platform_data[0].membase = IO_ADDRESS(TEGRA_UARTB_BASE); | ||
216 | debug_uart_platform_data[0].mapbase = TEGRA_UARTB_BASE; | ||
217 | debug_uart_platform_data[0].irq = INT_UARTB; | ||
218 | |||
219 | seaboard_common_init(); | ||
220 | |||
221 | seaboard_i2c_init(); | ||
222 | } | ||
223 | |||
224 | |||
225 | MACHINE_START(SEABOARD, "seaboard") | ||
226 | .boot_params = 0x00000100, | ||
227 | .map_io = tegra_map_common_io, | ||
228 | .init_early = tegra_init_early, | ||
229 | .init_irq = tegra_init_irq, | ||
230 | .timer = &tegra_timer, | ||
231 | .init_machine = tegra_seaboard_init, | ||
232 | MACHINE_END | ||
233 | |||
234 | MACHINE_START(KAEN, "kaen") | ||
235 | .boot_params = 0x00000100, | ||
236 | .map_io = tegra_map_common_io, | ||
237 | .init_early = tegra_init_early, | ||
238 | .init_irq = tegra_init_irq, | ||
239 | .timer = &tegra_timer, | ||
240 | .init_machine = tegra_kaen_init, | ||
241 | MACHINE_END | ||
242 | |||
243 | MACHINE_START(WARIO, "wario") | ||
244 | .boot_params = 0x00000100, | ||
245 | .map_io = tegra_map_common_io, | ||
246 | .init_early = tegra_init_early, | ||
247 | .init_irq = tegra_init_irq, | ||
248 | .timer = &tegra_timer, | ||
249 | .init_machine = tegra_wario_init, | ||
250 | MACHINE_END | ||
diff --git a/arch/arm/mach-tegra/board-seaboard.h b/arch/arm/mach-tegra/board-seaboard.h new file mode 100644 index 000000000000..d8415e1a8434 --- /dev/null +++ b/arch/arm/mach-tegra/board-seaboard.h | |||
@@ -0,0 +1,41 @@ | |||
1 | /* | ||
2 | * arch/arm/mach-tegra/board-seaboard.h | ||
3 | * | ||
4 | * Copyright (C) 2010 Google, Inc. | ||
5 | * | ||
6 | * This software is licensed under the terms of the GNU General Public | ||
7 | * License version 2, as published by the Free Software Foundation, and | ||
8 | * may be copied, distributed, and modified under those terms. | ||
9 | * | ||
10 | * This program is distributed in the hope that it will be useful, | ||
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
13 | * GNU General Public License for more details. | ||
14 | * | ||
15 | */ | ||
16 | |||
17 | #ifndef _MACH_TEGRA_BOARD_SEABOARD_H | ||
18 | #define _MACH_TEGRA_BOARD_SEABOARD_H | ||
19 | |||
20 | #define TEGRA_GPIO_SD2_CD TEGRA_GPIO_PI5 | ||
21 | #define TEGRA_GPIO_SD2_WP TEGRA_GPIO_PH1 | ||
22 | #define TEGRA_GPIO_SD2_POWER TEGRA_GPIO_PI6 | ||
23 | #define TEGRA_GPIO_LIDSWITCH TEGRA_GPIO_PC7 | ||
24 | #define TEGRA_GPIO_USB1 TEGRA_GPIO_PD0 | ||
25 | #define TEGRA_GPIO_POWERKEY TEGRA_GPIO_PV2 | ||
26 | #define TEGRA_GPIO_BACKLIGHT TEGRA_GPIO_PD4 | ||
27 | #define TEGRA_GPIO_LVDS_SHUTDOWN TEGRA_GPIO_PB2 | ||
28 | #define TEGRA_GPIO_BACKLIGHT_PWM TEGRA_GPIO_PU5 | ||
29 | #define TEGRA_GPIO_BACKLIGHT_VDD TEGRA_GPIO_PW0 | ||
30 | #define TEGRA_GPIO_EN_VDD_PNL TEGRA_GPIO_PC6 | ||
31 | #define TEGRA_GPIO_MAGNETOMETER TEGRA_GPIO_PN5 | ||
32 | #define TEGRA_GPIO_ISL29018_IRQ TEGRA_GPIO_PZ2 | ||
33 | #define TEGRA_GPIO_AC_ONLINE TEGRA_GPIO_PV3 | ||
34 | |||
35 | #define TPS_GPIO_BASE TEGRA_NR_GPIOS | ||
36 | |||
37 | #define TPS_GPIO_WWAN_PWR (TPS_GPIO_BASE + 2) | ||
38 | |||
39 | void seaboard_pinmux_init(void); | ||
40 | |||
41 | #endif | ||
diff --git a/arch/arm/mach-tegra/board-trimslice-pinmux.c b/arch/arm/mach-tegra/board-trimslice-pinmux.c new file mode 100644 index 000000000000..13534fa08abf --- /dev/null +++ b/arch/arm/mach-tegra/board-trimslice-pinmux.c | |||
@@ -0,0 +1,154 @@ | |||
1 | /* | ||
2 | * arch/arm/mach-tegra/board-trimslice-pinmux.c | ||
3 | * | ||
4 | * Copyright (C) 2011 CompuLab, Ltd. | ||
5 | * | ||
6 | * This software is licensed under the terms of the GNU General Public | ||
7 | * License version 2, as published by the Free Software Foundation, and | ||
8 | * may be copied, distributed, and modified under those terms. | ||
9 | * | ||
10 | * This program is distributed in the hope that it will be useful, | ||
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
13 | * GNU General Public License for more details. | ||
14 | * | ||
15 | */ | ||
16 | |||
17 | #include <linux/kernel.h> | ||
18 | #include <linux/init.h> | ||
19 | |||
20 | #include <mach/pinmux.h> | ||
21 | #include <mach/gpio.h> | ||
22 | |||
23 | #include "gpio-names.h" | ||
24 | #include "board-trimslice.h" | ||
25 | |||
26 | static __initdata struct tegra_pingroup_config trimslice_pinmux[] = { | ||
27 | {TEGRA_PINGROUP_ATA, TEGRA_MUX_IDE, TEGRA_PUPD_NORMAL, TEGRA_TRI_TRISTATE}, | ||
28 | {TEGRA_PINGROUP_ATB, TEGRA_MUX_SDIO4, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL}, | ||
29 | {TEGRA_PINGROUP_ATC, TEGRA_MUX_NAND, TEGRA_PUPD_NORMAL, TEGRA_TRI_TRISTATE}, | ||
30 | {TEGRA_PINGROUP_ATD, TEGRA_MUX_GMI, TEGRA_PUPD_NORMAL, TEGRA_TRI_TRISTATE}, | ||
31 | {TEGRA_PINGROUP_ATE, TEGRA_MUX_GMI, TEGRA_PUPD_NORMAL, TEGRA_TRI_TRISTATE}, | ||
32 | {TEGRA_PINGROUP_CDEV1, TEGRA_MUX_OSC, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL}, | ||
33 | {TEGRA_PINGROUP_CDEV2, TEGRA_MUX_PLLP_OUT4, TEGRA_PUPD_PULL_DOWN, TEGRA_TRI_TRISTATE}, | ||
34 | {TEGRA_PINGROUP_CRTP, TEGRA_MUX_CRT, TEGRA_PUPD_NORMAL, TEGRA_TRI_TRISTATE}, | ||
35 | {TEGRA_PINGROUP_CSUS, TEGRA_MUX_VI_SENSOR_CLK, TEGRA_PUPD_PULL_DOWN, TEGRA_TRI_TRISTATE}, | ||
36 | {TEGRA_PINGROUP_DAP1, TEGRA_MUX_DAP1, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL}, | ||
37 | {TEGRA_PINGROUP_DAP2, TEGRA_MUX_DAP2, TEGRA_PUPD_NORMAL, TEGRA_TRI_TRISTATE}, | ||
38 | {TEGRA_PINGROUP_DAP3, TEGRA_MUX_DAP3, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL}, | ||
39 | {TEGRA_PINGROUP_DAP4, TEGRA_MUX_DAP4, TEGRA_PUPD_NORMAL, TEGRA_TRI_TRISTATE}, | ||
40 | {TEGRA_PINGROUP_DDC, TEGRA_MUX_I2C2, TEGRA_PUPD_PULL_UP, TEGRA_TRI_NORMAL}, | ||
41 | {TEGRA_PINGROUP_DTA, TEGRA_MUX_VI, TEGRA_PUPD_NORMAL, TEGRA_TRI_TRISTATE}, | ||
42 | {TEGRA_PINGROUP_DTB, TEGRA_MUX_VI, TEGRA_PUPD_NORMAL, TEGRA_TRI_TRISTATE}, | ||
43 | {TEGRA_PINGROUP_DTC, TEGRA_MUX_VI, TEGRA_PUPD_NORMAL, TEGRA_TRI_TRISTATE}, | ||
44 | {TEGRA_PINGROUP_DTD, TEGRA_MUX_VI, TEGRA_PUPD_NORMAL, TEGRA_TRI_TRISTATE}, | ||
45 | {TEGRA_PINGROUP_DTE, TEGRA_MUX_VI, TEGRA_PUPD_NORMAL, TEGRA_TRI_TRISTATE}, | ||
46 | {TEGRA_PINGROUP_DTF, TEGRA_MUX_I2C3, TEGRA_PUPD_PULL_UP, TEGRA_TRI_NORMAL}, | ||
47 | {TEGRA_PINGROUP_GMA, TEGRA_MUX_SDIO4, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL}, | ||
48 | {TEGRA_PINGROUP_GMB, TEGRA_MUX_NAND, TEGRA_PUPD_NORMAL, TEGRA_TRI_TRISTATE}, | ||
49 | {TEGRA_PINGROUP_GMC, TEGRA_MUX_SFLASH, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL}, | ||
50 | {TEGRA_PINGROUP_GMD, TEGRA_MUX_SFLASH, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL}, | ||
51 | {TEGRA_PINGROUP_GME, TEGRA_MUX_GMI, TEGRA_PUPD_NORMAL, TEGRA_TRI_TRISTATE}, | ||
52 | {TEGRA_PINGROUP_GPU, TEGRA_MUX_UARTA, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL}, | ||
53 | {TEGRA_PINGROUP_GPU7, TEGRA_MUX_RTCK, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL}, | ||
54 | {TEGRA_PINGROUP_GPV, TEGRA_MUX_PCIE, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL}, | ||
55 | {TEGRA_PINGROUP_HDINT, TEGRA_MUX_HDMI, TEGRA_PUPD_PULL_UP, TEGRA_TRI_TRISTATE}, | ||
56 | {TEGRA_PINGROUP_I2CP, TEGRA_MUX_I2C, TEGRA_PUPD_NORMAL, TEGRA_TRI_TRISTATE}, | ||
57 | {TEGRA_PINGROUP_IRRX, TEGRA_MUX_UARTB, TEGRA_PUPD_PULL_UP, TEGRA_TRI_TRISTATE}, | ||
58 | {TEGRA_PINGROUP_IRTX, TEGRA_MUX_UARTB, TEGRA_PUPD_PULL_UP, TEGRA_TRI_TRISTATE}, | ||
59 | {TEGRA_PINGROUP_KBCA, TEGRA_MUX_KBC, TEGRA_PUPD_PULL_UP, TEGRA_TRI_TRISTATE}, | ||
60 | {TEGRA_PINGROUP_KBCB, TEGRA_MUX_KBC, TEGRA_PUPD_PULL_UP, TEGRA_TRI_TRISTATE}, | ||
61 | {TEGRA_PINGROUP_KBCC, TEGRA_MUX_KBC, TEGRA_PUPD_PULL_UP, TEGRA_TRI_TRISTATE}, | ||
62 | {TEGRA_PINGROUP_KBCD, TEGRA_MUX_KBC, TEGRA_PUPD_PULL_UP, TEGRA_TRI_TRISTATE}, | ||
63 | {TEGRA_PINGROUP_KBCE, TEGRA_MUX_KBC, TEGRA_PUPD_PULL_UP, TEGRA_TRI_TRISTATE}, | ||
64 | {TEGRA_PINGROUP_KBCF, TEGRA_MUX_KBC, TEGRA_PUPD_PULL_UP, TEGRA_TRI_TRISTATE}, | ||
65 | {TEGRA_PINGROUP_LCSN, TEGRA_MUX_DISPLAYA, TEGRA_PUPD_PULL_UP, TEGRA_TRI_TRISTATE}, | ||
66 | {TEGRA_PINGROUP_LD0, TEGRA_MUX_DISPLAYA, TEGRA_PUPD_PULL_DOWN, TEGRA_TRI_NORMAL}, | ||
67 | {TEGRA_PINGROUP_LD1, TEGRA_MUX_DISPLAYA, TEGRA_PUPD_PULL_DOWN, TEGRA_TRI_NORMAL}, | ||
68 | {TEGRA_PINGROUP_LD2, TEGRA_MUX_DISPLAYA, TEGRA_PUPD_PULL_DOWN, TEGRA_TRI_NORMAL}, | ||
69 | {TEGRA_PINGROUP_LD3, TEGRA_MUX_DISPLAYA, TEGRA_PUPD_PULL_DOWN, TEGRA_TRI_NORMAL}, | ||
70 | {TEGRA_PINGROUP_LD4, TEGRA_MUX_DISPLAYA, TEGRA_PUPD_PULL_DOWN, TEGRA_TRI_NORMAL}, | ||
71 | {TEGRA_PINGROUP_LD5, TEGRA_MUX_DISPLAYA, TEGRA_PUPD_PULL_DOWN, TEGRA_TRI_NORMAL}, | ||
72 | {TEGRA_PINGROUP_LD6, TEGRA_MUX_DISPLAYA, TEGRA_PUPD_PULL_DOWN, TEGRA_TRI_NORMAL}, | ||
73 | {TEGRA_PINGROUP_LD7, TEGRA_MUX_DISPLAYA, TEGRA_PUPD_PULL_DOWN, TEGRA_TRI_NORMAL}, | ||
74 | {TEGRA_PINGROUP_LD8, TEGRA_MUX_DISPLAYA, TEGRA_PUPD_PULL_DOWN, TEGRA_TRI_NORMAL}, | ||
75 | {TEGRA_PINGROUP_LD9, TEGRA_MUX_DISPLAYA, TEGRA_PUPD_PULL_DOWN, TEGRA_TRI_NORMAL}, | ||
76 | {TEGRA_PINGROUP_LD10, TEGRA_MUX_DISPLAYA, TEGRA_PUPD_PULL_DOWN, TEGRA_TRI_NORMAL}, | ||
77 | {TEGRA_PINGROUP_LD11, TEGRA_MUX_DISPLAYA, TEGRA_PUPD_PULL_DOWN, TEGRA_TRI_NORMAL}, | ||
78 | {TEGRA_PINGROUP_LD12, TEGRA_MUX_DISPLAYA, TEGRA_PUPD_PULL_DOWN, TEGRA_TRI_NORMAL}, | ||
79 | {TEGRA_PINGROUP_LD13, TEGRA_MUX_DISPLAYA, TEGRA_PUPD_PULL_DOWN, TEGRA_TRI_NORMAL}, | ||
80 | {TEGRA_PINGROUP_LD14, TEGRA_MUX_DISPLAYA, TEGRA_PUPD_PULL_DOWN, TEGRA_TRI_NORMAL}, | ||
81 | {TEGRA_PINGROUP_LD15, TEGRA_MUX_DISPLAYA, TEGRA_PUPD_PULL_DOWN, TEGRA_TRI_NORMAL}, | ||
82 | {TEGRA_PINGROUP_LD16, TEGRA_MUX_DISPLAYA, TEGRA_PUPD_PULL_DOWN, TEGRA_TRI_NORMAL}, | ||
83 | {TEGRA_PINGROUP_LD17, TEGRA_MUX_DISPLAYA, TEGRA_PUPD_PULL_DOWN, TEGRA_TRI_NORMAL}, | ||
84 | {TEGRA_PINGROUP_LDC, TEGRA_MUX_DISPLAYA, TEGRA_PUPD_PULL_UP, TEGRA_TRI_TRISTATE}, | ||
85 | {TEGRA_PINGROUP_LDI, TEGRA_MUX_DISPLAYA, TEGRA_PUPD_PULL_DOWN, TEGRA_TRI_NORMAL}, | ||
86 | {TEGRA_PINGROUP_LHP0, TEGRA_MUX_DISPLAYA, TEGRA_PUPD_PULL_DOWN, TEGRA_TRI_NORMAL}, | ||
87 | {TEGRA_PINGROUP_LHP1, TEGRA_MUX_DISPLAYA, TEGRA_PUPD_PULL_DOWN, TEGRA_TRI_NORMAL}, | ||
88 | {TEGRA_PINGROUP_LHP2, TEGRA_MUX_DISPLAYA, TEGRA_PUPD_PULL_DOWN, TEGRA_TRI_NORMAL}, | ||
89 | {TEGRA_PINGROUP_LHS, TEGRA_MUX_DISPLAYA, TEGRA_PUPD_PULL_UP, TEGRA_TRI_NORMAL}, | ||
90 | {TEGRA_PINGROUP_LM0, TEGRA_MUX_DISPLAYA, TEGRA_PUPD_PULL_UP, TEGRA_TRI_NORMAL}, | ||
91 | {TEGRA_PINGROUP_LM1, TEGRA_MUX_DISPLAYA, TEGRA_PUPD_PULL_UP, TEGRA_TRI_TRISTATE}, | ||
92 | {TEGRA_PINGROUP_LPP, TEGRA_MUX_DISPLAYA, TEGRA_PUPD_PULL_DOWN, TEGRA_TRI_NORMAL}, | ||
93 | {TEGRA_PINGROUP_LPW0, TEGRA_MUX_DISPLAYA, TEGRA_PUPD_PULL_UP, TEGRA_TRI_NORMAL}, | ||
94 | {TEGRA_PINGROUP_LPW1, TEGRA_MUX_DISPLAYA, TEGRA_PUPD_PULL_UP, TEGRA_TRI_TRISTATE}, | ||
95 | {TEGRA_PINGROUP_LPW2, TEGRA_MUX_DISPLAYA, TEGRA_PUPD_PULL_UP, TEGRA_TRI_NORMAL}, | ||
96 | {TEGRA_PINGROUP_LSC0, TEGRA_MUX_DISPLAYA, TEGRA_PUPD_PULL_UP, TEGRA_TRI_NORMAL}, | ||
97 | {TEGRA_PINGROUP_LSC1, TEGRA_MUX_DISPLAYA, TEGRA_PUPD_PULL_UP, TEGRA_TRI_TRISTATE}, | ||
98 | {TEGRA_PINGROUP_LSCK, TEGRA_MUX_DISPLAYA, TEGRA_PUPD_PULL_UP, TEGRA_TRI_TRISTATE}, | ||
99 | {TEGRA_PINGROUP_LSDA, TEGRA_MUX_DISPLAYA, TEGRA_PUPD_PULL_UP, TEGRA_TRI_TRISTATE}, | ||
100 | {TEGRA_PINGROUP_LSDI, TEGRA_MUX_DISPLAYA, TEGRA_PUPD_PULL_UP, TEGRA_TRI_TRISTATE}, | ||
101 | {TEGRA_PINGROUP_LSPI, TEGRA_MUX_DISPLAYA, TEGRA_PUPD_PULL_UP, TEGRA_TRI_NORMAL}, | ||
102 | {TEGRA_PINGROUP_LVP0, TEGRA_MUX_DISPLAYA, TEGRA_PUPD_PULL_UP, TEGRA_TRI_TRISTATE}, | ||
103 | {TEGRA_PINGROUP_LVP1, TEGRA_MUX_DISPLAYA, TEGRA_PUPD_PULL_DOWN, TEGRA_TRI_NORMAL}, | ||
104 | {TEGRA_PINGROUP_LVS, TEGRA_MUX_DISPLAYA, TEGRA_PUPD_PULL_UP, TEGRA_TRI_NORMAL}, | ||
105 | {TEGRA_PINGROUP_OWC, TEGRA_MUX_RSVD2, TEGRA_PUPD_PULL_UP, TEGRA_TRI_TRISTATE}, | ||
106 | {TEGRA_PINGROUP_PMC, TEGRA_MUX_PWR_ON, TEGRA_PUPD_NORMAL, TEGRA_TRI_TRISTATE}, | ||
107 | {TEGRA_PINGROUP_PTA, TEGRA_MUX_RSVD3, TEGRA_PUPD_NORMAL, TEGRA_TRI_TRISTATE}, | ||
108 | {TEGRA_PINGROUP_RM, TEGRA_MUX_I2C, TEGRA_PUPD_PULL_UP, TEGRA_TRI_NORMAL}, | ||
109 | {TEGRA_PINGROUP_SDB, TEGRA_MUX_PWM, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL}, | ||
110 | {TEGRA_PINGROUP_SDC, TEGRA_MUX_PWM, TEGRA_PUPD_PULL_UP, TEGRA_TRI_NORMAL}, | ||
111 | {TEGRA_PINGROUP_SDD, TEGRA_MUX_PWM, TEGRA_PUPD_PULL_UP, TEGRA_TRI_NORMAL}, | ||
112 | {TEGRA_PINGROUP_SDIO1, TEGRA_MUX_SDIO1, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL}, | ||
113 | {TEGRA_PINGROUP_SLXA, TEGRA_MUX_PCIE, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL}, | ||
114 | {TEGRA_PINGROUP_SLXC, TEGRA_MUX_SDIO3, TEGRA_PUPD_NORMAL, TEGRA_TRI_TRISTATE}, | ||
115 | {TEGRA_PINGROUP_SLXD, TEGRA_MUX_SDIO3, TEGRA_PUPD_NORMAL, TEGRA_TRI_TRISTATE}, | ||
116 | {TEGRA_PINGROUP_SLXK, TEGRA_MUX_PCIE, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL}, | ||
117 | {TEGRA_PINGROUP_SPDI, TEGRA_MUX_SPDIF, TEGRA_PUPD_NORMAL, TEGRA_TRI_TRISTATE}, | ||
118 | {TEGRA_PINGROUP_SPDO, TEGRA_MUX_SPDIF, TEGRA_PUPD_NORMAL, TEGRA_TRI_TRISTATE}, | ||
119 | {TEGRA_PINGROUP_SPIA, TEGRA_MUX_SPI2, TEGRA_PUPD_PULL_DOWN, TEGRA_TRI_TRISTATE}, | ||
120 | {TEGRA_PINGROUP_SPIB, TEGRA_MUX_SPI2, TEGRA_PUPD_PULL_DOWN, TEGRA_TRI_TRISTATE}, | ||
121 | {TEGRA_PINGROUP_SPIC, TEGRA_MUX_SPI2, TEGRA_PUPD_PULL_UP, TEGRA_TRI_TRISTATE}, | ||
122 | {TEGRA_PINGROUP_SPID, TEGRA_MUX_SPI1, TEGRA_PUPD_PULL_DOWN, TEGRA_TRI_TRISTATE}, | ||
123 | {TEGRA_PINGROUP_SPIE, TEGRA_MUX_SPI1, TEGRA_PUPD_PULL_UP, TEGRA_TRI_TRISTATE}, | ||
124 | {TEGRA_PINGROUP_SPIF, TEGRA_MUX_SPI1, TEGRA_PUPD_PULL_DOWN, TEGRA_TRI_TRISTATE}, | ||
125 | {TEGRA_PINGROUP_SPIG, TEGRA_MUX_SPI2_ALT, TEGRA_PUPD_PULL_UP, TEGRA_TRI_TRISTATE}, | ||
126 | {TEGRA_PINGROUP_SPIH, TEGRA_MUX_SPI2_ALT, TEGRA_PUPD_PULL_UP, TEGRA_TRI_TRISTATE}, | ||
127 | {TEGRA_PINGROUP_UAA, TEGRA_MUX_ULPI, TEGRA_PUPD_PULL_UP, TEGRA_TRI_TRISTATE}, | ||
128 | {TEGRA_PINGROUP_UAB, TEGRA_MUX_ULPI, TEGRA_PUPD_PULL_UP, TEGRA_TRI_TRISTATE}, | ||
129 | {TEGRA_PINGROUP_UAC, TEGRA_MUX_RSVD2, TEGRA_PUPD_NORMAL, TEGRA_TRI_TRISTATE}, | ||
130 | {TEGRA_PINGROUP_UAD, TEGRA_MUX_IRDA, TEGRA_PUPD_PULL_UP, TEGRA_TRI_TRISTATE}, | ||
131 | {TEGRA_PINGROUP_UCA, TEGRA_MUX_UARTC, TEGRA_PUPD_PULL_UP, TEGRA_TRI_TRISTATE}, | ||
132 | {TEGRA_PINGROUP_UCB, TEGRA_MUX_UARTC, TEGRA_PUPD_PULL_UP, TEGRA_TRI_TRISTATE}, | ||
133 | {TEGRA_PINGROUP_UDA, TEGRA_MUX_ULPI, TEGRA_PUPD_NORMAL, TEGRA_TRI_TRISTATE}, | ||
134 | {TEGRA_PINGROUP_CK32, TEGRA_MUX_NONE, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL}, | ||
135 | {TEGRA_PINGROUP_DDRC, TEGRA_MUX_NONE, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL}, | ||
136 | {TEGRA_PINGROUP_PMCA, TEGRA_MUX_NONE, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL}, | ||
137 | {TEGRA_PINGROUP_PMCB, TEGRA_MUX_NONE, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL}, | ||
138 | {TEGRA_PINGROUP_PMCC, TEGRA_MUX_NONE, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL}, | ||
139 | {TEGRA_PINGROUP_PMCD, TEGRA_MUX_NONE, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL}, | ||
140 | {TEGRA_PINGROUP_PMCE, TEGRA_MUX_NONE, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL}, | ||
141 | {TEGRA_PINGROUP_XM2C, TEGRA_MUX_NONE, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL}, | ||
142 | {TEGRA_PINGROUP_XM2D, TEGRA_MUX_NONE, TEGRA_PUPD_NORMAL, TEGRA_TRI_NORMAL}, | ||
143 | }; | ||
144 | |||
145 | static struct tegra_gpio_table gpio_table[] = { | ||
146 | { .gpio = TRIMSLICE_GPIO_SD4_CD, .enable = true }, /* mmc4 cd */ | ||
147 | { .gpio = TRIMSLICE_GPIO_SD4_WP, .enable = true }, /* mmc4 wp */ | ||
148 | }; | ||
149 | |||
150 | void __init trimslice_pinmux_init(void) | ||
151 | { | ||
152 | tegra_pinmux_config_table(trimslice_pinmux, ARRAY_SIZE(trimslice_pinmux)); | ||
153 | tegra_gpio_config(gpio_table, ARRAY_SIZE(gpio_table)); | ||
154 | } | ||
diff --git a/arch/arm/mach-tegra/board-trimslice.c b/arch/arm/mach-tegra/board-trimslice.c new file mode 100644 index 000000000000..cda4cfd78e84 --- /dev/null +++ b/arch/arm/mach-tegra/board-trimslice.c | |||
@@ -0,0 +1,125 @@ | |||
1 | /* | ||
2 | * arch/arm/mach-tegra/board-trimslice.c | ||
3 | * | ||
4 | * Copyright (C) 2011 CompuLab, Ltd. | ||
5 | * Author: Mike Rapoport <mike@compulab.co.il> | ||
6 | * | ||
7 | * Based on board-harmony.c | ||
8 | * Copyright (C) 2010 Google, Inc. | ||
9 | * | ||
10 | * This software is licensed under the terms of the GNU General Public | ||
11 | * License version 2, as published by the Free Software Foundation, and | ||
12 | * may be copied, distributed, and modified under those terms. | ||
13 | * | ||
14 | * This program is distributed in the hope that it will be useful, | ||
15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
17 | * GNU General Public License for more details. | ||
18 | * | ||
19 | */ | ||
20 | |||
21 | #include <linux/kernel.h> | ||
22 | #include <linux/init.h> | ||
23 | #include <linux/platform_device.h> | ||
24 | #include <linux/serial_8250.h> | ||
25 | #include <linux/io.h> | ||
26 | |||
27 | #include <asm/mach-types.h> | ||
28 | #include <asm/mach/arch.h> | ||
29 | #include <asm/setup.h> | ||
30 | |||
31 | #include <mach/iomap.h> | ||
32 | #include <mach/sdhci.h> | ||
33 | |||
34 | #include "board.h" | ||
35 | #include "clock.h" | ||
36 | #include "devices.h" | ||
37 | #include "gpio-names.h" | ||
38 | |||
39 | #include "board-trimslice.h" | ||
40 | |||
41 | static struct plat_serial8250_port debug_uart_platform_data[] = { | ||
42 | { | ||
43 | .membase = IO_ADDRESS(TEGRA_UARTA_BASE), | ||
44 | .mapbase = TEGRA_UARTA_BASE, | ||
45 | .irq = INT_UARTA, | ||
46 | .flags = UPF_BOOT_AUTOCONF, | ||
47 | .iotype = UPIO_MEM, | ||
48 | .regshift = 2, | ||
49 | .uartclk = 216000000, | ||
50 | }, { | ||
51 | .flags = 0 | ||
52 | } | ||
53 | }; | ||
54 | |||
55 | static struct platform_device debug_uart = { | ||
56 | .name = "serial8250", | ||
57 | .id = PLAT8250_DEV_PLATFORM, | ||
58 | .dev = { | ||
59 | .platform_data = debug_uart_platform_data, | ||
60 | }, | ||
61 | }; | ||
62 | static struct tegra_sdhci_platform_data sdhci_pdata1 = { | ||
63 | .cd_gpio = -1, | ||
64 | .wp_gpio = -1, | ||
65 | .power_gpio = -1, | ||
66 | }; | ||
67 | |||
68 | static struct tegra_sdhci_platform_data sdhci_pdata4 = { | ||
69 | .cd_gpio = TRIMSLICE_GPIO_SD4_CD, | ||
70 | .wp_gpio = TRIMSLICE_GPIO_SD4_WP, | ||
71 | .power_gpio = -1, | ||
72 | }; | ||
73 | |||
74 | static struct platform_device *trimslice_devices[] __initdata = { | ||
75 | &debug_uart, | ||
76 | &tegra_sdhci_device1, | ||
77 | &tegra_sdhci_device4, | ||
78 | }; | ||
79 | |||
80 | static void __init tegra_trimslice_fixup(struct machine_desc *desc, | ||
81 | struct tag *tags, char **cmdline, struct meminfo *mi) | ||
82 | { | ||
83 | mi->nr_banks = 2; | ||
84 | mi->bank[0].start = PHYS_OFFSET; | ||
85 | mi->bank[0].size = 448 * SZ_1M; | ||
86 | mi->bank[1].start = SZ_512M; | ||
87 | mi->bank[1].size = SZ_512M; | ||
88 | } | ||
89 | |||
90 | static __initdata struct tegra_clk_init_table trimslice_clk_init_table[] = { | ||
91 | /* name parent rate enabled */ | ||
92 | { "uarta", "pll_p", 216000000, true }, | ||
93 | { NULL, NULL, 0, 0}, | ||
94 | }; | ||
95 | |||
96 | static int __init tegra_trimslice_pci_init(void) | ||
97 | { | ||
98 | if (!machine_is_trimslice()) | ||
99 | return 0; | ||
100 | |||
101 | return tegra_pcie_init(true, true); | ||
102 | } | ||
103 | subsys_initcall(tegra_trimslice_pci_init); | ||
104 | |||
105 | static void __init tegra_trimslice_init(void) | ||
106 | { | ||
107 | tegra_clk_init_from_table(trimslice_clk_init_table); | ||
108 | |||
109 | trimslice_pinmux_init(); | ||
110 | |||
111 | tegra_sdhci_device1.dev.platform_data = &sdhci_pdata1; | ||
112 | tegra_sdhci_device4.dev.platform_data = &sdhci_pdata4; | ||
113 | |||
114 | platform_add_devices(trimslice_devices, ARRAY_SIZE(trimslice_devices)); | ||
115 | } | ||
116 | |||
117 | MACHINE_START(TRIMSLICE, "trimslice") | ||
118 | .boot_params = 0x00000100, | ||
119 | .fixup = tegra_trimslice_fixup, | ||
120 | .map_io = tegra_map_common_io, | ||
121 | .init_early = tegra_init_early, | ||
122 | .init_irq = tegra_init_irq, | ||
123 | .timer = &tegra_timer, | ||
124 | .init_machine = tegra_trimslice_init, | ||
125 | MACHINE_END | ||
diff --git a/arch/arm/mach-tegra/board-trimslice.h b/arch/arm/mach-tegra/board-trimslice.h new file mode 100644 index 000000000000..e8ef6291c6f1 --- /dev/null +++ b/arch/arm/mach-tegra/board-trimslice.h | |||
@@ -0,0 +1,25 @@ | |||
1 | /* | ||
2 | * arch/arm/mach-tegra/board-trimslice.h | ||
3 | * | ||
4 | * Copyright (C) 2011 CompuLab, Ltd. | ||
5 | * | ||
6 | * This software is licensed under the terms of the GNU General Public | ||
7 | * License version 2, as published by the Free Software Foundation, and | ||
8 | * may be copied, distributed, and modified under those terms. | ||
9 | * | ||
10 | * This program is distributed in the hope that it will be useful, | ||
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
13 | * GNU General Public License for more details. | ||
14 | * | ||
15 | */ | ||
16 | |||
17 | #ifndef _MACH_TEGRA_BOARD_TRIMSLICE_H | ||
18 | #define _MACH_TEGRA_BOARD_TRIMSLICE_H | ||
19 | |||
20 | #define TRIMSLICE_GPIO_SD4_CD TEGRA_GPIO_PP1 /* mmc4 cd */ | ||
21 | #define TRIMSLICE_GPIO_SD4_WP TEGRA_GPIO_PP2 /* mmc4 wp */ | ||
22 | |||
23 | void trimslice_pinmux_init(void); | ||
24 | |||
25 | #endif | ||
diff --git a/arch/arm/mach-tegra/board.h b/arch/arm/mach-tegra/board.h index 0de565ca37c5..1d14df7eb7de 100644 --- a/arch/arm/mach-tegra/board.h +++ b/arch/arm/mach-tegra/board.h | |||
@@ -23,7 +23,9 @@ | |||
23 | 23 | ||
24 | #include <linux/types.h> | 24 | #include <linux/types.h> |
25 | 25 | ||
26 | void __init tegra_common_init(void); | 26 | void tegra_assert_system_reset(char mode, const char *cmd); |
27 | |||
28 | void __init tegra_init_early(void); | ||
27 | void __init tegra_map_common_io(void); | 29 | void __init tegra_map_common_io(void); |
28 | void __init tegra_init_irq(void); | 30 | void __init tegra_init_irq(void); |
29 | void __init tegra_init_clock(void); | 31 | void __init tegra_init_clock(void); |
diff --git a/arch/arm/mach-tegra/clock.c b/arch/arm/mach-tegra/clock.c index 77948e0f4909..e028320ab423 100644 --- a/arch/arm/mach-tegra/clock.c +++ b/arch/arm/mach-tegra/clock.c | |||
@@ -18,238 +18,177 @@ | |||
18 | 18 | ||
19 | #include <linux/kernel.h> | 19 | #include <linux/kernel.h> |
20 | #include <linux/clk.h> | 20 | #include <linux/clk.h> |
21 | #include <linux/list.h> | 21 | #include <linux/clkdev.h> |
22 | #include <linux/debugfs.h> | ||
23 | #include <linux/delay.h> | ||
22 | #include <linux/init.h> | 24 | #include <linux/init.h> |
25 | #include <linux/list.h> | ||
23 | #include <linux/module.h> | 26 | #include <linux/module.h> |
24 | #include <linux/debugfs.h> | 27 | #include <linux/sched.h> |
25 | #include <linux/slab.h> | ||
26 | #include <linux/seq_file.h> | 28 | #include <linux/seq_file.h> |
27 | #include <linux/regulator/consumer.h> | 29 | #include <linux/slab.h> |
28 | #include <linux/clkdev.h> | 30 | |
31 | #include <mach/clk.h> | ||
29 | 32 | ||
30 | #include "clock.h" | ||
31 | #include "board.h" | 33 | #include "board.h" |
32 | #include "fuse.h" | 34 | #include "clock.h" |
33 | 35 | ||
36 | /* | ||
37 | * Locking: | ||
38 | * | ||
39 | * Each struct clk has a spinlock. | ||
40 | * | ||
41 | * To avoid AB-BA locking problems, locks must always be traversed from child | ||
42 | * clock to parent clock. For example, when enabling a clock, the clock's lock | ||
43 | * is taken, and then clk_enable is called on the parent, which take's the | ||
44 | * parent clock's lock. There is one exceptions to this ordering: When dumping | ||
45 | * the clock tree through debugfs. In this case, clk_lock_all is called, | ||
46 | * which attemps to iterate through the entire list of clocks and take every | ||
47 | * clock lock. If any call to spin_trylock fails, all locked clocks are | ||
48 | * unlocked, and the process is retried. When all the locks are held, | ||
49 | * the only clock operation that can be called is clk_get_rate_all_locked. | ||
50 | * | ||
51 | * Within a single clock, no clock operation can call another clock operation | ||
52 | * on itself, except for clk_get_rate_locked and clk_set_rate_locked. Any | ||
53 | * clock operation can call any other clock operation on any of it's possible | ||
54 | * parents. | ||
55 | * | ||
56 | * An additional mutex, clock_list_lock, is used to protect the list of all | ||
57 | * clocks. | ||
58 | * | ||
59 | * The clock operations must lock internally to protect against | ||
60 | * read-modify-write on registers that are shared by multiple clocks | ||
61 | */ | ||
62 | static DEFINE_MUTEX(clock_list_lock); | ||
34 | static LIST_HEAD(clocks); | 63 | static LIST_HEAD(clocks); |
35 | 64 | ||
36 | static DEFINE_SPINLOCK(clock_lock); | ||
37 | static DEFINE_MUTEX(dvfs_lock); | ||
38 | |||
39 | static int clk_is_dvfs(struct clk *c) | ||
40 | { | ||
41 | return (c->dvfs != NULL); | ||
42 | }; | ||
43 | |||
44 | static int dvfs_set_rate(struct dvfs *d, unsigned long rate) | ||
45 | { | ||
46 | struct dvfs_table *t; | ||
47 | |||
48 | if (d->table == NULL) | ||
49 | return -ENODEV; | ||
50 | |||
51 | for (t = d->table; t->rate != 0; t++) { | ||
52 | if (rate <= t->rate) { | ||
53 | if (!d->reg) | ||
54 | return 0; | ||
55 | |||
56 | return regulator_set_voltage(d->reg, | ||
57 | t->millivolts * 1000, | ||
58 | d->max_millivolts * 1000); | ||
59 | } | ||
60 | } | ||
61 | |||
62 | return -EINVAL; | ||
63 | } | ||
64 | |||
65 | static void dvfs_init(struct clk *c) | ||
66 | { | ||
67 | int process_id; | ||
68 | int i; | ||
69 | struct dvfs_table *table; | ||
70 | |||
71 | process_id = c->dvfs->cpu ? tegra_core_process_id() : | ||
72 | tegra_cpu_process_id(); | ||
73 | |||
74 | for (i = 0; i < c->dvfs->process_id_table_length; i++) | ||
75 | if (process_id == c->dvfs->process_id_table[i].process_id) | ||
76 | c->dvfs->table = c->dvfs->process_id_table[i].table; | ||
77 | |||
78 | if (c->dvfs->table == NULL) { | ||
79 | pr_err("Failed to find dvfs table for clock %s process %d\n", | ||
80 | c->name, process_id); | ||
81 | return; | ||
82 | } | ||
83 | |||
84 | c->dvfs->max_millivolts = 0; | ||
85 | for (table = c->dvfs->table; table->rate != 0; table++) | ||
86 | if (c->dvfs->max_millivolts < table->millivolts) | ||
87 | c->dvfs->max_millivolts = table->millivolts; | ||
88 | |||
89 | c->dvfs->reg = regulator_get(NULL, c->dvfs->reg_id); | ||
90 | |||
91 | if (IS_ERR(c->dvfs->reg)) { | ||
92 | pr_err("Failed to get regulator %s for clock %s\n", | ||
93 | c->dvfs->reg_id, c->name); | ||
94 | c->dvfs->reg = NULL; | ||
95 | return; | ||
96 | } | ||
97 | |||
98 | if (c->refcnt > 0) | ||
99 | dvfs_set_rate(c->dvfs, c->rate); | ||
100 | } | ||
101 | |||
102 | struct clk *tegra_get_clock_by_name(const char *name) | 65 | struct clk *tegra_get_clock_by_name(const char *name) |
103 | { | 66 | { |
104 | struct clk *c; | 67 | struct clk *c; |
105 | struct clk *ret = NULL; | 68 | struct clk *ret = NULL; |
106 | unsigned long flags; | 69 | mutex_lock(&clock_list_lock); |
107 | spin_lock_irqsave(&clock_lock, flags); | ||
108 | list_for_each_entry(c, &clocks, node) { | 70 | list_for_each_entry(c, &clocks, node) { |
109 | if (strcmp(c->name, name) == 0) { | 71 | if (strcmp(c->name, name) == 0) { |
110 | ret = c; | 72 | ret = c; |
111 | break; | 73 | break; |
112 | } | 74 | } |
113 | } | 75 | } |
114 | spin_unlock_irqrestore(&clock_lock, flags); | 76 | mutex_unlock(&clock_list_lock); |
115 | return ret; | 77 | return ret; |
116 | } | 78 | } |
117 | 79 | ||
118 | static void clk_recalculate_rate(struct clk *c) | 80 | /* Must be called with c->spinlock held */ |
81 | static unsigned long clk_predict_rate_from_parent(struct clk *c, struct clk *p) | ||
119 | { | 82 | { |
120 | u64 rate; | 83 | u64 rate; |
121 | 84 | ||
122 | if (!c->parent) | 85 | rate = clk_get_rate(p); |
123 | return; | ||
124 | |||
125 | rate = c->parent->rate; | ||
126 | 86 | ||
127 | if (c->mul != 0 && c->div != 0) { | 87 | if (c->mul != 0 && c->div != 0) { |
128 | rate = rate * c->mul; | 88 | rate *= c->mul; |
89 | rate += c->div - 1; /* round up */ | ||
129 | do_div(rate, c->div); | 90 | do_div(rate, c->div); |
130 | } | 91 | } |
131 | 92 | ||
132 | if (rate > c->max_rate) | 93 | return rate; |
133 | pr_warn("clocks: Set clock %s to rate %llu, max is %lu\n", | ||
134 | c->name, rate, c->max_rate); | ||
135 | |||
136 | c->rate = rate; | ||
137 | } | 94 | } |
138 | 95 | ||
139 | int clk_reparent(struct clk *c, struct clk *parent) | 96 | /* Must be called with c->spinlock held */ |
97 | unsigned long clk_get_rate_locked(struct clk *c) | ||
140 | { | 98 | { |
141 | pr_debug("%s: %s\n", __func__, c->name); | 99 | unsigned long rate; |
142 | c->parent = parent; | ||
143 | list_del(&c->sibling); | ||
144 | list_add_tail(&c->sibling, &parent->children); | ||
145 | return 0; | ||
146 | } | ||
147 | 100 | ||
148 | static void propagate_rate(struct clk *c) | 101 | if (c->parent) |
149 | { | 102 | rate = clk_predict_rate_from_parent(c, c->parent); |
150 | struct clk *clkp; | 103 | else |
151 | pr_debug("%s: %s\n", __func__, c->name); | 104 | rate = c->rate; |
152 | list_for_each_entry(clkp, &c->children, sibling) { | 105 | |
153 | pr_debug(" %s\n", clkp->name); | 106 | return rate; |
154 | clk_recalculate_rate(clkp); | ||
155 | propagate_rate(clkp); | ||
156 | } | ||
157 | } | 107 | } |
158 | 108 | ||
159 | void clk_init(struct clk *c) | 109 | unsigned long clk_get_rate(struct clk *c) |
160 | { | 110 | { |
161 | unsigned long flags; | 111 | unsigned long flags; |
112 | unsigned long rate; | ||
113 | |||
114 | spin_lock_irqsave(&c->spinlock, flags); | ||
162 | 115 | ||
163 | pr_debug("%s: %s\n", __func__, c->name); | 116 | rate = clk_get_rate_locked(c); |
164 | 117 | ||
165 | spin_lock_irqsave(&clock_lock, flags); | 118 | spin_unlock_irqrestore(&c->spinlock, flags); |
166 | 119 | ||
167 | INIT_LIST_HEAD(&c->children); | 120 | return rate; |
168 | INIT_LIST_HEAD(&c->sibling); | 121 | } |
122 | EXPORT_SYMBOL(clk_get_rate); | ||
123 | |||
124 | int clk_reparent(struct clk *c, struct clk *parent) | ||
125 | { | ||
126 | c->parent = parent; | ||
127 | return 0; | ||
128 | } | ||
129 | |||
130 | void clk_init(struct clk *c) | ||
131 | { | ||
132 | spin_lock_init(&c->spinlock); | ||
169 | 133 | ||
170 | if (c->ops && c->ops->init) | 134 | if (c->ops && c->ops->init) |
171 | c->ops->init(c); | 135 | c->ops->init(c); |
172 | 136 | ||
173 | clk_recalculate_rate(c); | 137 | if (!c->ops || !c->ops->enable) { |
138 | c->refcnt++; | ||
139 | c->set = true; | ||
140 | if (c->parent) | ||
141 | c->state = c->parent->state; | ||
142 | else | ||
143 | c->state = ON; | ||
144 | } | ||
174 | 145 | ||
146 | mutex_lock(&clock_list_lock); | ||
175 | list_add(&c->node, &clocks); | 147 | list_add(&c->node, &clocks); |
176 | 148 | mutex_unlock(&clock_list_lock); | |
177 | if (c->parent) | ||
178 | list_add_tail(&c->sibling, &c->parent->children); | ||
179 | |||
180 | spin_unlock_irqrestore(&clock_lock, flags); | ||
181 | } | 149 | } |
182 | 150 | ||
183 | int clk_enable_locked(struct clk *c) | 151 | int clk_enable(struct clk *c) |
184 | { | 152 | { |
185 | int ret; | 153 | int ret = 0; |
186 | pr_debug("%s: %s\n", __func__, c->name); | 154 | unsigned long flags; |
155 | |||
156 | spin_lock_irqsave(&c->spinlock, flags); | ||
157 | |||
187 | if (c->refcnt == 0) { | 158 | if (c->refcnt == 0) { |
188 | if (c->parent) { | 159 | if (c->parent) { |
189 | ret = clk_enable_locked(c->parent); | 160 | ret = clk_enable(c->parent); |
190 | if (ret) | 161 | if (ret) |
191 | return ret; | 162 | goto out; |
192 | } | 163 | } |
193 | 164 | ||
194 | if (c->ops && c->ops->enable) { | 165 | if (c->ops && c->ops->enable) { |
195 | ret = c->ops->enable(c); | 166 | ret = c->ops->enable(c); |
196 | if (ret) { | 167 | if (ret) { |
197 | if (c->parent) | 168 | if (c->parent) |
198 | clk_disable_locked(c->parent); | 169 | clk_disable(c->parent); |
199 | return ret; | 170 | goto out; |
200 | } | 171 | } |
201 | c->state = ON; | 172 | c->state = ON; |
202 | #ifdef CONFIG_DEBUG_FS | 173 | c->set = true; |
203 | c->set = 1; | ||
204 | #endif | ||
205 | } | 174 | } |
206 | } | 175 | } |
207 | c->refcnt++; | 176 | c->refcnt++; |
208 | 177 | out: | |
209 | return 0; | 178 | spin_unlock_irqrestore(&c->spinlock, flags); |
210 | } | ||
211 | |||
212 | int clk_enable_cansleep(struct clk *c) | ||
213 | { | ||
214 | int ret; | ||
215 | unsigned long flags; | ||
216 | |||
217 | mutex_lock(&dvfs_lock); | ||
218 | |||
219 | if (clk_is_dvfs(c) && c->refcnt > 0) | ||
220 | dvfs_set_rate(c->dvfs, c->rate); | ||
221 | |||
222 | spin_lock_irqsave(&clock_lock, flags); | ||
223 | ret = clk_enable_locked(c); | ||
224 | spin_unlock_irqrestore(&clock_lock, flags); | ||
225 | |||
226 | mutex_unlock(&dvfs_lock); | ||
227 | |||
228 | return ret; | 179 | return ret; |
229 | } | 180 | } |
230 | EXPORT_SYMBOL(clk_enable_cansleep); | 181 | EXPORT_SYMBOL(clk_enable); |
231 | 182 | ||
232 | int clk_enable(struct clk *c) | 183 | void clk_disable(struct clk *c) |
233 | { | 184 | { |
234 | int ret; | ||
235 | unsigned long flags; | 185 | unsigned long flags; |
236 | 186 | ||
237 | if (clk_is_dvfs(c)) | 187 | spin_lock_irqsave(&c->spinlock, flags); |
238 | BUG(); | ||
239 | |||
240 | spin_lock_irqsave(&clock_lock, flags); | ||
241 | ret = clk_enable_locked(c); | ||
242 | spin_unlock_irqrestore(&clock_lock, flags); | ||
243 | |||
244 | return ret; | ||
245 | } | ||
246 | EXPORT_SYMBOL(clk_enable); | ||
247 | 188 | ||
248 | void clk_disable_locked(struct clk *c) | ||
249 | { | ||
250 | pr_debug("%s: %s\n", __func__, c->name); | ||
251 | if (c->refcnt == 0) { | 189 | if (c->refcnt == 0) { |
252 | WARN(1, "Attempting to disable clock %s with refcnt 0", c->name); | 190 | WARN(1, "Attempting to disable clock %s with refcnt 0", c->name); |
191 | spin_unlock_irqrestore(&c->spinlock, flags); | ||
253 | return; | 192 | return; |
254 | } | 193 | } |
255 | if (c->refcnt == 1) { | 194 | if (c->refcnt == 1) { |
@@ -257,71 +196,39 @@ void clk_disable_locked(struct clk *c) | |||
257 | c->ops->disable(c); | 196 | c->ops->disable(c); |
258 | 197 | ||
259 | if (c->parent) | 198 | if (c->parent) |
260 | clk_disable_locked(c->parent); | 199 | clk_disable(c->parent); |
261 | 200 | ||
262 | c->state = OFF; | 201 | c->state = OFF; |
263 | } | 202 | } |
264 | c->refcnt--; | 203 | c->refcnt--; |
265 | } | ||
266 | |||
267 | void clk_disable_cansleep(struct clk *c) | ||
268 | { | ||
269 | unsigned long flags; | ||
270 | |||
271 | mutex_lock(&dvfs_lock); | ||
272 | |||
273 | spin_lock_irqsave(&clock_lock, flags); | ||
274 | clk_disable_locked(c); | ||
275 | spin_unlock_irqrestore(&clock_lock, flags); | ||
276 | 204 | ||
277 | if (clk_is_dvfs(c) && c->refcnt == 0) | 205 | spin_unlock_irqrestore(&c->spinlock, flags); |
278 | dvfs_set_rate(c->dvfs, c->rate); | ||
279 | |||
280 | mutex_unlock(&dvfs_lock); | ||
281 | } | ||
282 | EXPORT_SYMBOL(clk_disable_cansleep); | ||
283 | |||
284 | void clk_disable(struct clk *c) | ||
285 | { | ||
286 | unsigned long flags; | ||
287 | |||
288 | if (clk_is_dvfs(c)) | ||
289 | BUG(); | ||
290 | |||
291 | spin_lock_irqsave(&clock_lock, flags); | ||
292 | clk_disable_locked(c); | ||
293 | spin_unlock_irqrestore(&clock_lock, flags); | ||
294 | } | 206 | } |
295 | EXPORT_SYMBOL(clk_disable); | 207 | EXPORT_SYMBOL(clk_disable); |
296 | 208 | ||
297 | int clk_set_parent_locked(struct clk *c, struct clk *parent) | 209 | int clk_set_parent(struct clk *c, struct clk *parent) |
298 | { | 210 | { |
299 | int ret; | 211 | int ret; |
212 | unsigned long flags; | ||
213 | unsigned long new_rate; | ||
214 | unsigned long old_rate; | ||
300 | 215 | ||
301 | pr_debug("%s: %s\n", __func__, c->name); | 216 | spin_lock_irqsave(&c->spinlock, flags); |
302 | 217 | ||
303 | if (!c->ops || !c->ops->set_parent) | 218 | if (!c->ops || !c->ops->set_parent) { |
304 | return -ENOSYS; | 219 | ret = -ENOSYS; |
220 | goto out; | ||
221 | } | ||
305 | 222 | ||
306 | ret = c->ops->set_parent(c, parent); | 223 | new_rate = clk_predict_rate_from_parent(c, parent); |
224 | old_rate = clk_get_rate_locked(c); | ||
307 | 225 | ||
226 | ret = c->ops->set_parent(c, parent); | ||
308 | if (ret) | 227 | if (ret) |
309 | return ret; | 228 | goto out; |
310 | |||
311 | clk_recalculate_rate(c); | ||
312 | |||
313 | propagate_rate(c); | ||
314 | |||
315 | return 0; | ||
316 | } | ||
317 | 229 | ||
318 | int clk_set_parent(struct clk *c, struct clk *parent) | 230 | out: |
319 | { | 231 | spin_unlock_irqrestore(&c->spinlock, flags); |
320 | int ret; | ||
321 | unsigned long flags; | ||
322 | spin_lock_irqsave(&clock_lock, flags); | ||
323 | ret = clk_set_parent_locked(c, parent); | ||
324 | spin_unlock_irqrestore(&clock_lock, flags); | ||
325 | return ret; | 232 | return ret; |
326 | } | 233 | } |
327 | EXPORT_SYMBOL(clk_set_parent); | 234 | EXPORT_SYMBOL(clk_set_parent); |
@@ -334,100 +241,86 @@ EXPORT_SYMBOL(clk_get_parent); | |||
334 | 241 | ||
335 | int clk_set_rate_locked(struct clk *c, unsigned long rate) | 242 | int clk_set_rate_locked(struct clk *c, unsigned long rate) |
336 | { | 243 | { |
337 | int ret; | 244 | long new_rate; |
338 | |||
339 | if (rate > c->max_rate) | ||
340 | rate = c->max_rate; | ||
341 | 245 | ||
342 | if (!c->ops || !c->ops->set_rate) | 246 | if (!c->ops || !c->ops->set_rate) |
343 | return -ENOSYS; | 247 | return -ENOSYS; |
344 | 248 | ||
345 | ret = c->ops->set_rate(c, rate); | 249 | if (rate > c->max_rate) |
346 | 250 | rate = c->max_rate; | |
347 | if (ret) | ||
348 | return ret; | ||
349 | |||
350 | clk_recalculate_rate(c); | ||
351 | |||
352 | propagate_rate(c); | ||
353 | |||
354 | return 0; | ||
355 | } | ||
356 | |||
357 | int clk_set_rate_cansleep(struct clk *c, unsigned long rate) | ||
358 | { | ||
359 | int ret = 0; | ||
360 | unsigned long flags; | ||
361 | |||
362 | pr_debug("%s: %s\n", __func__, c->name); | ||
363 | |||
364 | mutex_lock(&dvfs_lock); | ||
365 | |||
366 | if (rate > c->rate) | ||
367 | ret = dvfs_set_rate(c->dvfs, rate); | ||
368 | if (ret) | ||
369 | goto out; | ||
370 | 251 | ||
371 | spin_lock_irqsave(&clock_lock, flags); | 252 | if (c->ops && c->ops->round_rate) { |
372 | ret = clk_set_rate_locked(c, rate); | 253 | new_rate = c->ops->round_rate(c, rate); |
373 | spin_unlock_irqrestore(&clock_lock, flags); | ||
374 | 254 | ||
375 | if (ret) | 255 | if (new_rate < 0) |
376 | goto out; | 256 | return new_rate; |
377 | 257 | ||
378 | ret = dvfs_set_rate(c->dvfs, rate); | 258 | rate = new_rate; |
259 | } | ||
379 | 260 | ||
380 | out: | 261 | return c->ops->set_rate(c, rate); |
381 | mutex_unlock(&dvfs_lock); | ||
382 | return ret; | ||
383 | } | 262 | } |
384 | EXPORT_SYMBOL(clk_set_rate_cansleep); | ||
385 | 263 | ||
386 | int clk_set_rate(struct clk *c, unsigned long rate) | 264 | int clk_set_rate(struct clk *c, unsigned long rate) |
387 | { | 265 | { |
388 | int ret = 0; | 266 | int ret; |
389 | unsigned long flags; | 267 | unsigned long flags; |
390 | 268 | ||
391 | pr_debug("%s: %s\n", __func__, c->name); | 269 | spin_lock_irqsave(&c->spinlock, flags); |
392 | |||
393 | if (clk_is_dvfs(c)) | ||
394 | BUG(); | ||
395 | 270 | ||
396 | spin_lock_irqsave(&clock_lock, flags); | ||
397 | ret = clk_set_rate_locked(c, rate); | 271 | ret = clk_set_rate_locked(c, rate); |
398 | spin_unlock_irqrestore(&clock_lock, flags); | 272 | |
273 | spin_unlock_irqrestore(&c->spinlock, flags); | ||
399 | 274 | ||
400 | return ret; | 275 | return ret; |
401 | } | 276 | } |
402 | EXPORT_SYMBOL(clk_set_rate); | 277 | EXPORT_SYMBOL(clk_set_rate); |
403 | 278 | ||
404 | unsigned long clk_get_rate(struct clk *c) | ||
405 | { | ||
406 | unsigned long flags; | ||
407 | unsigned long ret; | ||
408 | |||
409 | spin_lock_irqsave(&clock_lock, flags); | ||
410 | 279 | ||
411 | pr_debug("%s: %s\n", __func__, c->name); | 280 | /* Must be called with clocks lock and all indvidual clock locks held */ |
281 | unsigned long clk_get_rate_all_locked(struct clk *c) | ||
282 | { | ||
283 | u64 rate; | ||
284 | int mul = 1; | ||
285 | int div = 1; | ||
286 | struct clk *p = c; | ||
287 | |||
288 | while (p) { | ||
289 | c = p; | ||
290 | if (c->mul != 0 && c->div != 0) { | ||
291 | mul *= c->mul; | ||
292 | div *= c->div; | ||
293 | } | ||
294 | p = c->parent; | ||
295 | } | ||
412 | 296 | ||
413 | ret = c->rate; | 297 | rate = c->rate; |
298 | rate *= mul; | ||
299 | do_div(rate, div); | ||
414 | 300 | ||
415 | spin_unlock_irqrestore(&clock_lock, flags); | 301 | return rate; |
416 | return ret; | ||
417 | } | 302 | } |
418 | EXPORT_SYMBOL(clk_get_rate); | ||
419 | 303 | ||
420 | long clk_round_rate(struct clk *c, unsigned long rate) | 304 | long clk_round_rate(struct clk *c, unsigned long rate) |
421 | { | 305 | { |
422 | pr_debug("%s: %s\n", __func__, c->name); | 306 | unsigned long flags; |
307 | long ret; | ||
423 | 308 | ||
424 | if (!c->ops || !c->ops->round_rate) | 309 | spin_lock_irqsave(&c->spinlock, flags); |
425 | return -ENOSYS; | 310 | |
311 | if (!c->ops || !c->ops->round_rate) { | ||
312 | ret = -ENOSYS; | ||
313 | goto out; | ||
314 | } | ||
426 | 315 | ||
427 | if (rate > c->max_rate) | 316 | if (rate > c->max_rate) |
428 | rate = c->max_rate; | 317 | rate = c->max_rate; |
429 | 318 | ||
430 | return c->ops->round_rate(c, rate); | 319 | ret = c->ops->round_rate(c, rate); |
320 | |||
321 | out: | ||
322 | spin_unlock_irqrestore(&c->spinlock, flags); | ||
323 | return ret; | ||
431 | } | 324 | } |
432 | EXPORT_SYMBOL(clk_round_rate); | 325 | EXPORT_SYMBOL(clk_round_rate); |
433 | 326 | ||
@@ -509,31 +402,90 @@ void __init tegra_init_clock(void) | |||
509 | tegra2_init_clocks(); | 402 | tegra2_init_clocks(); |
510 | } | 403 | } |
511 | 404 | ||
512 | int __init tegra_init_dvfs(void) | 405 | /* |
406 | * The SDMMC controllers have extra bits in the clock source register that | ||
407 | * adjust the delay between the clock and data to compenstate for delays | ||
408 | * on the PCB. | ||
409 | */ | ||
410 | void tegra_sdmmc_tap_delay(struct clk *c, int delay) | ||
513 | { | 411 | { |
514 | struct clk *c, *safe; | 412 | unsigned long flags; |
413 | |||
414 | spin_lock_irqsave(&c->spinlock, flags); | ||
415 | tegra2_sdmmc_tap_delay(c, delay); | ||
416 | spin_unlock_irqrestore(&c->spinlock, flags); | ||
417 | } | ||
515 | 418 | ||
516 | mutex_lock(&dvfs_lock); | 419 | #ifdef CONFIG_DEBUG_FS |
517 | 420 | ||
518 | list_for_each_entry_safe(c, safe, &clocks, node) | 421 | static int __clk_lock_all_spinlocks(void) |
519 | if (c->dvfs) | 422 | { |
520 | dvfs_init(c); | 423 | struct clk *c; |
521 | 424 | ||
522 | mutex_unlock(&dvfs_lock); | 425 | list_for_each_entry(c, &clocks, node) |
426 | if (!spin_trylock(&c->spinlock)) | ||
427 | goto unlock_spinlocks; | ||
523 | 428 | ||
524 | return 0; | 429 | return 0; |
430 | |||
431 | unlock_spinlocks: | ||
432 | list_for_each_entry_continue_reverse(c, &clocks, node) | ||
433 | spin_unlock(&c->spinlock); | ||
434 | |||
435 | return -EAGAIN; | ||
525 | } | 436 | } |
526 | 437 | ||
527 | late_initcall(tegra_init_dvfs); | 438 | static void __clk_unlock_all_spinlocks(void) |
439 | { | ||
440 | struct clk *c; | ||
441 | |||
442 | list_for_each_entry_reverse(c, &clocks, node) | ||
443 | spin_unlock(&c->spinlock); | ||
444 | } | ||
445 | |||
446 | /* | ||
447 | * This function retries until it can take all locks, and may take | ||
448 | * an arbitrarily long time to complete. | ||
449 | * Must be called with irqs enabled, returns with irqs disabled | ||
450 | * Must be called with clock_list_lock held | ||
451 | */ | ||
452 | static void clk_lock_all(void) | ||
453 | { | ||
454 | int ret; | ||
455 | retry: | ||
456 | local_irq_disable(); | ||
457 | |||
458 | ret = __clk_lock_all_spinlocks(); | ||
459 | if (ret) | ||
460 | goto failed_spinlocks; | ||
461 | |||
462 | /* All locks taken successfully, return */ | ||
463 | return; | ||
464 | |||
465 | failed_spinlocks: | ||
466 | local_irq_enable(); | ||
467 | yield(); | ||
468 | goto retry; | ||
469 | } | ||
470 | |||
471 | /* | ||
472 | * Unlocks all clocks after a clk_lock_all | ||
473 | * Must be called with irqs disabled, returns with irqs enabled | ||
474 | * Must be called with clock_list_lock held | ||
475 | */ | ||
476 | static void clk_unlock_all(void) | ||
477 | { | ||
478 | __clk_unlock_all_spinlocks(); | ||
479 | |||
480 | local_irq_enable(); | ||
481 | } | ||
528 | 482 | ||
529 | #ifdef CONFIG_DEBUG_FS | ||
530 | static struct dentry *clk_debugfs_root; | 483 | static struct dentry *clk_debugfs_root; |
531 | 484 | ||
532 | 485 | ||
533 | static void clock_tree_show_one(struct seq_file *s, struct clk *c, int level) | 486 | static void clock_tree_show_one(struct seq_file *s, struct clk *c, int level) |
534 | { | 487 | { |
535 | struct clk *child; | 488 | struct clk *child; |
536 | struct clk *safe; | ||
537 | const char *state = "uninit"; | 489 | const char *state = "uninit"; |
538 | char div[8] = {0}; | 490 | char div[8] = {0}; |
539 | 491 | ||
@@ -564,8 +516,12 @@ static void clock_tree_show_one(struct seq_file *s, struct clk *c, int level) | |||
564 | c->rate > c->max_rate ? '!' : ' ', | 516 | c->rate > c->max_rate ? '!' : ' ', |
565 | !c->set ? '*' : ' ', | 517 | !c->set ? '*' : ' ', |
566 | 30 - level * 3, c->name, | 518 | 30 - level * 3, c->name, |
567 | state, c->refcnt, div, c->rate); | 519 | state, c->refcnt, div, clk_get_rate_all_locked(c)); |
568 | list_for_each_entry_safe(child, safe, &c->children, sibling) { | 520 | |
521 | list_for_each_entry(child, &clocks, node) { | ||
522 | if (child->parent != c) | ||
523 | continue; | ||
524 | |||
569 | clock_tree_show_one(s, child, level + 1); | 525 | clock_tree_show_one(s, child, level + 1); |
570 | } | 526 | } |
571 | } | 527 | } |
@@ -573,14 +529,20 @@ static void clock_tree_show_one(struct seq_file *s, struct clk *c, int level) | |||
573 | static int clock_tree_show(struct seq_file *s, void *data) | 529 | static int clock_tree_show(struct seq_file *s, void *data) |
574 | { | 530 | { |
575 | struct clk *c; | 531 | struct clk *c; |
576 | unsigned long flags; | ||
577 | seq_printf(s, " clock state ref div rate\n"); | 532 | seq_printf(s, " clock state ref div rate\n"); |
578 | seq_printf(s, "--------------------------------------------------------------\n"); | 533 | seq_printf(s, "--------------------------------------------------------------\n"); |
579 | spin_lock_irqsave(&clock_lock, flags); | 534 | |
535 | mutex_lock(&clock_list_lock); | ||
536 | |||
537 | clk_lock_all(); | ||
538 | |||
580 | list_for_each_entry(c, &clocks, node) | 539 | list_for_each_entry(c, &clocks, node) |
581 | if (c->parent == NULL) | 540 | if (c->parent == NULL) |
582 | clock_tree_show_one(s, c, 0); | 541 | clock_tree_show_one(s, c, 0); |
583 | spin_unlock_irqrestore(&clock_lock, flags); | 542 | |
543 | clk_unlock_all(); | ||
544 | |||
545 | mutex_unlock(&clock_list_lock); | ||
584 | return 0; | 546 | return 0; |
585 | } | 547 | } |
586 | 548 | ||
diff --git a/arch/arm/mach-tegra/clock.h b/arch/arm/mach-tegra/clock.h index 083a4cfc6cf0..688316abc64e 100644 --- a/arch/arm/mach-tegra/clock.h +++ b/arch/arm/mach-tegra/clock.h | |||
@@ -20,8 +20,9 @@ | |||
20 | #ifndef __MACH_TEGRA_CLOCK_H | 20 | #ifndef __MACH_TEGRA_CLOCK_H |
21 | #define __MACH_TEGRA_CLOCK_H | 21 | #define __MACH_TEGRA_CLOCK_H |
22 | 22 | ||
23 | #include <linux/list.h> | ||
24 | #include <linux/clkdev.h> | 23 | #include <linux/clkdev.h> |
24 | #include <linux/list.h> | ||
25 | #include <linux/spinlock.h> | ||
25 | 26 | ||
26 | #define DIV_BUS (1 << 0) | 27 | #define DIV_BUS (1 << 0) |
27 | #define DIV_U71 (1 << 1) | 28 | #define DIV_U71 (1 << 1) |
@@ -41,36 +42,13 @@ | |||
41 | #define ENABLE_ON_INIT (1 << 28) | 42 | #define ENABLE_ON_INIT (1 << 28) |
42 | 43 | ||
43 | struct clk; | 44 | struct clk; |
44 | struct regulator; | ||
45 | |||
46 | struct dvfs_table { | ||
47 | unsigned long rate; | ||
48 | int millivolts; | ||
49 | }; | ||
50 | |||
51 | struct dvfs_process_id_table { | ||
52 | int process_id; | ||
53 | struct dvfs_table *table; | ||
54 | }; | ||
55 | |||
56 | |||
57 | struct dvfs { | ||
58 | struct regulator *reg; | ||
59 | struct dvfs_table *table; | ||
60 | int max_millivolts; | ||
61 | |||
62 | int process_id_table_length; | ||
63 | const char *reg_id; | ||
64 | bool cpu; | ||
65 | struct dvfs_process_id_table process_id_table[]; | ||
66 | }; | ||
67 | 45 | ||
68 | struct clk_mux_sel { | 46 | struct clk_mux_sel { |
69 | struct clk *input; | 47 | struct clk *input; |
70 | u32 value; | 48 | u32 value; |
71 | }; | 49 | }; |
72 | 50 | ||
73 | struct clk_pll_table { | 51 | struct clk_pll_freq_table { |
74 | unsigned long input_rate; | 52 | unsigned long input_rate; |
75 | unsigned long output_rate; | 53 | unsigned long output_rate; |
76 | u16 n; | 54 | u16 n; |
@@ -86,6 +64,7 @@ struct clk_ops { | |||
86 | int (*set_parent)(struct clk *, struct clk *); | 64 | int (*set_parent)(struct clk *, struct clk *); |
87 | int (*set_rate)(struct clk *, unsigned long); | 65 | int (*set_rate)(struct clk *, unsigned long); |
88 | long (*round_rate)(struct clk *, unsigned long); | 66 | long (*round_rate)(struct clk *, unsigned long); |
67 | void (*reset)(struct clk *, bool); | ||
89 | }; | 68 | }; |
90 | 69 | ||
91 | enum clk_state { | 70 | enum clk_state { |
@@ -96,55 +75,64 @@ enum clk_state { | |||
96 | 75 | ||
97 | struct clk { | 76 | struct clk { |
98 | /* node for master clocks list */ | 77 | /* node for master clocks list */ |
99 | struct list_head node; | 78 | struct list_head node; /* node for list of all clocks */ |
100 | struct list_head children; /* list of children */ | 79 | struct clk_lookup lookup; |
101 | struct list_head sibling; /* node for children */ | 80 | |
102 | #ifdef CONFIG_DEBUG_FS | ||
103 | struct dentry *dent; | ||
104 | struct dentry *parent_dent; | ||
105 | #endif | ||
106 | struct clk_ops *ops; | ||
107 | struct clk *parent; | ||
108 | struct clk_lookup lookup; | ||
109 | unsigned long rate; | ||
110 | unsigned long max_rate; | ||
111 | u32 flags; | ||
112 | u32 refcnt; | ||
113 | const char *name; | ||
114 | u32 reg; | ||
115 | u32 reg_shift; | ||
116 | unsigned int clk_num; | ||
117 | enum clk_state state; | ||
118 | #ifdef CONFIG_DEBUG_FS | 81 | #ifdef CONFIG_DEBUG_FS |
119 | bool set; | 82 | struct dentry *dent; |
120 | #endif | 83 | #endif |
84 | bool set; | ||
85 | struct clk_ops *ops; | ||
86 | unsigned long rate; | ||
87 | unsigned long max_rate; | ||
88 | unsigned long min_rate; | ||
89 | u32 flags; | ||
90 | const char *name; | ||
91 | |||
92 | u32 refcnt; | ||
93 | enum clk_state state; | ||
94 | struct clk *parent; | ||
95 | u32 div; | ||
96 | u32 mul; | ||
121 | 97 | ||
122 | /* PLL */ | ||
123 | unsigned long input_min; | ||
124 | unsigned long input_max; | ||
125 | unsigned long cf_min; | ||
126 | unsigned long cf_max; | ||
127 | unsigned long vco_min; | ||
128 | unsigned long vco_max; | ||
129 | const struct clk_pll_table *pll_table; | ||
130 | |||
131 | /* DIV */ | ||
132 | u32 div; | ||
133 | u32 mul; | ||
134 | |||
135 | /* MUX */ | ||
136 | const struct clk_mux_sel *inputs; | 98 | const struct clk_mux_sel *inputs; |
137 | u32 sel; | 99 | u32 reg; |
138 | u32 reg_mask; | 100 | u32 reg_shift; |
139 | |||
140 | /* Virtual cpu clock */ | ||
141 | struct clk *main; | ||
142 | struct clk *backup; | ||
143 | 101 | ||
144 | struct dvfs *dvfs; | 102 | struct list_head shared_bus_list; |
103 | |||
104 | union { | ||
105 | struct { | ||
106 | unsigned int clk_num; | ||
107 | } periph; | ||
108 | struct { | ||
109 | unsigned long input_min; | ||
110 | unsigned long input_max; | ||
111 | unsigned long cf_min; | ||
112 | unsigned long cf_max; | ||
113 | unsigned long vco_min; | ||
114 | unsigned long vco_max; | ||
115 | const struct clk_pll_freq_table *freq_table; | ||
116 | int lock_delay; | ||
117 | } pll; | ||
118 | struct { | ||
119 | u32 sel; | ||
120 | u32 reg_mask; | ||
121 | } mux; | ||
122 | struct { | ||
123 | struct clk *main; | ||
124 | struct clk *backup; | ||
125 | } cpu; | ||
126 | struct { | ||
127 | struct list_head node; | ||
128 | bool enabled; | ||
129 | unsigned long rate; | ||
130 | } shared_bus_user; | ||
131 | } u; | ||
132 | |||
133 | spinlock_t spinlock; | ||
145 | }; | 134 | }; |
146 | 135 | ||
147 | |||
148 | struct clk_duplicate { | 136 | struct clk_duplicate { |
149 | const char *name; | 137 | const char *name; |
150 | struct clk_lookup lookup; | 138 | struct clk_lookup lookup; |
@@ -163,11 +151,10 @@ void tegra2_periph_reset_assert(struct clk *c); | |||
163 | void clk_init(struct clk *clk); | 151 | void clk_init(struct clk *clk); |
164 | struct clk *tegra_get_clock_by_name(const char *name); | 152 | struct clk *tegra_get_clock_by_name(const char *name); |
165 | unsigned long clk_measure_input_freq(void); | 153 | unsigned long clk_measure_input_freq(void); |
166 | void clk_disable_locked(struct clk *c); | ||
167 | int clk_enable_locked(struct clk *c); | ||
168 | int clk_set_parent_locked(struct clk *c, struct clk *parent); | ||
169 | int clk_set_rate_locked(struct clk *c, unsigned long rate); | ||
170 | int clk_reparent(struct clk *c, struct clk *parent); | 154 | int clk_reparent(struct clk *c, struct clk *parent); |
171 | void tegra_clk_init_from_table(struct tegra_clk_init_table *table); | 155 | void tegra_clk_init_from_table(struct tegra_clk_init_table *table); |
156 | unsigned long clk_get_rate_locked(struct clk *c); | ||
157 | int clk_set_rate_locked(struct clk *c, unsigned long rate); | ||
158 | void tegra2_sdmmc_tap_delay(struct clk *c, int delay); | ||
172 | 159 | ||
173 | #endif | 160 | #endif |
diff --git a/arch/arm/mach-tegra/common.c b/arch/arm/mach-tegra/common.c index 7c91e2b9d643..d5e3f89b05af 100644 --- a/arch/arm/mach-tegra/common.c +++ b/arch/arm/mach-tegra/common.c | |||
@@ -25,12 +25,25 @@ | |||
25 | #include <asm/hardware/cache-l2x0.h> | 25 | #include <asm/hardware/cache-l2x0.h> |
26 | 26 | ||
27 | #include <mach/iomap.h> | 27 | #include <mach/iomap.h> |
28 | #include <mach/dma.h> | 28 | #include <mach/system.h> |
29 | 29 | ||
30 | #include "board.h" | 30 | #include "board.h" |
31 | #include "clock.h" | 31 | #include "clock.h" |
32 | #include "fuse.h" | 32 | #include "fuse.h" |
33 | 33 | ||
34 | void (*arch_reset)(char mode, const char *cmd) = tegra_assert_system_reset; | ||
35 | |||
36 | void tegra_assert_system_reset(char mode, const char *cmd) | ||
37 | { | ||
38 | void __iomem *reset = IO_ADDRESS(TEGRA_CLK_RESET_BASE + 0x04); | ||
39 | u32 reg; | ||
40 | |||
41 | /* use *_related to avoid spinlock since caches are off */ | ||
42 | reg = readl_relaxed(reset); | ||
43 | reg |= 0x04; | ||
44 | writel_relaxed(reg, reset); | ||
45 | } | ||
46 | |||
34 | static __initdata struct tegra_clk_init_table common_clk_init_table[] = { | 47 | static __initdata struct tegra_clk_init_table common_clk_init_table[] = { |
35 | /* name parent rate enabled */ | 48 | /* name parent rate enabled */ |
36 | { "clk_m", NULL, 0, true }, | 49 | { "clk_m", NULL, 0, true }, |
@@ -42,6 +55,9 @@ static __initdata struct tegra_clk_init_table common_clk_init_table[] = { | |||
42 | { "sclk", "pll_p_out4", 108000000, true }, | 55 | { "sclk", "pll_p_out4", 108000000, true }, |
43 | { "hclk", "sclk", 108000000, true }, | 56 | { "hclk", "sclk", 108000000, true }, |
44 | { "pclk", "hclk", 54000000, true }, | 57 | { "pclk", "hclk", 54000000, true }, |
58 | { "csite", NULL, 0, true }, | ||
59 | { "emc", NULL, 0, true }, | ||
60 | { "cpu", NULL, 0, true }, | ||
45 | { NULL, NULL, 0, 0}, | 61 | { NULL, NULL, 0, 0}, |
46 | }; | 62 | }; |
47 | 63 | ||
@@ -50,21 +66,18 @@ void __init tegra_init_cache(void) | |||
50 | #ifdef CONFIG_CACHE_L2X0 | 66 | #ifdef CONFIG_CACHE_L2X0 |
51 | void __iomem *p = IO_ADDRESS(TEGRA_ARM_PERIF_BASE) + 0x3000; | 67 | void __iomem *p = IO_ADDRESS(TEGRA_ARM_PERIF_BASE) + 0x3000; |
52 | 68 | ||
53 | writel(0x331, p + L2X0_TAG_LATENCY_CTRL); | 69 | writel_relaxed(0x331, p + L2X0_TAG_LATENCY_CTRL); |
54 | writel(0x441, p + L2X0_DATA_LATENCY_CTRL); | 70 | writel_relaxed(0x441, p + L2X0_DATA_LATENCY_CTRL); |
55 | 71 | ||
56 | l2x0_init(p, 0x6C080001, 0x8200c3fe); | 72 | l2x0_init(p, 0x6C080001, 0x8200c3fe); |
57 | #endif | 73 | #endif |
58 | 74 | ||
59 | } | 75 | } |
60 | 76 | ||
61 | void __init tegra_common_init(void) | 77 | void __init tegra_init_early(void) |
62 | { | 78 | { |
63 | tegra_init_fuse(); | 79 | tegra_init_fuse(); |
64 | tegra_init_clock(); | 80 | tegra_init_clock(); |
65 | tegra_clk_init_from_table(common_clk_init_table); | 81 | tegra_clk_init_from_table(common_clk_init_table); |
66 | tegra_init_cache(); | 82 | tegra_init_cache(); |
67 | #ifdef CONFIG_TEGRA_SYSTEM_DMA | ||
68 | tegra_dma_init(); | ||
69 | #endif | ||
70 | } | 83 | } |
diff --git a/arch/arm/mach-tegra/cpu-tegra.c b/arch/arm/mach-tegra/cpu-tegra.c index fea5719c7072..0e1016a827ac 100644 --- a/arch/arm/mach-tegra/cpu-tegra.c +++ b/arch/arm/mach-tegra/cpu-tegra.c | |||
@@ -28,6 +28,7 @@ | |||
28 | #include <linux/err.h> | 28 | #include <linux/err.h> |
29 | #include <linux/clk.h> | 29 | #include <linux/clk.h> |
30 | #include <linux/io.h> | 30 | #include <linux/io.h> |
31 | #include <linux/suspend.h> | ||
31 | 32 | ||
32 | #include <asm/system.h> | 33 | #include <asm/system.h> |
33 | 34 | ||
@@ -36,21 +37,25 @@ | |||
36 | 37 | ||
37 | /* Frequency table index must be sequential starting at 0 */ | 38 | /* Frequency table index must be sequential starting at 0 */ |
38 | static struct cpufreq_frequency_table freq_table[] = { | 39 | static struct cpufreq_frequency_table freq_table[] = { |
39 | { 0, 312000 }, | 40 | { 0, 216000 }, |
40 | { 1, 456000 }, | 41 | { 1, 312000 }, |
41 | { 2, 608000 }, | 42 | { 2, 456000 }, |
42 | { 3, 760000 }, | 43 | { 3, 608000 }, |
43 | { 4, 816000 }, | 44 | { 4, 760000 }, |
44 | { 5, 912000 }, | 45 | { 5, 816000 }, |
45 | { 6, 1000000 }, | 46 | { 6, 912000 }, |
46 | { 7, CPUFREQ_TABLE_END }, | 47 | { 7, 1000000 }, |
48 | { 8, CPUFREQ_TABLE_END }, | ||
47 | }; | 49 | }; |
48 | 50 | ||
49 | #define NUM_CPUS 2 | 51 | #define NUM_CPUS 2 |
50 | 52 | ||
51 | static struct clk *cpu_clk; | 53 | static struct clk *cpu_clk; |
54 | static struct clk *emc_clk; | ||
52 | 55 | ||
53 | static unsigned long target_cpu_speed[NUM_CPUS]; | 56 | static unsigned long target_cpu_speed[NUM_CPUS]; |
57 | static DEFINE_MUTEX(tegra_cpu_lock); | ||
58 | static bool is_suspended; | ||
54 | 59 | ||
55 | int tegra_verify_speed(struct cpufreq_policy *policy) | 60 | int tegra_verify_speed(struct cpufreq_policy *policy) |
56 | { | 61 | { |
@@ -68,22 +73,28 @@ unsigned int tegra_getspeed(unsigned int cpu) | |||
68 | return rate; | 73 | return rate; |
69 | } | 74 | } |
70 | 75 | ||
71 | static int tegra_update_cpu_speed(void) | 76 | static int tegra_update_cpu_speed(unsigned long rate) |
72 | { | 77 | { |
73 | int i; | ||
74 | unsigned long rate = 0; | ||
75 | int ret = 0; | 78 | int ret = 0; |
76 | struct cpufreq_freqs freqs; | 79 | struct cpufreq_freqs freqs; |
77 | 80 | ||
78 | for_each_online_cpu(i) | ||
79 | rate = max(rate, target_cpu_speed[i]); | ||
80 | |||
81 | freqs.old = tegra_getspeed(0); | 81 | freqs.old = tegra_getspeed(0); |
82 | freqs.new = rate; | 82 | freqs.new = rate; |
83 | 83 | ||
84 | if (freqs.old == freqs.new) | 84 | if (freqs.old == freqs.new) |
85 | return ret; | 85 | return ret; |
86 | 86 | ||
87 | /* | ||
88 | * Vote on memory bus frequency based on cpu frequency | ||
89 | * This sets the minimum frequency, display or avp may request higher | ||
90 | */ | ||
91 | if (rate >= 816000) | ||
92 | clk_set_rate(emc_clk, 600000000); /* cpu 816 MHz, emc max */ | ||
93 | else if (rate >= 456000) | ||
94 | clk_set_rate(emc_clk, 300000000); /* cpu 456 MHz, emc 150Mhz */ | ||
95 | else | ||
96 | clk_set_rate(emc_clk, 100000000); /* emc 50Mhz */ | ||
97 | |||
87 | for_each_online_cpu(freqs.cpu) | 98 | for_each_online_cpu(freqs.cpu) |
88 | cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE); | 99 | cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE); |
89 | 100 | ||
@@ -92,7 +103,7 @@ static int tegra_update_cpu_speed(void) | |||
92 | freqs.old, freqs.new); | 103 | freqs.old, freqs.new); |
93 | #endif | 104 | #endif |
94 | 105 | ||
95 | ret = clk_set_rate_cansleep(cpu_clk, freqs.new * 1000); | 106 | ret = clk_set_rate(cpu_clk, freqs.new * 1000); |
96 | if (ret) { | 107 | if (ret) { |
97 | pr_err("cpu-tegra: Failed to set cpu frequency to %d kHz\n", | 108 | pr_err("cpu-tegra: Failed to set cpu frequency to %d kHz\n", |
98 | freqs.new); | 109 | freqs.new); |
@@ -105,12 +116,30 @@ static int tegra_update_cpu_speed(void) | |||
105 | return 0; | 116 | return 0; |
106 | } | 117 | } |
107 | 118 | ||
119 | static unsigned long tegra_cpu_highest_speed(void) | ||
120 | { | ||
121 | unsigned long rate = 0; | ||
122 | int i; | ||
123 | |||
124 | for_each_online_cpu(i) | ||
125 | rate = max(rate, target_cpu_speed[i]); | ||
126 | return rate; | ||
127 | } | ||
128 | |||
108 | static int tegra_target(struct cpufreq_policy *policy, | 129 | static int tegra_target(struct cpufreq_policy *policy, |
109 | unsigned int target_freq, | 130 | unsigned int target_freq, |
110 | unsigned int relation) | 131 | unsigned int relation) |
111 | { | 132 | { |
112 | int idx; | 133 | int idx; |
113 | unsigned int freq; | 134 | unsigned int freq; |
135 | int ret = 0; | ||
136 | |||
137 | mutex_lock(&tegra_cpu_lock); | ||
138 | |||
139 | if (is_suspended) { | ||
140 | ret = -EBUSY; | ||
141 | goto out; | ||
142 | } | ||
114 | 143 | ||
115 | cpufreq_frequency_table_target(policy, freq_table, target_freq, | 144 | cpufreq_frequency_table_target(policy, freq_table, target_freq, |
116 | relation, &idx); | 145 | relation, &idx); |
@@ -119,9 +148,34 @@ static int tegra_target(struct cpufreq_policy *policy, | |||
119 | 148 | ||
120 | target_cpu_speed[policy->cpu] = freq; | 149 | target_cpu_speed[policy->cpu] = freq; |
121 | 150 | ||
122 | return tegra_update_cpu_speed(); | 151 | ret = tegra_update_cpu_speed(tegra_cpu_highest_speed()); |
152 | |||
153 | out: | ||
154 | mutex_unlock(&tegra_cpu_lock); | ||
155 | return ret; | ||
123 | } | 156 | } |
124 | 157 | ||
158 | static int tegra_pm_notify(struct notifier_block *nb, unsigned long event, | ||
159 | void *dummy) | ||
160 | { | ||
161 | mutex_lock(&tegra_cpu_lock); | ||
162 | if (event == PM_SUSPEND_PREPARE) { | ||
163 | is_suspended = true; | ||
164 | pr_info("Tegra cpufreq suspend: setting frequency to %d kHz\n", | ||
165 | freq_table[0].frequency); | ||
166 | tegra_update_cpu_speed(freq_table[0].frequency); | ||
167 | } else if (event == PM_POST_SUSPEND) { | ||
168 | is_suspended = false; | ||
169 | } | ||
170 | mutex_unlock(&tegra_cpu_lock); | ||
171 | |||
172 | return NOTIFY_OK; | ||
173 | } | ||
174 | |||
175 | static struct notifier_block tegra_cpu_pm_notifier = { | ||
176 | .notifier_call = tegra_pm_notify, | ||
177 | }; | ||
178 | |||
125 | static int tegra_cpu_init(struct cpufreq_policy *policy) | 179 | static int tegra_cpu_init(struct cpufreq_policy *policy) |
126 | { | 180 | { |
127 | if (policy->cpu >= NUM_CPUS) | 181 | if (policy->cpu >= NUM_CPUS) |
@@ -131,6 +185,15 @@ static int tegra_cpu_init(struct cpufreq_policy *policy) | |||
131 | if (IS_ERR(cpu_clk)) | 185 | if (IS_ERR(cpu_clk)) |
132 | return PTR_ERR(cpu_clk); | 186 | return PTR_ERR(cpu_clk); |
133 | 187 | ||
188 | emc_clk = clk_get_sys("cpu", "emc"); | ||
189 | if (IS_ERR(emc_clk)) { | ||
190 | clk_put(cpu_clk); | ||
191 | return PTR_ERR(emc_clk); | ||
192 | } | ||
193 | |||
194 | clk_enable(emc_clk); | ||
195 | clk_enable(cpu_clk); | ||
196 | |||
134 | cpufreq_frequency_table_cpuinfo(policy, freq_table); | 197 | cpufreq_frequency_table_cpuinfo(policy, freq_table); |
135 | cpufreq_frequency_table_get_attr(freq_table, policy->cpu); | 198 | cpufreq_frequency_table_get_attr(freq_table, policy->cpu); |
136 | policy->cur = tegra_getspeed(policy->cpu); | 199 | policy->cur = tegra_getspeed(policy->cpu); |
@@ -142,12 +205,17 @@ static int tegra_cpu_init(struct cpufreq_policy *policy) | |||
142 | policy->shared_type = CPUFREQ_SHARED_TYPE_ALL; | 205 | policy->shared_type = CPUFREQ_SHARED_TYPE_ALL; |
143 | cpumask_copy(policy->related_cpus, cpu_possible_mask); | 206 | cpumask_copy(policy->related_cpus, cpu_possible_mask); |
144 | 207 | ||
208 | if (policy->cpu == 0) | ||
209 | register_pm_notifier(&tegra_cpu_pm_notifier); | ||
210 | |||
145 | return 0; | 211 | return 0; |
146 | } | 212 | } |
147 | 213 | ||
148 | static int tegra_cpu_exit(struct cpufreq_policy *policy) | 214 | static int tegra_cpu_exit(struct cpufreq_policy *policy) |
149 | { | 215 | { |
150 | cpufreq_frequency_table_cpuinfo(policy, freq_table); | 216 | cpufreq_frequency_table_cpuinfo(policy, freq_table); |
217 | clk_disable(emc_clk); | ||
218 | clk_put(emc_clk); | ||
151 | clk_put(cpu_clk); | 219 | clk_put(cpu_clk); |
152 | return 0; | 220 | return 0; |
153 | } | 221 | } |
diff --git a/arch/arm/mach-tegra/devices.c b/arch/arm/mach-tegra/devices.c new file mode 100644 index 000000000000..1528f9daef1f --- /dev/null +++ b/arch/arm/mach-tegra/devices.c | |||
@@ -0,0 +1,575 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2010,2011 Google, Inc. | ||
3 | * | ||
4 | * Author: | ||
5 | * Colin Cross <ccross@android.com> | ||
6 | * Erik Gilling <ccross@android.com> | ||
7 | * | ||
8 | * This software is licensed under the terms of the GNU General Public | ||
9 | * License version 2, as published by the Free Software Foundation, and | ||
10 | * may be copied, distributed, and modified under those terms. | ||
11 | * | ||
12 | * This program is distributed in the hope that it will be useful, | ||
13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
15 | * GNU General Public License for more details. | ||
16 | * | ||
17 | */ | ||
18 | |||
19 | |||
20 | #include <linux/resource.h> | ||
21 | #include <linux/platform_device.h> | ||
22 | #include <linux/dma-mapping.h> | ||
23 | #include <linux/fsl_devices.h> | ||
24 | #include <linux/serial_8250.h> | ||
25 | #include <asm/pmu.h> | ||
26 | #include <mach/irqs.h> | ||
27 | #include <mach/iomap.h> | ||
28 | #include <mach/dma.h> | ||
29 | |||
30 | static struct resource i2c_resource1[] = { | ||
31 | [0] = { | ||
32 | .start = INT_I2C, | ||
33 | .end = INT_I2C, | ||
34 | .flags = IORESOURCE_IRQ, | ||
35 | }, | ||
36 | [1] = { | ||
37 | .start = TEGRA_I2C_BASE, | ||
38 | .end = TEGRA_I2C_BASE + TEGRA_I2C_SIZE-1, | ||
39 | .flags = IORESOURCE_MEM, | ||
40 | }, | ||
41 | }; | ||
42 | |||
43 | static struct resource i2c_resource2[] = { | ||
44 | [0] = { | ||
45 | .start = INT_I2C2, | ||
46 | .end = INT_I2C2, | ||
47 | .flags = IORESOURCE_IRQ, | ||
48 | }, | ||
49 | [1] = { | ||
50 | .start = TEGRA_I2C2_BASE, | ||
51 | .end = TEGRA_I2C2_BASE + TEGRA_I2C2_SIZE-1, | ||
52 | .flags = IORESOURCE_MEM, | ||
53 | }, | ||
54 | }; | ||
55 | |||
56 | static struct resource i2c_resource3[] = { | ||
57 | [0] = { | ||
58 | .start = INT_I2C3, | ||
59 | .end = INT_I2C3, | ||
60 | .flags = IORESOURCE_IRQ, | ||
61 | }, | ||
62 | [1] = { | ||
63 | .start = TEGRA_I2C3_BASE, | ||
64 | .end = TEGRA_I2C3_BASE + TEGRA_I2C3_SIZE-1, | ||
65 | .flags = IORESOURCE_MEM, | ||
66 | }, | ||
67 | }; | ||
68 | |||
69 | static struct resource i2c_resource4[] = { | ||
70 | [0] = { | ||
71 | .start = INT_DVC, | ||
72 | .end = INT_DVC, | ||
73 | .flags = IORESOURCE_IRQ, | ||
74 | }, | ||
75 | [1] = { | ||
76 | .start = TEGRA_DVC_BASE, | ||
77 | .end = TEGRA_DVC_BASE + TEGRA_DVC_SIZE-1, | ||
78 | .flags = IORESOURCE_MEM, | ||
79 | }, | ||
80 | }; | ||
81 | |||
82 | struct platform_device tegra_i2c_device1 = { | ||
83 | .name = "tegra-i2c", | ||
84 | .id = 0, | ||
85 | .resource = i2c_resource1, | ||
86 | .num_resources = ARRAY_SIZE(i2c_resource1), | ||
87 | .dev = { | ||
88 | .platform_data = 0, | ||
89 | }, | ||
90 | }; | ||
91 | |||
92 | struct platform_device tegra_i2c_device2 = { | ||
93 | .name = "tegra-i2c", | ||
94 | .id = 1, | ||
95 | .resource = i2c_resource2, | ||
96 | .num_resources = ARRAY_SIZE(i2c_resource2), | ||
97 | .dev = { | ||
98 | .platform_data = 0, | ||
99 | }, | ||
100 | }; | ||
101 | |||
102 | struct platform_device tegra_i2c_device3 = { | ||
103 | .name = "tegra-i2c", | ||
104 | .id = 2, | ||
105 | .resource = i2c_resource3, | ||
106 | .num_resources = ARRAY_SIZE(i2c_resource3), | ||
107 | .dev = { | ||
108 | .platform_data = 0, | ||
109 | }, | ||
110 | }; | ||
111 | |||
112 | struct platform_device tegra_i2c_device4 = { | ||
113 | .name = "tegra-i2c", | ||
114 | .id = 3, | ||
115 | .resource = i2c_resource4, | ||
116 | .num_resources = ARRAY_SIZE(i2c_resource4), | ||
117 | .dev = { | ||
118 | .platform_data = 0, | ||
119 | }, | ||
120 | }; | ||
121 | |||
122 | static struct resource spi_resource1[] = { | ||
123 | [0] = { | ||
124 | .start = INT_S_LINK1, | ||
125 | .end = INT_S_LINK1, | ||
126 | .flags = IORESOURCE_IRQ, | ||
127 | }, | ||
128 | [1] = { | ||
129 | .start = TEGRA_SPI1_BASE, | ||
130 | .end = TEGRA_SPI1_BASE + TEGRA_SPI1_SIZE-1, | ||
131 | .flags = IORESOURCE_MEM, | ||
132 | }, | ||
133 | }; | ||
134 | |||
135 | static struct resource spi_resource2[] = { | ||
136 | [0] = { | ||
137 | .start = INT_SPI_2, | ||
138 | .end = INT_SPI_2, | ||
139 | .flags = IORESOURCE_IRQ, | ||
140 | }, | ||
141 | [1] = { | ||
142 | .start = TEGRA_SPI2_BASE, | ||
143 | .end = TEGRA_SPI2_BASE + TEGRA_SPI2_SIZE-1, | ||
144 | .flags = IORESOURCE_MEM, | ||
145 | }, | ||
146 | }; | ||
147 | |||
148 | static struct resource spi_resource3[] = { | ||
149 | [0] = { | ||
150 | .start = INT_SPI_3, | ||
151 | .end = INT_SPI_3, | ||
152 | .flags = IORESOURCE_IRQ, | ||
153 | }, | ||
154 | [1] = { | ||
155 | .start = TEGRA_SPI3_BASE, | ||
156 | .end = TEGRA_SPI3_BASE + TEGRA_SPI3_SIZE-1, | ||
157 | .flags = IORESOURCE_MEM, | ||
158 | }, | ||
159 | }; | ||
160 | |||
161 | static struct resource spi_resource4[] = { | ||
162 | [0] = { | ||
163 | .start = INT_SPI_4, | ||
164 | .end = INT_SPI_4, | ||
165 | .flags = IORESOURCE_IRQ, | ||
166 | }, | ||
167 | [1] = { | ||
168 | .start = TEGRA_SPI4_BASE, | ||
169 | .end = TEGRA_SPI4_BASE + TEGRA_SPI4_SIZE-1, | ||
170 | .flags = IORESOURCE_MEM, | ||
171 | }, | ||
172 | }; | ||
173 | |||
174 | struct platform_device tegra_spi_device1 = { | ||
175 | .name = "spi_tegra", | ||
176 | .id = 0, | ||
177 | .resource = spi_resource1, | ||
178 | .num_resources = ARRAY_SIZE(spi_resource1), | ||
179 | .dev = { | ||
180 | .coherent_dma_mask = 0xffffffff, | ||
181 | }, | ||
182 | }; | ||
183 | |||
184 | struct platform_device tegra_spi_device2 = { | ||
185 | .name = "spi_tegra", | ||
186 | .id = 1, | ||
187 | .resource = spi_resource2, | ||
188 | .num_resources = ARRAY_SIZE(spi_resource2), | ||
189 | .dev = { | ||
190 | .coherent_dma_mask = 0xffffffff, | ||
191 | }, | ||
192 | }; | ||
193 | |||
194 | struct platform_device tegra_spi_device3 = { | ||
195 | .name = "spi_tegra", | ||
196 | .id = 2, | ||
197 | .resource = spi_resource3, | ||
198 | .num_resources = ARRAY_SIZE(spi_resource3), | ||
199 | .dev = { | ||
200 | .coherent_dma_mask = 0xffffffff, | ||
201 | }, | ||
202 | }; | ||
203 | |||
204 | struct platform_device tegra_spi_device4 = { | ||
205 | .name = "spi_tegra", | ||
206 | .id = 3, | ||
207 | .resource = spi_resource4, | ||
208 | .num_resources = ARRAY_SIZE(spi_resource4), | ||
209 | .dev = { | ||
210 | .coherent_dma_mask = 0xffffffff, | ||
211 | }, | ||
212 | }; | ||
213 | |||
214 | |||
215 | static struct resource sdhci_resource1[] = { | ||
216 | [0] = { | ||
217 | .start = INT_SDMMC1, | ||
218 | .end = INT_SDMMC1, | ||
219 | .flags = IORESOURCE_IRQ, | ||
220 | }, | ||
221 | [1] = { | ||
222 | .start = TEGRA_SDMMC1_BASE, | ||
223 | .end = TEGRA_SDMMC1_BASE + TEGRA_SDMMC1_SIZE-1, | ||
224 | .flags = IORESOURCE_MEM, | ||
225 | }, | ||
226 | }; | ||
227 | |||
228 | static struct resource sdhci_resource2[] = { | ||
229 | [0] = { | ||
230 | .start = INT_SDMMC2, | ||
231 | .end = INT_SDMMC2, | ||
232 | .flags = IORESOURCE_IRQ, | ||
233 | }, | ||
234 | [1] = { | ||
235 | .start = TEGRA_SDMMC2_BASE, | ||
236 | .end = TEGRA_SDMMC2_BASE + TEGRA_SDMMC2_SIZE-1, | ||
237 | .flags = IORESOURCE_MEM, | ||
238 | }, | ||
239 | }; | ||
240 | |||
241 | static struct resource sdhci_resource3[] = { | ||
242 | [0] = { | ||
243 | .start = INT_SDMMC3, | ||
244 | .end = INT_SDMMC3, | ||
245 | .flags = IORESOURCE_IRQ, | ||
246 | }, | ||
247 | [1] = { | ||
248 | .start = TEGRA_SDMMC3_BASE, | ||
249 | .end = TEGRA_SDMMC3_BASE + TEGRA_SDMMC3_SIZE-1, | ||
250 | .flags = IORESOURCE_MEM, | ||
251 | }, | ||
252 | }; | ||
253 | |||
254 | static struct resource sdhci_resource4[] = { | ||
255 | [0] = { | ||
256 | .start = INT_SDMMC4, | ||
257 | .end = INT_SDMMC4, | ||
258 | .flags = IORESOURCE_IRQ, | ||
259 | }, | ||
260 | [1] = { | ||
261 | .start = TEGRA_SDMMC4_BASE, | ||
262 | .end = TEGRA_SDMMC4_BASE + TEGRA_SDMMC4_SIZE-1, | ||
263 | .flags = IORESOURCE_MEM, | ||
264 | }, | ||
265 | }; | ||
266 | |||
267 | /* board files should fill in platform_data register the devices themselvs. | ||
268 | * See board-harmony.c for an example | ||
269 | */ | ||
270 | struct platform_device tegra_sdhci_device1 = { | ||
271 | .name = "sdhci-tegra", | ||
272 | .id = 0, | ||
273 | .resource = sdhci_resource1, | ||
274 | .num_resources = ARRAY_SIZE(sdhci_resource1), | ||
275 | }; | ||
276 | |||
277 | struct platform_device tegra_sdhci_device2 = { | ||
278 | .name = "sdhci-tegra", | ||
279 | .id = 1, | ||
280 | .resource = sdhci_resource2, | ||
281 | .num_resources = ARRAY_SIZE(sdhci_resource2), | ||
282 | }; | ||
283 | |||
284 | struct platform_device tegra_sdhci_device3 = { | ||
285 | .name = "sdhci-tegra", | ||
286 | .id = 2, | ||
287 | .resource = sdhci_resource3, | ||
288 | .num_resources = ARRAY_SIZE(sdhci_resource3), | ||
289 | }; | ||
290 | |||
291 | struct platform_device tegra_sdhci_device4 = { | ||
292 | .name = "sdhci-tegra", | ||
293 | .id = 3, | ||
294 | .resource = sdhci_resource4, | ||
295 | .num_resources = ARRAY_SIZE(sdhci_resource4), | ||
296 | }; | ||
297 | |||
298 | static struct resource tegra_usb1_resources[] = { | ||
299 | [0] = { | ||
300 | .start = TEGRA_USB_BASE, | ||
301 | .end = TEGRA_USB_BASE + TEGRA_USB_SIZE - 1, | ||
302 | .flags = IORESOURCE_MEM, | ||
303 | }, | ||
304 | [1] = { | ||
305 | .start = INT_USB, | ||
306 | .end = INT_USB, | ||
307 | .flags = IORESOURCE_IRQ, | ||
308 | }, | ||
309 | }; | ||
310 | |||
311 | static struct resource tegra_usb2_resources[] = { | ||
312 | [0] = { | ||
313 | .start = TEGRA_USB2_BASE, | ||
314 | .end = TEGRA_USB2_BASE + TEGRA_USB2_SIZE - 1, | ||
315 | .flags = IORESOURCE_MEM, | ||
316 | }, | ||
317 | [1] = { | ||
318 | .start = INT_USB2, | ||
319 | .end = INT_USB2, | ||
320 | .flags = IORESOURCE_IRQ, | ||
321 | }, | ||
322 | }; | ||
323 | |||
324 | static struct resource tegra_usb3_resources[] = { | ||
325 | [0] = { | ||
326 | .start = TEGRA_USB3_BASE, | ||
327 | .end = TEGRA_USB3_BASE + TEGRA_USB3_SIZE - 1, | ||
328 | .flags = IORESOURCE_MEM, | ||
329 | }, | ||
330 | [1] = { | ||
331 | .start = INT_USB3, | ||
332 | .end = INT_USB3, | ||
333 | .flags = IORESOURCE_IRQ, | ||
334 | }, | ||
335 | }; | ||
336 | |||
337 | static u64 tegra_ehci_dmamask = DMA_BIT_MASK(32); | ||
338 | |||
339 | struct platform_device tegra_ehci1_device = { | ||
340 | .name = "tegra-ehci", | ||
341 | .id = 0, | ||
342 | .dev = { | ||
343 | .dma_mask = &tegra_ehci_dmamask, | ||
344 | .coherent_dma_mask = DMA_BIT_MASK(32), | ||
345 | }, | ||
346 | .resource = tegra_usb1_resources, | ||
347 | .num_resources = ARRAY_SIZE(tegra_usb1_resources), | ||
348 | }; | ||
349 | |||
350 | struct platform_device tegra_ehci2_device = { | ||
351 | .name = "tegra-ehci", | ||
352 | .id = 1, | ||
353 | .dev = { | ||
354 | .dma_mask = &tegra_ehci_dmamask, | ||
355 | .coherent_dma_mask = DMA_BIT_MASK(32), | ||
356 | }, | ||
357 | .resource = tegra_usb2_resources, | ||
358 | .num_resources = ARRAY_SIZE(tegra_usb2_resources), | ||
359 | }; | ||
360 | |||
361 | struct platform_device tegra_ehci3_device = { | ||
362 | .name = "tegra-ehci", | ||
363 | .id = 2, | ||
364 | .dev = { | ||
365 | .dma_mask = &tegra_ehci_dmamask, | ||
366 | .coherent_dma_mask = DMA_BIT_MASK(32), | ||
367 | }, | ||
368 | .resource = tegra_usb3_resources, | ||
369 | .num_resources = ARRAY_SIZE(tegra_usb3_resources), | ||
370 | }; | ||
371 | |||
372 | static struct resource tegra_pmu_resources[] = { | ||
373 | [0] = { | ||
374 | .start = INT_CPU0_PMU_INTR, | ||
375 | .end = INT_CPU0_PMU_INTR, | ||
376 | .flags = IORESOURCE_IRQ, | ||
377 | }, | ||
378 | [1] = { | ||
379 | .start = INT_CPU1_PMU_INTR, | ||
380 | .end = INT_CPU1_PMU_INTR, | ||
381 | .flags = IORESOURCE_IRQ, | ||
382 | }, | ||
383 | }; | ||
384 | |||
385 | struct platform_device tegra_pmu_device = { | ||
386 | .name = "arm-pmu", | ||
387 | .id = ARM_PMU_DEVICE_CPU, | ||
388 | .num_resources = ARRAY_SIZE(tegra_pmu_resources), | ||
389 | .resource = tegra_pmu_resources, | ||
390 | }; | ||
391 | |||
392 | static struct resource tegra_uarta_resources[] = { | ||
393 | [0] = { | ||
394 | .start = TEGRA_UARTA_BASE, | ||
395 | .end = TEGRA_UARTA_BASE + TEGRA_UARTA_SIZE - 1, | ||
396 | .flags = IORESOURCE_MEM, | ||
397 | }, | ||
398 | [1] = { | ||
399 | .start = INT_UARTA, | ||
400 | .end = INT_UARTA, | ||
401 | .flags = IORESOURCE_IRQ, | ||
402 | }, | ||
403 | }; | ||
404 | |||
405 | static struct resource tegra_uartb_resources[] = { | ||
406 | [0] = { | ||
407 | .start = TEGRA_UARTB_BASE, | ||
408 | .end = TEGRA_UARTB_BASE + TEGRA_UARTB_SIZE - 1, | ||
409 | .flags = IORESOURCE_MEM, | ||
410 | }, | ||
411 | [1] = { | ||
412 | .start = INT_UARTB, | ||
413 | .end = INT_UARTB, | ||
414 | .flags = IORESOURCE_IRQ, | ||
415 | }, | ||
416 | }; | ||
417 | |||
418 | static struct resource tegra_uartc_resources[] = { | ||
419 | [0] = { | ||
420 | .start = TEGRA_UARTC_BASE, | ||
421 | .end = TEGRA_UARTC_BASE + TEGRA_UARTC_SIZE - 1, | ||
422 | .flags = IORESOURCE_MEM, | ||
423 | }, | ||
424 | [1] = { | ||
425 | .start = INT_UARTC, | ||
426 | .end = INT_UARTC, | ||
427 | .flags = IORESOURCE_IRQ, | ||
428 | }, | ||
429 | }; | ||
430 | |||
431 | static struct resource tegra_uartd_resources[] = { | ||
432 | [0] = { | ||
433 | .start = TEGRA_UARTD_BASE, | ||
434 | .end = TEGRA_UARTD_BASE + TEGRA_UARTD_SIZE - 1, | ||
435 | .flags = IORESOURCE_MEM, | ||
436 | }, | ||
437 | [1] = { | ||
438 | .start = INT_UARTD, | ||
439 | .end = INT_UARTD, | ||
440 | .flags = IORESOURCE_IRQ, | ||
441 | }, | ||
442 | }; | ||
443 | |||
444 | static struct resource tegra_uarte_resources[] = { | ||
445 | [0] = { | ||
446 | .start = TEGRA_UARTE_BASE, | ||
447 | .end = TEGRA_UARTE_BASE + TEGRA_UARTE_SIZE - 1, | ||
448 | .flags = IORESOURCE_MEM, | ||
449 | }, | ||
450 | [1] = { | ||
451 | .start = INT_UARTE, | ||
452 | .end = INT_UARTE, | ||
453 | .flags = IORESOURCE_IRQ, | ||
454 | }, | ||
455 | }; | ||
456 | |||
457 | struct platform_device tegra_uarta_device = { | ||
458 | .name = "tegra_uart", | ||
459 | .id = 0, | ||
460 | .num_resources = ARRAY_SIZE(tegra_uarta_resources), | ||
461 | .resource = tegra_uarta_resources, | ||
462 | .dev = { | ||
463 | .coherent_dma_mask = DMA_BIT_MASK(32), | ||
464 | }, | ||
465 | }; | ||
466 | |||
467 | struct platform_device tegra_uartb_device = { | ||
468 | .name = "tegra_uart", | ||
469 | .id = 1, | ||
470 | .num_resources = ARRAY_SIZE(tegra_uartb_resources), | ||
471 | .resource = tegra_uartb_resources, | ||
472 | .dev = { | ||
473 | .coherent_dma_mask = DMA_BIT_MASK(32), | ||
474 | }, | ||
475 | }; | ||
476 | |||
477 | struct platform_device tegra_uartc_device = { | ||
478 | .name = "tegra_uart", | ||
479 | .id = 2, | ||
480 | .num_resources = ARRAY_SIZE(tegra_uartc_resources), | ||
481 | .resource = tegra_uartc_resources, | ||
482 | .dev = { | ||
483 | .coherent_dma_mask = DMA_BIT_MASK(32), | ||
484 | }, | ||
485 | }; | ||
486 | |||
487 | struct platform_device tegra_uartd_device = { | ||
488 | .name = "tegra_uart", | ||
489 | .id = 3, | ||
490 | .num_resources = ARRAY_SIZE(tegra_uartd_resources), | ||
491 | .resource = tegra_uartd_resources, | ||
492 | .dev = { | ||
493 | .coherent_dma_mask = DMA_BIT_MASK(32), | ||
494 | }, | ||
495 | }; | ||
496 | |||
497 | struct platform_device tegra_uarte_device = { | ||
498 | .name = "tegra_uart", | ||
499 | .id = 4, | ||
500 | .num_resources = ARRAY_SIZE(tegra_uarte_resources), | ||
501 | .resource = tegra_uarte_resources, | ||
502 | .dev = { | ||
503 | .coherent_dma_mask = DMA_BIT_MASK(32), | ||
504 | }, | ||
505 | }; | ||
506 | |||
507 | static struct resource i2s_resource1[] = { | ||
508 | [0] = { | ||
509 | .start = INT_I2S1, | ||
510 | .end = INT_I2S1, | ||
511 | .flags = IORESOURCE_IRQ | ||
512 | }, | ||
513 | [1] = { | ||
514 | .start = TEGRA_DMA_REQ_SEL_I2S_1, | ||
515 | .end = TEGRA_DMA_REQ_SEL_I2S_1, | ||
516 | .flags = IORESOURCE_DMA | ||
517 | }, | ||
518 | [2] = { | ||
519 | .start = TEGRA_I2S1_BASE, | ||
520 | .end = TEGRA_I2S1_BASE + TEGRA_I2S1_SIZE - 1, | ||
521 | .flags = IORESOURCE_MEM | ||
522 | } | ||
523 | }; | ||
524 | |||
525 | static struct resource i2s_resource2[] = { | ||
526 | [0] = { | ||
527 | .start = INT_I2S2, | ||
528 | .end = INT_I2S2, | ||
529 | .flags = IORESOURCE_IRQ | ||
530 | }, | ||
531 | [1] = { | ||
532 | .start = TEGRA_DMA_REQ_SEL_I2S2_1, | ||
533 | .end = TEGRA_DMA_REQ_SEL_I2S2_1, | ||
534 | .flags = IORESOURCE_DMA | ||
535 | }, | ||
536 | [2] = { | ||
537 | .start = TEGRA_I2S2_BASE, | ||
538 | .end = TEGRA_I2S2_BASE + TEGRA_I2S2_SIZE - 1, | ||
539 | .flags = IORESOURCE_MEM | ||
540 | } | ||
541 | }; | ||
542 | |||
543 | struct platform_device tegra_i2s_device1 = { | ||
544 | .name = "tegra-i2s", | ||
545 | .id = 0, | ||
546 | .resource = i2s_resource1, | ||
547 | .num_resources = ARRAY_SIZE(i2s_resource1), | ||
548 | }; | ||
549 | |||
550 | struct platform_device tegra_i2s_device2 = { | ||
551 | .name = "tegra-i2s", | ||
552 | .id = 1, | ||
553 | .resource = i2s_resource2, | ||
554 | .num_resources = ARRAY_SIZE(i2s_resource2), | ||
555 | }; | ||
556 | |||
557 | static struct resource tegra_das_resources[] = { | ||
558 | [0] = { | ||
559 | .start = TEGRA_APB_MISC_DAS_BASE, | ||
560 | .end = TEGRA_APB_MISC_DAS_BASE + TEGRA_APB_MISC_DAS_SIZE - 1, | ||
561 | .flags = IORESOURCE_MEM, | ||
562 | }, | ||
563 | }; | ||
564 | |||
565 | struct platform_device tegra_das_device = { | ||
566 | .name = "tegra-das", | ||
567 | .id = -1, | ||
568 | .num_resources = ARRAY_SIZE(tegra_das_resources), | ||
569 | .resource = tegra_das_resources, | ||
570 | }; | ||
571 | |||
572 | struct platform_device tegra_pcm_device = { | ||
573 | .name = "tegra-pcm-audio", | ||
574 | .id = -1, | ||
575 | }; | ||
diff --git a/arch/arm/mach-tegra/devices.h b/arch/arm/mach-tegra/devices.h new file mode 100644 index 000000000000..4a7dc0a097d6 --- /dev/null +++ b/arch/arm/mach-tegra/devices.h | |||
@@ -0,0 +1,50 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2010,2011 Google, Inc. | ||
3 | * | ||
4 | * Author: | ||
5 | * Colin Cross <ccross@android.com> | ||
6 | * Erik Gilling <ccross@android.com> | ||
7 | * | ||
8 | * This software is licensed under the terms of the GNU General Public | ||
9 | * License version 2, as published by the Free Software Foundation, and | ||
10 | * may be copied, distributed, and modified under those terms. | ||
11 | * | ||
12 | * This program is distributed in the hope that it will be useful, | ||
13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
15 | * GNU General Public License for more details. | ||
16 | * | ||
17 | */ | ||
18 | |||
19 | #ifndef __MACH_TEGRA_DEVICES_H | ||
20 | #define __MACH_TEGRA_DEVICES_H | ||
21 | |||
22 | #include <linux/platform_device.h> | ||
23 | |||
24 | extern struct platform_device tegra_sdhci_device1; | ||
25 | extern struct platform_device tegra_sdhci_device2; | ||
26 | extern struct platform_device tegra_sdhci_device3; | ||
27 | extern struct platform_device tegra_sdhci_device4; | ||
28 | extern struct platform_device tegra_i2c_device1; | ||
29 | extern struct platform_device tegra_i2c_device2; | ||
30 | extern struct platform_device tegra_i2c_device3; | ||
31 | extern struct platform_device tegra_i2c_device4; | ||
32 | extern struct platform_device tegra_spi_device1; | ||
33 | extern struct platform_device tegra_spi_device2; | ||
34 | extern struct platform_device tegra_spi_device3; | ||
35 | extern struct platform_device tegra_spi_device4; | ||
36 | extern struct platform_device tegra_ehci1_device; | ||
37 | extern struct platform_device tegra_ehci2_device; | ||
38 | extern struct platform_device tegra_ehci3_device; | ||
39 | extern struct platform_device tegra_uarta_device; | ||
40 | extern struct platform_device tegra_uartb_device; | ||
41 | extern struct platform_device tegra_uartc_device; | ||
42 | extern struct platform_device tegra_uartd_device; | ||
43 | extern struct platform_device tegra_uarte_device; | ||
44 | extern struct platform_device tegra_pmu_device; | ||
45 | extern struct platform_device tegra_i2s_device1; | ||
46 | extern struct platform_device tegra_i2s_device2; | ||
47 | extern struct platform_device tegra_das_device; | ||
48 | extern struct platform_device tegra_pcm_device; | ||
49 | |||
50 | #endif | ||
diff --git a/arch/arm/mach-tegra/dma.c b/arch/arm/mach-tegra/dma.c index edda6ec5e925..e945ae28ee77 100644 --- a/arch/arm/mach-tegra/dma.c +++ b/arch/arm/mach-tegra/dma.c | |||
@@ -27,9 +27,11 @@ | |||
27 | #include <linux/err.h> | 27 | #include <linux/err.h> |
28 | #include <linux/irq.h> | 28 | #include <linux/irq.h> |
29 | #include <linux/delay.h> | 29 | #include <linux/delay.h> |
30 | #include <linux/clk.h> | ||
30 | #include <mach/dma.h> | 31 | #include <mach/dma.h> |
31 | #include <mach/irqs.h> | 32 | #include <mach/irqs.h> |
32 | #include <mach/iomap.h> | 33 | #include <mach/iomap.h> |
34 | #include <mach/suspend.h> | ||
33 | 35 | ||
34 | #define APB_DMA_GEN 0x000 | 36 | #define APB_DMA_GEN 0x000 |
35 | #define GEN_ENABLE (1<<31) | 37 | #define GEN_ENABLE (1<<31) |
@@ -120,17 +122,14 @@ struct tegra_dma_channel { | |||
120 | void __iomem *addr; | 122 | void __iomem *addr; |
121 | int mode; | 123 | int mode; |
122 | int irq; | 124 | int irq; |
123 | 125 | int req_transfer_count; | |
124 | /* Register shadow */ | ||
125 | u32 csr; | ||
126 | u32 ahb_seq; | ||
127 | u32 ahb_ptr; | ||
128 | u32 apb_seq; | ||
129 | u32 apb_ptr; | ||
130 | }; | 126 | }; |
131 | 127 | ||
132 | #define NV_DMA_MAX_CHANNELS 32 | 128 | #define NV_DMA_MAX_CHANNELS 32 |
133 | 129 | ||
130 | static bool tegra_dma_initialized; | ||
131 | static DEFINE_MUTEX(tegra_dma_lock); | ||
132 | |||
134 | static DECLARE_BITMAP(channel_usage, NV_DMA_MAX_CHANNELS); | 133 | static DECLARE_BITMAP(channel_usage, NV_DMA_MAX_CHANNELS); |
135 | static struct tegra_dma_channel dma_channels[NV_DMA_MAX_CHANNELS]; | 134 | static struct tegra_dma_channel dma_channels[NV_DMA_MAX_CHANNELS]; |
136 | 135 | ||
@@ -138,7 +137,6 @@ static void tegra_dma_update_hw(struct tegra_dma_channel *ch, | |||
138 | struct tegra_dma_req *req); | 137 | struct tegra_dma_req *req); |
139 | static void tegra_dma_update_hw_partial(struct tegra_dma_channel *ch, | 138 | static void tegra_dma_update_hw_partial(struct tegra_dma_channel *ch, |
140 | struct tegra_dma_req *req); | 139 | struct tegra_dma_req *req); |
141 | static void tegra_dma_init_hw(struct tegra_dma_channel *ch); | ||
142 | static void tegra_dma_stop(struct tegra_dma_channel *ch); | 140 | static void tegra_dma_stop(struct tegra_dma_channel *ch); |
143 | 141 | ||
144 | void tegra_dma_flush(struct tegra_dma_channel *ch) | 142 | void tegra_dma_flush(struct tegra_dma_channel *ch) |
@@ -150,6 +148,9 @@ void tegra_dma_dequeue(struct tegra_dma_channel *ch) | |||
150 | { | 148 | { |
151 | struct tegra_dma_req *req; | 149 | struct tegra_dma_req *req; |
152 | 150 | ||
151 | if (tegra_dma_is_empty(ch)) | ||
152 | return; | ||
153 | |||
153 | req = list_entry(ch->list.next, typeof(*req), node); | 154 | req = list_entry(ch->list.next, typeof(*req), node); |
154 | 155 | ||
155 | tegra_dma_dequeue_req(ch, req); | 156 | tegra_dma_dequeue_req(ch, req); |
@@ -158,10 +159,10 @@ void tegra_dma_dequeue(struct tegra_dma_channel *ch) | |||
158 | 159 | ||
159 | void tegra_dma_stop(struct tegra_dma_channel *ch) | 160 | void tegra_dma_stop(struct tegra_dma_channel *ch) |
160 | { | 161 | { |
161 | unsigned int csr; | 162 | u32 csr; |
162 | unsigned int status; | 163 | u32 status; |
163 | 164 | ||
164 | csr = ch->csr; | 165 | csr = readl(ch->addr + APB_DMA_CHAN_CSR); |
165 | csr &= ~CSR_IE_EOC; | 166 | csr &= ~CSR_IE_EOC; |
166 | writel(csr, ch->addr + APB_DMA_CHAN_CSR); | 167 | writel(csr, ch->addr + APB_DMA_CHAN_CSR); |
167 | 168 | ||
@@ -175,19 +176,16 @@ void tegra_dma_stop(struct tegra_dma_channel *ch) | |||
175 | 176 | ||
176 | int tegra_dma_cancel(struct tegra_dma_channel *ch) | 177 | int tegra_dma_cancel(struct tegra_dma_channel *ch) |
177 | { | 178 | { |
178 | unsigned int csr; | 179 | u32 csr; |
179 | unsigned long irq_flags; | 180 | unsigned long irq_flags; |
180 | 181 | ||
181 | spin_lock_irqsave(&ch->lock, irq_flags); | 182 | spin_lock_irqsave(&ch->lock, irq_flags); |
182 | while (!list_empty(&ch->list)) | 183 | while (!list_empty(&ch->list)) |
183 | list_del(ch->list.next); | 184 | list_del(ch->list.next); |
184 | 185 | ||
185 | csr = ch->csr; | 186 | csr = readl(ch->addr + APB_DMA_CHAN_CSR); |
186 | csr &= ~CSR_REQ_SEL_MASK; | 187 | csr &= ~CSR_REQ_SEL_MASK; |
187 | csr |= CSR_REQ_SEL_INVALID; | 188 | csr |= CSR_REQ_SEL_INVALID; |
188 | |||
189 | /* Set the enable as that is not shadowed */ | ||
190 | csr |= CSR_ENB; | ||
191 | writel(csr, ch->addr + APB_DMA_CHAN_CSR); | 189 | writel(csr, ch->addr + APB_DMA_CHAN_CSR); |
192 | 190 | ||
193 | tegra_dma_stop(ch); | 191 | tegra_dma_stop(ch); |
@@ -229,18 +227,15 @@ int tegra_dma_dequeue_req(struct tegra_dma_channel *ch, | |||
229 | * - Finally stop or program the DMA to the next buffer in the | 227 | * - Finally stop or program the DMA to the next buffer in the |
230 | * list. | 228 | * list. |
231 | */ | 229 | */ |
232 | csr = ch->csr; | 230 | csr = readl(ch->addr + APB_DMA_CHAN_CSR); |
233 | csr &= ~CSR_REQ_SEL_MASK; | 231 | csr &= ~CSR_REQ_SEL_MASK; |
234 | csr |= CSR_REQ_SEL_INVALID; | 232 | csr |= CSR_REQ_SEL_INVALID; |
235 | |||
236 | /* Set the enable as that is not shadowed */ | ||
237 | csr |= CSR_ENB; | ||
238 | writel(csr, ch->addr + APB_DMA_CHAN_CSR); | 233 | writel(csr, ch->addr + APB_DMA_CHAN_CSR); |
239 | 234 | ||
240 | /* Get the transfer count */ | 235 | /* Get the transfer count */ |
241 | status = readl(ch->addr + APB_DMA_CHAN_STA); | 236 | status = readl(ch->addr + APB_DMA_CHAN_STA); |
242 | to_transfer = (status & STA_COUNT_MASK) >> STA_COUNT_SHIFT; | 237 | to_transfer = (status & STA_COUNT_MASK) >> STA_COUNT_SHIFT; |
243 | req_transfer_count = (ch->csr & CSR_WCOUNT_MASK) >> CSR_WCOUNT_SHIFT; | 238 | req_transfer_count = ch->req_transfer_count; |
244 | req_transfer_count += 1; | 239 | req_transfer_count += 1; |
245 | to_transfer += 1; | 240 | to_transfer += 1; |
246 | 241 | ||
@@ -318,6 +313,7 @@ int tegra_dma_enqueue_req(struct tegra_dma_channel *ch, | |||
318 | struct tegra_dma_req *req) | 313 | struct tegra_dma_req *req) |
319 | { | 314 | { |
320 | unsigned long irq_flags; | 315 | unsigned long irq_flags; |
316 | struct tegra_dma_req *_req; | ||
321 | int start_dma = 0; | 317 | int start_dma = 0; |
322 | 318 | ||
323 | if (req->size > NV_DMA_MAX_TRASFER_SIZE || | 319 | if (req->size > NV_DMA_MAX_TRASFER_SIZE || |
@@ -328,6 +324,13 @@ int tegra_dma_enqueue_req(struct tegra_dma_channel *ch, | |||
328 | 324 | ||
329 | spin_lock_irqsave(&ch->lock, irq_flags); | 325 | spin_lock_irqsave(&ch->lock, irq_flags); |
330 | 326 | ||
327 | list_for_each_entry(_req, &ch->list, node) { | ||
328 | if (req == _req) { | ||
329 | spin_unlock_irqrestore(&ch->lock, irq_flags); | ||
330 | return -EEXIST; | ||
331 | } | ||
332 | } | ||
333 | |||
331 | req->bytes_transferred = 0; | 334 | req->bytes_transferred = 0; |
332 | req->status = 0; | 335 | req->status = 0; |
333 | req->buffer_status = 0; | 336 | req->buffer_status = 0; |
@@ -348,7 +351,12 @@ EXPORT_SYMBOL(tegra_dma_enqueue_req); | |||
348 | struct tegra_dma_channel *tegra_dma_allocate_channel(int mode) | 351 | struct tegra_dma_channel *tegra_dma_allocate_channel(int mode) |
349 | { | 352 | { |
350 | int channel; | 353 | int channel; |
351 | struct tegra_dma_channel *ch; | 354 | struct tegra_dma_channel *ch = NULL; |
355 | |||
356 | if (WARN_ON(!tegra_dma_initialized)) | ||
357 | return NULL; | ||
358 | |||
359 | mutex_lock(&tegra_dma_lock); | ||
352 | 360 | ||
353 | /* first channel is the shared channel */ | 361 | /* first channel is the shared channel */ |
354 | if (mode & TEGRA_DMA_SHARED) { | 362 | if (mode & TEGRA_DMA_SHARED) { |
@@ -357,11 +365,14 @@ struct tegra_dma_channel *tegra_dma_allocate_channel(int mode) | |||
357 | channel = find_first_zero_bit(channel_usage, | 365 | channel = find_first_zero_bit(channel_usage, |
358 | ARRAY_SIZE(dma_channels)); | 366 | ARRAY_SIZE(dma_channels)); |
359 | if (channel >= ARRAY_SIZE(dma_channels)) | 367 | if (channel >= ARRAY_SIZE(dma_channels)) |
360 | return NULL; | 368 | goto out; |
361 | } | 369 | } |
362 | __set_bit(channel, channel_usage); | 370 | __set_bit(channel, channel_usage); |
363 | ch = &dma_channels[channel]; | 371 | ch = &dma_channels[channel]; |
364 | ch->mode = mode; | 372 | ch->mode = mode; |
373 | |||
374 | out: | ||
375 | mutex_unlock(&tegra_dma_lock); | ||
365 | return ch; | 376 | return ch; |
366 | } | 377 | } |
367 | EXPORT_SYMBOL(tegra_dma_allocate_channel); | 378 | EXPORT_SYMBOL(tegra_dma_allocate_channel); |
@@ -371,22 +382,27 @@ void tegra_dma_free_channel(struct tegra_dma_channel *ch) | |||
371 | if (ch->mode & TEGRA_DMA_SHARED) | 382 | if (ch->mode & TEGRA_DMA_SHARED) |
372 | return; | 383 | return; |
373 | tegra_dma_cancel(ch); | 384 | tegra_dma_cancel(ch); |
385 | mutex_lock(&tegra_dma_lock); | ||
374 | __clear_bit(ch->id, channel_usage); | 386 | __clear_bit(ch->id, channel_usage); |
387 | mutex_unlock(&tegra_dma_lock); | ||
375 | } | 388 | } |
376 | EXPORT_SYMBOL(tegra_dma_free_channel); | 389 | EXPORT_SYMBOL(tegra_dma_free_channel); |
377 | 390 | ||
378 | static void tegra_dma_update_hw_partial(struct tegra_dma_channel *ch, | 391 | static void tegra_dma_update_hw_partial(struct tegra_dma_channel *ch, |
379 | struct tegra_dma_req *req) | 392 | struct tegra_dma_req *req) |
380 | { | 393 | { |
394 | u32 apb_ptr; | ||
395 | u32 ahb_ptr; | ||
396 | |||
381 | if (req->to_memory) { | 397 | if (req->to_memory) { |
382 | ch->apb_ptr = req->source_addr; | 398 | apb_ptr = req->source_addr; |
383 | ch->ahb_ptr = req->dest_addr; | 399 | ahb_ptr = req->dest_addr; |
384 | } else { | 400 | } else { |
385 | ch->apb_ptr = req->dest_addr; | 401 | apb_ptr = req->dest_addr; |
386 | ch->ahb_ptr = req->source_addr; | 402 | ahb_ptr = req->source_addr; |
387 | } | 403 | } |
388 | writel(ch->apb_ptr, ch->addr + APB_DMA_CHAN_APB_PTR); | 404 | writel(apb_ptr, ch->addr + APB_DMA_CHAN_APB_PTR); |
389 | writel(ch->ahb_ptr, ch->addr + APB_DMA_CHAN_AHB_PTR); | 405 | writel(ahb_ptr, ch->addr + APB_DMA_CHAN_AHB_PTR); |
390 | 406 | ||
391 | req->status = TEGRA_DMA_REQ_INFLIGHT; | 407 | req->status = TEGRA_DMA_REQ_INFLIGHT; |
392 | return; | 408 | return; |
@@ -400,38 +416,39 @@ static void tegra_dma_update_hw(struct tegra_dma_channel *ch, | |||
400 | int ahb_bus_width; | 416 | int ahb_bus_width; |
401 | int apb_bus_width; | 417 | int apb_bus_width; |
402 | int index; | 418 | int index; |
403 | unsigned long csr; | ||
404 | 419 | ||
420 | u32 ahb_seq; | ||
421 | u32 apb_seq; | ||
422 | u32 ahb_ptr; | ||
423 | u32 apb_ptr; | ||
424 | u32 csr; | ||
425 | |||
426 | csr = CSR_IE_EOC | CSR_FLOW; | ||
427 | ahb_seq = AHB_SEQ_INTR_ENB | AHB_SEQ_BURST_1; | ||
428 | apb_seq = 0; | ||
405 | 429 | ||
406 | ch->csr |= CSR_FLOW; | 430 | csr |= req->req_sel << CSR_REQ_SEL_SHIFT; |
407 | ch->csr &= ~CSR_REQ_SEL_MASK; | ||
408 | ch->csr |= req->req_sel << CSR_REQ_SEL_SHIFT; | ||
409 | ch->ahb_seq &= ~AHB_SEQ_BURST_MASK; | ||
410 | ch->ahb_seq |= AHB_SEQ_BURST_1; | ||
411 | 431 | ||
412 | /* One shot mode is always single buffered, | 432 | /* One shot mode is always single buffered, |
413 | * continuous mode is always double buffered | 433 | * continuous mode is always double buffered |
414 | * */ | 434 | * */ |
415 | if (ch->mode & TEGRA_DMA_MODE_ONESHOT) { | 435 | if (ch->mode & TEGRA_DMA_MODE_ONESHOT) { |
416 | ch->csr |= CSR_ONCE; | 436 | csr |= CSR_ONCE; |
417 | ch->ahb_seq &= ~AHB_SEQ_DBL_BUF; | 437 | ch->req_transfer_count = (req->size >> 2) - 1; |
418 | ch->csr &= ~CSR_WCOUNT_MASK; | ||
419 | ch->csr |= ((req->size>>2) - 1) << CSR_WCOUNT_SHIFT; | ||
420 | } else { | 438 | } else { |
421 | ch->csr &= ~CSR_ONCE; | 439 | ahb_seq |= AHB_SEQ_DBL_BUF; |
422 | ch->ahb_seq |= AHB_SEQ_DBL_BUF; | ||
423 | 440 | ||
424 | /* In double buffered mode, we set the size to half the | 441 | /* In double buffered mode, we set the size to half the |
425 | * requested size and interrupt when half the buffer | 442 | * requested size and interrupt when half the buffer |
426 | * is full */ | 443 | * is full */ |
427 | ch->csr &= ~CSR_WCOUNT_MASK; | 444 | ch->req_transfer_count = (req->size >> 3) - 1; |
428 | ch->csr |= ((req->size>>3) - 1) << CSR_WCOUNT_SHIFT; | ||
429 | } | 445 | } |
430 | 446 | ||
447 | csr |= ch->req_transfer_count << CSR_WCOUNT_SHIFT; | ||
448 | |||
431 | if (req->to_memory) { | 449 | if (req->to_memory) { |
432 | ch->csr &= ~CSR_DIR; | 450 | apb_ptr = req->source_addr; |
433 | ch->apb_ptr = req->source_addr; | 451 | ahb_ptr = req->dest_addr; |
434 | ch->ahb_ptr = req->dest_addr; | ||
435 | 452 | ||
436 | apb_addr_wrap = req->source_wrap; | 453 | apb_addr_wrap = req->source_wrap; |
437 | ahb_addr_wrap = req->dest_wrap; | 454 | ahb_addr_wrap = req->dest_wrap; |
@@ -439,9 +456,9 @@ static void tegra_dma_update_hw(struct tegra_dma_channel *ch, | |||
439 | ahb_bus_width = req->dest_bus_width; | 456 | ahb_bus_width = req->dest_bus_width; |
440 | 457 | ||
441 | } else { | 458 | } else { |
442 | ch->csr |= CSR_DIR; | 459 | csr |= CSR_DIR; |
443 | ch->apb_ptr = req->dest_addr; | 460 | apb_ptr = req->dest_addr; |
444 | ch->ahb_ptr = req->source_addr; | 461 | ahb_ptr = req->source_addr; |
445 | 462 | ||
446 | apb_addr_wrap = req->dest_wrap; | 463 | apb_addr_wrap = req->dest_wrap; |
447 | ahb_addr_wrap = req->source_wrap; | 464 | ahb_addr_wrap = req->source_wrap; |
@@ -460,8 +477,7 @@ static void tegra_dma_update_hw(struct tegra_dma_channel *ch, | |||
460 | index++; | 477 | index++; |
461 | } while (index < ARRAY_SIZE(apb_addr_wrap_table)); | 478 | } while (index < ARRAY_SIZE(apb_addr_wrap_table)); |
462 | BUG_ON(index == ARRAY_SIZE(apb_addr_wrap_table)); | 479 | BUG_ON(index == ARRAY_SIZE(apb_addr_wrap_table)); |
463 | ch->apb_seq &= ~APB_SEQ_WRAP_MASK; | 480 | apb_seq |= index << APB_SEQ_WRAP_SHIFT; |
464 | ch->apb_seq |= index << APB_SEQ_WRAP_SHIFT; | ||
465 | 481 | ||
466 | /* set address wrap for AHB size */ | 482 | /* set address wrap for AHB size */ |
467 | index = 0; | 483 | index = 0; |
@@ -471,55 +487,42 @@ static void tegra_dma_update_hw(struct tegra_dma_channel *ch, | |||
471 | index++; | 487 | index++; |
472 | } while (index < ARRAY_SIZE(ahb_addr_wrap_table)); | 488 | } while (index < ARRAY_SIZE(ahb_addr_wrap_table)); |
473 | BUG_ON(index == ARRAY_SIZE(ahb_addr_wrap_table)); | 489 | BUG_ON(index == ARRAY_SIZE(ahb_addr_wrap_table)); |
474 | ch->ahb_seq &= ~AHB_SEQ_WRAP_MASK; | 490 | ahb_seq |= index << AHB_SEQ_WRAP_SHIFT; |
475 | ch->ahb_seq |= index << AHB_SEQ_WRAP_SHIFT; | ||
476 | 491 | ||
477 | for (index = 0; index < ARRAY_SIZE(bus_width_table); index++) { | 492 | for (index = 0; index < ARRAY_SIZE(bus_width_table); index++) { |
478 | if (bus_width_table[index] == ahb_bus_width) | 493 | if (bus_width_table[index] == ahb_bus_width) |
479 | break; | 494 | break; |
480 | } | 495 | } |
481 | BUG_ON(index == ARRAY_SIZE(bus_width_table)); | 496 | BUG_ON(index == ARRAY_SIZE(bus_width_table)); |
482 | ch->ahb_seq &= ~AHB_SEQ_BUS_WIDTH_MASK; | 497 | ahb_seq |= index << AHB_SEQ_BUS_WIDTH_SHIFT; |
483 | ch->ahb_seq |= index << AHB_SEQ_BUS_WIDTH_SHIFT; | ||
484 | 498 | ||
485 | for (index = 0; index < ARRAY_SIZE(bus_width_table); index++) { | 499 | for (index = 0; index < ARRAY_SIZE(bus_width_table); index++) { |
486 | if (bus_width_table[index] == apb_bus_width) | 500 | if (bus_width_table[index] == apb_bus_width) |
487 | break; | 501 | break; |
488 | } | 502 | } |
489 | BUG_ON(index == ARRAY_SIZE(bus_width_table)); | 503 | BUG_ON(index == ARRAY_SIZE(bus_width_table)); |
490 | ch->apb_seq &= ~APB_SEQ_BUS_WIDTH_MASK; | 504 | apb_seq |= index << APB_SEQ_BUS_WIDTH_SHIFT; |
491 | ch->apb_seq |= index << APB_SEQ_BUS_WIDTH_SHIFT; | ||
492 | |||
493 | ch->csr |= CSR_IE_EOC; | ||
494 | 505 | ||
495 | /* update hw registers with the shadow */ | 506 | writel(csr, ch->addr + APB_DMA_CHAN_CSR); |
496 | writel(ch->csr, ch->addr + APB_DMA_CHAN_CSR); | 507 | writel(apb_seq, ch->addr + APB_DMA_CHAN_APB_SEQ); |
497 | writel(ch->apb_seq, ch->addr + APB_DMA_CHAN_APB_SEQ); | 508 | writel(apb_ptr, ch->addr + APB_DMA_CHAN_APB_PTR); |
498 | writel(ch->apb_ptr, ch->addr + APB_DMA_CHAN_APB_PTR); | 509 | writel(ahb_seq, ch->addr + APB_DMA_CHAN_AHB_SEQ); |
499 | writel(ch->ahb_seq, ch->addr + APB_DMA_CHAN_AHB_SEQ); | 510 | writel(ahb_ptr, ch->addr + APB_DMA_CHAN_AHB_PTR); |
500 | writel(ch->ahb_ptr, ch->addr + APB_DMA_CHAN_AHB_PTR); | ||
501 | 511 | ||
502 | csr = ch->csr | CSR_ENB; | 512 | csr |= CSR_ENB; |
503 | writel(csr, ch->addr + APB_DMA_CHAN_CSR); | 513 | writel(csr, ch->addr + APB_DMA_CHAN_CSR); |
504 | 514 | ||
505 | req->status = TEGRA_DMA_REQ_INFLIGHT; | 515 | req->status = TEGRA_DMA_REQ_INFLIGHT; |
506 | } | 516 | } |
507 | 517 | ||
508 | static void tegra_dma_init_hw(struct tegra_dma_channel *ch) | ||
509 | { | ||
510 | /* One shot with an interrupt to CPU after transfer */ | ||
511 | ch->csr = CSR_ONCE | CSR_IE_EOC; | ||
512 | ch->ahb_seq = AHB_SEQ_BUS_WIDTH_32 | AHB_SEQ_INTR_ENB; | ||
513 | ch->apb_seq = APB_SEQ_BUS_WIDTH_32 | 1 << APB_SEQ_WRAP_SHIFT; | ||
514 | } | ||
515 | |||
516 | static void handle_oneshot_dma(struct tegra_dma_channel *ch) | 518 | static void handle_oneshot_dma(struct tegra_dma_channel *ch) |
517 | { | 519 | { |
518 | struct tegra_dma_req *req; | 520 | struct tegra_dma_req *req; |
521 | unsigned long irq_flags; | ||
519 | 522 | ||
520 | spin_lock(&ch->lock); | 523 | spin_lock_irqsave(&ch->lock, irq_flags); |
521 | if (list_empty(&ch->list)) { | 524 | if (list_empty(&ch->list)) { |
522 | spin_unlock(&ch->lock); | 525 | spin_unlock_irqrestore(&ch->lock, irq_flags); |
523 | return; | 526 | return; |
524 | } | 527 | } |
525 | 528 | ||
@@ -527,8 +530,7 @@ static void handle_oneshot_dma(struct tegra_dma_channel *ch) | |||
527 | if (req) { | 530 | if (req) { |
528 | int bytes_transferred; | 531 | int bytes_transferred; |
529 | 532 | ||
530 | bytes_transferred = | 533 | bytes_transferred = ch->req_transfer_count; |
531 | (ch->csr & CSR_WCOUNT_MASK) >> CSR_WCOUNT_SHIFT; | ||
532 | bytes_transferred += 1; | 534 | bytes_transferred += 1; |
533 | bytes_transferred <<= 2; | 535 | bytes_transferred <<= 2; |
534 | 536 | ||
@@ -536,12 +538,12 @@ static void handle_oneshot_dma(struct tegra_dma_channel *ch) | |||
536 | req->bytes_transferred = bytes_transferred; | 538 | req->bytes_transferred = bytes_transferred; |
537 | req->status = TEGRA_DMA_REQ_SUCCESS; | 539 | req->status = TEGRA_DMA_REQ_SUCCESS; |
538 | 540 | ||
539 | spin_unlock(&ch->lock); | 541 | spin_unlock_irqrestore(&ch->lock, irq_flags); |
540 | /* Callback should be called without any lock */ | 542 | /* Callback should be called without any lock */ |
541 | pr_debug("%s: transferred %d bytes\n", __func__, | 543 | pr_debug("%s: transferred %d bytes\n", __func__, |
542 | req->bytes_transferred); | 544 | req->bytes_transferred); |
543 | req->complete(req); | 545 | req->complete(req); |
544 | spin_lock(&ch->lock); | 546 | spin_lock_irqsave(&ch->lock, irq_flags); |
545 | } | 547 | } |
546 | 548 | ||
547 | if (!list_empty(&ch->list)) { | 549 | if (!list_empty(&ch->list)) { |
@@ -551,22 +553,55 @@ static void handle_oneshot_dma(struct tegra_dma_channel *ch) | |||
551 | if (req->status != TEGRA_DMA_REQ_INFLIGHT) | 553 | if (req->status != TEGRA_DMA_REQ_INFLIGHT) |
552 | tegra_dma_update_hw(ch, req); | 554 | tegra_dma_update_hw(ch, req); |
553 | } | 555 | } |
554 | spin_unlock(&ch->lock); | 556 | spin_unlock_irqrestore(&ch->lock, irq_flags); |
555 | } | 557 | } |
556 | 558 | ||
557 | static void handle_continuous_dma(struct tegra_dma_channel *ch) | 559 | static void handle_continuous_dma(struct tegra_dma_channel *ch) |
558 | { | 560 | { |
559 | struct tegra_dma_req *req; | 561 | struct tegra_dma_req *req; |
562 | unsigned long irq_flags; | ||
560 | 563 | ||
561 | spin_lock(&ch->lock); | 564 | spin_lock_irqsave(&ch->lock, irq_flags); |
562 | if (list_empty(&ch->list)) { | 565 | if (list_empty(&ch->list)) { |
563 | spin_unlock(&ch->lock); | 566 | spin_unlock_irqrestore(&ch->lock, irq_flags); |
564 | return; | 567 | return; |
565 | } | 568 | } |
566 | 569 | ||
567 | req = list_entry(ch->list.next, typeof(*req), node); | 570 | req = list_entry(ch->list.next, typeof(*req), node); |
568 | if (req) { | 571 | if (req) { |
569 | if (req->buffer_status == TEGRA_DMA_REQ_BUF_STATUS_EMPTY) { | 572 | if (req->buffer_status == TEGRA_DMA_REQ_BUF_STATUS_EMPTY) { |
573 | bool is_dma_ping_complete; | ||
574 | is_dma_ping_complete = (readl(ch->addr + APB_DMA_CHAN_STA) | ||
575 | & STA_PING_PONG) ? true : false; | ||
576 | if (req->to_memory) | ||
577 | is_dma_ping_complete = !is_dma_ping_complete; | ||
578 | /* Out of sync - Release current buffer */ | ||
579 | if (!is_dma_ping_complete) { | ||
580 | int bytes_transferred; | ||
581 | |||
582 | bytes_transferred = ch->req_transfer_count; | ||
583 | bytes_transferred += 1; | ||
584 | bytes_transferred <<= 3; | ||
585 | req->buffer_status = TEGRA_DMA_REQ_BUF_STATUS_FULL; | ||
586 | req->bytes_transferred = bytes_transferred; | ||
587 | req->status = TEGRA_DMA_REQ_SUCCESS; | ||
588 | tegra_dma_stop(ch); | ||
589 | |||
590 | if (!list_is_last(&req->node, &ch->list)) { | ||
591 | struct tegra_dma_req *next_req; | ||
592 | |||
593 | next_req = list_entry(req->node.next, | ||
594 | typeof(*next_req), node); | ||
595 | tegra_dma_update_hw(ch, next_req); | ||
596 | } | ||
597 | |||
598 | list_del(&req->node); | ||
599 | |||
600 | /* DMA lock is NOT held when callbak is called */ | ||
601 | spin_unlock_irqrestore(&ch->lock, irq_flags); | ||
602 | req->complete(req); | ||
603 | return; | ||
604 | } | ||
570 | /* Load the next request into the hardware, if available | 605 | /* Load the next request into the hardware, if available |
571 | * */ | 606 | * */ |
572 | if (!list_is_last(&req->node, &ch->list)) { | 607 | if (!list_is_last(&req->node, &ch->list)) { |
@@ -579,7 +614,7 @@ static void handle_continuous_dma(struct tegra_dma_channel *ch) | |||
579 | req->buffer_status = TEGRA_DMA_REQ_BUF_STATUS_HALF_FULL; | 614 | req->buffer_status = TEGRA_DMA_REQ_BUF_STATUS_HALF_FULL; |
580 | req->status = TEGRA_DMA_REQ_SUCCESS; | 615 | req->status = TEGRA_DMA_REQ_SUCCESS; |
581 | /* DMA lock is NOT held when callback is called */ | 616 | /* DMA lock is NOT held when callback is called */ |
582 | spin_unlock(&ch->lock); | 617 | spin_unlock_irqrestore(&ch->lock, irq_flags); |
583 | if (likely(req->threshold)) | 618 | if (likely(req->threshold)) |
584 | req->threshold(req); | 619 | req->threshold(req); |
585 | return; | 620 | return; |
@@ -590,8 +625,7 @@ static void handle_continuous_dma(struct tegra_dma_channel *ch) | |||
590 | * the second interrupt */ | 625 | * the second interrupt */ |
591 | int bytes_transferred; | 626 | int bytes_transferred; |
592 | 627 | ||
593 | bytes_transferred = | 628 | bytes_transferred = ch->req_transfer_count; |
594 | (ch->csr & CSR_WCOUNT_MASK) >> CSR_WCOUNT_SHIFT; | ||
595 | bytes_transferred += 1; | 629 | bytes_transferred += 1; |
596 | bytes_transferred <<= 3; | 630 | bytes_transferred <<= 3; |
597 | 631 | ||
@@ -601,7 +635,7 @@ static void handle_continuous_dma(struct tegra_dma_channel *ch) | |||
601 | list_del(&req->node); | 635 | list_del(&req->node); |
602 | 636 | ||
603 | /* DMA lock is NOT held when callbak is called */ | 637 | /* DMA lock is NOT held when callbak is called */ |
604 | spin_unlock(&ch->lock); | 638 | spin_unlock_irqrestore(&ch->lock, irq_flags); |
605 | req->complete(req); | 639 | req->complete(req); |
606 | return; | 640 | return; |
607 | 641 | ||
@@ -609,7 +643,7 @@ static void handle_continuous_dma(struct tegra_dma_channel *ch) | |||
609 | BUG(); | 643 | BUG(); |
610 | } | 644 | } |
611 | } | 645 | } |
612 | spin_unlock(&ch->lock); | 646 | spin_unlock_irqrestore(&ch->lock, irq_flags); |
613 | } | 647 | } |
614 | 648 | ||
615 | static irqreturn_t dma_isr(int irq, void *data) | 649 | static irqreturn_t dma_isr(int irq, void *data) |
@@ -646,6 +680,21 @@ int __init tegra_dma_init(void) | |||
646 | int i; | 680 | int i; |
647 | unsigned int irq; | 681 | unsigned int irq; |
648 | void __iomem *addr; | 682 | void __iomem *addr; |
683 | struct clk *c; | ||
684 | |||
685 | bitmap_fill(channel_usage, NV_DMA_MAX_CHANNELS); | ||
686 | |||
687 | c = clk_get_sys("tegra-dma", NULL); | ||
688 | if (IS_ERR(c)) { | ||
689 | pr_err("Unable to get clock for APB DMA\n"); | ||
690 | ret = PTR_ERR(c); | ||
691 | goto fail; | ||
692 | } | ||
693 | ret = clk_enable(c); | ||
694 | if (ret != 0) { | ||
695 | pr_err("Unable to enable clock for APB DMA\n"); | ||
696 | goto fail; | ||
697 | } | ||
649 | 698 | ||
650 | addr = IO_ADDRESS(TEGRA_APB_DMA_BASE); | 699 | addr = IO_ADDRESS(TEGRA_APB_DMA_BASE); |
651 | writel(GEN_ENABLE, addr + APB_DMA_GEN); | 700 | writel(GEN_ENABLE, addr + APB_DMA_GEN); |
@@ -653,18 +702,9 @@ int __init tegra_dma_init(void) | |||
653 | writel(0xFFFFFFFFul >> (31 - TEGRA_SYSTEM_DMA_CH_MAX), | 702 | writel(0xFFFFFFFFul >> (31 - TEGRA_SYSTEM_DMA_CH_MAX), |
654 | addr + APB_DMA_IRQ_MASK_SET); | 703 | addr + APB_DMA_IRQ_MASK_SET); |
655 | 704 | ||
656 | memset(channel_usage, 0, sizeof(channel_usage)); | ||
657 | memset(dma_channels, 0, sizeof(dma_channels)); | ||
658 | |||
659 | /* Reserve all the channels we are not supposed to touch */ | ||
660 | for (i = 0; i < TEGRA_SYSTEM_DMA_CH_MIN; i++) | ||
661 | __set_bit(i, channel_usage); | ||
662 | |||
663 | for (i = TEGRA_SYSTEM_DMA_CH_MIN; i <= TEGRA_SYSTEM_DMA_CH_MAX; i++) { | 705 | for (i = TEGRA_SYSTEM_DMA_CH_MIN; i <= TEGRA_SYSTEM_DMA_CH_MAX; i++) { |
664 | struct tegra_dma_channel *ch = &dma_channels[i]; | 706 | struct tegra_dma_channel *ch = &dma_channels[i]; |
665 | 707 | ||
666 | __clear_bit(i, channel_usage); | ||
667 | |||
668 | ch->id = i; | 708 | ch->id = i; |
669 | snprintf(ch->name, TEGRA_DMA_NAME_SIZE, "dma_channel_%d", i); | 709 | snprintf(ch->name, TEGRA_DMA_NAME_SIZE, "dma_channel_%d", i); |
670 | 710 | ||
@@ -673,7 +713,6 @@ int __init tegra_dma_init(void) | |||
673 | 713 | ||
674 | spin_lock_init(&ch->lock); | 714 | spin_lock_init(&ch->lock); |
675 | INIT_LIST_HEAD(&ch->list); | 715 | INIT_LIST_HEAD(&ch->list); |
676 | tegra_dma_init_hw(ch); | ||
677 | 716 | ||
678 | irq = INT_APB_DMA_CH0 + i; | 717 | irq = INT_APB_DMA_CH0 + i; |
679 | ret = request_threaded_irq(irq, dma_isr, dma_thread_fn, 0, | 718 | ret = request_threaded_irq(irq, dma_isr, dma_thread_fn, 0, |
@@ -684,14 +723,15 @@ int __init tegra_dma_init(void) | |||
684 | goto fail; | 723 | goto fail; |
685 | } | 724 | } |
686 | ch->irq = irq; | 725 | ch->irq = irq; |
726 | |||
727 | __clear_bit(i, channel_usage); | ||
687 | } | 728 | } |
688 | /* mark the shared channel allocated */ | 729 | /* mark the shared channel allocated */ |
689 | __set_bit(TEGRA_SYSTEM_DMA_CH_MIN, channel_usage); | 730 | __set_bit(TEGRA_SYSTEM_DMA_CH_MIN, channel_usage); |
690 | 731 | ||
691 | for (i = TEGRA_SYSTEM_DMA_CH_MAX+1; i < NV_DMA_MAX_CHANNELS; i++) | 732 | tegra_dma_initialized = true; |
692 | __set_bit(i, channel_usage); | ||
693 | 733 | ||
694 | return ret; | 734 | return 0; |
695 | fail: | 735 | fail: |
696 | writel(0, addr + APB_DMA_GEN); | 736 | writel(0, addr + APB_DMA_GEN); |
697 | for (i = TEGRA_SYSTEM_DMA_CH_MIN; i <= TEGRA_SYSTEM_DMA_CH_MAX; i++) { | 737 | for (i = TEGRA_SYSTEM_DMA_CH_MIN; i <= TEGRA_SYSTEM_DMA_CH_MAX; i++) { |
@@ -701,6 +741,7 @@ fail: | |||
701 | } | 741 | } |
702 | return ret; | 742 | return ret; |
703 | } | 743 | } |
744 | postcore_initcall(tegra_dma_init); | ||
704 | 745 | ||
705 | #ifdef CONFIG_PM | 746 | #ifdef CONFIG_PM |
706 | static u32 apb_dma[5*TEGRA_SYSTEM_DMA_CH_NR + 3]; | 747 | static u32 apb_dma[5*TEGRA_SYSTEM_DMA_CH_NR + 3]; |
diff --git a/arch/arm/mach-tegra/gpio.c b/arch/arm/mach-tegra/gpio.c index bd066206e110..12090a2cf3e0 100644 --- a/arch/arm/mach-tegra/gpio.c +++ b/arch/arm/mach-tegra/gpio.c | |||
@@ -25,6 +25,7 @@ | |||
25 | #include <linux/gpio.h> | 25 | #include <linux/gpio.h> |
26 | 26 | ||
27 | #include <mach/iomap.h> | 27 | #include <mach/iomap.h> |
28 | #include <mach/suspend.h> | ||
28 | 29 | ||
29 | #define GPIO_BANK(x) ((x) >> 5) | 30 | #define GPIO_BANK(x) ((x) >> 5) |
30 | #define GPIO_PORT(x) (((x) >> 3) & 0x3) | 31 | #define GPIO_PORT(x) (((x) >> 3) & 0x3) |
@@ -207,9 +208,9 @@ static int tegra_gpio_irq_set_type(struct irq_data *d, unsigned int type) | |||
207 | spin_unlock_irqrestore(&bank->lvl_lock[port], flags); | 208 | spin_unlock_irqrestore(&bank->lvl_lock[port], flags); |
208 | 209 | ||
209 | if (type & (IRQ_TYPE_LEVEL_LOW | IRQ_TYPE_LEVEL_HIGH)) | 210 | if (type & (IRQ_TYPE_LEVEL_LOW | IRQ_TYPE_LEVEL_HIGH)) |
210 | __set_irq_handler_unlocked(irq, handle_level_irq); | 211 | __set_irq_handler_unlocked(d->irq, handle_level_irq); |
211 | else if (type & (IRQ_TYPE_EDGE_FALLING | IRQ_TYPE_EDGE_RISING)) | 212 | else if (type & (IRQ_TYPE_EDGE_FALLING | IRQ_TYPE_EDGE_RISING)) |
212 | __set_irq_handler_unlocked(irq, handle_edge_irq); | 213 | __set_irq_handler_unlocked(d->irq, handle_edge_irq); |
213 | 214 | ||
214 | return 0; | 215 | return 0; |
215 | } | 216 | } |
@@ -380,6 +381,20 @@ static int __init tegra_gpio_init(void) | |||
380 | 381 | ||
381 | postcore_initcall(tegra_gpio_init); | 382 | postcore_initcall(tegra_gpio_init); |
382 | 383 | ||
384 | void __init tegra_gpio_config(struct tegra_gpio_table *table, int num) | ||
385 | { | ||
386 | int i; | ||
387 | |||
388 | for (i = 0; i < num; i++) { | ||
389 | int gpio = table[i].gpio; | ||
390 | |||
391 | if (table[i].enable) | ||
392 | tegra_gpio_enable(gpio); | ||
393 | else | ||
394 | tegra_gpio_disable(gpio); | ||
395 | } | ||
396 | } | ||
397 | |||
383 | #ifdef CONFIG_DEBUG_FS | 398 | #ifdef CONFIG_DEBUG_FS |
384 | 399 | ||
385 | #include <linux/debugfs.h> | 400 | #include <linux/debugfs.h> |
diff --git a/arch/arm/mach-tegra/include/mach/clk.h b/arch/arm/mach-tegra/include/mach/clk.h index d7723955dac7..c8baf8f80d23 100644 --- a/arch/arm/mach-tegra/include/mach/clk.h +++ b/arch/arm/mach-tegra/include/mach/clk.h | |||
@@ -20,12 +20,12 @@ | |||
20 | #ifndef __MACH_CLK_H | 20 | #ifndef __MACH_CLK_H |
21 | #define __MACH_CLK_H | 21 | #define __MACH_CLK_H |
22 | 22 | ||
23 | struct clk; | ||
24 | |||
23 | void tegra_periph_reset_deassert(struct clk *c); | 25 | void tegra_periph_reset_deassert(struct clk *c); |
24 | void tegra_periph_reset_assert(struct clk *c); | 26 | void tegra_periph_reset_assert(struct clk *c); |
25 | 27 | ||
26 | int clk_enable_cansleep(struct clk *clk); | 28 | unsigned long clk_get_rate_all_locked(struct clk *c); |
27 | void clk_disable_cansleep(struct clk *clk); | 29 | void tegra_sdmmc_tap_delay(struct clk *c, int delay); |
28 | int clk_set_rate_cansleep(struct clk *clk, unsigned long rate); | ||
29 | int clk_set_parent_cansleep(struct clk *clk, struct clk *parent); | ||
30 | 30 | ||
31 | #endif | 31 | #endif |
diff --git a/arch/arm/mach-tegra/include/mach/clkdev.h b/arch/arm/mach-tegra/include/mach/clkdev.h index 412f5c63e65a..66cd3f4fc896 100644 --- a/arch/arm/mach-tegra/include/mach/clkdev.h +++ b/arch/arm/mach-tegra/include/mach/clkdev.h | |||
@@ -20,6 +20,8 @@ | |||
20 | #ifndef __MACH_CLKDEV_H | 20 | #ifndef __MACH_CLKDEV_H |
21 | #define __MACH_CLKDEV_H | 21 | #define __MACH_CLKDEV_H |
22 | 22 | ||
23 | struct clk; | ||
24 | |||
23 | static inline int __clk_get(struct clk *clk) | 25 | static inline int __clk_get(struct clk *clk) |
24 | { | 26 | { |
25 | return 1; | 27 | return 1; |
diff --git a/arch/arm/mach-tegra/include/mach/debug-macro.S b/arch/arm/mach-tegra/include/mach/debug-macro.S index a0e7c12868bd..e0ebe65c1657 100644 --- a/arch/arm/mach-tegra/include/mach/debug-macro.S +++ b/arch/arm/mach-tegra/include/mach/debug-macro.S | |||
@@ -19,30 +19,15 @@ | |||
19 | */ | 19 | */ |
20 | 20 | ||
21 | #include <mach/io.h> | 21 | #include <mach/io.h> |
22 | #include <mach/iomap.h> | ||
22 | 23 | ||
23 | .macro addruart, rp, rv | 24 | .macro addruart, rp, rv |
24 | ldr \rp, =IO_APB_PHYS @ physical | 25 | ldr \rp, =IO_APB_PHYS @ physical |
25 | ldr \rv, =IO_APB_VIRT @ virtual | 26 | ldr \rv, =IO_APB_VIRT @ virtual |
26 | #if defined(CONFIG_TEGRA_DEBUG_UART_NONE) | 27 | orr \rp, \rp, #(TEGRA_DEBUG_UART_BASE & 0xFF) |
27 | #error "A debug UART must be selected in the kernel config to use DEBUG_LL" | 28 | orr \rp, \rp, #(TEGRA_DEBUG_UART_BASE & 0xFF00) |
28 | #elif defined(CONFIG_TEGRA_DEBUG_UARTA) | 29 | orr \rv, \rv, #(TEGRA_DEBUG_UART_BASE & 0xFF) |
29 | orr \rp, \rp, #0x6000 | 30 | orr \rv, \rv, #(TEGRA_DEBUG_UART_BASE & 0xFF00) |
30 | orr \rv, \rv, #0x6000 | ||
31 | #elif defined(CONFIG_TEGRA_DEBUG_UARTB) | ||
32 | orr \rp, \rp, #0x6000 | ||
33 | orr \rp, \rp, #0x40 | ||
34 | orr \rv, \rv, #0x6000 | ||
35 | orr \rv, \rv, #0x40 | ||
36 | #elif defined(CONFIG_TEGRA_DEBUG_UARTC) | ||
37 | orr \rp, \rp, #0x6200 | ||
38 | orr \rv, \rv, #0x6200 | ||
39 | #elif defined(CONFIG_TEGRA_DEBUG_UARTD) | ||
40 | orr \rp, \rp, #0x6300 | ||
41 | orr \rv, \rv, #0x6300 | ||
42 | #elif defined(CONFIG_TEGRA_DEBUG_UARTE) | ||
43 | orr \rp, \rp, #0x6400 | ||
44 | orr \rv, \rv, #0x6400 | ||
45 | #endif | ||
46 | .endm | 31 | .endm |
47 | 32 | ||
48 | #define UART_SHIFT 2 | 33 | #define UART_SHIFT 2 |
diff --git a/arch/arm/mach-tegra/include/mach/gpio.h b/arch/arm/mach-tegra/include/mach/gpio.h index e31f486d69a2..196f114dc241 100644 --- a/arch/arm/mach-tegra/include/mach/gpio.h +++ b/arch/arm/mach-tegra/include/mach/gpio.h | |||
@@ -20,6 +20,7 @@ | |||
20 | #ifndef __MACH_TEGRA_GPIO_H | 20 | #ifndef __MACH_TEGRA_GPIO_H |
21 | #define __MACH_TEGRA_GPIO_H | 21 | #define __MACH_TEGRA_GPIO_H |
22 | 22 | ||
23 | #include <linux/init.h> | ||
23 | #include <mach/irqs.h> | 24 | #include <mach/irqs.h> |
24 | 25 | ||
25 | #define TEGRA_NR_GPIOS INT_GPIO_NR | 26 | #define TEGRA_NR_GPIOS INT_GPIO_NR |
@@ -31,7 +32,7 @@ | |||
31 | #define gpio_cansleep __gpio_cansleep | 32 | #define gpio_cansleep __gpio_cansleep |
32 | 33 | ||
33 | #define TEGRA_GPIO_TO_IRQ(gpio) (INT_GPIO_BASE + (gpio)) | 34 | #define TEGRA_GPIO_TO_IRQ(gpio) (INT_GPIO_BASE + (gpio)) |
34 | #define TEGRA_IRQ_TO_GPIO(irq) ((gpio) - INT_GPIO_BASE) | 35 | #define TEGRA_IRQ_TO_GPIO(irq) ((irq) - INT_GPIO_BASE) |
35 | 36 | ||
36 | static inline int gpio_to_irq(unsigned int gpio) | 37 | static inline int gpio_to_irq(unsigned int gpio) |
37 | { | 38 | { |
@@ -47,6 +48,12 @@ static inline int irq_to_gpio(unsigned int irq) | |||
47 | return -EINVAL; | 48 | return -EINVAL; |
48 | } | 49 | } |
49 | 50 | ||
51 | struct tegra_gpio_table { | ||
52 | int gpio; /* GPIO number */ | ||
53 | bool enable; /* Enable for GPIO at init? */ | ||
54 | }; | ||
55 | |||
56 | void tegra_gpio_config(struct tegra_gpio_table *table, int num); | ||
50 | void tegra_gpio_enable(int gpio); | 57 | void tegra_gpio_enable(int gpio); |
51 | void tegra_gpio_disable(int gpio); | 58 | void tegra_gpio_disable(int gpio); |
52 | 59 | ||
diff --git a/arch/arm/mach-tegra/tegra2_dvfs.h b/arch/arm/mach-tegra/include/mach/harmony_audio.h index f8c1adba96a6..af086500ab7d 100644 --- a/arch/arm/mach-tegra/tegra2_dvfs.h +++ b/arch/arm/mach-tegra/include/mach/harmony_audio.h | |||
@@ -1,10 +1,7 @@ | |||
1 | /* | 1 | /* |
2 | * arch/arm/mach-tegra/tegra2_dvfs.h | 2 | * arch/arm/mach-tegra/include/mach/harmony_audio.h |
3 | * | 3 | * |
4 | * Copyright (C) 2010 Google, Inc. | 4 | * Copyright 2011 NVIDIA, Inc. |
5 | * | ||
6 | * Author: | ||
7 | * Colin Cross <ccross@google.com> | ||
8 | * | 5 | * |
9 | * This software is licensed under the terms of the GNU General Public | 6 | * This software is licensed under the terms of the GNU General Public |
10 | * License version 2, as published by the Free Software Foundation, and | 7 | * License version 2, as published by the Free Software Foundation, and |
@@ -17,4 +14,9 @@ | |||
17 | * | 14 | * |
18 | */ | 15 | */ |
19 | 16 | ||
20 | extern struct dvfs tegra_dvfs_virtual_cpu_dvfs; | 17 | struct harmony_audio_platform_data { |
18 | int gpio_spkr_en; | ||
19 | int gpio_hp_det; | ||
20 | int gpio_int_mic_en; | ||
21 | int gpio_ext_mic_en; | ||
22 | }; | ||
diff --git a/arch/arm/mach-tegra/include/mach/iomap.h b/arch/arm/mach-tegra/include/mach/iomap.h index 44a4f4bcf91f..19dec3ac0854 100644 --- a/arch/arm/mach-tegra/include/mach/iomap.h +++ b/arch/arm/mach-tegra/include/mach/iomap.h | |||
@@ -26,6 +26,9 @@ | |||
26 | #define TEGRA_IRAM_BASE 0x40000000 | 26 | #define TEGRA_IRAM_BASE 0x40000000 |
27 | #define TEGRA_IRAM_SIZE SZ_256K | 27 | #define TEGRA_IRAM_SIZE SZ_256K |
28 | 28 | ||
29 | #define TEGRA_HOST1X_BASE 0x50000000 | ||
30 | #define TEGRA_HOST1X_SIZE 0x24000 | ||
31 | |||
29 | #define TEGRA_ARM_PERIF_BASE 0x50040000 | 32 | #define TEGRA_ARM_PERIF_BASE 0x50040000 |
30 | #define TEGRA_ARM_PERIF_SIZE SZ_8K | 33 | #define TEGRA_ARM_PERIF_SIZE SZ_8K |
31 | 34 | ||
@@ -35,12 +38,30 @@ | |||
35 | #define TEGRA_ARM_INT_DIST_BASE 0x50041000 | 38 | #define TEGRA_ARM_INT_DIST_BASE 0x50041000 |
36 | #define TEGRA_ARM_INT_DIST_SIZE SZ_4K | 39 | #define TEGRA_ARM_INT_DIST_SIZE SZ_4K |
37 | 40 | ||
41 | #define TEGRA_MPE_BASE 0x54040000 | ||
42 | #define TEGRA_MPE_SIZE SZ_256K | ||
43 | |||
44 | #define TEGRA_VI_BASE 0x54080000 | ||
45 | #define TEGRA_VI_SIZE SZ_256K | ||
46 | |||
47 | #define TEGRA_ISP_BASE 0x54100000 | ||
48 | #define TEGRA_ISP_SIZE SZ_256K | ||
49 | |||
38 | #define TEGRA_DISPLAY_BASE 0x54200000 | 50 | #define TEGRA_DISPLAY_BASE 0x54200000 |
39 | #define TEGRA_DISPLAY_SIZE SZ_256K | 51 | #define TEGRA_DISPLAY_SIZE SZ_256K |
40 | 52 | ||
41 | #define TEGRA_DISPLAY2_BASE 0x54240000 | 53 | #define TEGRA_DISPLAY2_BASE 0x54240000 |
42 | #define TEGRA_DISPLAY2_SIZE SZ_256K | 54 | #define TEGRA_DISPLAY2_SIZE SZ_256K |
43 | 55 | ||
56 | #define TEGRA_HDMI_BASE 0x54280000 | ||
57 | #define TEGRA_HDMI_SIZE SZ_256K | ||
58 | |||
59 | #define TEGRA_GART_BASE 0x58000000 | ||
60 | #define TEGRA_GART_SIZE SZ_32M | ||
61 | |||
62 | #define TEGRA_RES_SEMA_BASE 0x60001000 | ||
63 | #define TEGRA_RES_SEMA_SIZE SZ_4K | ||
64 | |||
44 | #define TEGRA_PRIMARY_ICTLR_BASE 0x60004000 | 65 | #define TEGRA_PRIMARY_ICTLR_BASE 0x60004000 |
45 | #define TEGRA_PRIMARY_ICTLR_SIZE SZ_64 | 66 | #define TEGRA_PRIMARY_ICTLR_SIZE SZ_64 |
46 | 67 | ||
@@ -101,6 +122,9 @@ | |||
101 | #define TEGRA_APB_MISC_BASE 0x70000000 | 122 | #define TEGRA_APB_MISC_BASE 0x70000000 |
102 | #define TEGRA_APB_MISC_SIZE SZ_4K | 123 | #define TEGRA_APB_MISC_SIZE SZ_4K |
103 | 124 | ||
125 | #define TEGRA_APB_MISC_DAS_BASE 0x70000c00 | ||
126 | #define TEGRA_APB_MISC_DAS_SIZE SZ_128 | ||
127 | |||
104 | #define TEGRA_AC97_BASE 0x70002000 | 128 | #define TEGRA_AC97_BASE 0x70002000 |
105 | #define TEGRA_AC97_SIZE SZ_512 | 129 | #define TEGRA_AC97_SIZE SZ_512 |
106 | 130 | ||
@@ -140,6 +164,18 @@ | |||
140 | #define TEGRA_PWFM_BASE 0x7000A000 | 164 | #define TEGRA_PWFM_BASE 0x7000A000 |
141 | #define TEGRA_PWFM_SIZE SZ_256 | 165 | #define TEGRA_PWFM_SIZE SZ_256 |
142 | 166 | ||
167 | #define TEGRA_PWFM0_BASE 0x7000A000 | ||
168 | #define TEGRA_PWFM0_SIZE 4 | ||
169 | |||
170 | #define TEGRA_PWFM1_BASE 0x7000A010 | ||
171 | #define TEGRA_PWFM1_SIZE 4 | ||
172 | |||
173 | #define TEGRA_PWFM2_BASE 0x7000A020 | ||
174 | #define TEGRA_PWFM2_SIZE 4 | ||
175 | |||
176 | #define TEGRA_PWFM3_BASE 0x7000A030 | ||
177 | #define TEGRA_PWFM3_SIZE 4 | ||
178 | |||
143 | #define TEGRA_MIPI_BASE 0x7000B000 | 179 | #define TEGRA_MIPI_BASE 0x7000B000 |
144 | #define TEGRA_MIPI_SIZE SZ_256 | 180 | #define TEGRA_MIPI_SIZE SZ_256 |
145 | 181 | ||
@@ -221,4 +257,18 @@ | |||
221 | #define TEGRA_SDMMC4_BASE 0xC8000600 | 257 | #define TEGRA_SDMMC4_BASE 0xC8000600 |
222 | #define TEGRA_SDMMC4_SIZE SZ_512 | 258 | #define TEGRA_SDMMC4_SIZE SZ_512 |
223 | 259 | ||
260 | #if defined(CONFIG_TEGRA_DEBUG_UART_NONE) | ||
261 | # define TEGRA_DEBUG_UART_BASE 0 | ||
262 | #elif defined(CONFIG_TEGRA_DEBUG_UARTA) | ||
263 | # define TEGRA_DEBUG_UART_BASE TEGRA_UARTA_BASE | ||
264 | #elif defined(CONFIG_TEGRA_DEBUG_UARTB) | ||
265 | # define TEGRA_DEBUG_UART_BASE TEGRA_UARTB_BASE | ||
266 | #elif defined(CONFIG_TEGRA_DEBUG_UARTC) | ||
267 | # define TEGRA_DEBUG_UART_BASE TEGRA_UARTC_BASE | ||
268 | #elif defined(CONFIG_TEGRA_DEBUG_UARTD) | ||
269 | # define TEGRA_DEBUG_UART_BASE TEGRA_UARTD_BASE | ||
270 | #elif defined(CONFIG_TEGRA_DEBUG_UARTE) | ||
271 | # define TEGRA_DEBUG_UART_BASE TEGRA_UARTE_BASE | ||
272 | #endif | ||
273 | |||
224 | #endif | 274 | #endif |
diff --git a/arch/arm/mach-tegra/include/mach/irqs.h b/arch/arm/mach-tegra/include/mach/irqs.h index 71bbf3422953..73265af4dda3 100644 --- a/arch/arm/mach-tegra/include/mach/irqs.h +++ b/arch/arm/mach-tegra/include/mach/irqs.h | |||
@@ -88,7 +88,7 @@ | |||
88 | #define INT_SYS_STATS_MON (INT_SEC_BASE + 22) | 88 | #define INT_SYS_STATS_MON (INT_SEC_BASE + 22) |
89 | #define INT_GPIO5 (INT_SEC_BASE + 23) | 89 | #define INT_GPIO5 (INT_SEC_BASE + 23) |
90 | #define INT_CPU0_PMU_INTR (INT_SEC_BASE + 24) | 90 | #define INT_CPU0_PMU_INTR (INT_SEC_BASE + 24) |
91 | #define INT_CPU2_PMU_INTR (INT_SEC_BASE + 25) | 91 | #define INT_CPU1_PMU_INTR (INT_SEC_BASE + 25) |
92 | #define INT_SEC_RES_26 (INT_SEC_BASE + 26) | 92 | #define INT_SEC_RES_26 (INT_SEC_BASE + 26) |
93 | #define INT_S_LINK1 (INT_SEC_BASE + 27) | 93 | #define INT_S_LINK1 (INT_SEC_BASE + 27) |
94 | #define INT_APB_DMA_COP (INT_SEC_BASE + 28) | 94 | #define INT_APB_DMA_COP (INT_SEC_BASE + 28) |
@@ -166,10 +166,18 @@ | |||
166 | #define INT_QUAD_RES_30 (INT_QUAD_BASE + 30) | 166 | #define INT_QUAD_RES_30 (INT_QUAD_BASE + 30) |
167 | #define INT_QUAD_RES_31 (INT_QUAD_BASE + 31) | 167 | #define INT_QUAD_RES_31 (INT_QUAD_BASE + 31) |
168 | 168 | ||
169 | #define INT_GPIO_BASE (INT_QUAD_BASE + 32) | 169 | #define INT_MAIN_NR (INT_QUAD_BASE + 32 - INT_PRI_BASE) |
170 | |||
171 | #define INT_GPIO_BASE (INT_PRI_BASE + INT_MAIN_NR) | ||
172 | |||
170 | #define INT_GPIO_NR (28 * 8) | 173 | #define INT_GPIO_NR (28 * 8) |
171 | 174 | ||
172 | #define NR_IRQS (INT_GPIO_BASE + INT_GPIO_NR) | 175 | #define TEGRA_NR_IRQS (INT_GPIO_BASE + INT_GPIO_NR) |
176 | |||
177 | #define INT_BOARD_BASE TEGRA_NR_IRQS | ||
178 | #define NR_BOARD_IRQS 32 | ||
179 | |||
180 | #define NR_IRQS (INT_BOARD_BASE + NR_BOARD_IRQS) | ||
173 | #endif | 181 | #endif |
174 | 182 | ||
175 | #endif | 183 | #endif |
diff --git a/arch/arm/mach-tegra/include/mach/kbc.h b/arch/arm/mach-tegra/include/mach/kbc.h new file mode 100644 index 000000000000..04c779832c78 --- /dev/null +++ b/arch/arm/mach-tegra/include/mach/kbc.h | |||
@@ -0,0 +1,62 @@ | |||
1 | /* | ||
2 | * Platform definitions for tegra-kbc keyboard input driver | ||
3 | * | ||
4 | * Copyright (c) 2010-2011, NVIDIA Corporation. | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify | ||
7 | * it under the terms of the GNU General Public License as published by | ||
8 | * the Free Software Foundation; either version 2 of the License, or | ||
9 | * (at your option) any later version. | ||
10 | * | ||
11 | * This program is distributed in the hope that it will be useful, but WITHOUT | ||
12 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||
13 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | ||
14 | * more details. | ||
15 | * | ||
16 | * You should have received a copy of the GNU General Public License along | ||
17 | * with this program; if not, write to the Free Software Foundation, Inc., | ||
18 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. | ||
19 | */ | ||
20 | |||
21 | #ifndef ASMARM_ARCH_TEGRA_KBC_H | ||
22 | #define ASMARM_ARCH_TEGRA_KBC_H | ||
23 | |||
24 | #include <linux/types.h> | ||
25 | #include <linux/input/matrix_keypad.h> | ||
26 | |||
27 | #ifdef CONFIG_ARCH_TEGRA_2x_SOC | ||
28 | #define KBC_MAX_GPIO 24 | ||
29 | #define KBC_MAX_KPENT 8 | ||
30 | #else | ||
31 | #define KBC_MAX_GPIO 20 | ||
32 | #define KBC_MAX_KPENT 7 | ||
33 | #endif | ||
34 | |||
35 | #define KBC_MAX_ROW 16 | ||
36 | #define KBC_MAX_COL 8 | ||
37 | #define KBC_MAX_KEY (KBC_MAX_ROW * KBC_MAX_COL) | ||
38 | |||
39 | struct tegra_kbc_pin_cfg { | ||
40 | bool is_row; | ||
41 | unsigned char num; | ||
42 | }; | ||
43 | |||
44 | struct tegra_kbc_wake_key { | ||
45 | u8 row:4; | ||
46 | u8 col:4; | ||
47 | }; | ||
48 | |||
49 | struct tegra_kbc_platform_data { | ||
50 | unsigned int debounce_cnt; | ||
51 | unsigned int repeat_cnt; | ||
52 | |||
53 | unsigned int wake_cnt; /* 0:wake on any key >1:wake on wake_cfg */ | ||
54 | const struct tegra_kbc_wake_key *wake_cfg; | ||
55 | |||
56 | struct tegra_kbc_pin_cfg pin_cfg[KBC_MAX_GPIO]; | ||
57 | const struct matrix_keymap_data *keymap_data; | ||
58 | |||
59 | bool wakeup; | ||
60 | bool use_fn_map; | ||
61 | }; | ||
62 | #endif | ||
diff --git a/arch/arm/mach-tegra/include/mach/legacy_irq.h b/arch/arm/mach-tegra/include/mach/legacy_irq.h index db1eb3dd04c8..d898c0e3d905 100644 --- a/arch/arm/mach-tegra/include/mach/legacy_irq.h +++ b/arch/arm/mach-tegra/include/mach/legacy_irq.h | |||
@@ -27,5 +27,9 @@ int tegra_legacy_force_irq_status(unsigned int irq); | |||
27 | void tegra_legacy_select_fiq(unsigned int irq, bool fiq); | 27 | void tegra_legacy_select_fiq(unsigned int irq, bool fiq); |
28 | unsigned long tegra_legacy_vfiq(int nr); | 28 | unsigned long tegra_legacy_vfiq(int nr); |
29 | unsigned long tegra_legacy_class(int nr); | 29 | unsigned long tegra_legacy_class(int nr); |
30 | int tegra_legacy_irq_set_wake(int irq, int enable); | ||
31 | void tegra_legacy_irq_set_lp1_wake_mask(void); | ||
32 | void tegra_legacy_irq_restore_mask(void); | ||
33 | void tegra_init_legacy_irq(void); | ||
30 | 34 | ||
31 | #endif | 35 | #endif |
diff --git a/arch/arm/mach-tegra/include/mach/memory.h b/arch/arm/mach-tegra/include/mach/memory.h index 6151bab62af2..537db3aa81a7 100644 --- a/arch/arm/mach-tegra/include/mach/memory.h +++ b/arch/arm/mach-tegra/include/mach/memory.h | |||
@@ -22,7 +22,7 @@ | |||
22 | #define __MACH_TEGRA_MEMORY_H | 22 | #define __MACH_TEGRA_MEMORY_H |
23 | 23 | ||
24 | /* physical offset of RAM */ | 24 | /* physical offset of RAM */ |
25 | #define PHYS_OFFSET UL(0) | 25 | #define PLAT_PHYS_OFFSET UL(0) |
26 | 26 | ||
27 | #endif | 27 | #endif |
28 | 28 | ||
diff --git a/arch/arm/mach-tegra/include/mach/pinmux-t2.h b/arch/arm/mach-tegra/include/mach/pinmux-t2.h index e5b9d740f973..4c2626347263 100644 --- a/arch/arm/mach-tegra/include/mach/pinmux-t2.h +++ b/arch/arm/mach-tegra/include/mach/pinmux-t2.h | |||
@@ -167,6 +167,16 @@ enum tegra_drive_pingroup { | |||
167 | TEGRA_DRIVE_PINGROUP_XM2D, | 167 | TEGRA_DRIVE_PINGROUP_XM2D, |
168 | TEGRA_DRIVE_PINGROUP_XM2CLK, | 168 | TEGRA_DRIVE_PINGROUP_XM2CLK, |
169 | TEGRA_DRIVE_PINGROUP_MEMCOMP, | 169 | TEGRA_DRIVE_PINGROUP_MEMCOMP, |
170 | TEGRA_DRIVE_PINGROUP_SDIO1, | ||
171 | TEGRA_DRIVE_PINGROUP_CRT, | ||
172 | TEGRA_DRIVE_PINGROUP_DDC, | ||
173 | TEGRA_DRIVE_PINGROUP_GMA, | ||
174 | TEGRA_DRIVE_PINGROUP_GMB, | ||
175 | TEGRA_DRIVE_PINGROUP_GMC, | ||
176 | TEGRA_DRIVE_PINGROUP_GMD, | ||
177 | TEGRA_DRIVE_PINGROUP_GME, | ||
178 | TEGRA_DRIVE_PINGROUP_OWR, | ||
179 | TEGRA_DRIVE_PINGROUP_UAD, | ||
170 | TEGRA_MAX_DRIVE_PINGROUP, | 180 | TEGRA_MAX_DRIVE_PINGROUP, |
171 | }; | 181 | }; |
172 | 182 | ||
diff --git a/arch/arm/mach-tegra/include/mach/powergate.h b/arch/arm/mach-tegra/include/mach/powergate.h new file mode 100644 index 000000000000..401d1b725291 --- /dev/null +++ b/arch/arm/mach-tegra/include/mach/powergate.h | |||
@@ -0,0 +1,40 @@ | |||
1 | /* | ||
2 | * drivers/regulator/tegra-regulator.c | ||
3 | * | ||
4 | * Copyright (c) 2010 Google, Inc | ||
5 | * | ||
6 | * Author: | ||
7 | * Colin Cross <ccross@google.com> | ||
8 | * | ||
9 | * This software is licensed under the terms of the GNU General Public | ||
10 | * License version 2, as published by the Free Software Foundation, and | ||
11 | * may be copied, distributed, and modified under those terms. | ||
12 | * | ||
13 | * This program is distributed in the hope that it will be useful, | ||
14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
16 | * GNU General Public License for more details. | ||
17 | * | ||
18 | */ | ||
19 | |||
20 | #ifndef _MACH_TEGRA_POWERGATE_H_ | ||
21 | #define _MACH_TEGRA_POWERGATE_H_ | ||
22 | |||
23 | #define TEGRA_POWERGATE_CPU 0 | ||
24 | #define TEGRA_POWERGATE_3D 1 | ||
25 | #define TEGRA_POWERGATE_VENC 2 | ||
26 | #define TEGRA_POWERGATE_PCIE 3 | ||
27 | #define TEGRA_POWERGATE_VDEC 4 | ||
28 | #define TEGRA_POWERGATE_L2 5 | ||
29 | #define TEGRA_POWERGATE_MPE 6 | ||
30 | #define TEGRA_NUM_POWERGATE 7 | ||
31 | |||
32 | int tegra_powergate_power_on(int id); | ||
33 | int tegra_powergate_power_off(int id); | ||
34 | bool tegra_powergate_is_powered(int id); | ||
35 | int tegra_powergate_remove_clamping(int id); | ||
36 | |||
37 | /* Must be called with clk disabled, and returns with clk enabled */ | ||
38 | int tegra_powergate_sequence_power_up(int id, struct clk *clk); | ||
39 | |||
40 | #endif /* _MACH_TEGRA_POWERGATE_H_ */ | ||
diff --git a/arch/arm/mach-tegra/include/mach/suspend.h b/arch/arm/mach-tegra/include/mach/suspend.h new file mode 100644 index 000000000000..5af8715d2e1e --- /dev/null +++ b/arch/arm/mach-tegra/include/mach/suspend.h | |||
@@ -0,0 +1,38 @@ | |||
1 | /* | ||
2 | * arch/arm/mach-tegra/include/mach/suspend.h | ||
3 | * | ||
4 | * Copyright (C) 2010 Google, Inc. | ||
5 | * | ||
6 | * Author: | ||
7 | * Colin Cross <ccross@google.com> | ||
8 | * | ||
9 | * This software is licensed under the terms of the GNU General Public | ||
10 | * License version 2, as published by the Free Software Foundation, and | ||
11 | * may be copied, distributed, and modified under those terms. | ||
12 | * | ||
13 | * This program is distributed in the hope that it will be useful, | ||
14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
16 | * GNU General Public License for more details. | ||
17 | * | ||
18 | */ | ||
19 | |||
20 | |||
21 | #ifndef _MACH_TEGRA_SUSPEND_H_ | ||
22 | #define _MACH_TEGRA_SUSPEND_H_ | ||
23 | |||
24 | void tegra_pinmux_suspend(void); | ||
25 | void tegra_irq_suspend(void); | ||
26 | void tegra_gpio_suspend(void); | ||
27 | void tegra_clk_suspend(void); | ||
28 | void tegra_dma_suspend(void); | ||
29 | void tegra_timer_suspend(void); | ||
30 | |||
31 | void tegra_pinmux_resume(void); | ||
32 | void tegra_irq_resume(void); | ||
33 | void tegra_gpio_resume(void); | ||
34 | void tegra_clk_resume(void); | ||
35 | void tegra_dma_resume(void); | ||
36 | void tegra_timer_resume(void); | ||
37 | |||
38 | #endif /* _MACH_TEGRA_SUSPEND_H_ */ | ||
diff --git a/arch/arm/mach-tegra/include/mach/system.h b/arch/arm/mach-tegra/include/mach/system.h index 84d5d46113f7..d0183d876c3b 100644 --- a/arch/arm/mach-tegra/include/mach/system.h +++ b/arch/arm/mach-tegra/include/mach/system.h | |||
@@ -24,16 +24,10 @@ | |||
24 | #include <mach/hardware.h> | 24 | #include <mach/hardware.h> |
25 | #include <mach/iomap.h> | 25 | #include <mach/iomap.h> |
26 | 26 | ||
27 | static inline void arch_idle(void) | 27 | extern void (*arch_reset)(char mode, const char *cmd); |
28 | { | ||
29 | } | ||
30 | 28 | ||
31 | static inline void arch_reset(char mode, const char *cmd) | 29 | static inline void arch_idle(void) |
32 | { | 30 | { |
33 | void __iomem *reset = IO_ADDRESS(TEGRA_CLK_RESET_BASE + 0x04); | ||
34 | u32 reg = readl(reset); | ||
35 | reg |= 0x04; | ||
36 | writel(reg, reset); | ||
37 | } | 31 | } |
38 | 32 | ||
39 | #endif | 33 | #endif |
diff --git a/arch/arm/mach-tegra/include/mach/uncompress.h b/arch/arm/mach-tegra/include/mach/uncompress.h index 6c4dd815abd7..4e8323770c79 100644 --- a/arch/arm/mach-tegra/include/mach/uncompress.h +++ b/arch/arm/mach-tegra/include/mach/uncompress.h | |||
@@ -26,23 +26,9 @@ | |||
26 | 26 | ||
27 | #include <mach/iomap.h> | 27 | #include <mach/iomap.h> |
28 | 28 | ||
29 | #if defined(CONFIG_TEGRA_DEBUG_UARTA) | ||
30 | #define DEBUG_UART_BASE TEGRA_UARTA_BASE | ||
31 | #elif defined(CONFIG_TEGRA_DEBUG_UARTB) | ||
32 | #define DEBUG_UART_BASE TEGRA_UARTB_BASE | ||
33 | #elif defined(CONFIG_TEGRA_DEBUG_UARTC) | ||
34 | #define DEBUG_UART_BASE TEGRA_UARTC_BASE | ||
35 | #elif defined(CONFIG_TEGRA_DEBUG_UARTD) | ||
36 | #define DEBUG_UART_BASE TEGRA_UARTD_BASE | ||
37 | #elif defined(CONFIG_TEGRA_DEBUG_UARTE) | ||
38 | #define DEBUG_UART_BASE TEGRA_UARTE_BASE | ||
39 | #else | ||
40 | #define DEBUG_UART_BASE NULL | ||
41 | #endif | ||
42 | |||
43 | static void putc(int c) | 29 | static void putc(int c) |
44 | { | 30 | { |
45 | volatile u8 *uart = (volatile u8 *)DEBUG_UART_BASE; | 31 | volatile u8 *uart = (volatile u8 *)TEGRA_DEBUG_UART_BASE; |
46 | int shift = 2; | 32 | int shift = 2; |
47 | 33 | ||
48 | if (uart == NULL) | 34 | if (uart == NULL) |
@@ -59,7 +45,7 @@ static inline void flush(void) | |||
59 | 45 | ||
60 | static inline void arch_decomp_setup(void) | 46 | static inline void arch_decomp_setup(void) |
61 | { | 47 | { |
62 | volatile u8 *uart = (volatile u8 *)DEBUG_UART_BASE; | 48 | volatile u8 *uart = (volatile u8 *)TEGRA_DEBUG_UART_BASE; |
63 | int shift = 2; | 49 | int shift = 2; |
64 | 50 | ||
65 | if (uart == NULL) | 51 | if (uart == NULL) |
diff --git a/arch/arm/mach-tegra/include/mach/usb_phy.h b/arch/arm/mach-tegra/include/mach/usb_phy.h new file mode 100644 index 000000000000..d4b8f9e298a8 --- /dev/null +++ b/arch/arm/mach-tegra/include/mach/usb_phy.h | |||
@@ -0,0 +1,86 @@ | |||
1 | /* | ||
2 | * arch/arm/mach-tegra/include/mach/usb_phy.h | ||
3 | * | ||
4 | * Copyright (C) 2010 Google, Inc. | ||
5 | * | ||
6 | * This software is licensed under the terms of the GNU General Public | ||
7 | * License version 2, as published by the Free Software Foundation, and | ||
8 | * may be copied, distributed, and modified under those terms. | ||
9 | * | ||
10 | * This program is distributed in the hope that it will be useful, | ||
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
13 | * GNU General Public License for more details. | ||
14 | * | ||
15 | */ | ||
16 | |||
17 | #ifndef __MACH_USB_PHY_H | ||
18 | #define __MACH_USB_PHY_H | ||
19 | |||
20 | #include <linux/clk.h> | ||
21 | #include <linux/usb/otg.h> | ||
22 | |||
23 | struct tegra_utmip_config { | ||
24 | u8 hssync_start_delay; | ||
25 | u8 elastic_limit; | ||
26 | u8 idle_wait_delay; | ||
27 | u8 term_range_adj; | ||
28 | u8 xcvr_setup; | ||
29 | u8 xcvr_lsfslew; | ||
30 | u8 xcvr_lsrslew; | ||
31 | }; | ||
32 | |||
33 | struct tegra_ulpi_config { | ||
34 | int reset_gpio; | ||
35 | const char *clk; | ||
36 | }; | ||
37 | |||
38 | enum tegra_usb_phy_port_speed { | ||
39 | TEGRA_USB_PHY_PORT_SPEED_FULL = 0, | ||
40 | TEGRA_USB_PHY_PORT_SPEED_LOW, | ||
41 | TEGRA_USB_PHY_PORT_SPEED_HIGH, | ||
42 | }; | ||
43 | |||
44 | enum tegra_usb_phy_mode { | ||
45 | TEGRA_USB_PHY_MODE_DEVICE, | ||
46 | TEGRA_USB_PHY_MODE_HOST, | ||
47 | }; | ||
48 | |||
49 | struct tegra_xtal_freq; | ||
50 | |||
51 | struct tegra_usb_phy { | ||
52 | int instance; | ||
53 | const struct tegra_xtal_freq *freq; | ||
54 | void __iomem *regs; | ||
55 | void __iomem *pad_regs; | ||
56 | struct clk *clk; | ||
57 | struct clk *pll_u; | ||
58 | struct clk *pad_clk; | ||
59 | enum tegra_usb_phy_mode mode; | ||
60 | void *config; | ||
61 | struct otg_transceiver *ulpi; | ||
62 | }; | ||
63 | |||
64 | struct tegra_usb_phy *tegra_usb_phy_open(int instance, void __iomem *regs, | ||
65 | void *config, enum tegra_usb_phy_mode phy_mode); | ||
66 | |||
67 | int tegra_usb_phy_power_on(struct tegra_usb_phy *phy); | ||
68 | |||
69 | void tegra_usb_phy_clk_disable(struct tegra_usb_phy *phy); | ||
70 | |||
71 | void tegra_usb_phy_clk_enable(struct tegra_usb_phy *phy); | ||
72 | |||
73 | void tegra_usb_phy_power_off(struct tegra_usb_phy *phy); | ||
74 | |||
75 | void tegra_usb_phy_preresume(struct tegra_usb_phy *phy); | ||
76 | |||
77 | void tegra_usb_phy_postresume(struct tegra_usb_phy *phy); | ||
78 | |||
79 | void tegra_ehci_phy_restore_start(struct tegra_usb_phy *phy, | ||
80 | enum tegra_usb_phy_port_speed port_speed); | ||
81 | |||
82 | void tegra_ehci_phy_restore_end(struct tegra_usb_phy *phy); | ||
83 | |||
84 | void tegra_usb_phy_close(struct tegra_usb_phy *phy); | ||
85 | |||
86 | #endif /* __MACH_USB_PHY_H */ | ||
diff --git a/arch/arm/mach-tegra/irq.c b/arch/arm/mach-tegra/irq.c index de7dfad6f769..dfbc219ea492 100644 --- a/arch/arm/mach-tegra/irq.c +++ b/arch/arm/mach-tegra/irq.c | |||
@@ -18,6 +18,7 @@ | |||
18 | */ | 18 | */ |
19 | 19 | ||
20 | #include <linux/kernel.h> | 20 | #include <linux/kernel.h> |
21 | #include <linux/delay.h> | ||
21 | #include <linux/init.h> | 22 | #include <linux/init.h> |
22 | #include <linux/interrupt.h> | 23 | #include <linux/interrupt.h> |
23 | #include <linux/irq.h> | 24 | #include <linux/irq.h> |
@@ -26,146 +27,135 @@ | |||
26 | #include <asm/hardware/gic.h> | 27 | #include <asm/hardware/gic.h> |
27 | 28 | ||
28 | #include <mach/iomap.h> | 29 | #include <mach/iomap.h> |
30 | #include <mach/legacy_irq.h> | ||
31 | #include <mach/suspend.h> | ||
29 | 32 | ||
30 | #include "board.h" | 33 | #include "board.h" |
31 | 34 | ||
32 | #define INT_SYS_NR (INT_GPIO_BASE - INT_PRI_BASE) | 35 | #define PMC_CTRL 0x0 |
33 | #define INT_SYS_SZ (INT_SEC_BASE - INT_PRI_BASE) | 36 | #define PMC_CTRL_LATCH_WAKEUPS (1 << 5) |
34 | #define PPI_NR ((INT_SYS_NR+INT_SYS_SZ-1)/INT_SYS_SZ) | 37 | #define PMC_WAKE_MASK 0xc |
38 | #define PMC_WAKE_LEVEL 0x10 | ||
39 | #define PMC_WAKE_STATUS 0x14 | ||
40 | #define PMC_SW_WAKE_STATUS 0x18 | ||
41 | #define PMC_DPD_SAMPLE 0x20 | ||
35 | 42 | ||
36 | #define APBDMA_IRQ_STA_CPU 0x14 | 43 | static void __iomem *pmc = IO_ADDRESS(TEGRA_PMC_BASE); |
37 | #define APBDMA_IRQ_MASK_SET 0x20 | ||
38 | #define APBDMA_IRQ_MASK_CLR 0x24 | ||
39 | 44 | ||
40 | #define ICTLR_CPU_IER 0x20 | 45 | static u32 tegra_lp0_wake_enb; |
41 | #define ICTLR_CPU_IER_SET 0x24 | 46 | static u32 tegra_lp0_wake_level; |
42 | #define ICTLR_CPU_IER_CLR 0x28 | 47 | static u32 tegra_lp0_wake_level_any; |
43 | #define ICTLR_CPU_IEP_CLASS 0x2c | ||
44 | #define ICTLR_COP_IER 0x30 | ||
45 | #define ICTLR_COP_IER_SET 0x34 | ||
46 | #define ICTLR_COP_IER_CLR 0x38 | ||
47 | #define ICTLR_COP_IEP_CLASS 0x3c | ||
48 | 48 | ||
49 | static void (*gic_mask_irq)(struct irq_data *d); | 49 | static void (*tegra_gic_mask_irq)(struct irq_data *d); |
50 | static void (*gic_unmask_irq)(struct irq_data *d); | 50 | static void (*tegra_gic_unmask_irq)(struct irq_data *d); |
51 | static void (*tegra_gic_ack_irq)(struct irq_data *d); | ||
51 | 52 | ||
52 | #define irq_to_ictlr(irq) (((irq)-32) >> 5) | 53 | /* ensures that sufficient time is passed for a register write to |
53 | static void __iomem *tegra_ictlr_base = IO_ADDRESS(TEGRA_PRIMARY_ICTLR_BASE); | 54 | * serialize into the 32KHz domain */ |
54 | #define ictlr_to_virt(ictlr) (tegra_ictlr_base + (ictlr)*0x100) | 55 | static void pmc_32kwritel(u32 val, unsigned long offs) |
56 | { | ||
57 | writel(val, pmc + offs); | ||
58 | udelay(130); | ||
59 | } | ||
60 | |||
61 | int tegra_set_lp1_wake(int irq, int enable) | ||
62 | { | ||
63 | return tegra_legacy_irq_set_wake(irq, enable); | ||
64 | } | ||
65 | |||
66 | void tegra_set_lp0_wake_pads(u32 wake_enb, u32 wake_level, u32 wake_any) | ||
67 | { | ||
68 | u32 temp; | ||
69 | u32 status; | ||
70 | u32 lvl; | ||
71 | |||
72 | wake_level &= wake_enb; | ||
73 | wake_any &= wake_enb; | ||
74 | |||
75 | wake_level |= (tegra_lp0_wake_level & tegra_lp0_wake_enb); | ||
76 | wake_any |= (tegra_lp0_wake_level_any & tegra_lp0_wake_enb); | ||
77 | |||
78 | wake_enb |= tegra_lp0_wake_enb; | ||
79 | |||
80 | pmc_32kwritel(0, PMC_SW_WAKE_STATUS); | ||
81 | temp = readl(pmc + PMC_CTRL); | ||
82 | temp |= PMC_CTRL_LATCH_WAKEUPS; | ||
83 | pmc_32kwritel(temp, PMC_CTRL); | ||
84 | temp &= ~PMC_CTRL_LATCH_WAKEUPS; | ||
85 | pmc_32kwritel(temp, PMC_CTRL); | ||
86 | status = readl(pmc + PMC_SW_WAKE_STATUS); | ||
87 | lvl = readl(pmc + PMC_WAKE_LEVEL); | ||
88 | |||
89 | /* flip the wakeup trigger for any-edge triggered pads | ||
90 | * which are currently asserting as wakeups */ | ||
91 | lvl ^= status; | ||
92 | lvl &= wake_any; | ||
93 | |||
94 | wake_level |= lvl; | ||
95 | |||
96 | writel(wake_level, pmc + PMC_WAKE_LEVEL); | ||
97 | /* Enable DPD sample to trigger sampling pads data and direction | ||
98 | * in which pad will be driven during lp0 mode*/ | ||
99 | writel(0x1, pmc + PMC_DPD_SAMPLE); | ||
100 | |||
101 | writel(wake_enb, pmc + PMC_WAKE_MASK); | ||
102 | } | ||
55 | 103 | ||
56 | static void tegra_mask(struct irq_data *d) | 104 | static void tegra_mask(struct irq_data *d) |
57 | { | 105 | { |
58 | void __iomem *addr = ictlr_to_virt(irq_to_ictlr(d->irq)); | 106 | tegra_gic_mask_irq(d); |
59 | gic_mask_irq(d); | 107 | tegra_legacy_mask_irq(d->irq); |
60 | writel(1<<(d->irq&31), addr+ICTLR_CPU_IER_CLR); | ||
61 | } | 108 | } |
62 | 109 | ||
63 | static void tegra_unmask(struct irq_data *d) | 110 | static void tegra_unmask(struct irq_data *d) |
64 | { | 111 | { |
65 | void __iomem *addr = ictlr_to_virt(irq_to_ictlr(d->irq)); | 112 | tegra_gic_unmask_irq(d); |
66 | gic_unmask_irq(d); | 113 | tegra_legacy_unmask_irq(d->irq); |
67 | writel(1<<(d->irq&31), addr+ICTLR_CPU_IER_SET); | ||
68 | } | 114 | } |
69 | 115 | ||
70 | #ifdef CONFIG_PM | 116 | static void tegra_ack(struct irq_data *d) |
117 | { | ||
118 | tegra_legacy_force_irq_clr(d->irq); | ||
119 | tegra_gic_ack_irq(d); | ||
120 | } | ||
71 | 121 | ||
72 | static int tegra_set_wake(struct irq_data *d, unsigned int on) | 122 | static int tegra_retrigger(struct irq_data *d) |
73 | { | 123 | { |
74 | return 0; | 124 | tegra_legacy_force_irq_set(d->irq); |
125 | return 1; | ||
75 | } | 126 | } |
76 | #endif | ||
77 | 127 | ||
78 | static struct irq_chip tegra_irq = { | 128 | static struct irq_chip tegra_irq = { |
79 | .name = "PPI", | 129 | .name = "PPI", |
80 | .irq_mask = tegra_mask, | 130 | .irq_ack = tegra_ack, |
81 | .irq_unmask = tegra_unmask, | 131 | .irq_mask = tegra_mask, |
82 | #ifdef CONFIG_PM | 132 | .irq_unmask = tegra_unmask, |
83 | .irq_set_wake = tegra_set_wake, | 133 | .irq_retrigger = tegra_retrigger, |
84 | #endif | ||
85 | }; | 134 | }; |
86 | 135 | ||
87 | void __init tegra_init_irq(void) | 136 | void __init tegra_init_irq(void) |
88 | { | 137 | { |
89 | struct irq_chip *gic; | 138 | struct irq_chip *gic; |
90 | unsigned int i; | 139 | unsigned int i; |
140 | int irq; | ||
91 | 141 | ||
92 | for (i = 0; i < PPI_NR; i++) { | 142 | tegra_init_legacy_irq(); |
93 | writel(~0, ictlr_to_virt(i) + ICTLR_CPU_IER_CLR); | ||
94 | writel(0, ictlr_to_virt(i) + ICTLR_CPU_IEP_CLASS); | ||
95 | } | ||
96 | 143 | ||
97 | gic_init(0, 29, IO_ADDRESS(TEGRA_ARM_INT_DIST_BASE), | 144 | gic_init(0, 29, IO_ADDRESS(TEGRA_ARM_INT_DIST_BASE), |
98 | IO_ADDRESS(TEGRA_ARM_PERIF_BASE + 0x100)); | 145 | IO_ADDRESS(TEGRA_ARM_PERIF_BASE + 0x100)); |
99 | 146 | ||
100 | gic = get_irq_chip(29); | 147 | gic = get_irq_chip(29); |
101 | gic_unmask_irq = gic->irq_unmask; | 148 | tegra_gic_unmask_irq = gic->irq_unmask; |
102 | gic_mask_irq = gic->irq_mask; | 149 | tegra_gic_mask_irq = gic->irq_mask; |
103 | tegra_irq.irq_ack = gic->irq_ack; | 150 | tegra_gic_ack_irq = gic->irq_ack; |
104 | #ifdef CONFIG_SMP | 151 | #ifdef CONFIG_SMP |
105 | tegra_irq.irq_set_affinity = gic->irq_set_affinity; | 152 | tegra_irq.irq_set_affinity = gic->irq_set_affinity; |
106 | #endif | 153 | #endif |
107 | 154 | ||
108 | for (i = INT_PRI_BASE; i < INT_GPIO_BASE; i++) { | 155 | for (i = 0; i < INT_MAIN_NR; i++) { |
109 | set_irq_chip(i, &tegra_irq); | 156 | irq = INT_PRI_BASE + i; |
110 | set_irq_handler(i, handle_level_irq); | 157 | set_irq_chip(irq, &tegra_irq); |
111 | set_irq_flags(i, IRQF_VALID); | 158 | set_irq_handler(irq, handle_level_irq); |
159 | set_irq_flags(irq, IRQF_VALID); | ||
112 | } | 160 | } |
113 | } | 161 | } |
114 | |||
115 | #ifdef CONFIG_PM | ||
116 | static u32 cop_ier[PPI_NR]; | ||
117 | static u32 cpu_ier[PPI_NR]; | ||
118 | static u32 cpu_iep[PPI_NR]; | ||
119 | |||
120 | void tegra_irq_suspend(void) | ||
121 | { | ||
122 | unsigned long flags; | ||
123 | int i; | ||
124 | |||
125 | for (i = INT_PRI_BASE; i < INT_GPIO_BASE; i++) { | ||
126 | struct irq_desc *desc = irq_to_desc(i); | ||
127 | if (!desc) | ||
128 | continue; | ||
129 | if (desc->status & IRQ_WAKEUP) { | ||
130 | pr_debug("irq %d is wakeup\n", i); | ||
131 | continue; | ||
132 | } | ||
133 | disable_irq(i); | ||
134 | } | ||
135 | |||
136 | local_irq_save(flags); | ||
137 | for (i = 0; i < PPI_NR; i++) { | ||
138 | void __iomem *ictlr = ictlr_to_virt(i); | ||
139 | cpu_ier[i] = readl(ictlr + ICTLR_CPU_IER); | ||
140 | cpu_iep[i] = readl(ictlr + ICTLR_CPU_IEP_CLASS); | ||
141 | cop_ier[i] = readl(ictlr + ICTLR_COP_IER); | ||
142 | writel(~0, ictlr + ICTLR_COP_IER_CLR); | ||
143 | } | ||
144 | local_irq_restore(flags); | ||
145 | } | ||
146 | |||
147 | void tegra_irq_resume(void) | ||
148 | { | ||
149 | unsigned long flags; | ||
150 | int i; | ||
151 | |||
152 | local_irq_save(flags); | ||
153 | for (i = 0; i < PPI_NR; i++) { | ||
154 | void __iomem *ictlr = ictlr_to_virt(i); | ||
155 | writel(cpu_iep[i], ictlr + ICTLR_CPU_IEP_CLASS); | ||
156 | writel(~0ul, ictlr + ICTLR_CPU_IER_CLR); | ||
157 | writel(cpu_ier[i], ictlr + ICTLR_CPU_IER_SET); | ||
158 | writel(0, ictlr + ICTLR_COP_IEP_CLASS); | ||
159 | writel(~0ul, ictlr + ICTLR_COP_IER_CLR); | ||
160 | writel(cop_ier[i], ictlr + ICTLR_COP_IER_SET); | ||
161 | } | ||
162 | local_irq_restore(flags); | ||
163 | |||
164 | for (i = INT_PRI_BASE; i < INT_GPIO_BASE; i++) { | ||
165 | struct irq_desc *desc = irq_to_desc(i); | ||
166 | if (!desc || (desc->status & IRQ_WAKEUP)) | ||
167 | continue; | ||
168 | enable_irq(i); | ||
169 | } | ||
170 | } | ||
171 | #endif | ||
diff --git a/arch/arm/mach-tegra/legacy_irq.c b/arch/arm/mach-tegra/legacy_irq.c index 7cc8601c19ff..38eb719a4f53 100644 --- a/arch/arm/mach-tegra/legacy_irq.c +++ b/arch/arm/mach-tegra/legacy_irq.c | |||
@@ -18,17 +18,30 @@ | |||
18 | #include <linux/io.h> | 18 | #include <linux/io.h> |
19 | #include <linux/kernel.h> | 19 | #include <linux/kernel.h> |
20 | #include <mach/iomap.h> | 20 | #include <mach/iomap.h> |
21 | #include <mach/irqs.h> | ||
21 | #include <mach/legacy_irq.h> | 22 | #include <mach/legacy_irq.h> |
22 | 23 | ||
23 | #define ICTLR_CPU_IER 0x20 | 24 | #define INT_SYS_NR (INT_GPIO_BASE - INT_PRI_BASE) |
24 | #define ICTLR_CPU_IER_SET 0x24 | 25 | #define INT_SYS_SZ (INT_SEC_BASE - INT_PRI_BASE) |
25 | #define ICTLR_CPU_IER_CLR 0x28 | 26 | #define PPI_NR ((INT_SYS_NR+INT_SYS_SZ-1)/INT_SYS_SZ) |
26 | #define ICTLR_CPU_IEP_CLASS 0x2C | 27 | |
27 | #define ICTLR_CPU_IEP_VFIQ 0x08 | 28 | #define ICTLR_CPU_IEP_VFIQ 0x08 |
28 | #define ICTLR_CPU_IEP_FIR 0x14 | 29 | #define ICTLR_CPU_IEP_FIR 0x14 |
29 | #define ICTLR_CPU_IEP_FIR_SET 0x18 | 30 | #define ICTLR_CPU_IEP_FIR_SET 0x18 |
30 | #define ICTLR_CPU_IEP_FIR_CLR 0x1c | 31 | #define ICTLR_CPU_IEP_FIR_CLR 0x1c |
31 | 32 | ||
33 | #define ICTLR_CPU_IER 0x20 | ||
34 | #define ICTLR_CPU_IER_SET 0x24 | ||
35 | #define ICTLR_CPU_IER_CLR 0x28 | ||
36 | #define ICTLR_CPU_IEP_CLASS 0x2C | ||
37 | |||
38 | #define ICTLR_COP_IER 0x30 | ||
39 | #define ICTLR_COP_IER_SET 0x34 | ||
40 | #define ICTLR_COP_IER_CLR 0x38 | ||
41 | #define ICTLR_COP_IEP_CLASS 0x3c | ||
42 | |||
43 | #define NUM_ICTLRS 4 | ||
44 | |||
32 | static void __iomem *ictlr_reg_base[] = { | 45 | static void __iomem *ictlr_reg_base[] = { |
33 | IO_ADDRESS(TEGRA_PRIMARY_ICTLR_BASE), | 46 | IO_ADDRESS(TEGRA_PRIMARY_ICTLR_BASE), |
34 | IO_ADDRESS(TEGRA_SECONDARY_ICTLR_BASE), | 47 | IO_ADDRESS(TEGRA_SECONDARY_ICTLR_BASE), |
@@ -36,6 +49,9 @@ static void __iomem *ictlr_reg_base[] = { | |||
36 | IO_ADDRESS(TEGRA_QUATERNARY_ICTLR_BASE), | 49 | IO_ADDRESS(TEGRA_QUATERNARY_ICTLR_BASE), |
37 | }; | 50 | }; |
38 | 51 | ||
52 | static u32 tegra_legacy_wake_mask[4]; | ||
53 | static u32 tegra_legacy_saved_mask[4]; | ||
54 | |||
39 | /* When going into deep sleep, the CPU is powered down, taking the GIC with it | 55 | /* When going into deep sleep, the CPU is powered down, taking the GIC with it |
40 | In order to wake, the wake interrupts need to be enabled in the legacy | 56 | In order to wake, the wake interrupts need to be enabled in the legacy |
41 | interrupt controller. */ | 57 | interrupt controller. */ |
@@ -112,3 +128,88 @@ unsigned long tegra_legacy_class(int nr) | |||
112 | base = ictlr_reg_base[nr]; | 128 | base = ictlr_reg_base[nr]; |
113 | return readl(base + ICTLR_CPU_IEP_CLASS); | 129 | return readl(base + ICTLR_CPU_IEP_CLASS); |
114 | } | 130 | } |
131 | |||
132 | int tegra_legacy_irq_set_wake(int irq, int enable) | ||
133 | { | ||
134 | irq -= 32; | ||
135 | if (enable) | ||
136 | tegra_legacy_wake_mask[irq >> 5] |= 1 << (irq & 31); | ||
137 | else | ||
138 | tegra_legacy_wake_mask[irq >> 5] &= ~(1 << (irq & 31)); | ||
139 | |||
140 | return 0; | ||
141 | } | ||
142 | |||
143 | void tegra_legacy_irq_set_lp1_wake_mask(void) | ||
144 | { | ||
145 | void __iomem *base; | ||
146 | int i; | ||
147 | |||
148 | for (i = 0; i < NUM_ICTLRS; i++) { | ||
149 | base = ictlr_reg_base[i]; | ||
150 | tegra_legacy_saved_mask[i] = readl(base + ICTLR_CPU_IER); | ||
151 | writel(tegra_legacy_wake_mask[i], base + ICTLR_CPU_IER); | ||
152 | } | ||
153 | } | ||
154 | |||
155 | void tegra_legacy_irq_restore_mask(void) | ||
156 | { | ||
157 | void __iomem *base; | ||
158 | int i; | ||
159 | |||
160 | for (i = 0; i < NUM_ICTLRS; i++) { | ||
161 | base = ictlr_reg_base[i]; | ||
162 | writel(tegra_legacy_saved_mask[i], base + ICTLR_CPU_IER); | ||
163 | } | ||
164 | } | ||
165 | |||
166 | void tegra_init_legacy_irq(void) | ||
167 | { | ||
168 | int i; | ||
169 | |||
170 | for (i = 0; i < NUM_ICTLRS; i++) { | ||
171 | void __iomem *ictlr = ictlr_reg_base[i]; | ||
172 | writel(~0, ictlr + ICTLR_CPU_IER_CLR); | ||
173 | writel(0, ictlr + ICTLR_CPU_IEP_CLASS); | ||
174 | } | ||
175 | } | ||
176 | |||
177 | #ifdef CONFIG_PM | ||
178 | static u32 cop_ier[NUM_ICTLRS]; | ||
179 | static u32 cpu_ier[NUM_ICTLRS]; | ||
180 | static u32 cpu_iep[NUM_ICTLRS]; | ||
181 | |||
182 | void tegra_irq_suspend(void) | ||
183 | { | ||
184 | unsigned long flags; | ||
185 | int i; | ||
186 | |||
187 | local_irq_save(flags); | ||
188 | for (i = 0; i < NUM_ICTLRS; i++) { | ||
189 | void __iomem *ictlr = ictlr_reg_base[i]; | ||
190 | cpu_ier[i] = readl(ictlr + ICTLR_CPU_IER); | ||
191 | cpu_iep[i] = readl(ictlr + ICTLR_CPU_IEP_CLASS); | ||
192 | cop_ier[i] = readl(ictlr + ICTLR_COP_IER); | ||
193 | writel(~0, ictlr + ICTLR_COP_IER_CLR); | ||
194 | } | ||
195 | local_irq_restore(flags); | ||
196 | } | ||
197 | |||
198 | void tegra_irq_resume(void) | ||
199 | { | ||
200 | unsigned long flags; | ||
201 | int i; | ||
202 | |||
203 | local_irq_save(flags); | ||
204 | for (i = 0; i < NUM_ICTLRS; i++) { | ||
205 | void __iomem *ictlr = ictlr_reg_base[i]; | ||
206 | writel(cpu_iep[i], ictlr + ICTLR_CPU_IEP_CLASS); | ||
207 | writel(~0ul, ictlr + ICTLR_CPU_IER_CLR); | ||
208 | writel(cpu_ier[i], ictlr + ICTLR_CPU_IER_SET); | ||
209 | writel(0, ictlr + ICTLR_COP_IEP_CLASS); | ||
210 | writel(~0ul, ictlr + ICTLR_COP_IER_CLR); | ||
211 | writel(cop_ier[i], ictlr + ICTLR_COP_IER_SET); | ||
212 | } | ||
213 | local_irq_restore(flags); | ||
214 | } | ||
215 | #endif | ||
diff --git a/arch/arm/mach-tegra/localtimer.c b/arch/arm/mach-tegra/localtimer.c index f81ca7cbbc1f..e91d681d45a2 100644 --- a/arch/arm/mach-tegra/localtimer.c +++ b/arch/arm/mach-tegra/localtimer.c | |||
@@ -18,8 +18,9 @@ | |||
18 | /* | 18 | /* |
19 | * Setup the local clock events for a CPU. | 19 | * Setup the local clock events for a CPU. |
20 | */ | 20 | */ |
21 | void __cpuinit local_timer_setup(struct clock_event_device *evt) | 21 | int __cpuinit local_timer_setup(struct clock_event_device *evt) |
22 | { | 22 | { |
23 | evt->irq = IRQ_LOCALTIMER; | 23 | evt->irq = IRQ_LOCALTIMER; |
24 | twd_timer_setup(evt); | 24 | twd_timer_setup(evt); |
25 | return 0; | ||
25 | } | 26 | } |
diff --git a/arch/arm/mach-tegra/pcie.c b/arch/arm/mach-tegra/pcie.c index 53f5fa37014a..2941212b853c 100644 --- a/arch/arm/mach-tegra/pcie.c +++ b/arch/arm/mach-tegra/pcie.c | |||
@@ -39,6 +39,7 @@ | |||
39 | #include <mach/pinmux.h> | 39 | #include <mach/pinmux.h> |
40 | #include <mach/iomap.h> | 40 | #include <mach/iomap.h> |
41 | #include <mach/clk.h> | 41 | #include <mach/clk.h> |
42 | #include <mach/powergate.h> | ||
42 | 43 | ||
43 | /* register definitions */ | 44 | /* register definitions */ |
44 | #define AFI_OFFSET 0x3800 | 45 | #define AFI_OFFSET 0x3800 |
@@ -682,24 +683,41 @@ static void tegra_pcie_xclk_clamp(bool clamp) | |||
682 | pmc_writel(reg, PMC_SCRATCH42); | 683 | pmc_writel(reg, PMC_SCRATCH42); |
683 | } | 684 | } |
684 | 685 | ||
685 | static int tegra_pcie_power_on(void) | 686 | static void tegra_pcie_power_off(void) |
686 | { | 687 | { |
687 | tegra_pcie_xclk_clamp(true); | ||
688 | tegra_periph_reset_assert(tegra_pcie.pcie_xclk); | 688 | tegra_periph_reset_assert(tegra_pcie.pcie_xclk); |
689 | tegra_pcie_xclk_clamp(false); | 689 | tegra_periph_reset_assert(tegra_pcie.afi_clk); |
690 | tegra_periph_reset_assert(tegra_pcie.pex_clk); | ||
690 | 691 | ||
691 | clk_enable(tegra_pcie.afi_clk); | 692 | tegra_powergate_power_off(TEGRA_POWERGATE_PCIE); |
692 | clk_enable(tegra_pcie.pex_clk); | 693 | tegra_pcie_xclk_clamp(true); |
693 | return clk_enable(tegra_pcie.pll_e); | ||
694 | } | 694 | } |
695 | 695 | ||
696 | static void tegra_pcie_power_off(void) | 696 | static int tegra_pcie_power_regate(void) |
697 | { | 697 | { |
698 | int err; | ||
699 | |||
700 | tegra_pcie_power_off(); | ||
701 | |||
702 | tegra_pcie_xclk_clamp(true); | ||
703 | |||
698 | tegra_periph_reset_assert(tegra_pcie.pcie_xclk); | 704 | tegra_periph_reset_assert(tegra_pcie.pcie_xclk); |
699 | tegra_periph_reset_assert(tegra_pcie.afi_clk); | 705 | tegra_periph_reset_assert(tegra_pcie.afi_clk); |
700 | tegra_periph_reset_assert(tegra_pcie.pex_clk); | ||
701 | 706 | ||
702 | tegra_pcie_xclk_clamp(true); | 707 | err = tegra_powergate_sequence_power_up(TEGRA_POWERGATE_PCIE, |
708 | tegra_pcie.pex_clk); | ||
709 | if (err) { | ||
710 | pr_err("PCIE: powerup sequence failed: %d\n", err); | ||
711 | return err; | ||
712 | } | ||
713 | |||
714 | tegra_periph_reset_deassert(tegra_pcie.afi_clk); | ||
715 | |||
716 | tegra_pcie_xclk_clamp(false); | ||
717 | |||
718 | clk_enable(tegra_pcie.afi_clk); | ||
719 | clk_enable(tegra_pcie.pex_clk); | ||
720 | return clk_enable(tegra_pcie.pll_e); | ||
703 | } | 721 | } |
704 | 722 | ||
705 | static int tegra_pcie_clocks_get(void) | 723 | static int tegra_pcie_clocks_get(void) |
@@ -759,7 +777,7 @@ static int __init tegra_pcie_get_resources(void) | |||
759 | return err; | 777 | return err; |
760 | } | 778 | } |
761 | 779 | ||
762 | err = tegra_pcie_power_on(); | 780 | err = tegra_pcie_power_regate(); |
763 | if (err) { | 781 | if (err) { |
764 | pr_err("PCIE: failed to power up: %d\n", err); | 782 | pr_err("PCIE: failed to power up: %d\n", err); |
765 | goto err_pwr_on; | 783 | goto err_pwr_on; |
diff --git a/arch/arm/mach-tegra/pinmux-t2-tables.c b/arch/arm/mach-tegra/pinmux-t2-tables.c index a6ea34e782dc..a475367befa3 100644 --- a/arch/arm/mach-tegra/pinmux-t2-tables.c +++ b/arch/arm/mach-tegra/pinmux-t2-tables.c | |||
@@ -29,6 +29,7 @@ | |||
29 | 29 | ||
30 | #include <mach/iomap.h> | 30 | #include <mach/iomap.h> |
31 | #include <mach/pinmux.h> | 31 | #include <mach/pinmux.h> |
32 | #include <mach/suspend.h> | ||
32 | 33 | ||
33 | #define DRIVE_PINGROUP(pg_name, r) \ | 34 | #define DRIVE_PINGROUP(pg_name, r) \ |
34 | [TEGRA_DRIVE_PINGROUP_ ## pg_name] = { \ | 35 | [TEGRA_DRIVE_PINGROUP_ ## pg_name] = { \ |
@@ -65,6 +66,16 @@ const struct tegra_drive_pingroup_desc tegra_soc_drive_pingroups[TEGRA_MAX_DRIVE | |||
65 | DRIVE_PINGROUP(XM2D, 0x8cc), | 66 | DRIVE_PINGROUP(XM2D, 0x8cc), |
66 | DRIVE_PINGROUP(XM2CLK, 0x8d0), | 67 | DRIVE_PINGROUP(XM2CLK, 0x8d0), |
67 | DRIVE_PINGROUP(MEMCOMP, 0x8d4), | 68 | DRIVE_PINGROUP(MEMCOMP, 0x8d4), |
69 | DRIVE_PINGROUP(SDIO1, 0x8e0), | ||
70 | DRIVE_PINGROUP(CRT, 0x8ec), | ||
71 | DRIVE_PINGROUP(DDC, 0x8f0), | ||
72 | DRIVE_PINGROUP(GMA, 0x8f4), | ||
73 | DRIVE_PINGROUP(GMB, 0x8f8), | ||
74 | DRIVE_PINGROUP(GMC, 0x8fc), | ||
75 | DRIVE_PINGROUP(GMD, 0x900), | ||
76 | DRIVE_PINGROUP(GME, 0x904), | ||
77 | DRIVE_PINGROUP(OWR, 0x908), | ||
78 | DRIVE_PINGROUP(UAD, 0x90c), | ||
68 | }; | 79 | }; |
69 | 80 | ||
70 | #define PINGROUP(pg_name, vdd, f0, f1, f2, f3, f_safe, \ | 81 | #define PINGROUP(pg_name, vdd, f0, f1, f2, f3, f_safe, \ |
@@ -216,7 +227,8 @@ const struct tegra_pingroup_desc tegra_soc_pingroups[TEGRA_MAX_PINGROUP] = { | |||
216 | #define PULLUPDOWN_REG_NUM 5 | 227 | #define PULLUPDOWN_REG_NUM 5 |
217 | 228 | ||
218 | static u32 pinmux_reg[TRISTATE_REG_NUM + PIN_MUX_CTL_REG_NUM + | 229 | static u32 pinmux_reg[TRISTATE_REG_NUM + PIN_MUX_CTL_REG_NUM + |
219 | PULLUPDOWN_REG_NUM]; | 230 | PULLUPDOWN_REG_NUM + |
231 | ARRAY_SIZE(tegra_soc_drive_pingroups)]; | ||
220 | 232 | ||
221 | static inline unsigned long pg_readl(unsigned long offset) | 233 | static inline unsigned long pg_readl(unsigned long offset) |
222 | { | 234 | { |
@@ -233,14 +245,17 @@ void tegra_pinmux_suspend(void) | |||
233 | unsigned int i; | 245 | unsigned int i; |
234 | u32 *ctx = pinmux_reg; | 246 | u32 *ctx = pinmux_reg; |
235 | 247 | ||
236 | for (i = 0; i < TRISTATE_REG_NUM; i++) | ||
237 | *ctx++ = pg_readl(TRISTATE_REG_A + i*4); | ||
238 | |||
239 | for (i = 0; i < PIN_MUX_CTL_REG_NUM; i++) | 248 | for (i = 0; i < PIN_MUX_CTL_REG_NUM; i++) |
240 | *ctx++ = pg_readl(PIN_MUX_CTL_REG_A + i*4); | 249 | *ctx++ = pg_readl(PIN_MUX_CTL_REG_A + i*4); |
241 | 250 | ||
242 | for (i = 0; i < PULLUPDOWN_REG_NUM; i++) | 251 | for (i = 0; i < PULLUPDOWN_REG_NUM; i++) |
243 | *ctx++ = pg_readl(PULLUPDOWN_REG_A + i*4); | 252 | *ctx++ = pg_readl(PULLUPDOWN_REG_A + i*4); |
253 | |||
254 | for (i = 0; i < TRISTATE_REG_NUM; i++) | ||
255 | *ctx++ = pg_readl(TRISTATE_REG_A + i*4); | ||
256 | |||
257 | for (i = 0; i < ARRAY_SIZE(tegra_soc_drive_pingroups); i++) | ||
258 | *ctx++ = pg_readl(tegra_soc_drive_pingroups[i].reg); | ||
244 | } | 259 | } |
245 | 260 | ||
246 | void tegra_pinmux_resume(void) | 261 | void tegra_pinmux_resume(void) |
@@ -256,5 +271,8 @@ void tegra_pinmux_resume(void) | |||
256 | 271 | ||
257 | for (i = 0; i < TRISTATE_REG_NUM; i++) | 272 | for (i = 0; i < TRISTATE_REG_NUM; i++) |
258 | pg_writel(*ctx++, TRISTATE_REG_A + i*4); | 273 | pg_writel(*ctx++, TRISTATE_REG_A + i*4); |
274 | |||
275 | for (i = 0; i < ARRAY_SIZE(tegra_soc_drive_pingroups); i++) | ||
276 | pg_writel(*ctx++, tegra_soc_drive_pingroups[i].reg); | ||
259 | } | 277 | } |
260 | #endif | 278 | #endif |
diff --git a/arch/arm/mach-tegra/powergate.c b/arch/arm/mach-tegra/powergate.c new file mode 100644 index 000000000000..3cee9aa1f2c8 --- /dev/null +++ b/arch/arm/mach-tegra/powergate.c | |||
@@ -0,0 +1,212 @@ | |||
1 | /* | ||
2 | * drivers/powergate/tegra-powergate.c | ||
3 | * | ||
4 | * Copyright (c) 2010 Google, Inc | ||
5 | * | ||
6 | * Author: | ||
7 | * Colin Cross <ccross@google.com> | ||
8 | * | ||
9 | * This software is licensed under the terms of the GNU General Public | ||
10 | * License version 2, as published by the Free Software Foundation, and | ||
11 | * may be copied, distributed, and modified under those terms. | ||
12 | * | ||
13 | * This program is distributed in the hope that it will be useful, | ||
14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
16 | * GNU General Public License for more details. | ||
17 | * | ||
18 | */ | ||
19 | |||
20 | #include <linux/kernel.h> | ||
21 | #include <linux/clk.h> | ||
22 | #include <linux/debugfs.h> | ||
23 | #include <linux/delay.h> | ||
24 | #include <linux/err.h> | ||
25 | #include <linux/init.h> | ||
26 | #include <linux/io.h> | ||
27 | #include <linux/seq_file.h> | ||
28 | #include <linux/spinlock.h> | ||
29 | |||
30 | #include <mach/clk.h> | ||
31 | #include <mach/iomap.h> | ||
32 | #include <mach/powergate.h> | ||
33 | |||
34 | #define PWRGATE_TOGGLE 0x30 | ||
35 | #define PWRGATE_TOGGLE_START (1 << 8) | ||
36 | |||
37 | #define REMOVE_CLAMPING 0x34 | ||
38 | |||
39 | #define PWRGATE_STATUS 0x38 | ||
40 | |||
41 | static DEFINE_SPINLOCK(tegra_powergate_lock); | ||
42 | |||
43 | static void __iomem *pmc = IO_ADDRESS(TEGRA_PMC_BASE); | ||
44 | |||
45 | static u32 pmc_read(unsigned long reg) | ||
46 | { | ||
47 | return readl(pmc + reg); | ||
48 | } | ||
49 | |||
50 | static void pmc_write(u32 val, unsigned long reg) | ||
51 | { | ||
52 | writel(val, pmc + reg); | ||
53 | } | ||
54 | |||
55 | static int tegra_powergate_set(int id, bool new_state) | ||
56 | { | ||
57 | bool status; | ||
58 | unsigned long flags; | ||
59 | |||
60 | spin_lock_irqsave(&tegra_powergate_lock, flags); | ||
61 | |||
62 | status = pmc_read(PWRGATE_STATUS) & (1 << id); | ||
63 | |||
64 | if (status == new_state) { | ||
65 | spin_unlock_irqrestore(&tegra_powergate_lock, flags); | ||
66 | return -EINVAL; | ||
67 | } | ||
68 | |||
69 | pmc_write(PWRGATE_TOGGLE_START | id, PWRGATE_TOGGLE); | ||
70 | |||
71 | spin_unlock_irqrestore(&tegra_powergate_lock, flags); | ||
72 | |||
73 | return 0; | ||
74 | } | ||
75 | |||
76 | int tegra_powergate_power_on(int id) | ||
77 | { | ||
78 | if (id < 0 || id >= TEGRA_NUM_POWERGATE) | ||
79 | return -EINVAL; | ||
80 | |||
81 | return tegra_powergate_set(id, true); | ||
82 | } | ||
83 | |||
84 | int tegra_powergate_power_off(int id) | ||
85 | { | ||
86 | if (id < 0 || id >= TEGRA_NUM_POWERGATE) | ||
87 | return -EINVAL; | ||
88 | |||
89 | return tegra_powergate_set(id, false); | ||
90 | } | ||
91 | |||
92 | bool tegra_powergate_is_powered(int id) | ||
93 | { | ||
94 | u32 status; | ||
95 | |||
96 | if (id < 0 || id >= TEGRA_NUM_POWERGATE) | ||
97 | return -EINVAL; | ||
98 | |||
99 | status = pmc_read(PWRGATE_STATUS) & (1 << id); | ||
100 | return !!status; | ||
101 | } | ||
102 | |||
103 | int tegra_powergate_remove_clamping(int id) | ||
104 | { | ||
105 | u32 mask; | ||
106 | |||
107 | if (id < 0 || id >= TEGRA_NUM_POWERGATE) | ||
108 | return -EINVAL; | ||
109 | |||
110 | /* | ||
111 | * Tegra 2 has a bug where PCIE and VDE clamping masks are | ||
112 | * swapped relatively to the partition ids | ||
113 | */ | ||
114 | if (id == TEGRA_POWERGATE_VDEC) | ||
115 | mask = (1 << TEGRA_POWERGATE_PCIE); | ||
116 | else if (id == TEGRA_POWERGATE_PCIE) | ||
117 | mask = (1 << TEGRA_POWERGATE_VDEC); | ||
118 | else | ||
119 | mask = (1 << id); | ||
120 | |||
121 | pmc_write(mask, REMOVE_CLAMPING); | ||
122 | |||
123 | return 0; | ||
124 | } | ||
125 | |||
126 | /* Must be called with clk disabled, and returns with clk enabled */ | ||
127 | int tegra_powergate_sequence_power_up(int id, struct clk *clk) | ||
128 | { | ||
129 | int ret; | ||
130 | |||
131 | tegra_periph_reset_assert(clk); | ||
132 | |||
133 | ret = tegra_powergate_power_on(id); | ||
134 | if (ret) | ||
135 | goto err_power; | ||
136 | |||
137 | ret = clk_enable(clk); | ||
138 | if (ret) | ||
139 | goto err_clk; | ||
140 | |||
141 | udelay(10); | ||
142 | |||
143 | ret = tegra_powergate_remove_clamping(id); | ||
144 | if (ret) | ||
145 | goto err_clamp; | ||
146 | |||
147 | udelay(10); | ||
148 | tegra_periph_reset_deassert(clk); | ||
149 | |||
150 | return 0; | ||
151 | |||
152 | err_clamp: | ||
153 | clk_disable(clk); | ||
154 | err_clk: | ||
155 | tegra_powergate_power_off(id); | ||
156 | err_power: | ||
157 | return ret; | ||
158 | } | ||
159 | |||
160 | #ifdef CONFIG_DEBUG_FS | ||
161 | |||
162 | static const char * const powergate_name[] = { | ||
163 | [TEGRA_POWERGATE_CPU] = "cpu", | ||
164 | [TEGRA_POWERGATE_3D] = "3d", | ||
165 | [TEGRA_POWERGATE_VENC] = "venc", | ||
166 | [TEGRA_POWERGATE_VDEC] = "vdec", | ||
167 | [TEGRA_POWERGATE_PCIE] = "pcie", | ||
168 | [TEGRA_POWERGATE_L2] = "l2", | ||
169 | [TEGRA_POWERGATE_MPE] = "mpe", | ||
170 | }; | ||
171 | |||
172 | static int powergate_show(struct seq_file *s, void *data) | ||
173 | { | ||
174 | int i; | ||
175 | |||
176 | seq_printf(s, " powergate powered\n"); | ||
177 | seq_printf(s, "------------------\n"); | ||
178 | |||
179 | for (i = 0; i < TEGRA_NUM_POWERGATE; i++) | ||
180 | seq_printf(s, " %9s %7s\n", powergate_name[i], | ||
181 | tegra_powergate_is_powered(i) ? "yes" : "no"); | ||
182 | return 0; | ||
183 | } | ||
184 | |||
185 | static int powergate_open(struct inode *inode, struct file *file) | ||
186 | { | ||
187 | return single_open(file, powergate_show, inode->i_private); | ||
188 | } | ||
189 | |||
190 | static const struct file_operations powergate_fops = { | ||
191 | .open = powergate_open, | ||
192 | .read = seq_read, | ||
193 | .llseek = seq_lseek, | ||
194 | .release = single_release, | ||
195 | }; | ||
196 | |||
197 | static int __init powergate_debugfs_init(void) | ||
198 | { | ||
199 | struct dentry *d; | ||
200 | int err = -ENOMEM; | ||
201 | |||
202 | d = debugfs_create_file("powergate", S_IRUGO, NULL, NULL, | ||
203 | &powergate_fops); | ||
204 | if (!d) | ||
205 | return -ENOMEM; | ||
206 | |||
207 | return err; | ||
208 | } | ||
209 | |||
210 | late_initcall(powergate_debugfs_init); | ||
211 | |||
212 | #endif | ||
diff --git a/arch/arm/mach-tegra/tegra2_clocks.c b/arch/arm/mach-tegra/tegra2_clocks.c index f0dae6d8ba52..6d7c4eea4dcb 100644 --- a/arch/arm/mach-tegra/tegra2_clocks.c +++ b/arch/arm/mach-tegra/tegra2_clocks.c | |||
@@ -23,14 +23,15 @@ | |||
23 | #include <linux/spinlock.h> | 23 | #include <linux/spinlock.h> |
24 | #include <linux/delay.h> | 24 | #include <linux/delay.h> |
25 | #include <linux/io.h> | 25 | #include <linux/io.h> |
26 | #include <linux/hrtimer.h> | ||
27 | #include <linux/clkdev.h> | 26 | #include <linux/clkdev.h> |
27 | #include <linux/clk.h> | ||
28 | 28 | ||
29 | #include <mach/iomap.h> | 29 | #include <mach/iomap.h> |
30 | #include <mach/suspend.h> | ||
30 | 31 | ||
31 | #include "clock.h" | 32 | #include "clock.h" |
32 | #include "fuse.h" | 33 | #include "fuse.h" |
33 | #include "tegra2_dvfs.h" | 34 | #include "tegra2_emc.h" |
34 | 35 | ||
35 | #define RST_DEVICES 0x004 | 36 | #define RST_DEVICES 0x004 |
36 | #define RST_DEVICES_SET 0x300 | 37 | #define RST_DEVICES_SET 0x300 |
@@ -51,7 +52,7 @@ | |||
51 | #define OSC_CTRL_OSC_FREQ_19_2MHZ (1<<30) | 52 | #define OSC_CTRL_OSC_FREQ_19_2MHZ (1<<30) |
52 | #define OSC_CTRL_OSC_FREQ_12MHZ (2<<30) | 53 | #define OSC_CTRL_OSC_FREQ_12MHZ (2<<30) |
53 | #define OSC_CTRL_OSC_FREQ_26MHZ (3<<30) | 54 | #define OSC_CTRL_OSC_FREQ_26MHZ (3<<30) |
54 | #define OSC_CTRL_MASK 0x3f2 | 55 | #define OSC_CTRL_MASK (0x3f2 | OSC_CTRL_OSC_FREQ_MASK) |
55 | 56 | ||
56 | #define OSC_FREQ_DET 0x58 | 57 | #define OSC_FREQ_DET 0x58 |
57 | #define OSC_FREQ_DET_TRIG (1<<31) | 58 | #define OSC_FREQ_DET_TRIG (1<<31) |
@@ -73,12 +74,15 @@ | |||
73 | #define PERIPH_CLK_SOURCE_DIVU16_MASK 0xFFFF | 74 | #define PERIPH_CLK_SOURCE_DIVU16_MASK 0xFFFF |
74 | #define PERIPH_CLK_SOURCE_DIV_SHIFT 0 | 75 | #define PERIPH_CLK_SOURCE_DIV_SHIFT 0 |
75 | 76 | ||
77 | #define SDMMC_CLK_INT_FB_SEL (1 << 23) | ||
78 | #define SDMMC_CLK_INT_FB_DLY_SHIFT 16 | ||
79 | #define SDMMC_CLK_INT_FB_DLY_MASK (0xF << SDMMC_CLK_INT_FB_DLY_SHIFT) | ||
80 | |||
76 | #define PLL_BASE 0x0 | 81 | #define PLL_BASE 0x0 |
77 | #define PLL_BASE_BYPASS (1<<31) | 82 | #define PLL_BASE_BYPASS (1<<31) |
78 | #define PLL_BASE_ENABLE (1<<30) | 83 | #define PLL_BASE_ENABLE (1<<30) |
79 | #define PLL_BASE_REF_ENABLE (1<<29) | 84 | #define PLL_BASE_REF_ENABLE (1<<29) |
80 | #define PLL_BASE_OVERRIDE (1<<28) | 85 | #define PLL_BASE_OVERRIDE (1<<28) |
81 | #define PLL_BASE_LOCK (1<<27) | ||
82 | #define PLL_BASE_DIVP_MASK (0x7<<20) | 86 | #define PLL_BASE_DIVP_MASK (0x7<<20) |
83 | #define PLL_BASE_DIVP_SHIFT 20 | 87 | #define PLL_BASE_DIVP_SHIFT 20 |
84 | #define PLL_BASE_DIVN_MASK (0x3FF<<8) | 88 | #define PLL_BASE_DIVN_MASK (0x3FF<<8) |
@@ -93,7 +97,6 @@ | |||
93 | #define PLL_OUT_RESET_DISABLE (1<<0) | 97 | #define PLL_OUT_RESET_DISABLE (1<<0) |
94 | 98 | ||
95 | #define PLL_MISC(c) (((c)->flags & PLL_ALT_MISC_REG) ? 0x4 : 0xc) | 99 | #define PLL_MISC(c) (((c)->flags & PLL_ALT_MISC_REG) ? 0x4 : 0xc) |
96 | #define PLL_MISC_LOCK_ENABLE(c) (((c)->flags & PLLU) ? (1<<22) : (1<<18)) | ||
97 | 100 | ||
98 | #define PLL_MISC_DCCON_SHIFT 20 | 101 | #define PLL_MISC_DCCON_SHIFT 20 |
99 | #define PLL_MISC_CPCON_SHIFT 8 | 102 | #define PLL_MISC_CPCON_SHIFT 8 |
@@ -111,9 +114,9 @@ | |||
111 | 114 | ||
112 | #define PLLE_MISC_READY (1 << 15) | 115 | #define PLLE_MISC_READY (1 << 15) |
113 | 116 | ||
114 | #define PERIPH_CLK_TO_ENB_REG(c) ((c->clk_num / 32) * 4) | 117 | #define PERIPH_CLK_TO_ENB_REG(c) ((c->u.periph.clk_num / 32) * 4) |
115 | #define PERIPH_CLK_TO_ENB_SET_REG(c) ((c->clk_num / 32) * 8) | 118 | #define PERIPH_CLK_TO_ENB_SET_REG(c) ((c->u.periph.clk_num / 32) * 8) |
116 | #define PERIPH_CLK_TO_ENB_BIT(c) (1 << (c->clk_num % 32)) | 119 | #define PERIPH_CLK_TO_ENB_BIT(c) (1 << (c->u.periph.clk_num % 32)) |
117 | 120 | ||
118 | #define SUPER_CLK_MUX 0x00 | 121 | #define SUPER_CLK_MUX 0x00 |
119 | #define SUPER_STATE_SHIFT 28 | 122 | #define SUPER_STATE_SHIFT 28 |
@@ -134,12 +137,42 @@ | |||
134 | #define BUS_CLK_DISABLE (1<<3) | 137 | #define BUS_CLK_DISABLE (1<<3) |
135 | #define BUS_CLK_DIV_MASK 0x3 | 138 | #define BUS_CLK_DIV_MASK 0x3 |
136 | 139 | ||
140 | #define PMC_CTRL 0x0 | ||
141 | #define PMC_CTRL_BLINK_ENB (1 << 7) | ||
142 | |||
143 | #define PMC_DPD_PADS_ORIDE 0x1c | ||
144 | #define PMC_DPD_PADS_ORIDE_BLINK_ENB (1 << 20) | ||
145 | |||
146 | #define PMC_BLINK_TIMER_DATA_ON_SHIFT 0 | ||
147 | #define PMC_BLINK_TIMER_DATA_ON_MASK 0x7fff | ||
148 | #define PMC_BLINK_TIMER_ENB (1 << 15) | ||
149 | #define PMC_BLINK_TIMER_DATA_OFF_SHIFT 16 | ||
150 | #define PMC_BLINK_TIMER_DATA_OFF_MASK 0xffff | ||
151 | |||
137 | static void __iomem *reg_clk_base = IO_ADDRESS(TEGRA_CLK_RESET_BASE); | 152 | static void __iomem *reg_clk_base = IO_ADDRESS(TEGRA_CLK_RESET_BASE); |
153 | static void __iomem *reg_pmc_base = IO_ADDRESS(TEGRA_PMC_BASE); | ||
154 | |||
155 | /* | ||
156 | * Some clocks share a register with other clocks. Any clock op that | ||
157 | * non-atomically modifies a register used by another clock must lock | ||
158 | * clock_register_lock first. | ||
159 | */ | ||
160 | static DEFINE_SPINLOCK(clock_register_lock); | ||
161 | |||
162 | /* | ||
163 | * Some peripheral clocks share an enable bit, so refcount the enable bits | ||
164 | * in registers CLK_ENABLE_L, CLK_ENABLE_H, and CLK_ENABLE_U | ||
165 | */ | ||
166 | static int tegra_periph_clk_enable_refcount[3 * 32]; | ||
138 | 167 | ||
139 | #define clk_writel(value, reg) \ | 168 | #define clk_writel(value, reg) \ |
140 | __raw_writel(value, (u32)reg_clk_base + (reg)) | 169 | __raw_writel(value, (u32)reg_clk_base + (reg)) |
141 | #define clk_readl(reg) \ | 170 | #define clk_readl(reg) \ |
142 | __raw_readl((u32)reg_clk_base + (reg)) | 171 | __raw_readl((u32)reg_clk_base + (reg)) |
172 | #define pmc_writel(value, reg) \ | ||
173 | __raw_writel(value, (u32)reg_pmc_base + (reg)) | ||
174 | #define pmc_readl(reg) \ | ||
175 | __raw_readl((u32)reg_pmc_base + (reg)) | ||
143 | 176 | ||
144 | unsigned long clk_measure_input_freq(void) | 177 | unsigned long clk_measure_input_freq(void) |
145 | { | 178 | { |
@@ -245,6 +278,18 @@ static struct clk_ops tegra_clk_m_ops = { | |||
245 | .disable = tegra2_clk_m_disable, | 278 | .disable = tegra2_clk_m_disable, |
246 | }; | 279 | }; |
247 | 280 | ||
281 | void tegra2_periph_reset_assert(struct clk *c) | ||
282 | { | ||
283 | BUG_ON(!c->ops->reset); | ||
284 | c->ops->reset(c, true); | ||
285 | } | ||
286 | |||
287 | void tegra2_periph_reset_deassert(struct clk *c) | ||
288 | { | ||
289 | BUG_ON(!c->ops->reset); | ||
290 | c->ops->reset(c, false); | ||
291 | } | ||
292 | |||
248 | /* super clock functions */ | 293 | /* super clock functions */ |
249 | /* "super clocks" on tegra have two-stage muxes and a clock skipping | 294 | /* "super clocks" on tegra have two-stage muxes and a clock skipping |
250 | * super divider. We will ignore the clock skipping divider, since we | 295 | * super divider. We will ignore the clock skipping divider, since we |
@@ -303,12 +348,12 @@ static int tegra2_super_clk_set_parent(struct clk *c, struct clk *p) | |||
303 | val |= sel->value << shift; | 348 | val |= sel->value << shift; |
304 | 349 | ||
305 | if (c->refcnt) | 350 | if (c->refcnt) |
306 | clk_enable_locked(p); | 351 | clk_enable(p); |
307 | 352 | ||
308 | clk_writel(val, c->reg); | 353 | clk_writel(val, c->reg); |
309 | 354 | ||
310 | if (c->refcnt && c->parent) | 355 | if (c->refcnt && c->parent) |
311 | clk_disable_locked(c->parent); | 356 | clk_disable(c->parent); |
312 | 357 | ||
313 | clk_reparent(c, p); | 358 | clk_reparent(c, p); |
314 | return 0; | 359 | return 0; |
@@ -317,11 +362,24 @@ static int tegra2_super_clk_set_parent(struct clk *c, struct clk *p) | |||
317 | return -EINVAL; | 362 | return -EINVAL; |
318 | } | 363 | } |
319 | 364 | ||
365 | /* | ||
366 | * Super clocks have "clock skippers" instead of dividers. Dividing using | ||
367 | * a clock skipper does not allow the voltage to be scaled down, so instead | ||
368 | * adjust the rate of the parent clock. This requires that the parent of a | ||
369 | * super clock have no other children, otherwise the rate will change | ||
370 | * underneath the other children. | ||
371 | */ | ||
372 | static int tegra2_super_clk_set_rate(struct clk *c, unsigned long rate) | ||
373 | { | ||
374 | return clk_set_rate(c->parent, rate); | ||
375 | } | ||
376 | |||
320 | static struct clk_ops tegra_super_ops = { | 377 | static struct clk_ops tegra_super_ops = { |
321 | .init = tegra2_super_clk_init, | 378 | .init = tegra2_super_clk_init, |
322 | .enable = tegra2_super_clk_enable, | 379 | .enable = tegra2_super_clk_enable, |
323 | .disable = tegra2_super_clk_disable, | 380 | .disable = tegra2_super_clk_disable, |
324 | .set_parent = tegra2_super_clk_set_parent, | 381 | .set_parent = tegra2_super_clk_set_parent, |
382 | .set_rate = tegra2_super_clk_set_rate, | ||
325 | }; | 383 | }; |
326 | 384 | ||
327 | /* virtual cpu clock functions */ | 385 | /* virtual cpu clock functions */ |
@@ -351,25 +409,36 @@ static void tegra2_cpu_clk_disable(struct clk *c) | |||
351 | static int tegra2_cpu_clk_set_rate(struct clk *c, unsigned long rate) | 409 | static int tegra2_cpu_clk_set_rate(struct clk *c, unsigned long rate) |
352 | { | 410 | { |
353 | int ret; | 411 | int ret; |
354 | ret = clk_set_parent_locked(c->parent, c->backup); | 412 | /* |
413 | * Take an extra reference to the main pll so it doesn't turn | ||
414 | * off when we move the cpu off of it | ||
415 | */ | ||
416 | clk_enable(c->u.cpu.main); | ||
417 | |||
418 | ret = clk_set_parent(c->parent, c->u.cpu.backup); | ||
355 | if (ret) { | 419 | if (ret) { |
356 | pr_err("Failed to switch cpu to clock %s\n", c->backup->name); | 420 | pr_err("Failed to switch cpu to clock %s\n", c->u.cpu.backup->name); |
357 | return ret; | 421 | goto out; |
358 | } | 422 | } |
359 | 423 | ||
360 | ret = clk_set_rate_locked(c->main, rate); | 424 | if (rate == clk_get_rate(c->u.cpu.backup)) |
425 | goto out; | ||
426 | |||
427 | ret = clk_set_rate(c->u.cpu.main, rate); | ||
361 | if (ret) { | 428 | if (ret) { |
362 | pr_err("Failed to change cpu pll to %lu\n", rate); | 429 | pr_err("Failed to change cpu pll to %lu\n", rate); |
363 | return ret; | 430 | goto out; |
364 | } | 431 | } |
365 | 432 | ||
366 | ret = clk_set_parent_locked(c->parent, c->main); | 433 | ret = clk_set_parent(c->parent, c->u.cpu.main); |
367 | if (ret) { | 434 | if (ret) { |
368 | pr_err("Failed to switch cpu to clock %s\n", c->main->name); | 435 | pr_err("Failed to switch cpu to clock %s\n", c->u.cpu.main->name); |
369 | return ret; | 436 | goto out; |
370 | } | 437 | } |
371 | 438 | ||
372 | return 0; | 439 | out: |
440 | clk_disable(c->u.cpu.main); | ||
441 | return ret; | ||
373 | } | 442 | } |
374 | 443 | ||
375 | static struct clk_ops tegra_cpu_ops = { | 444 | static struct clk_ops tegra_cpu_ops = { |
@@ -379,6 +448,20 @@ static struct clk_ops tegra_cpu_ops = { | |||
379 | .set_rate = tegra2_cpu_clk_set_rate, | 448 | .set_rate = tegra2_cpu_clk_set_rate, |
380 | }; | 449 | }; |
381 | 450 | ||
451 | /* virtual cop clock functions. Used to acquire the fake 'cop' clock to | ||
452 | * reset the COP block (i.e. AVP) */ | ||
453 | static void tegra2_cop_clk_reset(struct clk *c, bool assert) | ||
454 | { | ||
455 | unsigned long reg = assert ? RST_DEVICES_SET : RST_DEVICES_CLR; | ||
456 | |||
457 | pr_debug("%s %s\n", __func__, assert ? "assert" : "deassert"); | ||
458 | clk_writel(1 << 1, reg); | ||
459 | } | ||
460 | |||
461 | static struct clk_ops tegra_cop_ops = { | ||
462 | .reset = tegra2_cop_clk_reset, | ||
463 | }; | ||
464 | |||
382 | /* bus clock functions */ | 465 | /* bus clock functions */ |
383 | static void tegra2_bus_clk_init(struct clk *c) | 466 | static void tegra2_bus_clk_init(struct clk *c) |
384 | { | 467 | { |
@@ -390,24 +473,45 @@ static void tegra2_bus_clk_init(struct clk *c) | |||
390 | 473 | ||
391 | static int tegra2_bus_clk_enable(struct clk *c) | 474 | static int tegra2_bus_clk_enable(struct clk *c) |
392 | { | 475 | { |
393 | u32 val = clk_readl(c->reg); | 476 | u32 val; |
477 | unsigned long flags; | ||
478 | |||
479 | spin_lock_irqsave(&clock_register_lock, flags); | ||
480 | |||
481 | val = clk_readl(c->reg); | ||
394 | val &= ~(BUS_CLK_DISABLE << c->reg_shift); | 482 | val &= ~(BUS_CLK_DISABLE << c->reg_shift); |
395 | clk_writel(val, c->reg); | 483 | clk_writel(val, c->reg); |
484 | |||
485 | spin_unlock_irqrestore(&clock_register_lock, flags); | ||
486 | |||
396 | return 0; | 487 | return 0; |
397 | } | 488 | } |
398 | 489 | ||
399 | static void tegra2_bus_clk_disable(struct clk *c) | 490 | static void tegra2_bus_clk_disable(struct clk *c) |
400 | { | 491 | { |
401 | u32 val = clk_readl(c->reg); | 492 | u32 val; |
493 | unsigned long flags; | ||
494 | |||
495 | spin_lock_irqsave(&clock_register_lock, flags); | ||
496 | |||
497 | val = clk_readl(c->reg); | ||
402 | val |= BUS_CLK_DISABLE << c->reg_shift; | 498 | val |= BUS_CLK_DISABLE << c->reg_shift; |
403 | clk_writel(val, c->reg); | 499 | clk_writel(val, c->reg); |
500 | |||
501 | spin_unlock_irqrestore(&clock_register_lock, flags); | ||
404 | } | 502 | } |
405 | 503 | ||
406 | static int tegra2_bus_clk_set_rate(struct clk *c, unsigned long rate) | 504 | static int tegra2_bus_clk_set_rate(struct clk *c, unsigned long rate) |
407 | { | 505 | { |
408 | u32 val = clk_readl(c->reg); | 506 | u32 val; |
409 | unsigned long parent_rate = c->parent->rate; | 507 | unsigned long parent_rate = clk_get_rate(c->parent); |
508 | unsigned long flags; | ||
509 | int ret = -EINVAL; | ||
410 | int i; | 510 | int i; |
511 | |||
512 | spin_lock_irqsave(&clock_register_lock, flags); | ||
513 | |||
514 | val = clk_readl(c->reg); | ||
411 | for (i = 1; i <= 4; i++) { | 515 | for (i = 1; i <= 4; i++) { |
412 | if (rate == parent_rate / i) { | 516 | if (rate == parent_rate / i) { |
413 | val &= ~(BUS_CLK_DIV_MASK << c->reg_shift); | 517 | val &= ~(BUS_CLK_DIV_MASK << c->reg_shift); |
@@ -415,10 +519,14 @@ static int tegra2_bus_clk_set_rate(struct clk *c, unsigned long rate) | |||
415 | clk_writel(val, c->reg); | 519 | clk_writel(val, c->reg); |
416 | c->div = i; | 520 | c->div = i; |
417 | c->mul = 1; | 521 | c->mul = 1; |
418 | return 0; | 522 | ret = 0; |
523 | break; | ||
419 | } | 524 | } |
420 | } | 525 | } |
421 | return -EINVAL; | 526 | |
527 | spin_unlock_irqrestore(&clock_register_lock, flags); | ||
528 | |||
529 | return ret; | ||
422 | } | 530 | } |
423 | 531 | ||
424 | static struct clk_ops tegra_bus_ops = { | 532 | static struct clk_ops tegra_bus_ops = { |
@@ -428,24 +536,96 @@ static struct clk_ops tegra_bus_ops = { | |||
428 | .set_rate = tegra2_bus_clk_set_rate, | 536 | .set_rate = tegra2_bus_clk_set_rate, |
429 | }; | 537 | }; |
430 | 538 | ||
431 | /* PLL Functions */ | 539 | /* Blink output functions */ |
432 | static int tegra2_pll_clk_wait_for_lock(struct clk *c) | 540 | |
541 | static void tegra2_blink_clk_init(struct clk *c) | ||
433 | { | 542 | { |
434 | ktime_t before; | 543 | u32 val; |
435 | 544 | ||
436 | before = ktime_get(); | 545 | val = pmc_readl(PMC_CTRL); |
546 | c->state = (val & PMC_CTRL_BLINK_ENB) ? ON : OFF; | ||
547 | c->mul = 1; | ||
548 | val = pmc_readl(c->reg); | ||
549 | |||
550 | if (val & PMC_BLINK_TIMER_ENB) { | ||
551 | unsigned int on_off; | ||
552 | |||
553 | on_off = (val >> PMC_BLINK_TIMER_DATA_ON_SHIFT) & | ||
554 | PMC_BLINK_TIMER_DATA_ON_MASK; | ||
555 | val >>= PMC_BLINK_TIMER_DATA_OFF_SHIFT; | ||
556 | val &= PMC_BLINK_TIMER_DATA_OFF_MASK; | ||
557 | on_off += val; | ||
558 | /* each tick in the blink timer is 4 32KHz clocks */ | ||
559 | c->div = on_off * 4; | ||
560 | } else { | ||
561 | c->div = 1; | ||
562 | } | ||
563 | } | ||
437 | 564 | ||
438 | while (!(clk_readl(c->reg + PLL_BASE) & PLL_BASE_LOCK)) { | 565 | static int tegra2_blink_clk_enable(struct clk *c) |
439 | if (ktime_us_delta(ktime_get(), before) > 5000) { | 566 | { |
440 | pr_err("Timed out waiting for lock bit on pll %s", | 567 | u32 val; |
441 | c->name); | 568 | |
442 | return -1; | 569 | val = pmc_readl(PMC_DPD_PADS_ORIDE); |
443 | } | 570 | pmc_writel(val | PMC_DPD_PADS_ORIDE_BLINK_ENB, PMC_DPD_PADS_ORIDE); |
571 | |||
572 | val = pmc_readl(PMC_CTRL); | ||
573 | pmc_writel(val | PMC_CTRL_BLINK_ENB, PMC_CTRL); | ||
574 | |||
575 | return 0; | ||
576 | } | ||
577 | |||
578 | static void tegra2_blink_clk_disable(struct clk *c) | ||
579 | { | ||
580 | u32 val; | ||
581 | |||
582 | val = pmc_readl(PMC_CTRL); | ||
583 | pmc_writel(val & ~PMC_CTRL_BLINK_ENB, PMC_CTRL); | ||
584 | |||
585 | val = pmc_readl(PMC_DPD_PADS_ORIDE); | ||
586 | pmc_writel(val & ~PMC_DPD_PADS_ORIDE_BLINK_ENB, PMC_DPD_PADS_ORIDE); | ||
587 | } | ||
588 | |||
589 | static int tegra2_blink_clk_set_rate(struct clk *c, unsigned long rate) | ||
590 | { | ||
591 | unsigned long parent_rate = clk_get_rate(c->parent); | ||
592 | if (rate >= parent_rate) { | ||
593 | c->div = 1; | ||
594 | pmc_writel(0, c->reg); | ||
595 | } else { | ||
596 | unsigned int on_off; | ||
597 | u32 val; | ||
598 | |||
599 | on_off = DIV_ROUND_UP(parent_rate / 8, rate); | ||
600 | c->div = on_off * 8; | ||
601 | |||
602 | val = (on_off & PMC_BLINK_TIMER_DATA_ON_MASK) << | ||
603 | PMC_BLINK_TIMER_DATA_ON_SHIFT; | ||
604 | on_off &= PMC_BLINK_TIMER_DATA_OFF_MASK; | ||
605 | on_off <<= PMC_BLINK_TIMER_DATA_OFF_SHIFT; | ||
606 | val |= on_off; | ||
607 | val |= PMC_BLINK_TIMER_ENB; | ||
608 | pmc_writel(val, c->reg); | ||
444 | } | 609 | } |
445 | 610 | ||
446 | return 0; | 611 | return 0; |
447 | } | 612 | } |
448 | 613 | ||
614 | static struct clk_ops tegra_blink_clk_ops = { | ||
615 | .init = &tegra2_blink_clk_init, | ||
616 | .enable = &tegra2_blink_clk_enable, | ||
617 | .disable = &tegra2_blink_clk_disable, | ||
618 | .set_rate = &tegra2_blink_clk_set_rate, | ||
619 | }; | ||
620 | |||
621 | /* PLL Functions */ | ||
622 | static int tegra2_pll_clk_wait_for_lock(struct clk *c) | ||
623 | { | ||
624 | udelay(c->u.pll.lock_delay); | ||
625 | |||
626 | return 0; | ||
627 | } | ||
628 | |||
449 | static void tegra2_pll_clk_init(struct clk *c) | 629 | static void tegra2_pll_clk_init(struct clk *c) |
450 | { | 630 | { |
451 | u32 val = clk_readl(c->reg + PLL_BASE); | 631 | u32 val = clk_readl(c->reg + PLL_BASE); |
@@ -479,10 +659,6 @@ static int tegra2_pll_clk_enable(struct clk *c) | |||
479 | val |= PLL_BASE_ENABLE; | 659 | val |= PLL_BASE_ENABLE; |
480 | clk_writel(val, c->reg + PLL_BASE); | 660 | clk_writel(val, c->reg + PLL_BASE); |
481 | 661 | ||
482 | val = clk_readl(c->reg + PLL_MISC(c)); | ||
483 | val |= PLL_MISC_LOCK_ENABLE(c); | ||
484 | clk_writel(val, c->reg + PLL_MISC(c)); | ||
485 | |||
486 | tegra2_pll_clk_wait_for_lock(c); | 662 | tegra2_pll_clk_wait_for_lock(c); |
487 | 663 | ||
488 | return 0; | 664 | return 0; |
@@ -502,13 +678,12 @@ static int tegra2_pll_clk_set_rate(struct clk *c, unsigned long rate) | |||
502 | { | 678 | { |
503 | u32 val; | 679 | u32 val; |
504 | unsigned long input_rate; | 680 | unsigned long input_rate; |
505 | const struct clk_pll_table *sel; | 681 | const struct clk_pll_freq_table *sel; |
506 | 682 | ||
507 | pr_debug("%s: %s %lu\n", __func__, c->name, rate); | 683 | pr_debug("%s: %s %lu\n", __func__, c->name, rate); |
508 | BUG_ON(c->refcnt != 0); | ||
509 | 684 | ||
510 | input_rate = c->parent->rate; | 685 | input_rate = clk_get_rate(c->parent); |
511 | for (sel = c->pll_table; sel->input_rate != 0; sel++) { | 686 | for (sel = c->u.pll.freq_table; sel->input_rate != 0; sel++) { |
512 | if (sel->input_rate == input_rate && sel->output_rate == rate) { | 687 | if (sel->input_rate == input_rate && sel->output_rate == rate) { |
513 | c->mul = sel->n; | 688 | c->mul = sel->n; |
514 | c->div = sel->m * sel->p; | 689 | c->div = sel->m * sel->p; |
@@ -620,9 +795,11 @@ static int tegra2_pll_div_clk_enable(struct clk *c) | |||
620 | { | 795 | { |
621 | u32 val; | 796 | u32 val; |
622 | u32 new_val; | 797 | u32 new_val; |
798 | unsigned long flags; | ||
623 | 799 | ||
624 | pr_debug("%s: %s\n", __func__, c->name); | 800 | pr_debug("%s: %s\n", __func__, c->name); |
625 | if (c->flags & DIV_U71) { | 801 | if (c->flags & DIV_U71) { |
802 | spin_lock_irqsave(&clock_register_lock, flags); | ||
626 | val = clk_readl(c->reg); | 803 | val = clk_readl(c->reg); |
627 | new_val = val >> c->reg_shift; | 804 | new_val = val >> c->reg_shift; |
628 | new_val &= 0xFFFF; | 805 | new_val &= 0xFFFF; |
@@ -632,12 +809,15 @@ static int tegra2_pll_div_clk_enable(struct clk *c) | |||
632 | val &= ~(0xFFFF << c->reg_shift); | 809 | val &= ~(0xFFFF << c->reg_shift); |
633 | val |= new_val << c->reg_shift; | 810 | val |= new_val << c->reg_shift; |
634 | clk_writel(val, c->reg); | 811 | clk_writel(val, c->reg); |
812 | spin_unlock_irqrestore(&clock_register_lock, flags); | ||
635 | return 0; | 813 | return 0; |
636 | } else if (c->flags & DIV_2) { | 814 | } else if (c->flags & DIV_2) { |
637 | BUG_ON(!(c->flags & PLLD)); | 815 | BUG_ON(!(c->flags & PLLD)); |
816 | spin_lock_irqsave(&clock_register_lock, flags); | ||
638 | val = clk_readl(c->reg); | 817 | val = clk_readl(c->reg); |
639 | val &= ~PLLD_MISC_DIV_RST; | 818 | val &= ~PLLD_MISC_DIV_RST; |
640 | clk_writel(val, c->reg); | 819 | clk_writel(val, c->reg); |
820 | spin_unlock_irqrestore(&clock_register_lock, flags); | ||
641 | return 0; | 821 | return 0; |
642 | } | 822 | } |
643 | return -EINVAL; | 823 | return -EINVAL; |
@@ -647,9 +827,11 @@ static void tegra2_pll_div_clk_disable(struct clk *c) | |||
647 | { | 827 | { |
648 | u32 val; | 828 | u32 val; |
649 | u32 new_val; | 829 | u32 new_val; |
830 | unsigned long flags; | ||
650 | 831 | ||
651 | pr_debug("%s: %s\n", __func__, c->name); | 832 | pr_debug("%s: %s\n", __func__, c->name); |
652 | if (c->flags & DIV_U71) { | 833 | if (c->flags & DIV_U71) { |
834 | spin_lock_irqsave(&clock_register_lock, flags); | ||
653 | val = clk_readl(c->reg); | 835 | val = clk_readl(c->reg); |
654 | new_val = val >> c->reg_shift; | 836 | new_val = val >> c->reg_shift; |
655 | new_val &= 0xFFFF; | 837 | new_val &= 0xFFFF; |
@@ -659,11 +841,14 @@ static void tegra2_pll_div_clk_disable(struct clk *c) | |||
659 | val &= ~(0xFFFF << c->reg_shift); | 841 | val &= ~(0xFFFF << c->reg_shift); |
660 | val |= new_val << c->reg_shift; | 842 | val |= new_val << c->reg_shift; |
661 | clk_writel(val, c->reg); | 843 | clk_writel(val, c->reg); |
844 | spin_unlock_irqrestore(&clock_register_lock, flags); | ||
662 | } else if (c->flags & DIV_2) { | 845 | } else if (c->flags & DIV_2) { |
663 | BUG_ON(!(c->flags & PLLD)); | 846 | BUG_ON(!(c->flags & PLLD)); |
847 | spin_lock_irqsave(&clock_register_lock, flags); | ||
664 | val = clk_readl(c->reg); | 848 | val = clk_readl(c->reg); |
665 | val |= PLLD_MISC_DIV_RST; | 849 | val |= PLLD_MISC_DIV_RST; |
666 | clk_writel(val, c->reg); | 850 | clk_writel(val, c->reg); |
851 | spin_unlock_irqrestore(&clock_register_lock, flags); | ||
667 | } | 852 | } |
668 | } | 853 | } |
669 | 854 | ||
@@ -672,10 +857,14 @@ static int tegra2_pll_div_clk_set_rate(struct clk *c, unsigned long rate) | |||
672 | u32 val; | 857 | u32 val; |
673 | u32 new_val; | 858 | u32 new_val; |
674 | int divider_u71; | 859 | int divider_u71; |
860 | unsigned long parent_rate = clk_get_rate(c->parent); | ||
861 | unsigned long flags; | ||
862 | |||
675 | pr_debug("%s: %s %lu\n", __func__, c->name, rate); | 863 | pr_debug("%s: %s %lu\n", __func__, c->name, rate); |
676 | if (c->flags & DIV_U71) { | 864 | if (c->flags & DIV_U71) { |
677 | divider_u71 = clk_div71_get_divider(c->parent->rate, rate); | 865 | divider_u71 = clk_div71_get_divider(parent_rate, rate); |
678 | if (divider_u71 >= 0) { | 866 | if (divider_u71 >= 0) { |
867 | spin_lock_irqsave(&clock_register_lock, flags); | ||
679 | val = clk_readl(c->reg); | 868 | val = clk_readl(c->reg); |
680 | new_val = val >> c->reg_shift; | 869 | new_val = val >> c->reg_shift; |
681 | new_val &= 0xFFFF; | 870 | new_val &= 0xFFFF; |
@@ -689,10 +878,11 @@ static int tegra2_pll_div_clk_set_rate(struct clk *c, unsigned long rate) | |||
689 | clk_writel(val, c->reg); | 878 | clk_writel(val, c->reg); |
690 | c->div = divider_u71 + 2; | 879 | c->div = divider_u71 + 2; |
691 | c->mul = 2; | 880 | c->mul = 2; |
881 | spin_unlock_irqrestore(&clock_register_lock, flags); | ||
692 | return 0; | 882 | return 0; |
693 | } | 883 | } |
694 | } else if (c->flags & DIV_2) { | 884 | } else if (c->flags & DIV_2) { |
695 | if (c->parent->rate == rate * 2) | 885 | if (parent_rate == rate * 2) |
696 | return 0; | 886 | return 0; |
697 | } | 887 | } |
698 | return -EINVAL; | 888 | return -EINVAL; |
@@ -701,15 +891,16 @@ static int tegra2_pll_div_clk_set_rate(struct clk *c, unsigned long rate) | |||
701 | static long tegra2_pll_div_clk_round_rate(struct clk *c, unsigned long rate) | 891 | static long tegra2_pll_div_clk_round_rate(struct clk *c, unsigned long rate) |
702 | { | 892 | { |
703 | int divider; | 893 | int divider; |
894 | unsigned long parent_rate = clk_get_rate(c->parent); | ||
704 | pr_debug("%s: %s %lu\n", __func__, c->name, rate); | 895 | pr_debug("%s: %s %lu\n", __func__, c->name, rate); |
705 | 896 | ||
706 | if (c->flags & DIV_U71) { | 897 | if (c->flags & DIV_U71) { |
707 | divider = clk_div71_get_divider(c->parent->rate, rate); | 898 | divider = clk_div71_get_divider(parent_rate, rate); |
708 | if (divider < 0) | 899 | if (divider < 0) |
709 | return divider; | 900 | return divider; |
710 | return c->parent->rate * 2 / (divider + 2); | 901 | return DIV_ROUND_UP(parent_rate * 2, divider + 2); |
711 | } else if (c->flags & DIV_2) { | 902 | } else if (c->flags & DIV_2) { |
712 | return c->parent->rate / 2; | 903 | return DIV_ROUND_UP(parent_rate, 2); |
713 | } | 904 | } |
714 | return -EINVAL; | 905 | return -EINVAL; |
715 | } | 906 | } |
@@ -755,9 +946,14 @@ static void tegra2_periph_clk_init(struct clk *c) | |||
755 | } | 946 | } |
756 | 947 | ||
757 | c->state = ON; | 948 | c->state = ON; |
949 | |||
950 | if (!c->u.periph.clk_num) | ||
951 | return; | ||
952 | |||
758 | if (!(clk_readl(CLK_OUT_ENB + PERIPH_CLK_TO_ENB_REG(c)) & | 953 | if (!(clk_readl(CLK_OUT_ENB + PERIPH_CLK_TO_ENB_REG(c)) & |
759 | PERIPH_CLK_TO_ENB_BIT(c))) | 954 | PERIPH_CLK_TO_ENB_BIT(c))) |
760 | c->state = OFF; | 955 | c->state = OFF; |
956 | |||
761 | if (!(c->flags & PERIPH_NO_RESET)) | 957 | if (!(c->flags & PERIPH_NO_RESET)) |
762 | if (clk_readl(RST_DEVICES + PERIPH_CLK_TO_ENB_REG(c)) & | 958 | if (clk_readl(RST_DEVICES + PERIPH_CLK_TO_ENB_REG(c)) & |
763 | PERIPH_CLK_TO_ENB_BIT(c)) | 959 | PERIPH_CLK_TO_ENB_BIT(c)) |
@@ -767,8 +963,20 @@ static void tegra2_periph_clk_init(struct clk *c) | |||
767 | static int tegra2_periph_clk_enable(struct clk *c) | 963 | static int tegra2_periph_clk_enable(struct clk *c) |
768 | { | 964 | { |
769 | u32 val; | 965 | u32 val; |
966 | unsigned long flags; | ||
967 | int refcount; | ||
770 | pr_debug("%s on clock %s\n", __func__, c->name); | 968 | pr_debug("%s on clock %s\n", __func__, c->name); |
771 | 969 | ||
970 | if (!c->u.periph.clk_num) | ||
971 | return 0; | ||
972 | |||
973 | spin_lock_irqsave(&clock_register_lock, flags); | ||
974 | |||
975 | refcount = tegra_periph_clk_enable_refcount[c->u.periph.clk_num]++; | ||
976 | |||
977 | if (refcount > 1) | ||
978 | goto out; | ||
979 | |||
772 | clk_writel(PERIPH_CLK_TO_ENB_BIT(c), | 980 | clk_writel(PERIPH_CLK_TO_ENB_BIT(c), |
773 | CLK_OUT_ENB_SET + PERIPH_CLK_TO_ENB_SET_REG(c)); | 981 | CLK_OUT_ENB_SET + PERIPH_CLK_TO_ENB_SET_REG(c)); |
774 | if (!(c->flags & PERIPH_NO_RESET) && !(c->flags & PERIPH_MANUAL_RESET)) | 982 | if (!(c->flags & PERIPH_NO_RESET) && !(c->flags & PERIPH_MANUAL_RESET)) |
@@ -781,34 +989,48 @@ static int tegra2_periph_clk_enable(struct clk *c) | |||
781 | val |= 0x3 << 24; | 989 | val |= 0x3 << 24; |
782 | clk_writel(val, c->reg); | 990 | clk_writel(val, c->reg); |
783 | } | 991 | } |
992 | |||
993 | out: | ||
994 | spin_unlock_irqrestore(&clock_register_lock, flags); | ||
995 | |||
784 | return 0; | 996 | return 0; |
785 | } | 997 | } |
786 | 998 | ||
787 | static void tegra2_periph_clk_disable(struct clk *c) | 999 | static void tegra2_periph_clk_disable(struct clk *c) |
788 | { | 1000 | { |
1001 | unsigned long flags; | ||
1002 | |||
789 | pr_debug("%s on clock %s\n", __func__, c->name); | 1003 | pr_debug("%s on clock %s\n", __func__, c->name); |
790 | 1004 | ||
791 | clk_writel(PERIPH_CLK_TO_ENB_BIT(c), | 1005 | if (!c->u.periph.clk_num) |
792 | CLK_OUT_ENB_CLR + PERIPH_CLK_TO_ENB_SET_REG(c)); | 1006 | return; |
793 | } | ||
794 | 1007 | ||
795 | void tegra2_periph_reset_deassert(struct clk *c) | 1008 | spin_lock_irqsave(&clock_register_lock, flags); |
796 | { | 1009 | |
797 | pr_debug("%s on clock %s\n", __func__, c->name); | 1010 | if (c->refcnt) |
798 | if (!(c->flags & PERIPH_NO_RESET)) | 1011 | tegra_periph_clk_enable_refcount[c->u.periph.clk_num]--; |
1012 | |||
1013 | if (tegra_periph_clk_enable_refcount[c->u.periph.clk_num] == 0) | ||
799 | clk_writel(PERIPH_CLK_TO_ENB_BIT(c), | 1014 | clk_writel(PERIPH_CLK_TO_ENB_BIT(c), |
800 | RST_DEVICES_CLR + PERIPH_CLK_TO_ENB_SET_REG(c)); | 1015 | CLK_OUT_ENB_CLR + PERIPH_CLK_TO_ENB_SET_REG(c)); |
1016 | |||
1017 | spin_unlock_irqrestore(&clock_register_lock, flags); | ||
801 | } | 1018 | } |
802 | 1019 | ||
803 | void tegra2_periph_reset_assert(struct clk *c) | 1020 | static void tegra2_periph_clk_reset(struct clk *c, bool assert) |
804 | { | 1021 | { |
805 | pr_debug("%s on clock %s\n", __func__, c->name); | 1022 | unsigned long base = assert ? RST_DEVICES_SET : RST_DEVICES_CLR; |
1023 | |||
1024 | pr_debug("%s %s on clock %s\n", __func__, | ||
1025 | assert ? "assert" : "deassert", c->name); | ||
1026 | |||
1027 | BUG_ON(!c->u.periph.clk_num); | ||
1028 | |||
806 | if (!(c->flags & PERIPH_NO_RESET)) | 1029 | if (!(c->flags & PERIPH_NO_RESET)) |
807 | clk_writel(PERIPH_CLK_TO_ENB_BIT(c), | 1030 | clk_writel(PERIPH_CLK_TO_ENB_BIT(c), |
808 | RST_DEVICES_SET + PERIPH_CLK_TO_ENB_SET_REG(c)); | 1031 | base + PERIPH_CLK_TO_ENB_SET_REG(c)); |
809 | } | 1032 | } |
810 | 1033 | ||
811 | |||
812 | static int tegra2_periph_clk_set_parent(struct clk *c, struct clk *p) | 1034 | static int tegra2_periph_clk_set_parent(struct clk *c, struct clk *p) |
813 | { | 1035 | { |
814 | u32 val; | 1036 | u32 val; |
@@ -821,12 +1043,12 @@ static int tegra2_periph_clk_set_parent(struct clk *c, struct clk *p) | |||
821 | val |= (sel->value) << PERIPH_CLK_SOURCE_SHIFT; | 1043 | val |= (sel->value) << PERIPH_CLK_SOURCE_SHIFT; |
822 | 1044 | ||
823 | if (c->refcnt) | 1045 | if (c->refcnt) |
824 | clk_enable_locked(p); | 1046 | clk_enable(p); |
825 | 1047 | ||
826 | clk_writel(val, c->reg); | 1048 | clk_writel(val, c->reg); |
827 | 1049 | ||
828 | if (c->refcnt && c->parent) | 1050 | if (c->refcnt && c->parent) |
829 | clk_disable_locked(c->parent); | 1051 | clk_disable(c->parent); |
830 | 1052 | ||
831 | clk_reparent(c, p); | 1053 | clk_reparent(c, p); |
832 | return 0; | 1054 | return 0; |
@@ -840,9 +1062,10 @@ static int tegra2_periph_clk_set_rate(struct clk *c, unsigned long rate) | |||
840 | { | 1062 | { |
841 | u32 val; | 1063 | u32 val; |
842 | int divider; | 1064 | int divider; |
843 | pr_debug("%s: %lu\n", __func__, rate); | 1065 | unsigned long parent_rate = clk_get_rate(c->parent); |
1066 | |||
844 | if (c->flags & DIV_U71) { | 1067 | if (c->flags & DIV_U71) { |
845 | divider = clk_div71_get_divider(c->parent->rate, rate); | 1068 | divider = clk_div71_get_divider(parent_rate, rate); |
846 | if (divider >= 0) { | 1069 | if (divider >= 0) { |
847 | val = clk_readl(c->reg); | 1070 | val = clk_readl(c->reg); |
848 | val &= ~PERIPH_CLK_SOURCE_DIVU71_MASK; | 1071 | val &= ~PERIPH_CLK_SOURCE_DIVU71_MASK; |
@@ -853,7 +1076,7 @@ static int tegra2_periph_clk_set_rate(struct clk *c, unsigned long rate) | |||
853 | return 0; | 1076 | return 0; |
854 | } | 1077 | } |
855 | } else if (c->flags & DIV_U16) { | 1078 | } else if (c->flags & DIV_U16) { |
856 | divider = clk_div16_get_divider(c->parent->rate, rate); | 1079 | divider = clk_div16_get_divider(parent_rate, rate); |
857 | if (divider >= 0) { | 1080 | if (divider >= 0) { |
858 | val = clk_readl(c->reg); | 1081 | val = clk_readl(c->reg); |
859 | val &= ~PERIPH_CLK_SOURCE_DIVU16_MASK; | 1082 | val &= ~PERIPH_CLK_SOURCE_DIVU16_MASK; |
@@ -863,7 +1086,7 @@ static int tegra2_periph_clk_set_rate(struct clk *c, unsigned long rate) | |||
863 | c->mul = 1; | 1086 | c->mul = 1; |
864 | return 0; | 1087 | return 0; |
865 | } | 1088 | } |
866 | } else if (c->parent->rate <= rate) { | 1089 | } else if (parent_rate <= rate) { |
867 | c->div = 1; | 1090 | c->div = 1; |
868 | c->mul = 1; | 1091 | c->mul = 1; |
869 | return 0; | 1092 | return 0; |
@@ -875,19 +1098,20 @@ static long tegra2_periph_clk_round_rate(struct clk *c, | |||
875 | unsigned long rate) | 1098 | unsigned long rate) |
876 | { | 1099 | { |
877 | int divider; | 1100 | int divider; |
1101 | unsigned long parent_rate = clk_get_rate(c->parent); | ||
878 | pr_debug("%s: %s %lu\n", __func__, c->name, rate); | 1102 | pr_debug("%s: %s %lu\n", __func__, c->name, rate); |
879 | 1103 | ||
880 | if (c->flags & DIV_U71) { | 1104 | if (c->flags & DIV_U71) { |
881 | divider = clk_div71_get_divider(c->parent->rate, rate); | 1105 | divider = clk_div71_get_divider(parent_rate, rate); |
882 | if (divider < 0) | 1106 | if (divider < 0) |
883 | return divider; | 1107 | return divider; |
884 | 1108 | ||
885 | return c->parent->rate * 2 / (divider + 2); | 1109 | return DIV_ROUND_UP(parent_rate * 2, divider + 2); |
886 | } else if (c->flags & DIV_U16) { | 1110 | } else if (c->flags & DIV_U16) { |
887 | divider = clk_div16_get_divider(c->parent->rate, rate); | 1111 | divider = clk_div16_get_divider(parent_rate, rate); |
888 | if (divider < 0) | 1112 | if (divider < 0) |
889 | return divider; | 1113 | return divider; |
890 | return c->parent->rate / (divider + 1); | 1114 | return DIV_ROUND_UP(parent_rate, divider + 1); |
891 | } | 1115 | } |
892 | return -EINVAL; | 1116 | return -EINVAL; |
893 | } | 1117 | } |
@@ -899,6 +1123,71 @@ static struct clk_ops tegra_periph_clk_ops = { | |||
899 | .set_parent = &tegra2_periph_clk_set_parent, | 1123 | .set_parent = &tegra2_periph_clk_set_parent, |
900 | .set_rate = &tegra2_periph_clk_set_rate, | 1124 | .set_rate = &tegra2_periph_clk_set_rate, |
901 | .round_rate = &tegra2_periph_clk_round_rate, | 1125 | .round_rate = &tegra2_periph_clk_round_rate, |
1126 | .reset = &tegra2_periph_clk_reset, | ||
1127 | }; | ||
1128 | |||
1129 | /* The SDMMC controllers have extra bits in the clock source register that | ||
1130 | * adjust the delay between the clock and data to compenstate for delays | ||
1131 | * on the PCB. */ | ||
1132 | void tegra2_sdmmc_tap_delay(struct clk *c, int delay) | ||
1133 | { | ||
1134 | u32 reg; | ||
1135 | |||
1136 | delay = clamp(delay, 0, 15); | ||
1137 | reg = clk_readl(c->reg); | ||
1138 | reg &= ~SDMMC_CLK_INT_FB_DLY_MASK; | ||
1139 | reg |= SDMMC_CLK_INT_FB_SEL; | ||
1140 | reg |= delay << SDMMC_CLK_INT_FB_DLY_SHIFT; | ||
1141 | clk_writel(reg, c->reg); | ||
1142 | } | ||
1143 | |||
1144 | /* External memory controller clock ops */ | ||
1145 | static void tegra2_emc_clk_init(struct clk *c) | ||
1146 | { | ||
1147 | tegra2_periph_clk_init(c); | ||
1148 | c->max_rate = clk_get_rate_locked(c); | ||
1149 | } | ||
1150 | |||
1151 | static long tegra2_emc_clk_round_rate(struct clk *c, unsigned long rate) | ||
1152 | { | ||
1153 | long new_rate = rate; | ||
1154 | |||
1155 | new_rate = tegra_emc_round_rate(new_rate); | ||
1156 | if (new_rate < 0) | ||
1157 | return c->max_rate; | ||
1158 | |||
1159 | BUG_ON(new_rate != tegra2_periph_clk_round_rate(c, new_rate)); | ||
1160 | |||
1161 | return new_rate; | ||
1162 | } | ||
1163 | |||
1164 | static int tegra2_emc_clk_set_rate(struct clk *c, unsigned long rate) | ||
1165 | { | ||
1166 | int ret; | ||
1167 | /* | ||
1168 | * The Tegra2 memory controller has an interlock with the clock | ||
1169 | * block that allows memory shadowed registers to be updated, | ||
1170 | * and then transfer them to the main registers at the same | ||
1171 | * time as the clock update without glitches. | ||
1172 | */ | ||
1173 | ret = tegra_emc_set_rate(rate); | ||
1174 | if (ret < 0) | ||
1175 | return ret; | ||
1176 | |||
1177 | ret = tegra2_periph_clk_set_rate(c, rate); | ||
1178 | udelay(1); | ||
1179 | |||
1180 | return ret; | ||
1181 | } | ||
1182 | |||
1183 | static struct clk_ops tegra_emc_clk_ops = { | ||
1184 | .init = &tegra2_emc_clk_init, | ||
1185 | .enable = &tegra2_periph_clk_enable, | ||
1186 | .disable = &tegra2_periph_clk_disable, | ||
1187 | .set_parent = &tegra2_periph_clk_set_parent, | ||
1188 | .set_rate = &tegra2_emc_clk_set_rate, | ||
1189 | .round_rate = &tegra2_emc_clk_round_rate, | ||
1190 | .reset = &tegra2_periph_clk_reset, | ||
902 | }; | 1191 | }; |
903 | 1192 | ||
904 | /* Clock doubler ops */ | 1193 | /* Clock doubler ops */ |
@@ -907,6 +1196,10 @@ static void tegra2_clk_double_init(struct clk *c) | |||
907 | c->mul = 2; | 1196 | c->mul = 2; |
908 | c->div = 1; | 1197 | c->div = 1; |
909 | c->state = ON; | 1198 | c->state = ON; |
1199 | |||
1200 | if (!c->u.periph.clk_num) | ||
1201 | return; | ||
1202 | |||
910 | if (!(clk_readl(CLK_OUT_ENB + PERIPH_CLK_TO_ENB_REG(c)) & | 1203 | if (!(clk_readl(CLK_OUT_ENB + PERIPH_CLK_TO_ENB_REG(c)) & |
911 | PERIPH_CLK_TO_ENB_BIT(c))) | 1204 | PERIPH_CLK_TO_ENB_BIT(c))) |
912 | c->state = OFF; | 1205 | c->state = OFF; |
@@ -914,7 +1207,7 @@ static void tegra2_clk_double_init(struct clk *c) | |||
914 | 1207 | ||
915 | static int tegra2_clk_double_set_rate(struct clk *c, unsigned long rate) | 1208 | static int tegra2_clk_double_set_rate(struct clk *c, unsigned long rate) |
916 | { | 1209 | { |
917 | if (rate != 2 * c->parent->rate) | 1210 | if (rate != 2 * clk_get_rate(c->parent)) |
918 | return -EINVAL; | 1211 | return -EINVAL; |
919 | c->mul = 2; | 1212 | c->mul = 2; |
920 | c->div = 1; | 1213 | c->div = 1; |
@@ -928,6 +1221,7 @@ static struct clk_ops tegra_clk_double_ops = { | |||
928 | .set_rate = &tegra2_clk_double_set_rate, | 1221 | .set_rate = &tegra2_clk_double_set_rate, |
929 | }; | 1222 | }; |
930 | 1223 | ||
1224 | /* Audio sync clock ops */ | ||
931 | static void tegra2_audio_sync_clk_init(struct clk *c) | 1225 | static void tegra2_audio_sync_clk_init(struct clk *c) |
932 | { | 1226 | { |
933 | int source; | 1227 | int source; |
@@ -964,12 +1258,12 @@ static int tegra2_audio_sync_clk_set_parent(struct clk *c, struct clk *p) | |||
964 | val |= sel->value; | 1258 | val |= sel->value; |
965 | 1259 | ||
966 | if (c->refcnt) | 1260 | if (c->refcnt) |
967 | clk_enable_locked(p); | 1261 | clk_enable(p); |
968 | 1262 | ||
969 | clk_writel(val, c->reg); | 1263 | clk_writel(val, c->reg); |
970 | 1264 | ||
971 | if (c->refcnt && c->parent) | 1265 | if (c->refcnt && c->parent) |
972 | clk_disable_locked(c->parent); | 1266 | clk_disable(c->parent); |
973 | 1267 | ||
974 | clk_reparent(c, p); | 1268 | clk_reparent(c, p); |
975 | return 0; | 1269 | return 0; |
@@ -979,33 +1273,153 @@ static int tegra2_audio_sync_clk_set_parent(struct clk *c, struct clk *p) | |||
979 | return -EINVAL; | 1273 | return -EINVAL; |
980 | } | 1274 | } |
981 | 1275 | ||
982 | static int tegra2_audio_sync_clk_set_rate(struct clk *c, unsigned long rate) | ||
983 | { | ||
984 | unsigned long parent_rate; | ||
985 | if (!c->parent) { | ||
986 | pr_err("%s: clock has no parent\n", __func__); | ||
987 | return -EINVAL; | ||
988 | } | ||
989 | parent_rate = c->parent->rate; | ||
990 | if (rate != parent_rate) { | ||
991 | pr_err("%s: %s/%ld differs from parent %s/%ld\n", | ||
992 | __func__, | ||
993 | c->name, rate, | ||
994 | c->parent->name, parent_rate); | ||
995 | return -EINVAL; | ||
996 | } | ||
997 | c->rate = parent_rate; | ||
998 | return 0; | ||
999 | } | ||
1000 | |||
1001 | static struct clk_ops tegra_audio_sync_clk_ops = { | 1276 | static struct clk_ops tegra_audio_sync_clk_ops = { |
1002 | .init = tegra2_audio_sync_clk_init, | 1277 | .init = tegra2_audio_sync_clk_init, |
1003 | .enable = tegra2_audio_sync_clk_enable, | 1278 | .enable = tegra2_audio_sync_clk_enable, |
1004 | .disable = tegra2_audio_sync_clk_disable, | 1279 | .disable = tegra2_audio_sync_clk_disable, |
1005 | .set_rate = tegra2_audio_sync_clk_set_rate, | ||
1006 | .set_parent = tegra2_audio_sync_clk_set_parent, | 1280 | .set_parent = tegra2_audio_sync_clk_set_parent, |
1007 | }; | 1281 | }; |
1008 | 1282 | ||
1283 | /* cdev1 and cdev2 (dap_mclk1 and dap_mclk2) ops */ | ||
1284 | |||
1285 | static void tegra2_cdev_clk_init(struct clk *c) | ||
1286 | { | ||
1287 | /* We could un-tristate the cdev1 or cdev2 pingroup here; this is | ||
1288 | * currently done in the pinmux code. */ | ||
1289 | c->state = ON; | ||
1290 | |||
1291 | BUG_ON(!c->u.periph.clk_num); | ||
1292 | |||
1293 | if (!(clk_readl(CLK_OUT_ENB + PERIPH_CLK_TO_ENB_REG(c)) & | ||
1294 | PERIPH_CLK_TO_ENB_BIT(c))) | ||
1295 | c->state = OFF; | ||
1296 | } | ||
1297 | |||
1298 | static int tegra2_cdev_clk_enable(struct clk *c) | ||
1299 | { | ||
1300 | BUG_ON(!c->u.periph.clk_num); | ||
1301 | |||
1302 | clk_writel(PERIPH_CLK_TO_ENB_BIT(c), | ||
1303 | CLK_OUT_ENB_SET + PERIPH_CLK_TO_ENB_SET_REG(c)); | ||
1304 | return 0; | ||
1305 | } | ||
1306 | |||
1307 | static void tegra2_cdev_clk_disable(struct clk *c) | ||
1308 | { | ||
1309 | BUG_ON(!c->u.periph.clk_num); | ||
1310 | |||
1311 | clk_writel(PERIPH_CLK_TO_ENB_BIT(c), | ||
1312 | CLK_OUT_ENB_CLR + PERIPH_CLK_TO_ENB_SET_REG(c)); | ||
1313 | } | ||
1314 | |||
1315 | static struct clk_ops tegra_cdev_clk_ops = { | ||
1316 | .init = &tegra2_cdev_clk_init, | ||
1317 | .enable = &tegra2_cdev_clk_enable, | ||
1318 | .disable = &tegra2_cdev_clk_disable, | ||
1319 | }; | ||
1320 | |||
1321 | /* shared bus ops */ | ||
1322 | /* | ||
1323 | * Some clocks may have multiple downstream users that need to request a | ||
1324 | * higher clock rate. Shared bus clocks provide a unique shared_bus_user | ||
1325 | * clock to each user. The frequency of the bus is set to the highest | ||
1326 | * enabled shared_bus_user clock, with a minimum value set by the | ||
1327 | * shared bus. | ||
1328 | */ | ||
1329 | static int tegra_clk_shared_bus_update(struct clk *bus) | ||
1330 | { | ||
1331 | struct clk *c; | ||
1332 | unsigned long rate = bus->min_rate; | ||
1333 | |||
1334 | list_for_each_entry(c, &bus->shared_bus_list, u.shared_bus_user.node) | ||
1335 | if (c->u.shared_bus_user.enabled) | ||
1336 | rate = max(c->u.shared_bus_user.rate, rate); | ||
1337 | |||
1338 | if (rate == clk_get_rate_locked(bus)) | ||
1339 | return 0; | ||
1340 | |||
1341 | return clk_set_rate_locked(bus, rate); | ||
1342 | }; | ||
1343 | |||
1344 | static void tegra_clk_shared_bus_init(struct clk *c) | ||
1345 | { | ||
1346 | unsigned long flags; | ||
1347 | |||
1348 | c->max_rate = c->parent->max_rate; | ||
1349 | c->u.shared_bus_user.rate = c->parent->max_rate; | ||
1350 | c->state = OFF; | ||
1351 | c->set = true; | ||
1352 | |||
1353 | spin_lock_irqsave(&c->parent->spinlock, flags); | ||
1354 | |||
1355 | list_add_tail(&c->u.shared_bus_user.node, | ||
1356 | &c->parent->shared_bus_list); | ||
1357 | |||
1358 | spin_unlock_irqrestore(&c->parent->spinlock, flags); | ||
1359 | } | ||
1360 | |||
1361 | static int tegra_clk_shared_bus_set_rate(struct clk *c, unsigned long rate) | ||
1362 | { | ||
1363 | unsigned long flags; | ||
1364 | int ret; | ||
1365 | |||
1366 | rate = clk_round_rate(c->parent, rate); | ||
1367 | if (rate < 0) | ||
1368 | return rate; | ||
1369 | |||
1370 | spin_lock_irqsave(&c->parent->spinlock, flags); | ||
1371 | |||
1372 | c->u.shared_bus_user.rate = rate; | ||
1373 | ret = tegra_clk_shared_bus_update(c->parent); | ||
1374 | |||
1375 | spin_unlock_irqrestore(&c->parent->spinlock, flags); | ||
1376 | |||
1377 | return ret; | ||
1378 | } | ||
1379 | |||
1380 | static long tegra_clk_shared_bus_round_rate(struct clk *c, unsigned long rate) | ||
1381 | { | ||
1382 | return clk_round_rate(c->parent, rate); | ||
1383 | } | ||
1384 | |||
1385 | static int tegra_clk_shared_bus_enable(struct clk *c) | ||
1386 | { | ||
1387 | unsigned long flags; | ||
1388 | int ret; | ||
1389 | |||
1390 | spin_lock_irqsave(&c->parent->spinlock, flags); | ||
1391 | |||
1392 | c->u.shared_bus_user.enabled = true; | ||
1393 | ret = tegra_clk_shared_bus_update(c->parent); | ||
1394 | |||
1395 | spin_unlock_irqrestore(&c->parent->spinlock, flags); | ||
1396 | |||
1397 | return ret; | ||
1398 | } | ||
1399 | |||
1400 | static void tegra_clk_shared_bus_disable(struct clk *c) | ||
1401 | { | ||
1402 | unsigned long flags; | ||
1403 | int ret; | ||
1404 | |||
1405 | spin_lock_irqsave(&c->parent->spinlock, flags); | ||
1406 | |||
1407 | c->u.shared_bus_user.enabled = false; | ||
1408 | ret = tegra_clk_shared_bus_update(c->parent); | ||
1409 | WARN_ON_ONCE(ret); | ||
1410 | |||
1411 | spin_unlock_irqrestore(&c->parent->spinlock, flags); | ||
1412 | } | ||
1413 | |||
1414 | static struct clk_ops tegra_clk_shared_bus_ops = { | ||
1415 | .init = tegra_clk_shared_bus_init, | ||
1416 | .enable = tegra_clk_shared_bus_enable, | ||
1417 | .disable = tegra_clk_shared_bus_disable, | ||
1418 | .set_rate = tegra_clk_shared_bus_set_rate, | ||
1419 | .round_rate = tegra_clk_shared_bus_round_rate, | ||
1420 | }; | ||
1421 | |||
1422 | |||
1009 | /* Clock definitions */ | 1423 | /* Clock definitions */ |
1010 | static struct clk tegra_clk_32k = { | 1424 | static struct clk tegra_clk_32k = { |
1011 | .name = "clk_32k", | 1425 | .name = "clk_32k", |
@@ -1014,7 +1428,7 @@ static struct clk tegra_clk_32k = { | |||
1014 | .max_rate = 32768, | 1428 | .max_rate = 32768, |
1015 | }; | 1429 | }; |
1016 | 1430 | ||
1017 | static struct clk_pll_table tegra_pll_s_table[] = { | 1431 | static struct clk_pll_freq_table tegra_pll_s_freq_table[] = { |
1018 | {32768, 12000000, 366, 1, 1, 0}, | 1432 | {32768, 12000000, 366, 1, 1, 0}, |
1019 | {32768, 13000000, 397, 1, 1, 0}, | 1433 | {32768, 13000000, 397, 1, 1, 0}, |
1020 | {32768, 19200000, 586, 1, 1, 0}, | 1434 | {32768, 19200000, 586, 1, 1, 0}, |
@@ -1026,16 +1440,19 @@ static struct clk tegra_pll_s = { | |||
1026 | .name = "pll_s", | 1440 | .name = "pll_s", |
1027 | .flags = PLL_ALT_MISC_REG, | 1441 | .flags = PLL_ALT_MISC_REG, |
1028 | .ops = &tegra_pll_ops, | 1442 | .ops = &tegra_pll_ops, |
1029 | .reg = 0xf0, | ||
1030 | .input_min = 32768, | ||
1031 | .input_max = 32768, | ||
1032 | .parent = &tegra_clk_32k, | 1443 | .parent = &tegra_clk_32k, |
1033 | .cf_min = 0, /* FIXME */ | ||
1034 | .cf_max = 0, /* FIXME */ | ||
1035 | .vco_min = 12000000, | ||
1036 | .vco_max = 26000000, | ||
1037 | .pll_table = tegra_pll_s_table, | ||
1038 | .max_rate = 26000000, | 1444 | .max_rate = 26000000, |
1445 | .reg = 0xf0, | ||
1446 | .u.pll = { | ||
1447 | .input_min = 32768, | ||
1448 | .input_max = 32768, | ||
1449 | .cf_min = 0, /* FIXME */ | ||
1450 | .cf_max = 0, /* FIXME */ | ||
1451 | .vco_min = 12000000, | ||
1452 | .vco_max = 26000000, | ||
1453 | .freq_table = tegra_pll_s_freq_table, | ||
1454 | .lock_delay = 300, | ||
1455 | }, | ||
1039 | }; | 1456 | }; |
1040 | 1457 | ||
1041 | static struct clk_mux_sel tegra_clk_m_sel[] = { | 1458 | static struct clk_mux_sel tegra_clk_m_sel[] = { |
@@ -1043,18 +1460,18 @@ static struct clk_mux_sel tegra_clk_m_sel[] = { | |||
1043 | { .input = &tegra_pll_s, .value = 1}, | 1460 | { .input = &tegra_pll_s, .value = 1}, |
1044 | { 0, 0}, | 1461 | { 0, 0}, |
1045 | }; | 1462 | }; |
1463 | |||
1046 | static struct clk tegra_clk_m = { | 1464 | static struct clk tegra_clk_m = { |
1047 | .name = "clk_m", | 1465 | .name = "clk_m", |
1048 | .flags = ENABLE_ON_INIT, | 1466 | .flags = ENABLE_ON_INIT, |
1049 | .ops = &tegra_clk_m_ops, | 1467 | .ops = &tegra_clk_m_ops, |
1050 | .inputs = tegra_clk_m_sel, | 1468 | .inputs = tegra_clk_m_sel, |
1051 | .reg = 0x1fc, | 1469 | .reg = 0x1fc, |
1052 | .reg_mask = (1<<28), | ||
1053 | .reg_shift = 28, | 1470 | .reg_shift = 28, |
1054 | .max_rate = 26000000, | 1471 | .max_rate = 26000000, |
1055 | }; | 1472 | }; |
1056 | 1473 | ||
1057 | static struct clk_pll_table tegra_pll_c_table[] = { | 1474 | static struct clk_pll_freq_table tegra_pll_c_freq_table[] = { |
1058 | { 0, 0, 0, 0, 0, 0 }, | 1475 | { 0, 0, 0, 0, 0, 0 }, |
1059 | }; | 1476 | }; |
1060 | 1477 | ||
@@ -1063,15 +1480,18 @@ static struct clk tegra_pll_c = { | |||
1063 | .flags = PLL_HAS_CPCON, | 1480 | .flags = PLL_HAS_CPCON, |
1064 | .ops = &tegra_pll_ops, | 1481 | .ops = &tegra_pll_ops, |
1065 | .reg = 0x80, | 1482 | .reg = 0x80, |
1066 | .input_min = 2000000, | ||
1067 | .input_max = 31000000, | ||
1068 | .parent = &tegra_clk_m, | 1483 | .parent = &tegra_clk_m, |
1069 | .cf_min = 1000000, | ||
1070 | .cf_max = 6000000, | ||
1071 | .vco_min = 20000000, | ||
1072 | .vco_max = 1400000000, | ||
1073 | .pll_table = tegra_pll_c_table, | ||
1074 | .max_rate = 600000000, | 1484 | .max_rate = 600000000, |
1485 | .u.pll = { | ||
1486 | .input_min = 2000000, | ||
1487 | .input_max = 31000000, | ||
1488 | .cf_min = 1000000, | ||
1489 | .cf_max = 6000000, | ||
1490 | .vco_min = 20000000, | ||
1491 | .vco_max = 1400000000, | ||
1492 | .freq_table = tegra_pll_c_freq_table, | ||
1493 | .lock_delay = 300, | ||
1494 | }, | ||
1075 | }; | 1495 | }; |
1076 | 1496 | ||
1077 | static struct clk tegra_pll_c_out1 = { | 1497 | static struct clk tegra_pll_c_out1 = { |
@@ -1084,7 +1504,7 @@ static struct clk tegra_pll_c_out1 = { | |||
1084 | .max_rate = 600000000, | 1504 | .max_rate = 600000000, |
1085 | }; | 1505 | }; |
1086 | 1506 | ||
1087 | static struct clk_pll_table tegra_pll_m_table[] = { | 1507 | static struct clk_pll_freq_table tegra_pll_m_freq_table[] = { |
1088 | { 12000000, 666000000, 666, 12, 1, 8}, | 1508 | { 12000000, 666000000, 666, 12, 1, 8}, |
1089 | { 13000000, 666000000, 666, 13, 1, 8}, | 1509 | { 13000000, 666000000, 666, 13, 1, 8}, |
1090 | { 19200000, 666000000, 555, 16, 1, 8}, | 1510 | { 19200000, 666000000, 555, 16, 1, 8}, |
@@ -1101,15 +1521,18 @@ static struct clk tegra_pll_m = { | |||
1101 | .flags = PLL_HAS_CPCON, | 1521 | .flags = PLL_HAS_CPCON, |
1102 | .ops = &tegra_pll_ops, | 1522 | .ops = &tegra_pll_ops, |
1103 | .reg = 0x90, | 1523 | .reg = 0x90, |
1104 | .input_min = 2000000, | ||
1105 | .input_max = 31000000, | ||
1106 | .parent = &tegra_clk_m, | 1524 | .parent = &tegra_clk_m, |
1107 | .cf_min = 1000000, | ||
1108 | .cf_max = 6000000, | ||
1109 | .vco_min = 20000000, | ||
1110 | .vco_max = 1200000000, | ||
1111 | .pll_table = tegra_pll_m_table, | ||
1112 | .max_rate = 800000000, | 1525 | .max_rate = 800000000, |
1526 | .u.pll = { | ||
1527 | .input_min = 2000000, | ||
1528 | .input_max = 31000000, | ||
1529 | .cf_min = 1000000, | ||
1530 | .cf_max = 6000000, | ||
1531 | .vco_min = 20000000, | ||
1532 | .vco_max = 1200000000, | ||
1533 | .freq_table = tegra_pll_m_freq_table, | ||
1534 | .lock_delay = 300, | ||
1535 | }, | ||
1113 | }; | 1536 | }; |
1114 | 1537 | ||
1115 | static struct clk tegra_pll_m_out1 = { | 1538 | static struct clk tegra_pll_m_out1 = { |
@@ -1122,7 +1545,7 @@ static struct clk tegra_pll_m_out1 = { | |||
1122 | .max_rate = 600000000, | 1545 | .max_rate = 600000000, |
1123 | }; | 1546 | }; |
1124 | 1547 | ||
1125 | static struct clk_pll_table tegra_pll_p_table[] = { | 1548 | static struct clk_pll_freq_table tegra_pll_p_freq_table[] = { |
1126 | { 12000000, 216000000, 432, 12, 2, 8}, | 1549 | { 12000000, 216000000, 432, 12, 2, 8}, |
1127 | { 13000000, 216000000, 432, 13, 2, 8}, | 1550 | { 13000000, 216000000, 432, 13, 2, 8}, |
1128 | { 19200000, 216000000, 90, 4, 2, 1}, | 1551 | { 19200000, 216000000, 90, 4, 2, 1}, |
@@ -1139,15 +1562,18 @@ static struct clk tegra_pll_p = { | |||
1139 | .flags = ENABLE_ON_INIT | PLL_FIXED | PLL_HAS_CPCON, | 1562 | .flags = ENABLE_ON_INIT | PLL_FIXED | PLL_HAS_CPCON, |
1140 | .ops = &tegra_pll_ops, | 1563 | .ops = &tegra_pll_ops, |
1141 | .reg = 0xa0, | 1564 | .reg = 0xa0, |
1142 | .input_min = 2000000, | ||
1143 | .input_max = 31000000, | ||
1144 | .parent = &tegra_clk_m, | 1565 | .parent = &tegra_clk_m, |
1145 | .cf_min = 1000000, | ||
1146 | .cf_max = 6000000, | ||
1147 | .vco_min = 20000000, | ||
1148 | .vco_max = 1400000000, | ||
1149 | .pll_table = tegra_pll_p_table, | ||
1150 | .max_rate = 432000000, | 1566 | .max_rate = 432000000, |
1567 | .u.pll = { | ||
1568 | .input_min = 2000000, | ||
1569 | .input_max = 31000000, | ||
1570 | .cf_min = 1000000, | ||
1571 | .cf_max = 6000000, | ||
1572 | .vco_min = 20000000, | ||
1573 | .vco_max = 1400000000, | ||
1574 | .freq_table = tegra_pll_p_freq_table, | ||
1575 | .lock_delay = 300, | ||
1576 | }, | ||
1151 | }; | 1577 | }; |
1152 | 1578 | ||
1153 | static struct clk tegra_pll_p_out1 = { | 1579 | static struct clk tegra_pll_p_out1 = { |
@@ -1190,11 +1616,9 @@ static struct clk tegra_pll_p_out4 = { | |||
1190 | .max_rate = 432000000, | 1616 | .max_rate = 432000000, |
1191 | }; | 1617 | }; |
1192 | 1618 | ||
1193 | static struct clk_pll_table tegra_pll_a_table[] = { | 1619 | static struct clk_pll_freq_table tegra_pll_a_freq_table[] = { |
1194 | { 28800000, 56448000, 49, 25, 1, 1}, | 1620 | { 28800000, 56448000, 49, 25, 1, 1}, |
1195 | { 28800000, 73728000, 64, 25, 1, 1}, | 1621 | { 28800000, 73728000, 64, 25, 1, 1}, |
1196 | { 28800000, 11289600, 49, 25, 1, 1}, | ||
1197 | { 28800000, 12288000, 64, 25, 1, 1}, | ||
1198 | { 28800000, 24000000, 5, 6, 1, 1}, | 1622 | { 28800000, 24000000, 5, 6, 1, 1}, |
1199 | { 0, 0, 0, 0, 0, 0 }, | 1623 | { 0, 0, 0, 0, 0, 0 }, |
1200 | }; | 1624 | }; |
@@ -1204,15 +1628,18 @@ static struct clk tegra_pll_a = { | |||
1204 | .flags = PLL_HAS_CPCON, | 1628 | .flags = PLL_HAS_CPCON, |
1205 | .ops = &tegra_pll_ops, | 1629 | .ops = &tegra_pll_ops, |
1206 | .reg = 0xb0, | 1630 | .reg = 0xb0, |
1207 | .input_min = 2000000, | ||
1208 | .input_max = 31000000, | ||
1209 | .parent = &tegra_pll_p_out1, | 1631 | .parent = &tegra_pll_p_out1, |
1210 | .cf_min = 1000000, | 1632 | .max_rate = 73728000, |
1211 | .cf_max = 6000000, | 1633 | .u.pll = { |
1212 | .vco_min = 20000000, | 1634 | .input_min = 2000000, |
1213 | .vco_max = 1400000000, | 1635 | .input_max = 31000000, |
1214 | .pll_table = tegra_pll_a_table, | 1636 | .cf_min = 1000000, |
1215 | .max_rate = 56448000, | 1637 | .cf_max = 6000000, |
1638 | .vco_min = 20000000, | ||
1639 | .vco_max = 1400000000, | ||
1640 | .freq_table = tegra_pll_a_freq_table, | ||
1641 | .lock_delay = 300, | ||
1642 | }, | ||
1216 | }; | 1643 | }; |
1217 | 1644 | ||
1218 | static struct clk tegra_pll_a_out0 = { | 1645 | static struct clk tegra_pll_a_out0 = { |
@@ -1222,14 +1649,25 @@ static struct clk tegra_pll_a_out0 = { | |||
1222 | .parent = &tegra_pll_a, | 1649 | .parent = &tegra_pll_a, |
1223 | .reg = 0xb4, | 1650 | .reg = 0xb4, |
1224 | .reg_shift = 0, | 1651 | .reg_shift = 0, |
1225 | .max_rate = 56448000, | 1652 | .max_rate = 73728000, |
1226 | }; | 1653 | }; |
1227 | 1654 | ||
1228 | static struct clk_pll_table tegra_pll_d_table[] = { | 1655 | static struct clk_pll_freq_table tegra_pll_d_freq_table[] = { |
1656 | { 12000000, 216000000, 216, 12, 1, 4}, | ||
1657 | { 13000000, 216000000, 216, 13, 1, 4}, | ||
1658 | { 19200000, 216000000, 135, 12, 1, 3}, | ||
1659 | { 26000000, 216000000, 216, 26, 1, 4}, | ||
1660 | |||
1661 | { 12000000, 594000000, 594, 12, 1, 8}, | ||
1662 | { 13000000, 594000000, 594, 13, 1, 8}, | ||
1663 | { 19200000, 594000000, 495, 16, 1, 8}, | ||
1664 | { 26000000, 594000000, 594, 26, 1, 8}, | ||
1665 | |||
1229 | { 12000000, 1000000000, 1000, 12, 1, 12}, | 1666 | { 12000000, 1000000000, 1000, 12, 1, 12}, |
1230 | { 13000000, 1000000000, 1000, 13, 1, 12}, | 1667 | { 13000000, 1000000000, 1000, 13, 1, 12}, |
1231 | { 19200000, 1000000000, 625, 12, 1, 8}, | 1668 | { 19200000, 1000000000, 625, 12, 1, 8}, |
1232 | { 26000000, 1000000000, 1000, 26, 1, 12}, | 1669 | { 26000000, 1000000000, 1000, 26, 1, 12}, |
1670 | |||
1233 | { 0, 0, 0, 0, 0, 0 }, | 1671 | { 0, 0, 0, 0, 0, 0 }, |
1234 | }; | 1672 | }; |
1235 | 1673 | ||
@@ -1238,15 +1676,18 @@ static struct clk tegra_pll_d = { | |||
1238 | .flags = PLL_HAS_CPCON | PLLD, | 1676 | .flags = PLL_HAS_CPCON | PLLD, |
1239 | .ops = &tegra_pll_ops, | 1677 | .ops = &tegra_pll_ops, |
1240 | .reg = 0xd0, | 1678 | .reg = 0xd0, |
1241 | .input_min = 2000000, | ||
1242 | .input_max = 40000000, | ||
1243 | .parent = &tegra_clk_m, | 1679 | .parent = &tegra_clk_m, |
1244 | .cf_min = 1000000, | ||
1245 | .cf_max = 6000000, | ||
1246 | .vco_min = 40000000, | ||
1247 | .vco_max = 1000000000, | ||
1248 | .pll_table = tegra_pll_d_table, | ||
1249 | .max_rate = 1000000000, | 1680 | .max_rate = 1000000000, |
1681 | .u.pll = { | ||
1682 | .input_min = 2000000, | ||
1683 | .input_max = 40000000, | ||
1684 | .cf_min = 1000000, | ||
1685 | .cf_max = 6000000, | ||
1686 | .vco_min = 40000000, | ||
1687 | .vco_max = 1000000000, | ||
1688 | .freq_table = tegra_pll_d_freq_table, | ||
1689 | .lock_delay = 1000, | ||
1690 | }, | ||
1250 | }; | 1691 | }; |
1251 | 1692 | ||
1252 | static struct clk tegra_pll_d_out0 = { | 1693 | static struct clk tegra_pll_d_out0 = { |
@@ -1257,7 +1698,7 @@ static struct clk tegra_pll_d_out0 = { | |||
1257 | .max_rate = 500000000, | 1698 | .max_rate = 500000000, |
1258 | }; | 1699 | }; |
1259 | 1700 | ||
1260 | static struct clk_pll_table tegra_pll_u_table[] = { | 1701 | static struct clk_pll_freq_table tegra_pll_u_freq_table[] = { |
1261 | { 12000000, 480000000, 960, 12, 2, 0}, | 1702 | { 12000000, 480000000, 960, 12, 2, 0}, |
1262 | { 13000000, 480000000, 960, 13, 2, 0}, | 1703 | { 13000000, 480000000, 960, 13, 2, 0}, |
1263 | { 19200000, 480000000, 200, 4, 2, 0}, | 1704 | { 19200000, 480000000, 200, 4, 2, 0}, |
@@ -1270,18 +1711,21 @@ static struct clk tegra_pll_u = { | |||
1270 | .flags = PLLU, | 1711 | .flags = PLLU, |
1271 | .ops = &tegra_pll_ops, | 1712 | .ops = &tegra_pll_ops, |
1272 | .reg = 0xc0, | 1713 | .reg = 0xc0, |
1273 | .input_min = 2000000, | ||
1274 | .input_max = 40000000, | ||
1275 | .parent = &tegra_clk_m, | 1714 | .parent = &tegra_clk_m, |
1276 | .cf_min = 1000000, | ||
1277 | .cf_max = 6000000, | ||
1278 | .vco_min = 480000000, | ||
1279 | .vco_max = 960000000, | ||
1280 | .pll_table = tegra_pll_u_table, | ||
1281 | .max_rate = 480000000, | 1715 | .max_rate = 480000000, |
1282 | }; | 1716 | .u.pll = { |
1283 | 1717 | .input_min = 2000000, | |
1284 | static struct clk_pll_table tegra_pll_x_table[] = { | 1718 | .input_max = 40000000, |
1719 | .cf_min = 1000000, | ||
1720 | .cf_max = 6000000, | ||
1721 | .vco_min = 480000000, | ||
1722 | .vco_max = 960000000, | ||
1723 | .freq_table = tegra_pll_u_freq_table, | ||
1724 | .lock_delay = 1000, | ||
1725 | }, | ||
1726 | }; | ||
1727 | |||
1728 | static struct clk_pll_freq_table tegra_pll_x_freq_table[] = { | ||
1285 | /* 1 GHz */ | 1729 | /* 1 GHz */ |
1286 | { 12000000, 1000000000, 1000, 12, 1, 12}, | 1730 | { 12000000, 1000000000, 1000, 12, 1, 12}, |
1287 | { 13000000, 1000000000, 1000, 13, 1, 12}, | 1731 | { 13000000, 1000000000, 1000, 13, 1, 12}, |
@@ -1307,10 +1751,10 @@ static struct clk_pll_table tegra_pll_x_table[] = { | |||
1307 | { 26000000, 760000000, 760, 26, 1, 12}, | 1751 | { 26000000, 760000000, 760, 26, 1, 12}, |
1308 | 1752 | ||
1309 | /* 608 MHz */ | 1753 | /* 608 MHz */ |
1310 | { 12000000, 608000000, 760, 12, 1, 12}, | 1754 | { 12000000, 608000000, 608, 12, 1, 12}, |
1311 | { 13000000, 608000000, 760, 13, 1, 12}, | 1755 | { 13000000, 608000000, 608, 13, 1, 12}, |
1312 | { 19200000, 608000000, 380, 12, 1, 8}, | 1756 | { 19200000, 608000000, 380, 12, 1, 8}, |
1313 | { 26000000, 608000000, 760, 26, 1, 12}, | 1757 | { 26000000, 608000000, 608, 26, 1, 12}, |
1314 | 1758 | ||
1315 | /* 456 MHz */ | 1759 | /* 456 MHz */ |
1316 | { 12000000, 456000000, 456, 12, 1, 12}, | 1760 | { 12000000, 456000000, 456, 12, 1, 12}, |
@@ -1332,18 +1776,21 @@ static struct clk tegra_pll_x = { | |||
1332 | .flags = PLL_HAS_CPCON | PLL_ALT_MISC_REG, | 1776 | .flags = PLL_HAS_CPCON | PLL_ALT_MISC_REG, |
1333 | .ops = &tegra_pllx_ops, | 1777 | .ops = &tegra_pllx_ops, |
1334 | .reg = 0xe0, | 1778 | .reg = 0xe0, |
1335 | .input_min = 2000000, | ||
1336 | .input_max = 31000000, | ||
1337 | .parent = &tegra_clk_m, | 1779 | .parent = &tegra_clk_m, |
1338 | .cf_min = 1000000, | ||
1339 | .cf_max = 6000000, | ||
1340 | .vco_min = 20000000, | ||
1341 | .vco_max = 1200000000, | ||
1342 | .pll_table = tegra_pll_x_table, | ||
1343 | .max_rate = 1000000000, | 1780 | .max_rate = 1000000000, |
1344 | }; | 1781 | .u.pll = { |
1345 | 1782 | .input_min = 2000000, | |
1346 | static struct clk_pll_table tegra_pll_e_table[] = { | 1783 | .input_max = 31000000, |
1784 | .cf_min = 1000000, | ||
1785 | .cf_max = 6000000, | ||
1786 | .vco_min = 20000000, | ||
1787 | .vco_max = 1200000000, | ||
1788 | .freq_table = tegra_pll_x_freq_table, | ||
1789 | .lock_delay = 300, | ||
1790 | }, | ||
1791 | }; | ||
1792 | |||
1793 | static struct clk_pll_freq_table tegra_pll_e_freq_table[] = { | ||
1347 | { 12000000, 100000000, 200, 24, 1, 0 }, | 1794 | { 12000000, 100000000, 200, 24, 1, 0 }, |
1348 | { 0, 0, 0, 0, 0, 0 }, | 1795 | { 0, 0, 0, 0, 0, 0 }, |
1349 | }; | 1796 | }; |
@@ -1352,23 +1799,49 @@ static struct clk tegra_pll_e = { | |||
1352 | .name = "pll_e", | 1799 | .name = "pll_e", |
1353 | .flags = PLL_ALT_MISC_REG, | 1800 | .flags = PLL_ALT_MISC_REG, |
1354 | .ops = &tegra_plle_ops, | 1801 | .ops = &tegra_plle_ops, |
1355 | .input_min = 12000000, | ||
1356 | .input_max = 12000000, | ||
1357 | .max_rate = 100000000, | ||
1358 | .parent = &tegra_clk_m, | 1802 | .parent = &tegra_clk_m, |
1359 | .reg = 0xe8, | 1803 | .reg = 0xe8, |
1360 | .pll_table = tegra_pll_e_table, | 1804 | .max_rate = 100000000, |
1805 | .u.pll = { | ||
1806 | .input_min = 12000000, | ||
1807 | .input_max = 12000000, | ||
1808 | .freq_table = tegra_pll_e_freq_table, | ||
1809 | }, | ||
1361 | }; | 1810 | }; |
1362 | 1811 | ||
1363 | static struct clk tegra_clk_d = { | 1812 | static struct clk tegra_clk_d = { |
1364 | .name = "clk_d", | 1813 | .name = "clk_d", |
1365 | .flags = PERIPH_NO_RESET, | 1814 | .flags = PERIPH_NO_RESET, |
1366 | .ops = &tegra_clk_double_ops, | 1815 | .ops = &tegra_clk_double_ops, |
1367 | .clk_num = 90, | ||
1368 | .reg = 0x34, | 1816 | .reg = 0x34, |
1369 | .reg_shift = 12, | 1817 | .reg_shift = 12, |
1370 | .parent = &tegra_clk_m, | 1818 | .parent = &tegra_clk_m, |
1371 | .max_rate = 52000000, | 1819 | .max_rate = 52000000, |
1820 | .u.periph = { | ||
1821 | .clk_num = 90, | ||
1822 | }, | ||
1823 | }; | ||
1824 | |||
1825 | /* dap_mclk1, belongs to the cdev1 pingroup. */ | ||
1826 | static struct clk tegra_clk_cdev1 = { | ||
1827 | .name = "cdev1", | ||
1828 | .ops = &tegra_cdev_clk_ops, | ||
1829 | .rate = 26000000, | ||
1830 | .max_rate = 26000000, | ||
1831 | .u.periph = { | ||
1832 | .clk_num = 94, | ||
1833 | }, | ||
1834 | }; | ||
1835 | |||
1836 | /* dap_mclk2, belongs to the cdev2 pingroup. */ | ||
1837 | static struct clk tegra_clk_cdev2 = { | ||
1838 | .name = "cdev2", | ||
1839 | .ops = &tegra_cdev_clk_ops, | ||
1840 | .rate = 26000000, | ||
1841 | .max_rate = 26000000, | ||
1842 | .u.periph = { | ||
1843 | .clk_num = 93, | ||
1844 | }, | ||
1372 | }; | 1845 | }; |
1373 | 1846 | ||
1374 | /* initialized before peripheral clocks */ | 1847 | /* initialized before peripheral clocks */ |
@@ -1394,7 +1867,7 @@ static struct clk tegra_clk_audio = { | |||
1394 | .name = "audio", | 1867 | .name = "audio", |
1395 | .inputs = mux_audio_sync_clk, | 1868 | .inputs = mux_audio_sync_clk, |
1396 | .reg = 0x38, | 1869 | .reg = 0x38, |
1397 | .max_rate = 24000000, | 1870 | .max_rate = 73728000, |
1398 | .ops = &tegra_audio_sync_clk_ops | 1871 | .ops = &tegra_audio_sync_clk_ops |
1399 | }; | 1872 | }; |
1400 | 1873 | ||
@@ -1403,10 +1876,12 @@ static struct clk tegra_clk_audio_2x = { | |||
1403 | .flags = PERIPH_NO_RESET, | 1876 | .flags = PERIPH_NO_RESET, |
1404 | .max_rate = 48000000, | 1877 | .max_rate = 48000000, |
1405 | .ops = &tegra_clk_double_ops, | 1878 | .ops = &tegra_clk_double_ops, |
1406 | .clk_num = 89, | ||
1407 | .reg = 0x34, | 1879 | .reg = 0x34, |
1408 | .reg_shift = 8, | 1880 | .reg_shift = 8, |
1409 | .parent = &tegra_clk_audio, | 1881 | .parent = &tegra_clk_audio, |
1882 | .u.periph = { | ||
1883 | .clk_num = 89, | ||
1884 | }, | ||
1410 | }; | 1885 | }; |
1411 | 1886 | ||
1412 | struct clk_lookup tegra_audio_clk_lookups[] = { | 1887 | struct clk_lookup tegra_audio_clk_lookups[] = { |
@@ -1478,17 +1953,26 @@ static struct clk tegra_clk_sclk = { | |||
1478 | .inputs = mux_sclk, | 1953 | .inputs = mux_sclk, |
1479 | .reg = 0x28, | 1954 | .reg = 0x28, |
1480 | .ops = &tegra_super_ops, | 1955 | .ops = &tegra_super_ops, |
1481 | .max_rate = 600000000, | 1956 | .max_rate = 240000000, |
1957 | .min_rate = 120000000, | ||
1482 | }; | 1958 | }; |
1483 | 1959 | ||
1484 | static struct clk tegra_clk_virtual_cpu = { | 1960 | static struct clk tegra_clk_virtual_cpu = { |
1485 | .name = "cpu", | 1961 | .name = "cpu", |
1486 | .parent = &tegra_clk_cclk, | 1962 | .parent = &tegra_clk_cclk, |
1487 | .main = &tegra_pll_x, | ||
1488 | .backup = &tegra_clk_m, | ||
1489 | .ops = &tegra_cpu_ops, | 1963 | .ops = &tegra_cpu_ops, |
1490 | .max_rate = 1000000000, | 1964 | .max_rate = 1000000000, |
1491 | .dvfs = &tegra_dvfs_virtual_cpu_dvfs, | 1965 | .u.cpu = { |
1966 | .main = &tegra_pll_x, | ||
1967 | .backup = &tegra_pll_p, | ||
1968 | }, | ||
1969 | }; | ||
1970 | |||
1971 | static struct clk tegra_clk_cop = { | ||
1972 | .name = "cop", | ||
1973 | .parent = &tegra_clk_sclk, | ||
1974 | .ops = &tegra_cop_ops, | ||
1975 | .max_rate = 240000000, | ||
1492 | }; | 1976 | }; |
1493 | 1977 | ||
1494 | static struct clk tegra_clk_hclk = { | 1978 | static struct clk tegra_clk_hclk = { |
@@ -1508,7 +1992,15 @@ static struct clk tegra_clk_pclk = { | |||
1508 | .reg = 0x30, | 1992 | .reg = 0x30, |
1509 | .reg_shift = 0, | 1993 | .reg_shift = 0, |
1510 | .ops = &tegra_bus_ops, | 1994 | .ops = &tegra_bus_ops, |
1511 | .max_rate = 108000000, | 1995 | .max_rate = 120000000, |
1996 | }; | ||
1997 | |||
1998 | static struct clk tegra_clk_blink = { | ||
1999 | .name = "blink", | ||
2000 | .parent = &tegra_clk_32k, | ||
2001 | .reg = 0x40, | ||
2002 | .ops = &tegra_blink_clk_ops, | ||
2003 | .max_rate = 32768, | ||
1512 | }; | 2004 | }; |
1513 | 2005 | ||
1514 | static struct clk_mux_sel mux_pllm_pllc_pllp_plla[] = { | 2006 | static struct clk_mux_sel mux_pllm_pllc_pllp_plla[] = { |
@@ -1587,6 +2079,23 @@ static struct clk_mux_sel mux_clk_32k[] = { | |||
1587 | { 0, 0}, | 2079 | { 0, 0}, |
1588 | }; | 2080 | }; |
1589 | 2081 | ||
2082 | static struct clk_mux_sel mux_pclk[] = { | ||
2083 | { .input = &tegra_clk_pclk, .value = 0}, | ||
2084 | { 0, 0}, | ||
2085 | }; | ||
2086 | |||
2087 | static struct clk tegra_clk_emc = { | ||
2088 | .name = "emc", | ||
2089 | .ops = &tegra_emc_clk_ops, | ||
2090 | .reg = 0x19c, | ||
2091 | .max_rate = 800000000, | ||
2092 | .inputs = mux_pllm_pllc_pllp_clkm, | ||
2093 | .flags = MUX | DIV_U71 | PERIPH_EMC_ENB, | ||
2094 | .u.periph = { | ||
2095 | .clk_num = 57, | ||
2096 | }, | ||
2097 | }; | ||
2098 | |||
1590 | #define PERIPH_CLK(_name, _dev, _con, _clk_num, _reg, _max, _inputs, _flags) \ | 2099 | #define PERIPH_CLK(_name, _dev, _con, _clk_num, _reg, _max, _inputs, _flags) \ |
1591 | { \ | 2100 | { \ |
1592 | .name = _name, \ | 2101 | .name = _name, \ |
@@ -1595,19 +2104,32 @@ static struct clk_mux_sel mux_clk_32k[] = { | |||
1595 | .con_id = _con, \ | 2104 | .con_id = _con, \ |
1596 | }, \ | 2105 | }, \ |
1597 | .ops = &tegra_periph_clk_ops, \ | 2106 | .ops = &tegra_periph_clk_ops, \ |
1598 | .clk_num = _clk_num, \ | ||
1599 | .reg = _reg, \ | 2107 | .reg = _reg, \ |
1600 | .inputs = _inputs, \ | 2108 | .inputs = _inputs, \ |
1601 | .flags = _flags, \ | 2109 | .flags = _flags, \ |
1602 | .max_rate = _max, \ | 2110 | .max_rate = _max, \ |
2111 | .u.periph = { \ | ||
2112 | .clk_num = _clk_num, \ | ||
2113 | }, \ | ||
2114 | } | ||
2115 | |||
2116 | #define SHARED_CLK(_name, _dev, _con, _parent) \ | ||
2117 | { \ | ||
2118 | .name = _name, \ | ||
2119 | .lookup = { \ | ||
2120 | .dev_id = _dev, \ | ||
2121 | .con_id = _con, \ | ||
2122 | }, \ | ||
2123 | .ops = &tegra_clk_shared_bus_ops, \ | ||
2124 | .parent = _parent, \ | ||
1603 | } | 2125 | } |
1604 | 2126 | ||
1605 | struct clk tegra_periph_clks[] = { | 2127 | struct clk tegra_list_clks[] = { |
2128 | PERIPH_CLK("apbdma", "tegra-dma", NULL, 34, 0, 108000000, mux_pclk, 0), | ||
1606 | PERIPH_CLK("rtc", "rtc-tegra", NULL, 4, 0, 32768, mux_clk_32k, PERIPH_NO_RESET), | 2129 | PERIPH_CLK("rtc", "rtc-tegra", NULL, 4, 0, 32768, mux_clk_32k, PERIPH_NO_RESET), |
1607 | PERIPH_CLK("timer", "timer", NULL, 5, 0, 26000000, mux_clk_m, 0), | 2130 | PERIPH_CLK("timer", "timer", NULL, 5, 0, 26000000, mux_clk_m, 0), |
1608 | PERIPH_CLK("i2s1", "i2s.0", NULL, 11, 0x100, 26000000, mux_pllaout0_audio2x_pllp_clkm, MUX | DIV_U71), | 2131 | PERIPH_CLK("i2s1", "tegra-i2s.0", NULL, 11, 0x100, 26000000, mux_pllaout0_audio2x_pllp_clkm, MUX | DIV_U71), |
1609 | PERIPH_CLK("i2s2", "i2s.1", NULL, 18, 0x104, 26000000, mux_pllaout0_audio2x_pllp_clkm, MUX | DIV_U71), | 2132 | PERIPH_CLK("i2s2", "tegra-i2s.1", NULL, 18, 0x104, 26000000, mux_pllaout0_audio2x_pllp_clkm, MUX | DIV_U71), |
1610 | /* FIXME: spdif has 2 clocks but 1 enable */ | ||
1611 | PERIPH_CLK("spdif_out", "spdif_out", NULL, 10, 0x108, 100000000, mux_pllaout0_audio2x_pllp_clkm, MUX | DIV_U71), | 2133 | PERIPH_CLK("spdif_out", "spdif_out", NULL, 10, 0x108, 100000000, mux_pllaout0_audio2x_pllp_clkm, MUX | DIV_U71), |
1612 | PERIPH_CLK("spdif_in", "spdif_in", NULL, 10, 0x10c, 100000000, mux_pllp_pllc_pllm, MUX | DIV_U71), | 2134 | PERIPH_CLK("spdif_in", "spdif_in", NULL, 10, 0x10c, 100000000, mux_pllp_pllc_pllm, MUX | DIV_U71), |
1613 | PERIPH_CLK("pwm", "pwm", NULL, 17, 0x110, 432000000, mux_pllp_pllc_audio_clkm_clk32, MUX | DIV_U71), | 2135 | PERIPH_CLK("pwm", "pwm", NULL, 17, 0x110, 432000000, mux_pllp_pllc_audio_clkm_clk32, MUX | DIV_U71), |
@@ -1620,13 +2142,15 @@ struct clk tegra_periph_clks[] = { | |||
1620 | PERIPH_CLK("sbc4", "spi_tegra.3", NULL, 68, 0x1b4, 160000000, mux_pllp_pllc_pllm_clkm, MUX | DIV_U71), | 2142 | PERIPH_CLK("sbc4", "spi_tegra.3", NULL, 68, 0x1b4, 160000000, mux_pllp_pllc_pllm_clkm, MUX | DIV_U71), |
1621 | PERIPH_CLK("ide", "ide", NULL, 25, 0x144, 100000000, mux_pllp_pllc_pllm_clkm, MUX | DIV_U71), /* requires min voltage */ | 2143 | PERIPH_CLK("ide", "ide", NULL, 25, 0x144, 100000000, mux_pllp_pllc_pllm_clkm, MUX | DIV_U71), /* requires min voltage */ |
1622 | PERIPH_CLK("ndflash", "tegra_nand", NULL, 13, 0x160, 164000000, mux_pllp_pllc_pllm_clkm, MUX | DIV_U71), /* scales with voltage */ | 2144 | PERIPH_CLK("ndflash", "tegra_nand", NULL, 13, 0x160, 164000000, mux_pllp_pllc_pllm_clkm, MUX | DIV_U71), /* scales with voltage */ |
1623 | /* FIXME: vfir shares an enable with uartb */ | ||
1624 | PERIPH_CLK("vfir", "vfir", NULL, 7, 0x168, 72000000, mux_pllp_pllc_pllm_clkm, MUX | DIV_U71), | 2145 | PERIPH_CLK("vfir", "vfir", NULL, 7, 0x168, 72000000, mux_pllp_pllc_pllm_clkm, MUX | DIV_U71), |
1625 | PERIPH_CLK("sdmmc1", "sdhci-tegra.0", NULL, 14, 0x150, 52000000, mux_pllp_pllc_pllm_clkm, MUX | DIV_U71), /* scales with voltage */ | 2146 | PERIPH_CLK("sdmmc1", "sdhci-tegra.0", NULL, 14, 0x150, 52000000, mux_pllp_pllc_pllm_clkm, MUX | DIV_U71), /* scales with voltage */ |
1626 | PERIPH_CLK("sdmmc2", "sdhci-tegra.1", NULL, 9, 0x154, 52000000, mux_pllp_pllc_pllm_clkm, MUX | DIV_U71), /* scales with voltage */ | 2147 | PERIPH_CLK("sdmmc2", "sdhci-tegra.1", NULL, 9, 0x154, 52000000, mux_pllp_pllc_pllm_clkm, MUX | DIV_U71), /* scales with voltage */ |
1627 | PERIPH_CLK("sdmmc3", "sdhci-tegra.2", NULL, 69, 0x1bc, 52000000, mux_pllp_pllc_pllm_clkm, MUX | DIV_U71), /* scales with voltage */ | 2148 | PERIPH_CLK("sdmmc3", "sdhci-tegra.2", NULL, 69, 0x1bc, 52000000, mux_pllp_pllc_pllm_clkm, MUX | DIV_U71), /* scales with voltage */ |
1628 | PERIPH_CLK("sdmmc4", "sdhci-tegra.3", NULL, 15, 0x160, 52000000, mux_pllp_pllc_pllm_clkm, MUX | DIV_U71), /* scales with voltage */ | 2149 | PERIPH_CLK("sdmmc4", "sdhci-tegra.3", NULL, 15, 0x164, 52000000, mux_pllp_pllc_pllm_clkm, MUX | DIV_U71), /* scales with voltage */ |
1629 | PERIPH_CLK("vde", "vde", NULL, 61, 0x1c8, 250000000, mux_pllp_pllc_pllm_clkm, MUX | DIV_U71), /* scales with voltage and process_id */ | 2150 | PERIPH_CLK("vcp", "tegra-avp", "vcp", 29, 0, 250000000, mux_clk_m, 0), |
2151 | PERIPH_CLK("bsea", "tegra-avp", "bsea", 62, 0, 250000000, mux_clk_m, 0), | ||
2152 | PERIPH_CLK("bsev", "tegra-aes", "bsev", 63, 0, 250000000, mux_clk_m, 0), | ||
2153 | PERIPH_CLK("vde", "tegra-avp", "vde", 61, 0x1c8, 250000000, mux_pllp_pllc_pllm_clkm, MUX | DIV_U71), /* scales with voltage and process_id */ | ||
1630 | PERIPH_CLK("csite", "csite", NULL, 73, 0x1d4, 144000000, mux_pllp_pllc_pllm_clkm, MUX | DIV_U71), /* max rate ??? */ | 2154 | PERIPH_CLK("csite", "csite", NULL, 73, 0x1d4, 144000000, mux_pllp_pllc_pllm_clkm, MUX | DIV_U71), /* max rate ??? */ |
1631 | /* FIXME: what is la? */ | 2155 | /* FIXME: what is la? */ |
1632 | PERIPH_CLK("la", "la", NULL, 76, 0x1f8, 26000000, mux_pllp_pllc_pllm_clkm, MUX | DIV_U71), | 2156 | PERIPH_CLK("la", "la", NULL, 76, 0x1f8, 26000000, mux_pllp_pllc_pllm_clkm, MUX | DIV_U71), |
@@ -1641,37 +2165,46 @@ struct clk tegra_periph_clks[] = { | |||
1641 | PERIPH_CLK("i2c2_i2c", "tegra-i2c.1", "i2c", 0, 0, 72000000, mux_pllp_out3, 0), | 2165 | PERIPH_CLK("i2c2_i2c", "tegra-i2c.1", "i2c", 0, 0, 72000000, mux_pllp_out3, 0), |
1642 | PERIPH_CLK("i2c3_i2c", "tegra-i2c.2", "i2c", 0, 0, 72000000, mux_pllp_out3, 0), | 2166 | PERIPH_CLK("i2c3_i2c", "tegra-i2c.2", "i2c", 0, 0, 72000000, mux_pllp_out3, 0), |
1643 | PERIPH_CLK("dvc_i2c", "tegra-i2c.3", "i2c", 0, 0, 72000000, mux_pllp_out3, 0), | 2167 | PERIPH_CLK("dvc_i2c", "tegra-i2c.3", "i2c", 0, 0, 72000000, mux_pllp_out3, 0), |
1644 | PERIPH_CLK("uarta", "uart.0", NULL, 6, 0x178, 216000000, mux_pllp_pllc_pllm_clkm, MUX), | 2168 | PERIPH_CLK("uarta", "uart.0", NULL, 6, 0x178, 600000000, mux_pllp_pllc_pllm_clkm, MUX), |
1645 | PERIPH_CLK("uartb", "uart.1", NULL, 7, 0x17c, 216000000, mux_pllp_pllc_pllm_clkm, MUX), | 2169 | PERIPH_CLK("uartb", "uart.1", NULL, 7, 0x17c, 600000000, mux_pllp_pllc_pllm_clkm, MUX), |
1646 | PERIPH_CLK("uartc", "uart.2", NULL, 55, 0x1a0, 216000000, mux_pllp_pllc_pllm_clkm, MUX), | 2170 | PERIPH_CLK("uartc", "uart.2", NULL, 55, 0x1a0, 600000000, mux_pllp_pllc_pllm_clkm, MUX), |
1647 | PERIPH_CLK("uartd", "uart.3", NULL, 65, 0x1c0, 216000000, mux_pllp_pllc_pllm_clkm, MUX), | 2171 | PERIPH_CLK("uartd", "uart.3", NULL, 65, 0x1c0, 600000000, mux_pllp_pllc_pllm_clkm, MUX), |
1648 | PERIPH_CLK("uarte", "uart.4", NULL, 66, 0x1c4, 216000000, mux_pllp_pllc_pllm_clkm, MUX), | 2172 | PERIPH_CLK("uarte", "uart.4", NULL, 66, 0x1c4, 600000000, mux_pllp_pllc_pllm_clkm, MUX), |
1649 | PERIPH_CLK("3d", "3d", NULL, 24, 0x158, 300000000, mux_pllm_pllc_pllp_plla, MUX | DIV_U71 | PERIPH_MANUAL_RESET), /* scales with voltage and process_id */ | 2173 | PERIPH_CLK("3d", "3d", NULL, 24, 0x158, 300000000, mux_pllm_pllc_pllp_plla, MUX | DIV_U71 | PERIPH_MANUAL_RESET), /* scales with voltage and process_id */ |
1650 | PERIPH_CLK("2d", "2d", NULL, 21, 0x15c, 300000000, mux_pllm_pllc_pllp_plla, MUX | DIV_U71), /* scales with voltage and process_id */ | 2174 | PERIPH_CLK("2d", "2d", NULL, 21, 0x15c, 300000000, mux_pllm_pllc_pllp_plla, MUX | DIV_U71), /* scales with voltage and process_id */ |
1651 | /* FIXME: vi and vi_sensor share an enable */ | 2175 | PERIPH_CLK("vi", "tegra_camera", "vi", 20, 0x148, 150000000, mux_pllm_pllc_pllp_plla, MUX | DIV_U71), /* scales with voltage and process_id */ |
1652 | PERIPH_CLK("vi", "vi", NULL, 20, 0x148, 150000000, mux_pllm_pllc_pllp_plla, MUX | DIV_U71), /* scales with voltage and process_id */ | 2176 | PERIPH_CLK("vi_sensor", "tegra_camera", "vi_sensor", 20, 0x1a8, 150000000, mux_pllm_pllc_pllp_plla, MUX | DIV_U71 | PERIPH_NO_RESET), /* scales with voltage and process_id */ |
1653 | PERIPH_CLK("vi_sensor", "vi_sensor", NULL, 20, 0x1a8, 150000000, mux_pllm_pllc_pllp_plla, MUX | DIV_U71 | PERIPH_NO_RESET), /* scales with voltage and process_id */ | ||
1654 | PERIPH_CLK("epp", "epp", NULL, 19, 0x16c, 300000000, mux_pllm_pllc_pllp_plla, MUX | DIV_U71), /* scales with voltage and process_id */ | 2177 | PERIPH_CLK("epp", "epp", NULL, 19, 0x16c, 300000000, mux_pllm_pllc_pllp_plla, MUX | DIV_U71), /* scales with voltage and process_id */ |
1655 | PERIPH_CLK("mpe", "mpe", NULL, 60, 0x170, 250000000, mux_pllm_pllc_pllp_plla, MUX | DIV_U71), /* scales with voltage and process_id */ | 2178 | PERIPH_CLK("mpe", "mpe", NULL, 60, 0x170, 250000000, mux_pllm_pllc_pllp_plla, MUX | DIV_U71), /* scales with voltage and process_id */ |
1656 | PERIPH_CLK("host1x", "host1x", NULL, 28, 0x180, 166000000, mux_pllm_pllc_pllp_plla, MUX | DIV_U71), /* scales with voltage and process_id */ | 2179 | PERIPH_CLK("host1x", "host1x", NULL, 28, 0x180, 166000000, mux_pllm_pllc_pllp_plla, MUX | DIV_U71), /* scales with voltage and process_id */ |
1657 | /* FIXME: cve and tvo share an enable */ | ||
1658 | PERIPH_CLK("cve", "cve", NULL, 49, 0x140, 250000000, mux_pllp_plld_pllc_clkm, MUX | DIV_U71), /* requires min voltage */ | 2180 | PERIPH_CLK("cve", "cve", NULL, 49, 0x140, 250000000, mux_pllp_plld_pllc_clkm, MUX | DIV_U71), /* requires min voltage */ |
1659 | PERIPH_CLK("tvo", "tvo", NULL, 49, 0x188, 250000000, mux_pllp_plld_pllc_clkm, MUX | DIV_U71), /* requires min voltage */ | 2181 | PERIPH_CLK("tvo", "tvo", NULL, 49, 0x188, 250000000, mux_pllp_plld_pllc_clkm, MUX | DIV_U71), /* requires min voltage */ |
1660 | PERIPH_CLK("hdmi", "hdmi", NULL, 51, 0x18c, 148500000, mux_pllp_plld_pllc_clkm, MUX | DIV_U71), /* requires min voltage */ | 2182 | PERIPH_CLK("hdmi", "hdmi", NULL, 51, 0x18c, 600000000, mux_pllp_plld_pllc_clkm, MUX | DIV_U71), /* requires min voltage */ |
1661 | PERIPH_CLK("tvdac", "tvdac", NULL, 53, 0x194, 250000000, mux_pllp_plld_pllc_clkm, MUX | DIV_U71), /* requires min voltage */ | 2183 | PERIPH_CLK("tvdac", "tvdac", NULL, 53, 0x194, 250000000, mux_pllp_plld_pllc_clkm, MUX | DIV_U71), /* requires min voltage */ |
1662 | PERIPH_CLK("disp1", "tegrafb.0", NULL, 27, 0x138, 190000000, mux_pllp_plld_pllc_clkm, MUX | DIV_U71), /* scales with voltage and process_id */ | 2184 | PERIPH_CLK("disp1", "tegradc.0", NULL, 27, 0x138, 600000000, mux_pllp_plld_pllc_clkm, MUX | DIV_U71), /* scales with voltage and process_id */ |
1663 | PERIPH_CLK("disp2", "tegrafb.1", NULL, 26, 0x13c, 190000000, mux_pllp_plld_pllc_clkm, MUX | DIV_U71), /* scales with voltage and process_id */ | 2185 | PERIPH_CLK("disp2", "tegradc.1", NULL, 26, 0x13c, 600000000, mux_pllp_plld_pllc_clkm, MUX | DIV_U71), /* scales with voltage and process_id */ |
1664 | PERIPH_CLK("usbd", "fsl-tegra-udc", NULL, 22, 0, 480000000, mux_clk_m, 0), /* requires min voltage */ | 2186 | PERIPH_CLK("usbd", "fsl-tegra-udc", NULL, 22, 0, 480000000, mux_clk_m, 0), /* requires min voltage */ |
1665 | PERIPH_CLK("usb2", "tegra-ehci.1", NULL, 58, 0, 480000000, mux_clk_m, 0), /* requires min voltage */ | 2187 | PERIPH_CLK("usb2", "tegra-ehci.1", NULL, 58, 0, 480000000, mux_clk_m, 0), /* requires min voltage */ |
1666 | PERIPH_CLK("usb3", "tegra-ehci.2", NULL, 59, 0, 480000000, mux_clk_m, 0), /* requires min voltage */ | 2188 | PERIPH_CLK("usb3", "tegra-ehci.2", NULL, 59, 0, 480000000, mux_clk_m, 0), /* requires min voltage */ |
1667 | PERIPH_CLK("emc", "emc", NULL, 57, 0x19c, 800000000, mux_pllm_pllc_pllp_clkm, MUX | DIV_U71 | PERIPH_EMC_ENB), | ||
1668 | PERIPH_CLK("dsi", "dsi", NULL, 48, 0, 500000000, mux_plld, 0), /* scales with voltage */ | 2189 | PERIPH_CLK("dsi", "dsi", NULL, 48, 0, 500000000, mux_plld, 0), /* scales with voltage */ |
1669 | PERIPH_CLK("csi", "csi", NULL, 52, 0, 72000000, mux_pllp_out3, 0), | 2190 | PERIPH_CLK("csi", "tegra_camera", "csi", 52, 0, 72000000, mux_pllp_out3, 0), |
1670 | PERIPH_CLK("isp", "isp", NULL, 23, 0, 150000000, mux_clk_m, 0), /* same frequency as VI */ | 2191 | PERIPH_CLK("isp", "tegra_camera", "isp", 23, 0, 150000000, mux_clk_m, 0), /* same frequency as VI */ |
1671 | PERIPH_CLK("csus", "csus", NULL, 92, 0, 150000000, mux_clk_m, PERIPH_NO_RESET), | 2192 | PERIPH_CLK("csus", "tegra_camera", "csus", 92, 0, 150000000, mux_clk_m, PERIPH_NO_RESET), |
1672 | PERIPH_CLK("pex", NULL, "pex", 70, 0, 26000000, mux_clk_m, PERIPH_MANUAL_RESET), | 2193 | PERIPH_CLK("pex", NULL, "pex", 70, 0, 26000000, mux_clk_m, PERIPH_MANUAL_RESET), |
1673 | PERIPH_CLK("afi", NULL, "afi", 72, 0, 26000000, mux_clk_m, PERIPH_MANUAL_RESET), | 2194 | PERIPH_CLK("afi", NULL, "afi", 72, 0, 26000000, mux_clk_m, PERIPH_MANUAL_RESET), |
1674 | PERIPH_CLK("pcie_xclk", NULL, "pcie_xclk", 74, 0, 26000000, mux_clk_m, PERIPH_MANUAL_RESET), | 2195 | PERIPH_CLK("pcie_xclk", NULL, "pcie_xclk", 74, 0, 26000000, mux_clk_m, PERIPH_MANUAL_RESET), |
2196 | |||
2197 | SHARED_CLK("avp.sclk", "tegra-avp", "sclk", &tegra_clk_sclk), | ||
2198 | SHARED_CLK("avp.emc", "tegra-avp", "emc", &tegra_clk_emc), | ||
2199 | SHARED_CLK("cpu.emc", "cpu", "emc", &tegra_clk_emc), | ||
2200 | SHARED_CLK("disp1.emc", "tegradc.0", "emc", &tegra_clk_emc), | ||
2201 | SHARED_CLK("disp2.emc", "tegradc.1", "emc", &tegra_clk_emc), | ||
2202 | SHARED_CLK("hdmi.emc", "hdmi", "emc", &tegra_clk_emc), | ||
2203 | SHARED_CLK("host.emc", "tegra_grhost", "emc", &tegra_clk_emc), | ||
2204 | SHARED_CLK("usbd.emc", "fsl-tegra-udc", "emc", &tegra_clk_emc), | ||
2205 | SHARED_CLK("usb1.emc", "tegra-ehci.0", "emc", &tegra_clk_emc), | ||
2206 | SHARED_CLK("usb2.emc", "tegra-ehci.1", "emc", &tegra_clk_emc), | ||
2207 | SHARED_CLK("usb3.emc", "tegra-ehci.2", "emc", &tegra_clk_emc), | ||
1675 | }; | 2208 | }; |
1676 | 2209 | ||
1677 | #define CLK_DUPLICATE(_name, _dev, _con) \ | 2210 | #define CLK_DUPLICATE(_name, _dev, _con) \ |
@@ -1693,9 +2226,22 @@ struct clk_duplicate tegra_clk_duplicates[] = { | |||
1693 | CLK_DUPLICATE("uartc", "tegra_uart.2", NULL), | 2226 | CLK_DUPLICATE("uartc", "tegra_uart.2", NULL), |
1694 | CLK_DUPLICATE("uartd", "tegra_uart.3", NULL), | 2227 | CLK_DUPLICATE("uartd", "tegra_uart.3", NULL), |
1695 | CLK_DUPLICATE("uarte", "tegra_uart.4", NULL), | 2228 | CLK_DUPLICATE("uarte", "tegra_uart.4", NULL), |
1696 | CLK_DUPLICATE("host1x", "tegrafb.0", "host1x"), | 2229 | CLK_DUPLICATE("usbd", "utmip-pad", NULL), |
1697 | CLK_DUPLICATE("host1x", "tegrafb.1", "host1x"), | ||
1698 | CLK_DUPLICATE("usbd", "tegra-ehci.0", NULL), | 2230 | CLK_DUPLICATE("usbd", "tegra-ehci.0", NULL), |
2231 | CLK_DUPLICATE("usbd", "tegra-otg", NULL), | ||
2232 | CLK_DUPLICATE("hdmi", "tegradc.0", "hdmi"), | ||
2233 | CLK_DUPLICATE("hdmi", "tegradc.1", "hdmi"), | ||
2234 | CLK_DUPLICATE("pwm", "tegra_pwm.0", NULL), | ||
2235 | CLK_DUPLICATE("pwm", "tegra_pwm.1", NULL), | ||
2236 | CLK_DUPLICATE("pwm", "tegra_pwm.2", NULL), | ||
2237 | CLK_DUPLICATE("pwm", "tegra_pwm.3", NULL), | ||
2238 | CLK_DUPLICATE("host1x", "tegra_grhost", "host1x"), | ||
2239 | CLK_DUPLICATE("2d", "tegra_grhost", "gr2d"), | ||
2240 | CLK_DUPLICATE("3d", "tegra_grhost", "gr3d"), | ||
2241 | CLK_DUPLICATE("epp", "tegra_grhost", "epp"), | ||
2242 | CLK_DUPLICATE("mpe", "tegra_grhost", "mpe"), | ||
2243 | CLK_DUPLICATE("cop", "tegra-avp", "cop"), | ||
2244 | CLK_DUPLICATE("vde", "tegra-aes", "vde"), | ||
1699 | }; | 2245 | }; |
1700 | 2246 | ||
1701 | #define CLK(dev, con, ck) \ | 2247 | #define CLK(dev, con, ck) \ |
@@ -1705,68 +2251,70 @@ struct clk_duplicate tegra_clk_duplicates[] = { | |||
1705 | .clk = ck, \ | 2251 | .clk = ck, \ |
1706 | } | 2252 | } |
1707 | 2253 | ||
1708 | struct clk_lookup tegra_clk_lookups[] = { | 2254 | struct clk *tegra_ptr_clks[] = { |
1709 | /* external root sources */ | 2255 | &tegra_clk_32k, |
1710 | CLK(NULL, "32k_clk", &tegra_clk_32k), | 2256 | &tegra_pll_s, |
1711 | CLK(NULL, "pll_s", &tegra_pll_s), | 2257 | &tegra_clk_m, |
1712 | CLK(NULL, "clk_m", &tegra_clk_m), | 2258 | &tegra_pll_m, |
1713 | CLK(NULL, "pll_m", &tegra_pll_m), | 2259 | &tegra_pll_m_out1, |
1714 | CLK(NULL, "pll_m_out1", &tegra_pll_m_out1), | 2260 | &tegra_pll_c, |
1715 | CLK(NULL, "pll_c", &tegra_pll_c), | 2261 | &tegra_pll_c_out1, |
1716 | CLK(NULL, "pll_c_out1", &tegra_pll_c_out1), | 2262 | &tegra_pll_p, |
1717 | CLK(NULL, "pll_p", &tegra_pll_p), | 2263 | &tegra_pll_p_out1, |
1718 | CLK(NULL, "pll_p_out1", &tegra_pll_p_out1), | 2264 | &tegra_pll_p_out2, |
1719 | CLK(NULL, "pll_p_out2", &tegra_pll_p_out2), | 2265 | &tegra_pll_p_out3, |
1720 | CLK(NULL, "pll_p_out3", &tegra_pll_p_out3), | 2266 | &tegra_pll_p_out4, |
1721 | CLK(NULL, "pll_p_out4", &tegra_pll_p_out4), | 2267 | &tegra_pll_a, |
1722 | CLK(NULL, "pll_a", &tegra_pll_a), | 2268 | &tegra_pll_a_out0, |
1723 | CLK(NULL, "pll_a_out0", &tegra_pll_a_out0), | 2269 | &tegra_pll_d, |
1724 | CLK(NULL, "pll_d", &tegra_pll_d), | 2270 | &tegra_pll_d_out0, |
1725 | CLK(NULL, "pll_d_out0", &tegra_pll_d_out0), | 2271 | &tegra_pll_u, |
1726 | CLK(NULL, "pll_u", &tegra_pll_u), | 2272 | &tegra_pll_x, |
1727 | CLK(NULL, "pll_x", &tegra_pll_x), | 2273 | &tegra_pll_e, |
1728 | CLK(NULL, "pll_e", &tegra_pll_e), | 2274 | &tegra_clk_cclk, |
1729 | CLK(NULL, "cclk", &tegra_clk_cclk), | 2275 | &tegra_clk_sclk, |
1730 | CLK(NULL, "sclk", &tegra_clk_sclk), | 2276 | &tegra_clk_hclk, |
1731 | CLK(NULL, "hclk", &tegra_clk_hclk), | 2277 | &tegra_clk_pclk, |
1732 | CLK(NULL, "pclk", &tegra_clk_pclk), | 2278 | &tegra_clk_d, |
1733 | CLK(NULL, "clk_d", &tegra_clk_d), | 2279 | &tegra_clk_cdev1, |
1734 | CLK(NULL, "cpu", &tegra_clk_virtual_cpu), | 2280 | &tegra_clk_cdev2, |
1735 | }; | 2281 | &tegra_clk_virtual_cpu, |
2282 | &tegra_clk_blink, | ||
2283 | &tegra_clk_cop, | ||
2284 | &tegra_clk_emc, | ||
2285 | }; | ||
2286 | |||
2287 | static void tegra2_init_one_clock(struct clk *c) | ||
2288 | { | ||
2289 | clk_init(c); | ||
2290 | INIT_LIST_HEAD(&c->shared_bus_list); | ||
2291 | if (!c->lookup.dev_id && !c->lookup.con_id) | ||
2292 | c->lookup.con_id = c->name; | ||
2293 | c->lookup.clk = c; | ||
2294 | clkdev_add(&c->lookup); | ||
2295 | } | ||
1736 | 2296 | ||
1737 | void __init tegra2_init_clocks(void) | 2297 | void __init tegra2_init_clocks(void) |
1738 | { | 2298 | { |
1739 | int i; | 2299 | int i; |
1740 | struct clk_lookup *cl; | ||
1741 | struct clk *c; | 2300 | struct clk *c; |
1742 | struct clk_duplicate *cd; | ||
1743 | |||
1744 | for (i = 0; i < ARRAY_SIZE(tegra_clk_lookups); i++) { | ||
1745 | cl = &tegra_clk_lookups[i]; | ||
1746 | clk_init(cl->clk); | ||
1747 | clkdev_add(cl); | ||
1748 | } | ||
1749 | 2301 | ||
1750 | for (i = 0; i < ARRAY_SIZE(tegra_periph_clks); i++) { | 2302 | for (i = 0; i < ARRAY_SIZE(tegra_ptr_clks); i++) |
1751 | c = &tegra_periph_clks[i]; | 2303 | tegra2_init_one_clock(tegra_ptr_clks[i]); |
1752 | cl = &c->lookup; | ||
1753 | cl->clk = c; | ||
1754 | 2304 | ||
1755 | clk_init(cl->clk); | 2305 | for (i = 0; i < ARRAY_SIZE(tegra_list_clks); i++) |
1756 | clkdev_add(cl); | 2306 | tegra2_init_one_clock(&tegra_list_clks[i]); |
1757 | } | ||
1758 | 2307 | ||
1759 | for (i = 0; i < ARRAY_SIZE(tegra_clk_duplicates); i++) { | 2308 | for (i = 0; i < ARRAY_SIZE(tegra_clk_duplicates); i++) { |
1760 | cd = &tegra_clk_duplicates[i]; | 2309 | c = tegra_get_clock_by_name(tegra_clk_duplicates[i].name); |
1761 | c = tegra_get_clock_by_name(cd->name); | 2310 | if (!c) { |
1762 | if (c) { | ||
1763 | cl = &cd->lookup; | ||
1764 | cl->clk = c; | ||
1765 | clkdev_add(cl); | ||
1766 | } else { | ||
1767 | pr_err("%s: Unknown duplicate clock %s\n", __func__, | 2311 | pr_err("%s: Unknown duplicate clock %s\n", __func__, |
1768 | cd->name); | 2312 | tegra_clk_duplicates[i].name); |
2313 | continue; | ||
1769 | } | 2314 | } |
2315 | |||
2316 | tegra_clk_duplicates[i].lookup.clk = c; | ||
2317 | clkdev_add(&tegra_clk_duplicates[i].lookup); | ||
1770 | } | 2318 | } |
1771 | 2319 | ||
1772 | init_audio_sync_clock_mux(); | 2320 | init_audio_sync_clock_mux(); |
@@ -1774,7 +2322,7 @@ void __init tegra2_init_clocks(void) | |||
1774 | 2322 | ||
1775 | #ifdef CONFIG_PM | 2323 | #ifdef CONFIG_PM |
1776 | static u32 clk_rst_suspend[RST_DEVICES_NUM + CLK_OUT_ENB_NUM + | 2324 | static u32 clk_rst_suspend[RST_DEVICES_NUM + CLK_OUT_ENB_NUM + |
1777 | PERIPH_CLK_SOURCE_NUM + 3]; | 2325 | PERIPH_CLK_SOURCE_NUM + 22]; |
1778 | 2326 | ||
1779 | void tegra_clk_suspend(void) | 2327 | void tegra_clk_suspend(void) |
1780 | { | 2328 | { |
@@ -1782,6 +2330,29 @@ void tegra_clk_suspend(void) | |||
1782 | u32 *ctx = clk_rst_suspend; | 2330 | u32 *ctx = clk_rst_suspend; |
1783 | 2331 | ||
1784 | *ctx++ = clk_readl(OSC_CTRL) & OSC_CTRL_MASK; | 2332 | *ctx++ = clk_readl(OSC_CTRL) & OSC_CTRL_MASK; |
2333 | *ctx++ = clk_readl(tegra_pll_c.reg + PLL_BASE); | ||
2334 | *ctx++ = clk_readl(tegra_pll_c.reg + PLL_MISC(&tegra_pll_c)); | ||
2335 | *ctx++ = clk_readl(tegra_pll_a.reg + PLL_BASE); | ||
2336 | *ctx++ = clk_readl(tegra_pll_a.reg + PLL_MISC(&tegra_pll_a)); | ||
2337 | *ctx++ = clk_readl(tegra_pll_s.reg + PLL_BASE); | ||
2338 | *ctx++ = clk_readl(tegra_pll_s.reg + PLL_MISC(&tegra_pll_s)); | ||
2339 | *ctx++ = clk_readl(tegra_pll_d.reg + PLL_BASE); | ||
2340 | *ctx++ = clk_readl(tegra_pll_d.reg + PLL_MISC(&tegra_pll_d)); | ||
2341 | *ctx++ = clk_readl(tegra_pll_u.reg + PLL_BASE); | ||
2342 | *ctx++ = clk_readl(tegra_pll_u.reg + PLL_MISC(&tegra_pll_u)); | ||
2343 | |||
2344 | *ctx++ = clk_readl(tegra_pll_m_out1.reg); | ||
2345 | *ctx++ = clk_readl(tegra_pll_a_out0.reg); | ||
2346 | *ctx++ = clk_readl(tegra_pll_c_out1.reg); | ||
2347 | |||
2348 | *ctx++ = clk_readl(tegra_clk_cclk.reg); | ||
2349 | *ctx++ = clk_readl(tegra_clk_cclk.reg + SUPER_CLK_DIVIDER); | ||
2350 | |||
2351 | *ctx++ = clk_readl(tegra_clk_sclk.reg); | ||
2352 | *ctx++ = clk_readl(tegra_clk_sclk.reg + SUPER_CLK_DIVIDER); | ||
2353 | *ctx++ = clk_readl(tegra_clk_pclk.reg); | ||
2354 | |||
2355 | *ctx++ = clk_readl(tegra_clk_audio.reg); | ||
1785 | 2356 | ||
1786 | for (off = PERIPH_CLK_SOURCE_I2S1; off <= PERIPH_CLK_SOURCE_OSC; | 2357 | for (off = PERIPH_CLK_SOURCE_I2S1; off <= PERIPH_CLK_SOURCE_OSC; |
1787 | off += 4) { | 2358 | off += 4) { |
@@ -1800,6 +2371,8 @@ void tegra_clk_suspend(void) | |||
1800 | 2371 | ||
1801 | *ctx++ = clk_readl(MISC_CLK_ENB); | 2372 | *ctx++ = clk_readl(MISC_CLK_ENB); |
1802 | *ctx++ = clk_readl(CLK_MASK_ARM); | 2373 | *ctx++ = clk_readl(CLK_MASK_ARM); |
2374 | |||
2375 | BUG_ON(ctx - clk_rst_suspend != ARRAY_SIZE(clk_rst_suspend)); | ||
1803 | } | 2376 | } |
1804 | 2377 | ||
1805 | void tegra_clk_resume(void) | 2378 | void tegra_clk_resume(void) |
@@ -1812,6 +2385,31 @@ void tegra_clk_resume(void) | |||
1812 | val |= *ctx++; | 2385 | val |= *ctx++; |
1813 | clk_writel(val, OSC_CTRL); | 2386 | clk_writel(val, OSC_CTRL); |
1814 | 2387 | ||
2388 | clk_writel(*ctx++, tegra_pll_c.reg + PLL_BASE); | ||
2389 | clk_writel(*ctx++, tegra_pll_c.reg + PLL_MISC(&tegra_pll_c)); | ||
2390 | clk_writel(*ctx++, tegra_pll_a.reg + PLL_BASE); | ||
2391 | clk_writel(*ctx++, tegra_pll_a.reg + PLL_MISC(&tegra_pll_a)); | ||
2392 | clk_writel(*ctx++, tegra_pll_s.reg + PLL_BASE); | ||
2393 | clk_writel(*ctx++, tegra_pll_s.reg + PLL_MISC(&tegra_pll_s)); | ||
2394 | clk_writel(*ctx++, tegra_pll_d.reg + PLL_BASE); | ||
2395 | clk_writel(*ctx++, tegra_pll_d.reg + PLL_MISC(&tegra_pll_d)); | ||
2396 | clk_writel(*ctx++, tegra_pll_u.reg + PLL_BASE); | ||
2397 | clk_writel(*ctx++, tegra_pll_u.reg + PLL_MISC(&tegra_pll_u)); | ||
2398 | udelay(1000); | ||
2399 | |||
2400 | clk_writel(*ctx++, tegra_pll_m_out1.reg); | ||
2401 | clk_writel(*ctx++, tegra_pll_a_out0.reg); | ||
2402 | clk_writel(*ctx++, tegra_pll_c_out1.reg); | ||
2403 | |||
2404 | clk_writel(*ctx++, tegra_clk_cclk.reg); | ||
2405 | clk_writel(*ctx++, tegra_clk_cclk.reg + SUPER_CLK_DIVIDER); | ||
2406 | |||
2407 | clk_writel(*ctx++, tegra_clk_sclk.reg); | ||
2408 | clk_writel(*ctx++, tegra_clk_sclk.reg + SUPER_CLK_DIVIDER); | ||
2409 | clk_writel(*ctx++, tegra_clk_pclk.reg); | ||
2410 | |||
2411 | clk_writel(*ctx++, tegra_clk_audio.reg); | ||
2412 | |||
1815 | /* enable all clocks before configuring clock sources */ | 2413 | /* enable all clocks before configuring clock sources */ |
1816 | clk_writel(0xbffffff9ul, CLK_OUT_ENB); | 2414 | clk_writel(0xbffffff9ul, CLK_OUT_ENB); |
1817 | clk_writel(0xfefffff7ul, CLK_OUT_ENB + 4); | 2415 | clk_writel(0xfefffff7ul, CLK_OUT_ENB + 4); |
diff --git a/arch/arm/mach-tegra/tegra2_dvfs.c b/arch/arm/mach-tegra/tegra2_dvfs.c deleted file mode 100644 index 5529c238dd77..000000000000 --- a/arch/arm/mach-tegra/tegra2_dvfs.c +++ /dev/null | |||
@@ -1,86 +0,0 @@ | |||
1 | /* | ||
2 | * arch/arm/mach-tegra/tegra2_dvfs.c | ||
3 | * | ||
4 | * Copyright (C) 2010 Google, Inc. | ||
5 | * | ||
6 | * Author: | ||
7 | * Colin Cross <ccross@google.com> | ||
8 | * | ||
9 | * This software is licensed under the terms of the GNU General Public | ||
10 | * License version 2, as published by the Free Software Foundation, and | ||
11 | * may be copied, distributed, and modified under those terms. | ||
12 | * | ||
13 | * This program is distributed in the hope that it will be useful, | ||
14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
16 | * GNU General Public License for more details. | ||
17 | * | ||
18 | */ | ||
19 | |||
20 | #include <linux/kernel.h> | ||
21 | |||
22 | #include "clock.h" | ||
23 | #include "tegra2_dvfs.h" | ||
24 | |||
25 | static struct dvfs_table virtual_cpu_process_0[] = { | ||
26 | {314000000, 750}, | ||
27 | {456000000, 825}, | ||
28 | {608000000, 900}, | ||
29 | {760000000, 975}, | ||
30 | {817000000, 1000}, | ||
31 | {912000000, 1050}, | ||
32 | {1000000000, 1100}, | ||
33 | {0, 0}, | ||
34 | }; | ||
35 | |||
36 | static struct dvfs_table virtual_cpu_process_1[] = { | ||
37 | {314000000, 750}, | ||
38 | {456000000, 825}, | ||
39 | {618000000, 900}, | ||
40 | {770000000, 975}, | ||
41 | {827000000, 1000}, | ||
42 | {922000000, 1050}, | ||
43 | {1000000000, 1100}, | ||
44 | {0, 0}, | ||
45 | }; | ||
46 | |||
47 | static struct dvfs_table virtual_cpu_process_2[] = { | ||
48 | {494000000, 750}, | ||
49 | {675000000, 825}, | ||
50 | {817000000, 875}, | ||
51 | {922000000, 925}, | ||
52 | {1000000000, 975}, | ||
53 | {0, 0}, | ||
54 | }; | ||
55 | |||
56 | static struct dvfs_table virtual_cpu_process_3[] = { | ||
57 | {730000000, 750}, | ||
58 | {760000000, 775}, | ||
59 | {845000000, 800}, | ||
60 | {1000000000, 875}, | ||
61 | {0, 0}, | ||
62 | }; | ||
63 | |||
64 | struct dvfs tegra_dvfs_virtual_cpu_dvfs = { | ||
65 | .reg_id = "vdd_cpu", | ||
66 | .process_id_table = { | ||
67 | { | ||
68 | .process_id = 0, | ||
69 | .table = virtual_cpu_process_0, | ||
70 | }, | ||
71 | { | ||
72 | .process_id = 1, | ||
73 | .table = virtual_cpu_process_1, | ||
74 | }, | ||
75 | { | ||
76 | .process_id = 2, | ||
77 | .table = virtual_cpu_process_2, | ||
78 | }, | ||
79 | { | ||
80 | .process_id = 3, | ||
81 | .table = virtual_cpu_process_3, | ||
82 | }, | ||
83 | }, | ||
84 | .process_id_table_length = 4, | ||
85 | .cpu = 1, | ||
86 | }; | ||
diff --git a/arch/arm/mach-tegra/tegra2_emc.c b/arch/arm/mach-tegra/tegra2_emc.c new file mode 100644 index 000000000000..0f7ae6e90b55 --- /dev/null +++ b/arch/arm/mach-tegra/tegra2_emc.c | |||
@@ -0,0 +1,178 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2011 Google, Inc. | ||
3 | * | ||
4 | * Author: | ||
5 | * Colin Cross <ccross@android.com> | ||
6 | * | ||
7 | * This software is licensed under the terms of the GNU General Public | ||
8 | * License version 2, as published by the Free Software Foundation, and | ||
9 | * may be copied, distributed, and modified under those terms. | ||
10 | * | ||
11 | * This program is distributed in the hope that it will be useful, | ||
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
14 | * GNU General Public License for more details. | ||
15 | * | ||
16 | */ | ||
17 | |||
18 | #include <linux/kernel.h> | ||
19 | #include <linux/clk.h> | ||
20 | #include <linux/err.h> | ||
21 | #include <linux/io.h> | ||
22 | #include <linux/module.h> | ||
23 | |||
24 | #include <mach/iomap.h> | ||
25 | |||
26 | #include "tegra2_emc.h" | ||
27 | |||
28 | #ifdef CONFIG_TEGRA_EMC_SCALING_ENABLE | ||
29 | static bool emc_enable = true; | ||
30 | #else | ||
31 | static bool emc_enable; | ||
32 | #endif | ||
33 | module_param(emc_enable, bool, 0644); | ||
34 | |||
35 | static void __iomem *emc = IO_ADDRESS(TEGRA_EMC_BASE); | ||
36 | static const struct tegra_emc_table *tegra_emc_table; | ||
37 | static int tegra_emc_table_size; | ||
38 | |||
39 | static inline void emc_writel(u32 val, unsigned long addr) | ||
40 | { | ||
41 | writel(val, emc + addr); | ||
42 | } | ||
43 | |||
44 | static inline u32 emc_readl(unsigned long addr) | ||
45 | { | ||
46 | return readl(emc + addr); | ||
47 | } | ||
48 | |||
49 | static const unsigned long emc_reg_addr[TEGRA_EMC_NUM_REGS] = { | ||
50 | 0x2c, /* RC */ | ||
51 | 0x30, /* RFC */ | ||
52 | 0x34, /* RAS */ | ||
53 | 0x38, /* RP */ | ||
54 | 0x3c, /* R2W */ | ||
55 | 0x40, /* W2R */ | ||
56 | 0x44, /* R2P */ | ||
57 | 0x48, /* W2P */ | ||
58 | 0x4c, /* RD_RCD */ | ||
59 | 0x50, /* WR_RCD */ | ||
60 | 0x54, /* RRD */ | ||
61 | 0x58, /* REXT */ | ||
62 | 0x5c, /* WDV */ | ||
63 | 0x60, /* QUSE */ | ||
64 | 0x64, /* QRST */ | ||
65 | 0x68, /* QSAFE */ | ||
66 | 0x6c, /* RDV */ | ||
67 | 0x70, /* REFRESH */ | ||
68 | 0x74, /* BURST_REFRESH_NUM */ | ||
69 | 0x78, /* PDEX2WR */ | ||
70 | 0x7c, /* PDEX2RD */ | ||
71 | 0x80, /* PCHG2PDEN */ | ||
72 | 0x84, /* ACT2PDEN */ | ||
73 | 0x88, /* AR2PDEN */ | ||
74 | 0x8c, /* RW2PDEN */ | ||
75 | 0x90, /* TXSR */ | ||
76 | 0x94, /* TCKE */ | ||
77 | 0x98, /* TFAW */ | ||
78 | 0x9c, /* TRPAB */ | ||
79 | 0xa0, /* TCLKSTABLE */ | ||
80 | 0xa4, /* TCLKSTOP */ | ||
81 | 0xa8, /* TREFBW */ | ||
82 | 0xac, /* QUSE_EXTRA */ | ||
83 | 0x114, /* FBIO_CFG6 */ | ||
84 | 0xb0, /* ODT_WRITE */ | ||
85 | 0xb4, /* ODT_READ */ | ||
86 | 0x104, /* FBIO_CFG5 */ | ||
87 | 0x2bc, /* CFG_DIG_DLL */ | ||
88 | 0x2c0, /* DLL_XFORM_DQS */ | ||
89 | 0x2c4, /* DLL_XFORM_QUSE */ | ||
90 | 0x2e0, /* ZCAL_REF_CNT */ | ||
91 | 0x2e4, /* ZCAL_WAIT_CNT */ | ||
92 | 0x2a8, /* AUTO_CAL_INTERVAL */ | ||
93 | 0x2d0, /* CFG_CLKTRIM_0 */ | ||
94 | 0x2d4, /* CFG_CLKTRIM_1 */ | ||
95 | 0x2d8, /* CFG_CLKTRIM_2 */ | ||
96 | }; | ||
97 | |||
98 | /* Select the closest EMC rate that is higher than the requested rate */ | ||
99 | long tegra_emc_round_rate(unsigned long rate) | ||
100 | { | ||
101 | int i; | ||
102 | int best = -1; | ||
103 | unsigned long distance = ULONG_MAX; | ||
104 | |||
105 | if (!tegra_emc_table) | ||
106 | return -EINVAL; | ||
107 | |||
108 | if (!emc_enable) | ||
109 | return -EINVAL; | ||
110 | |||
111 | pr_debug("%s: %lu\n", __func__, rate); | ||
112 | |||
113 | /* | ||
114 | * The EMC clock rate is twice the bus rate, and the bus rate is | ||
115 | * measured in kHz | ||
116 | */ | ||
117 | rate = rate / 2 / 1000; | ||
118 | |||
119 | for (i = 0; i < tegra_emc_table_size; i++) { | ||
120 | if (tegra_emc_table[i].rate >= rate && | ||
121 | (tegra_emc_table[i].rate - rate) < distance) { | ||
122 | distance = tegra_emc_table[i].rate - rate; | ||
123 | best = i; | ||
124 | } | ||
125 | } | ||
126 | |||
127 | if (best < 0) | ||
128 | return -EINVAL; | ||
129 | |||
130 | pr_debug("%s: using %lu\n", __func__, tegra_emc_table[best].rate); | ||
131 | |||
132 | return tegra_emc_table[best].rate * 2 * 1000; | ||
133 | } | ||
134 | |||
135 | /* | ||
136 | * The EMC registers have shadow registers. When the EMC clock is updated | ||
137 | * in the clock controller, the shadow registers are copied to the active | ||
138 | * registers, allowing glitchless memory bus frequency changes. | ||
139 | * This function updates the shadow registers for a new clock frequency, | ||
140 | * and relies on the clock lock on the emc clock to avoid races between | ||
141 | * multiple frequency changes | ||
142 | */ | ||
143 | int tegra_emc_set_rate(unsigned long rate) | ||
144 | { | ||
145 | int i; | ||
146 | int j; | ||
147 | |||
148 | if (!tegra_emc_table) | ||
149 | return -EINVAL; | ||
150 | |||
151 | /* | ||
152 | * The EMC clock rate is twice the bus rate, and the bus rate is | ||
153 | * measured in kHz | ||
154 | */ | ||
155 | rate = rate / 2 / 1000; | ||
156 | |||
157 | for (i = 0; i < tegra_emc_table_size; i++) | ||
158 | if (tegra_emc_table[i].rate == rate) | ||
159 | break; | ||
160 | |||
161 | if (i >= tegra_emc_table_size) | ||
162 | return -EINVAL; | ||
163 | |||
164 | pr_debug("%s: setting to %lu\n", __func__, rate); | ||
165 | |||
166 | for (j = 0; j < TEGRA_EMC_NUM_REGS; j++) | ||
167 | emc_writel(tegra_emc_table[i].regs[j], emc_reg_addr[j]); | ||
168 | |||
169 | emc_readl(tegra_emc_table[i].regs[TEGRA_EMC_NUM_REGS - 1]); | ||
170 | |||
171 | return 0; | ||
172 | } | ||
173 | |||
174 | void tegra_init_emc(const struct tegra_emc_table *table, int table_size) | ||
175 | { | ||
176 | tegra_emc_table = table; | ||
177 | tegra_emc_table_size = table_size; | ||
178 | } | ||
diff --git a/arch/arm/mach-tegra/tegra2_emc.h b/arch/arm/mach-tegra/tegra2_emc.h new file mode 100644 index 000000000000..19f08cb31603 --- /dev/null +++ b/arch/arm/mach-tegra/tegra2_emc.h | |||
@@ -0,0 +1,27 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2011 Google, Inc. | ||
3 | * | ||
4 | * Author: | ||
5 | * Colin Cross <ccross@android.com> | ||
6 | * | ||
7 | * This software is licensed under the terms of the GNU General Public | ||
8 | * License version 2, as published by the Free Software Foundation, and | ||
9 | * may be copied, distributed, and modified under those terms. | ||
10 | * | ||
11 | * This program is distributed in the hope that it will be useful, | ||
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
14 | * GNU General Public License for more details. | ||
15 | * | ||
16 | */ | ||
17 | |||
18 | #define TEGRA_EMC_NUM_REGS 46 | ||
19 | |||
20 | struct tegra_emc_table { | ||
21 | unsigned long rate; | ||
22 | u32 regs[TEGRA_EMC_NUM_REGS]; | ||
23 | }; | ||
24 | |||
25 | int tegra_emc_set_rate(unsigned long rate); | ||
26 | long tegra_emc_round_rate(unsigned long rate); | ||
27 | void tegra_init_emc(const struct tegra_emc_table *table, int table_size); | ||
diff --git a/arch/arm/mach-tegra/timer.c b/arch/arm/mach-tegra/timer.c index 7b8ad1f98f44..0fcb1eb4214d 100644 --- a/arch/arm/mach-tegra/timer.c +++ b/arch/arm/mach-tegra/timer.c | |||
@@ -18,6 +18,7 @@ | |||
18 | */ | 18 | */ |
19 | 19 | ||
20 | #include <linux/init.h> | 20 | #include <linux/init.h> |
21 | #include <linux/err.h> | ||
21 | #include <linux/sched.h> | 22 | #include <linux/sched.h> |
22 | #include <linux/time.h> | 23 | #include <linux/time.h> |
23 | #include <linux/interrupt.h> | 24 | #include <linux/interrupt.h> |
@@ -33,10 +34,15 @@ | |||
33 | 34 | ||
34 | #include <mach/iomap.h> | 35 | #include <mach/iomap.h> |
35 | #include <mach/irqs.h> | 36 | #include <mach/irqs.h> |
37 | #include <mach/suspend.h> | ||
36 | 38 | ||
37 | #include "board.h" | 39 | #include "board.h" |
38 | #include "clock.h" | 40 | #include "clock.h" |
39 | 41 | ||
42 | #define RTC_SECONDS 0x08 | ||
43 | #define RTC_SHADOW_SECONDS 0x0c | ||
44 | #define RTC_MILLISECONDS 0x10 | ||
45 | |||
40 | #define TIMERUS_CNTR_1US 0x10 | 46 | #define TIMERUS_CNTR_1US 0x10 |
41 | #define TIMERUS_USEC_CFG 0x14 | 47 | #define TIMERUS_USEC_CFG 0x14 |
42 | #define TIMERUS_CNTR_FREEZE 0x4c | 48 | #define TIMERUS_CNTR_FREEZE 0x4c |
@@ -49,9 +55,11 @@ | |||
49 | #define TIMER_PTV 0x0 | 55 | #define TIMER_PTV 0x0 |
50 | #define TIMER_PCR 0x4 | 56 | #define TIMER_PCR 0x4 |
51 | 57 | ||
52 | struct tegra_timer; | ||
53 | |||
54 | static void __iomem *timer_reg_base = IO_ADDRESS(TEGRA_TMR1_BASE); | 58 | static void __iomem *timer_reg_base = IO_ADDRESS(TEGRA_TMR1_BASE); |
59 | static void __iomem *rtc_base = IO_ADDRESS(TEGRA_RTC_BASE); | ||
60 | |||
61 | static struct timespec persistent_ts; | ||
62 | static u64 persistent_ms, last_persistent_ms; | ||
55 | 63 | ||
56 | #define timer_writel(value, reg) \ | 64 | #define timer_writel(value, reg) \ |
57 | __raw_writel(value, (u32)timer_reg_base + (reg)) | 65 | __raw_writel(value, (u32)timer_reg_base + (reg)) |
@@ -132,6 +140,42 @@ static void notrace tegra_update_sched_clock(void) | |||
132 | update_sched_clock(&cd, cyc, (u32)~0); | 140 | update_sched_clock(&cd, cyc, (u32)~0); |
133 | } | 141 | } |
134 | 142 | ||
143 | /* | ||
144 | * tegra_rtc_read - Reads the Tegra RTC registers | ||
145 | * Care must be taken that this funciton is not called while the | ||
146 | * tegra_rtc driver could be executing to avoid race conditions | ||
147 | * on the RTC shadow register | ||
148 | */ | ||
149 | u64 tegra_rtc_read_ms(void) | ||
150 | { | ||
151 | u32 ms = readl(rtc_base + RTC_MILLISECONDS); | ||
152 | u32 s = readl(rtc_base + RTC_SHADOW_SECONDS); | ||
153 | return (u64)s * MSEC_PER_SEC + ms; | ||
154 | } | ||
155 | |||
156 | /* | ||
157 | * read_persistent_clock - Return time from a persistent clock. | ||
158 | * | ||
159 | * Reads the time from a source which isn't disabled during PM, the | ||
160 | * 32k sync timer. Convert the cycles elapsed since last read into | ||
161 | * nsecs and adds to a monotonically increasing timespec. | ||
162 | * Care must be taken that this funciton is not called while the | ||
163 | * tegra_rtc driver could be executing to avoid race conditions | ||
164 | * on the RTC shadow register | ||
165 | */ | ||
166 | void read_persistent_clock(struct timespec *ts) | ||
167 | { | ||
168 | u64 delta; | ||
169 | struct timespec *tsp = &persistent_ts; | ||
170 | |||
171 | last_persistent_ms = persistent_ms; | ||
172 | persistent_ms = tegra_rtc_read_ms(); | ||
173 | delta = persistent_ms - last_persistent_ms; | ||
174 | |||
175 | timespec_add_ns(tsp, delta * NSEC_PER_MSEC); | ||
176 | *ts = *tsp; | ||
177 | } | ||
178 | |||
135 | static irqreturn_t tegra_timer_interrupt(int irq, void *dev_id) | 179 | static irqreturn_t tegra_timer_interrupt(int irq, void *dev_id) |
136 | { | 180 | { |
137 | struct clock_event_device *evt = (struct clock_event_device *)dev_id; | 181 | struct clock_event_device *evt = (struct clock_event_device *)dev_id; |
@@ -150,9 +194,22 @@ static struct irqaction tegra_timer_irq = { | |||
150 | 194 | ||
151 | static void __init tegra_init_timer(void) | 195 | static void __init tegra_init_timer(void) |
152 | { | 196 | { |
197 | struct clk *clk; | ||
153 | unsigned long rate = clk_measure_input_freq(); | 198 | unsigned long rate = clk_measure_input_freq(); |
154 | int ret; | 199 | int ret; |
155 | 200 | ||
201 | clk = clk_get_sys("timer", NULL); | ||
202 | BUG_ON(IS_ERR(clk)); | ||
203 | clk_enable(clk); | ||
204 | |||
205 | /* | ||
206 | * rtc registers are used by read_persistent_clock, keep the rtc clock | ||
207 | * enabled | ||
208 | */ | ||
209 | clk = clk_get_sys("rtc-tegra", NULL); | ||
210 | BUG_ON(IS_ERR(clk)); | ||
211 | clk_enable(clk); | ||
212 | |||
156 | #ifdef CONFIG_HAVE_ARM_TWD | 213 | #ifdef CONFIG_HAVE_ARM_TWD |
157 | twd_base = IO_ADDRESS(TEGRA_ARM_PERIF_BASE + 0x600); | 214 | twd_base = IO_ADDRESS(TEGRA_ARM_PERIF_BASE + 0x600); |
158 | #endif | 215 | #endif |
@@ -196,10 +253,22 @@ static void __init tegra_init_timer(void) | |||
196 | tegra_clockevent.cpumask = cpu_all_mask; | 253 | tegra_clockevent.cpumask = cpu_all_mask; |
197 | tegra_clockevent.irq = tegra_timer_irq.irq; | 254 | tegra_clockevent.irq = tegra_timer_irq.irq; |
198 | clockevents_register_device(&tegra_clockevent); | 255 | clockevents_register_device(&tegra_clockevent); |
199 | |||
200 | return; | ||
201 | } | 256 | } |
202 | 257 | ||
203 | struct sys_timer tegra_timer = { | 258 | struct sys_timer tegra_timer = { |
204 | .init = tegra_init_timer, | 259 | .init = tegra_init_timer, |
205 | }; | 260 | }; |
261 | |||
262 | #ifdef CONFIG_PM | ||
263 | static u32 usec_config; | ||
264 | |||
265 | void tegra_timer_suspend(void) | ||
266 | { | ||
267 | usec_config = timer_readl(TIMERUS_USEC_CFG); | ||
268 | } | ||
269 | |||
270 | void tegra_timer_resume(void) | ||
271 | { | ||
272 | timer_writel(usec_config, TIMERUS_USEC_CFG); | ||
273 | } | ||
274 | #endif | ||
diff --git a/arch/arm/mach-tegra/usb_phy.c b/arch/arm/mach-tegra/usb_phy.c new file mode 100644 index 000000000000..88081bb3ec52 --- /dev/null +++ b/arch/arm/mach-tegra/usb_phy.c | |||
@@ -0,0 +1,795 @@ | |||
1 | /* | ||
2 | * arch/arm/mach-tegra/usb_phy.c | ||
3 | * | ||
4 | * Copyright (C) 2010 Google, Inc. | ||
5 | * | ||
6 | * Author: | ||
7 | * Erik Gilling <konkers@google.com> | ||
8 | * Benoit Goby <benoit@android.com> | ||
9 | * | ||
10 | * This software is licensed under the terms of the GNU General Public | ||
11 | * License version 2, as published by the Free Software Foundation, and | ||
12 | * may be copied, distributed, and modified under those terms. | ||
13 | * | ||
14 | * This program is distributed in the hope that it will be useful, | ||
15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
17 | * GNU General Public License for more details. | ||
18 | * | ||
19 | */ | ||
20 | |||
21 | #include <linux/resource.h> | ||
22 | #include <linux/delay.h> | ||
23 | #include <linux/slab.h> | ||
24 | #include <linux/err.h> | ||
25 | #include <linux/platform_device.h> | ||
26 | #include <linux/io.h> | ||
27 | #include <linux/gpio.h> | ||
28 | #include <linux/usb/otg.h> | ||
29 | #include <linux/usb/ulpi.h> | ||
30 | #include <asm/mach-types.h> | ||
31 | #include <mach/usb_phy.h> | ||
32 | #include <mach/iomap.h> | ||
33 | |||
34 | #define ULPI_VIEWPORT 0x170 | ||
35 | |||
36 | #define USB_PORTSC1 0x184 | ||
37 | #define USB_PORTSC1_PTS(x) (((x) & 0x3) << 30) | ||
38 | #define USB_PORTSC1_PSPD(x) (((x) & 0x3) << 26) | ||
39 | #define USB_PORTSC1_PHCD (1 << 23) | ||
40 | #define USB_PORTSC1_WKOC (1 << 22) | ||
41 | #define USB_PORTSC1_WKDS (1 << 21) | ||
42 | #define USB_PORTSC1_WKCN (1 << 20) | ||
43 | #define USB_PORTSC1_PTC(x) (((x) & 0xf) << 16) | ||
44 | #define USB_PORTSC1_PP (1 << 12) | ||
45 | #define USB_PORTSC1_SUSP (1 << 7) | ||
46 | #define USB_PORTSC1_PE (1 << 2) | ||
47 | #define USB_PORTSC1_CCS (1 << 0) | ||
48 | |||
49 | #define USB_SUSP_CTRL 0x400 | ||
50 | #define USB_WAKE_ON_CNNT_EN_DEV (1 << 3) | ||
51 | #define USB_WAKE_ON_DISCON_EN_DEV (1 << 4) | ||
52 | #define USB_SUSP_CLR (1 << 5) | ||
53 | #define USB_PHY_CLK_VALID (1 << 7) | ||
54 | #define UTMIP_RESET (1 << 11) | ||
55 | #define UHSIC_RESET (1 << 11) | ||
56 | #define UTMIP_PHY_ENABLE (1 << 12) | ||
57 | #define ULPI_PHY_ENABLE (1 << 13) | ||
58 | #define USB_SUSP_SET (1 << 14) | ||
59 | #define USB_WAKEUP_DEBOUNCE_COUNT(x) (((x) & 0x7) << 16) | ||
60 | |||
61 | #define USB1_LEGACY_CTRL 0x410 | ||
62 | #define USB1_NO_LEGACY_MODE (1 << 0) | ||
63 | #define USB1_VBUS_SENSE_CTL_MASK (3 << 1) | ||
64 | #define USB1_VBUS_SENSE_CTL_VBUS_WAKEUP (0 << 1) | ||
65 | #define USB1_VBUS_SENSE_CTL_AB_SESS_VLD_OR_VBUS_WAKEUP \ | ||
66 | (1 << 1) | ||
67 | #define USB1_VBUS_SENSE_CTL_AB_SESS_VLD (2 << 1) | ||
68 | #define USB1_VBUS_SENSE_CTL_A_SESS_VLD (3 << 1) | ||
69 | |||
70 | #define ULPI_TIMING_CTRL_0 0x424 | ||
71 | #define ULPI_OUTPUT_PINMUX_BYP (1 << 10) | ||
72 | #define ULPI_CLKOUT_PINMUX_BYP (1 << 11) | ||
73 | |||
74 | #define ULPI_TIMING_CTRL_1 0x428 | ||
75 | #define ULPI_DATA_TRIMMER_LOAD (1 << 0) | ||
76 | #define ULPI_DATA_TRIMMER_SEL(x) (((x) & 0x7) << 1) | ||
77 | #define ULPI_STPDIRNXT_TRIMMER_LOAD (1 << 16) | ||
78 | #define ULPI_STPDIRNXT_TRIMMER_SEL(x) (((x) & 0x7) << 17) | ||
79 | #define ULPI_DIR_TRIMMER_LOAD (1 << 24) | ||
80 | #define ULPI_DIR_TRIMMER_SEL(x) (((x) & 0x7) << 25) | ||
81 | |||
82 | #define UTMIP_PLL_CFG1 0x804 | ||
83 | #define UTMIP_XTAL_FREQ_COUNT(x) (((x) & 0xfff) << 0) | ||
84 | #define UTMIP_PLLU_ENABLE_DLY_COUNT(x) (((x) & 0x1f) << 27) | ||
85 | |||
86 | #define UTMIP_XCVR_CFG0 0x808 | ||
87 | #define UTMIP_XCVR_SETUP(x) (((x) & 0xf) << 0) | ||
88 | #define UTMIP_XCVR_LSRSLEW(x) (((x) & 0x3) << 8) | ||
89 | #define UTMIP_XCVR_LSFSLEW(x) (((x) & 0x3) << 10) | ||
90 | #define UTMIP_FORCE_PD_POWERDOWN (1 << 14) | ||
91 | #define UTMIP_FORCE_PD2_POWERDOWN (1 << 16) | ||
92 | #define UTMIP_FORCE_PDZI_POWERDOWN (1 << 18) | ||
93 | #define UTMIP_XCVR_HSSLEW_MSB(x) (((x) & 0x7f) << 25) | ||
94 | |||
95 | #define UTMIP_BIAS_CFG0 0x80c | ||
96 | #define UTMIP_OTGPD (1 << 11) | ||
97 | #define UTMIP_BIASPD (1 << 10) | ||
98 | |||
99 | #define UTMIP_HSRX_CFG0 0x810 | ||
100 | #define UTMIP_ELASTIC_LIMIT(x) (((x) & 0x1f) << 10) | ||
101 | #define UTMIP_IDLE_WAIT(x) (((x) & 0x1f) << 15) | ||
102 | |||
103 | #define UTMIP_HSRX_CFG1 0x814 | ||
104 | #define UTMIP_HS_SYNC_START_DLY(x) (((x) & 0x1f) << 1) | ||
105 | |||
106 | #define UTMIP_TX_CFG0 0x820 | ||
107 | #define UTMIP_FS_PREABMLE_J (1 << 19) | ||
108 | #define UTMIP_HS_DISCON_DISABLE (1 << 8) | ||
109 | |||
110 | #define UTMIP_MISC_CFG0 0x824 | ||
111 | #define UTMIP_DPDM_OBSERVE (1 << 26) | ||
112 | #define UTMIP_DPDM_OBSERVE_SEL(x) (((x) & 0xf) << 27) | ||
113 | #define UTMIP_DPDM_OBSERVE_SEL_FS_J UTMIP_DPDM_OBSERVE_SEL(0xf) | ||
114 | #define UTMIP_DPDM_OBSERVE_SEL_FS_K UTMIP_DPDM_OBSERVE_SEL(0xe) | ||
115 | #define UTMIP_DPDM_OBSERVE_SEL_FS_SE1 UTMIP_DPDM_OBSERVE_SEL(0xd) | ||
116 | #define UTMIP_DPDM_OBSERVE_SEL_FS_SE0 UTMIP_DPDM_OBSERVE_SEL(0xc) | ||
117 | #define UTMIP_SUSPEND_EXIT_ON_EDGE (1 << 22) | ||
118 | |||
119 | #define UTMIP_MISC_CFG1 0x828 | ||
120 | #define UTMIP_PLL_ACTIVE_DLY_COUNT(x) (((x) & 0x1f) << 18) | ||
121 | #define UTMIP_PLLU_STABLE_COUNT(x) (((x) & 0xfff) << 6) | ||
122 | |||
123 | #define UTMIP_DEBOUNCE_CFG0 0x82c | ||
124 | #define UTMIP_BIAS_DEBOUNCE_A(x) (((x) & 0xffff) << 0) | ||
125 | |||
126 | #define UTMIP_BAT_CHRG_CFG0 0x830 | ||
127 | #define UTMIP_PD_CHRG (1 << 0) | ||
128 | |||
129 | #define UTMIP_SPARE_CFG0 0x834 | ||
130 | #define FUSE_SETUP_SEL (1 << 3) | ||
131 | |||
132 | #define UTMIP_XCVR_CFG1 0x838 | ||
133 | #define UTMIP_FORCE_PDDISC_POWERDOWN (1 << 0) | ||
134 | #define UTMIP_FORCE_PDCHRP_POWERDOWN (1 << 2) | ||
135 | #define UTMIP_FORCE_PDDR_POWERDOWN (1 << 4) | ||
136 | #define UTMIP_XCVR_TERM_RANGE_ADJ(x) (((x) & 0xf) << 18) | ||
137 | |||
138 | #define UTMIP_BIAS_CFG1 0x83c | ||
139 | #define UTMIP_BIAS_PDTRK_COUNT(x) (((x) & 0x1f) << 3) | ||
140 | |||
141 | static DEFINE_SPINLOCK(utmip_pad_lock); | ||
142 | static int utmip_pad_count; | ||
143 | |||
144 | struct tegra_xtal_freq { | ||
145 | int freq; | ||
146 | u8 enable_delay; | ||
147 | u8 stable_count; | ||
148 | u8 active_delay; | ||
149 | u8 xtal_freq_count; | ||
150 | u16 debounce; | ||
151 | }; | ||
152 | |||
153 | static const struct tegra_xtal_freq tegra_freq_table[] = { | ||
154 | { | ||
155 | .freq = 12000000, | ||
156 | .enable_delay = 0x02, | ||
157 | .stable_count = 0x2F, | ||
158 | .active_delay = 0x04, | ||
159 | .xtal_freq_count = 0x76, | ||
160 | .debounce = 0x7530, | ||
161 | }, | ||
162 | { | ||
163 | .freq = 13000000, | ||
164 | .enable_delay = 0x02, | ||
165 | .stable_count = 0x33, | ||
166 | .active_delay = 0x05, | ||
167 | .xtal_freq_count = 0x7F, | ||
168 | .debounce = 0x7EF4, | ||
169 | }, | ||
170 | { | ||
171 | .freq = 19200000, | ||
172 | .enable_delay = 0x03, | ||
173 | .stable_count = 0x4B, | ||
174 | .active_delay = 0x06, | ||
175 | .xtal_freq_count = 0xBB, | ||
176 | .debounce = 0xBB80, | ||
177 | }, | ||
178 | { | ||
179 | .freq = 26000000, | ||
180 | .enable_delay = 0x04, | ||
181 | .stable_count = 0x66, | ||
182 | .active_delay = 0x09, | ||
183 | .xtal_freq_count = 0xFE, | ||
184 | .debounce = 0xFDE8, | ||
185 | }, | ||
186 | }; | ||
187 | |||
188 | static struct tegra_utmip_config utmip_default[] = { | ||
189 | [0] = { | ||
190 | .hssync_start_delay = 9, | ||
191 | .idle_wait_delay = 17, | ||
192 | .elastic_limit = 16, | ||
193 | .term_range_adj = 6, | ||
194 | .xcvr_setup = 9, | ||
195 | .xcvr_lsfslew = 1, | ||
196 | .xcvr_lsrslew = 1, | ||
197 | }, | ||
198 | [2] = { | ||
199 | .hssync_start_delay = 9, | ||
200 | .idle_wait_delay = 17, | ||
201 | .elastic_limit = 16, | ||
202 | .term_range_adj = 6, | ||
203 | .xcvr_setup = 9, | ||
204 | .xcvr_lsfslew = 2, | ||
205 | .xcvr_lsrslew = 2, | ||
206 | }, | ||
207 | }; | ||
208 | |||
209 | static inline bool phy_is_ulpi(struct tegra_usb_phy *phy) | ||
210 | { | ||
211 | return (phy->instance == 1); | ||
212 | } | ||
213 | |||
214 | static int utmip_pad_open(struct tegra_usb_phy *phy) | ||
215 | { | ||
216 | phy->pad_clk = clk_get_sys("utmip-pad", NULL); | ||
217 | if (IS_ERR(phy->pad_clk)) { | ||
218 | pr_err("%s: can't get utmip pad clock\n", __func__); | ||
219 | return PTR_ERR(phy->pad_clk); | ||
220 | } | ||
221 | |||
222 | if (phy->instance == 0) { | ||
223 | phy->pad_regs = phy->regs; | ||
224 | } else { | ||
225 | phy->pad_regs = ioremap(TEGRA_USB_BASE, TEGRA_USB_SIZE); | ||
226 | if (!phy->pad_regs) { | ||
227 | pr_err("%s: can't remap usb registers\n", __func__); | ||
228 | clk_put(phy->pad_clk); | ||
229 | return -ENOMEM; | ||
230 | } | ||
231 | } | ||
232 | return 0; | ||
233 | } | ||
234 | |||
235 | static void utmip_pad_close(struct tegra_usb_phy *phy) | ||
236 | { | ||
237 | if (phy->instance != 0) | ||
238 | iounmap(phy->pad_regs); | ||
239 | clk_put(phy->pad_clk); | ||
240 | } | ||
241 | |||
242 | static void utmip_pad_power_on(struct tegra_usb_phy *phy) | ||
243 | { | ||
244 | unsigned long val, flags; | ||
245 | void __iomem *base = phy->pad_regs; | ||
246 | |||
247 | clk_enable(phy->pad_clk); | ||
248 | |||
249 | spin_lock_irqsave(&utmip_pad_lock, flags); | ||
250 | |||
251 | if (utmip_pad_count++ == 0) { | ||
252 | val = readl(base + UTMIP_BIAS_CFG0); | ||
253 | val &= ~(UTMIP_OTGPD | UTMIP_BIASPD); | ||
254 | writel(val, base + UTMIP_BIAS_CFG0); | ||
255 | } | ||
256 | |||
257 | spin_unlock_irqrestore(&utmip_pad_lock, flags); | ||
258 | |||
259 | clk_disable(phy->pad_clk); | ||
260 | } | ||
261 | |||
262 | static int utmip_pad_power_off(struct tegra_usb_phy *phy) | ||
263 | { | ||
264 | unsigned long val, flags; | ||
265 | void __iomem *base = phy->pad_regs; | ||
266 | |||
267 | if (!utmip_pad_count) { | ||
268 | pr_err("%s: utmip pad already powered off\n", __func__); | ||
269 | return -EINVAL; | ||
270 | } | ||
271 | |||
272 | clk_enable(phy->pad_clk); | ||
273 | |||
274 | spin_lock_irqsave(&utmip_pad_lock, flags); | ||
275 | |||
276 | if (--utmip_pad_count == 0) { | ||
277 | val = readl(base + UTMIP_BIAS_CFG0); | ||
278 | val |= UTMIP_OTGPD | UTMIP_BIASPD; | ||
279 | writel(val, base + UTMIP_BIAS_CFG0); | ||
280 | } | ||
281 | |||
282 | spin_unlock_irqrestore(&utmip_pad_lock, flags); | ||
283 | |||
284 | clk_disable(phy->pad_clk); | ||
285 | |||
286 | return 0; | ||
287 | } | ||
288 | |||
289 | static int utmi_wait_register(void __iomem *reg, u32 mask, u32 result) | ||
290 | { | ||
291 | unsigned long timeout = 2000; | ||
292 | do { | ||
293 | if ((readl(reg) & mask) == result) | ||
294 | return 0; | ||
295 | udelay(1); | ||
296 | timeout--; | ||
297 | } while (timeout); | ||
298 | return -1; | ||
299 | } | ||
300 | |||
301 | static void utmi_phy_clk_disable(struct tegra_usb_phy *phy) | ||
302 | { | ||
303 | unsigned long val; | ||
304 | void __iomem *base = phy->regs; | ||
305 | |||
306 | if (phy->instance == 0) { | ||
307 | val = readl(base + USB_SUSP_CTRL); | ||
308 | val |= USB_SUSP_SET; | ||
309 | writel(val, base + USB_SUSP_CTRL); | ||
310 | |||
311 | udelay(10); | ||
312 | |||
313 | val = readl(base + USB_SUSP_CTRL); | ||
314 | val &= ~USB_SUSP_SET; | ||
315 | writel(val, base + USB_SUSP_CTRL); | ||
316 | } | ||
317 | |||
318 | if (phy->instance == 2) { | ||
319 | val = readl(base + USB_PORTSC1); | ||
320 | val |= USB_PORTSC1_PHCD; | ||
321 | writel(val, base + USB_PORTSC1); | ||
322 | } | ||
323 | |||
324 | if (utmi_wait_register(base + USB_SUSP_CTRL, USB_PHY_CLK_VALID, 0) < 0) | ||
325 | pr_err("%s: timeout waiting for phy to stabilize\n", __func__); | ||
326 | } | ||
327 | |||
328 | static void utmi_phy_clk_enable(struct tegra_usb_phy *phy) | ||
329 | { | ||
330 | unsigned long val; | ||
331 | void __iomem *base = phy->regs; | ||
332 | |||
333 | if (phy->instance == 0) { | ||
334 | val = readl(base + USB_SUSP_CTRL); | ||
335 | val |= USB_SUSP_CLR; | ||
336 | writel(val, base + USB_SUSP_CTRL); | ||
337 | |||
338 | udelay(10); | ||
339 | |||
340 | val = readl(base + USB_SUSP_CTRL); | ||
341 | val &= ~USB_SUSP_CLR; | ||
342 | writel(val, base + USB_SUSP_CTRL); | ||
343 | } | ||
344 | |||
345 | if (phy->instance == 2) { | ||
346 | val = readl(base + USB_PORTSC1); | ||
347 | val &= ~USB_PORTSC1_PHCD; | ||
348 | writel(val, base + USB_PORTSC1); | ||
349 | } | ||
350 | |||
351 | if (utmi_wait_register(base + USB_SUSP_CTRL, USB_PHY_CLK_VALID, | ||
352 | USB_PHY_CLK_VALID)) | ||
353 | pr_err("%s: timeout waiting for phy to stabilize\n", __func__); | ||
354 | } | ||
355 | |||
356 | static int utmi_phy_power_on(struct tegra_usb_phy *phy) | ||
357 | { | ||
358 | unsigned long val; | ||
359 | void __iomem *base = phy->regs; | ||
360 | struct tegra_utmip_config *config = phy->config; | ||
361 | |||
362 | val = readl(base + USB_SUSP_CTRL); | ||
363 | val |= UTMIP_RESET; | ||
364 | writel(val, base + USB_SUSP_CTRL); | ||
365 | |||
366 | if (phy->instance == 0) { | ||
367 | val = readl(base + USB1_LEGACY_CTRL); | ||
368 | val |= USB1_NO_LEGACY_MODE; | ||
369 | writel(val, base + USB1_LEGACY_CTRL); | ||
370 | } | ||
371 | |||
372 | val = readl(base + UTMIP_TX_CFG0); | ||
373 | val &= ~UTMIP_FS_PREABMLE_J; | ||
374 | writel(val, base + UTMIP_TX_CFG0); | ||
375 | |||
376 | val = readl(base + UTMIP_HSRX_CFG0); | ||
377 | val &= ~(UTMIP_IDLE_WAIT(~0) | UTMIP_ELASTIC_LIMIT(~0)); | ||
378 | val |= UTMIP_IDLE_WAIT(config->idle_wait_delay); | ||
379 | val |= UTMIP_ELASTIC_LIMIT(config->elastic_limit); | ||
380 | writel(val, base + UTMIP_HSRX_CFG0); | ||
381 | |||
382 | val = readl(base + UTMIP_HSRX_CFG1); | ||
383 | val &= ~UTMIP_HS_SYNC_START_DLY(~0); | ||
384 | val |= UTMIP_HS_SYNC_START_DLY(config->hssync_start_delay); | ||
385 | writel(val, base + UTMIP_HSRX_CFG1); | ||
386 | |||
387 | val = readl(base + UTMIP_DEBOUNCE_CFG0); | ||
388 | val &= ~UTMIP_BIAS_DEBOUNCE_A(~0); | ||
389 | val |= UTMIP_BIAS_DEBOUNCE_A(phy->freq->debounce); | ||
390 | writel(val, base + UTMIP_DEBOUNCE_CFG0); | ||
391 | |||
392 | val = readl(base + UTMIP_MISC_CFG0); | ||
393 | val &= ~UTMIP_SUSPEND_EXIT_ON_EDGE; | ||
394 | writel(val, base + UTMIP_MISC_CFG0); | ||
395 | |||
396 | val = readl(base + UTMIP_MISC_CFG1); | ||
397 | val &= ~(UTMIP_PLL_ACTIVE_DLY_COUNT(~0) | UTMIP_PLLU_STABLE_COUNT(~0)); | ||
398 | val |= UTMIP_PLL_ACTIVE_DLY_COUNT(phy->freq->active_delay) | | ||
399 | UTMIP_PLLU_STABLE_COUNT(phy->freq->stable_count); | ||
400 | writel(val, base + UTMIP_MISC_CFG1); | ||
401 | |||
402 | val = readl(base + UTMIP_PLL_CFG1); | ||
403 | val &= ~(UTMIP_XTAL_FREQ_COUNT(~0) | UTMIP_PLLU_ENABLE_DLY_COUNT(~0)); | ||
404 | val |= UTMIP_XTAL_FREQ_COUNT(phy->freq->xtal_freq_count) | | ||
405 | UTMIP_PLLU_ENABLE_DLY_COUNT(phy->freq->enable_delay); | ||
406 | writel(val, base + UTMIP_PLL_CFG1); | ||
407 | |||
408 | if (phy->mode == TEGRA_USB_PHY_MODE_DEVICE) { | ||
409 | val = readl(base + USB_SUSP_CTRL); | ||
410 | val &= ~(USB_WAKE_ON_CNNT_EN_DEV | USB_WAKE_ON_DISCON_EN_DEV); | ||
411 | writel(val, base + USB_SUSP_CTRL); | ||
412 | } | ||
413 | |||
414 | utmip_pad_power_on(phy); | ||
415 | |||
416 | val = readl(base + UTMIP_XCVR_CFG0); | ||
417 | val &= ~(UTMIP_FORCE_PD_POWERDOWN | UTMIP_FORCE_PD2_POWERDOWN | | ||
418 | UTMIP_FORCE_PDZI_POWERDOWN | UTMIP_XCVR_SETUP(~0) | | ||
419 | UTMIP_XCVR_LSFSLEW(~0) | UTMIP_XCVR_LSRSLEW(~0) | | ||
420 | UTMIP_XCVR_HSSLEW_MSB(~0)); | ||
421 | val |= UTMIP_XCVR_SETUP(config->xcvr_setup); | ||
422 | val |= UTMIP_XCVR_LSFSLEW(config->xcvr_lsfslew); | ||
423 | val |= UTMIP_XCVR_LSRSLEW(config->xcvr_lsrslew); | ||
424 | writel(val, base + UTMIP_XCVR_CFG0); | ||
425 | |||
426 | val = readl(base + UTMIP_XCVR_CFG1); | ||
427 | val &= ~(UTMIP_FORCE_PDDISC_POWERDOWN | UTMIP_FORCE_PDCHRP_POWERDOWN | | ||
428 | UTMIP_FORCE_PDDR_POWERDOWN | UTMIP_XCVR_TERM_RANGE_ADJ(~0)); | ||
429 | val |= UTMIP_XCVR_TERM_RANGE_ADJ(config->term_range_adj); | ||
430 | writel(val, base + UTMIP_XCVR_CFG1); | ||
431 | |||
432 | val = readl(base + UTMIP_BAT_CHRG_CFG0); | ||
433 | val &= ~UTMIP_PD_CHRG; | ||
434 | writel(val, base + UTMIP_BAT_CHRG_CFG0); | ||
435 | |||
436 | val = readl(base + UTMIP_BIAS_CFG1); | ||
437 | val &= ~UTMIP_BIAS_PDTRK_COUNT(~0); | ||
438 | val |= UTMIP_BIAS_PDTRK_COUNT(0x5); | ||
439 | writel(val, base + UTMIP_BIAS_CFG1); | ||
440 | |||
441 | if (phy->instance == 0) { | ||
442 | val = readl(base + UTMIP_SPARE_CFG0); | ||
443 | if (phy->mode == TEGRA_USB_PHY_MODE_DEVICE) | ||
444 | val &= ~FUSE_SETUP_SEL; | ||
445 | else | ||
446 | val |= FUSE_SETUP_SEL; | ||
447 | writel(val, base + UTMIP_SPARE_CFG0); | ||
448 | } | ||
449 | |||
450 | if (phy->instance == 2) { | ||
451 | val = readl(base + USB_SUSP_CTRL); | ||
452 | val |= UTMIP_PHY_ENABLE; | ||
453 | writel(val, base + USB_SUSP_CTRL); | ||
454 | } | ||
455 | |||
456 | val = readl(base + USB_SUSP_CTRL); | ||
457 | val &= ~UTMIP_RESET; | ||
458 | writel(val, base + USB_SUSP_CTRL); | ||
459 | |||
460 | if (phy->instance == 0) { | ||
461 | val = readl(base + USB1_LEGACY_CTRL); | ||
462 | val &= ~USB1_VBUS_SENSE_CTL_MASK; | ||
463 | val |= USB1_VBUS_SENSE_CTL_A_SESS_VLD; | ||
464 | writel(val, base + USB1_LEGACY_CTRL); | ||
465 | |||
466 | val = readl(base + USB_SUSP_CTRL); | ||
467 | val &= ~USB_SUSP_SET; | ||
468 | writel(val, base + USB_SUSP_CTRL); | ||
469 | } | ||
470 | |||
471 | utmi_phy_clk_enable(phy); | ||
472 | |||
473 | if (phy->instance == 2) { | ||
474 | val = readl(base + USB_PORTSC1); | ||
475 | val &= ~USB_PORTSC1_PTS(~0); | ||
476 | writel(val, base + USB_PORTSC1); | ||
477 | } | ||
478 | |||
479 | return 0; | ||
480 | } | ||
481 | |||
482 | static void utmi_phy_power_off(struct tegra_usb_phy *phy) | ||
483 | { | ||
484 | unsigned long val; | ||
485 | void __iomem *base = phy->regs; | ||
486 | |||
487 | utmi_phy_clk_disable(phy); | ||
488 | |||
489 | if (phy->mode == TEGRA_USB_PHY_MODE_DEVICE) { | ||
490 | val = readl(base + USB_SUSP_CTRL); | ||
491 | val &= ~USB_WAKEUP_DEBOUNCE_COUNT(~0); | ||
492 | val |= USB_WAKE_ON_CNNT_EN_DEV | USB_WAKEUP_DEBOUNCE_COUNT(5); | ||
493 | writel(val, base + USB_SUSP_CTRL); | ||
494 | } | ||
495 | |||
496 | val = readl(base + USB_SUSP_CTRL); | ||
497 | val |= UTMIP_RESET; | ||
498 | writel(val, base + USB_SUSP_CTRL); | ||
499 | |||
500 | val = readl(base + UTMIP_BAT_CHRG_CFG0); | ||
501 | val |= UTMIP_PD_CHRG; | ||
502 | writel(val, base + UTMIP_BAT_CHRG_CFG0); | ||
503 | |||
504 | val = readl(base + UTMIP_XCVR_CFG0); | ||
505 | val |= UTMIP_FORCE_PD_POWERDOWN | UTMIP_FORCE_PD2_POWERDOWN | | ||
506 | UTMIP_FORCE_PDZI_POWERDOWN; | ||
507 | writel(val, base + UTMIP_XCVR_CFG0); | ||
508 | |||
509 | val = readl(base + UTMIP_XCVR_CFG1); | ||
510 | val |= UTMIP_FORCE_PDDISC_POWERDOWN | UTMIP_FORCE_PDCHRP_POWERDOWN | | ||
511 | UTMIP_FORCE_PDDR_POWERDOWN; | ||
512 | writel(val, base + UTMIP_XCVR_CFG1); | ||
513 | |||
514 | utmip_pad_power_off(phy); | ||
515 | } | ||
516 | |||
517 | static void utmi_phy_preresume(struct tegra_usb_phy *phy) | ||
518 | { | ||
519 | unsigned long val; | ||
520 | void __iomem *base = phy->regs; | ||
521 | |||
522 | val = readl(base + UTMIP_TX_CFG0); | ||
523 | val |= UTMIP_HS_DISCON_DISABLE; | ||
524 | writel(val, base + UTMIP_TX_CFG0); | ||
525 | } | ||
526 | |||
527 | static void utmi_phy_postresume(struct tegra_usb_phy *phy) | ||
528 | { | ||
529 | unsigned long val; | ||
530 | void __iomem *base = phy->regs; | ||
531 | |||
532 | val = readl(base + UTMIP_TX_CFG0); | ||
533 | val &= ~UTMIP_HS_DISCON_DISABLE; | ||
534 | writel(val, base + UTMIP_TX_CFG0); | ||
535 | } | ||
536 | |||
537 | static void utmi_phy_restore_start(struct tegra_usb_phy *phy, | ||
538 | enum tegra_usb_phy_port_speed port_speed) | ||
539 | { | ||
540 | unsigned long val; | ||
541 | void __iomem *base = phy->regs; | ||
542 | |||
543 | val = readl(base + UTMIP_MISC_CFG0); | ||
544 | val &= ~UTMIP_DPDM_OBSERVE_SEL(~0); | ||
545 | if (port_speed == TEGRA_USB_PHY_PORT_SPEED_LOW) | ||
546 | val |= UTMIP_DPDM_OBSERVE_SEL_FS_K; | ||
547 | else | ||
548 | val |= UTMIP_DPDM_OBSERVE_SEL_FS_J; | ||
549 | writel(val, base + UTMIP_MISC_CFG0); | ||
550 | udelay(1); | ||
551 | |||
552 | val = readl(base + UTMIP_MISC_CFG0); | ||
553 | val |= UTMIP_DPDM_OBSERVE; | ||
554 | writel(val, base + UTMIP_MISC_CFG0); | ||
555 | udelay(10); | ||
556 | } | ||
557 | |||
558 | static void utmi_phy_restore_end(struct tegra_usb_phy *phy) | ||
559 | { | ||
560 | unsigned long val; | ||
561 | void __iomem *base = phy->regs; | ||
562 | |||
563 | val = readl(base + UTMIP_MISC_CFG0); | ||
564 | val &= ~UTMIP_DPDM_OBSERVE; | ||
565 | writel(val, base + UTMIP_MISC_CFG0); | ||
566 | udelay(10); | ||
567 | } | ||
568 | |||
569 | static int ulpi_phy_power_on(struct tegra_usb_phy *phy) | ||
570 | { | ||
571 | int ret; | ||
572 | unsigned long val; | ||
573 | void __iomem *base = phy->regs; | ||
574 | struct tegra_ulpi_config *config = phy->config; | ||
575 | |||
576 | gpio_direction_output(config->reset_gpio, 0); | ||
577 | msleep(5); | ||
578 | gpio_direction_output(config->reset_gpio, 1); | ||
579 | |||
580 | clk_enable(phy->clk); | ||
581 | msleep(1); | ||
582 | |||
583 | val = readl(base + USB_SUSP_CTRL); | ||
584 | val |= UHSIC_RESET; | ||
585 | writel(val, base + USB_SUSP_CTRL); | ||
586 | |||
587 | val = readl(base + ULPI_TIMING_CTRL_0); | ||
588 | val |= ULPI_OUTPUT_PINMUX_BYP | ULPI_CLKOUT_PINMUX_BYP; | ||
589 | writel(val, base + ULPI_TIMING_CTRL_0); | ||
590 | |||
591 | val = readl(base + USB_SUSP_CTRL); | ||
592 | val |= ULPI_PHY_ENABLE; | ||
593 | writel(val, base + USB_SUSP_CTRL); | ||
594 | |||
595 | val = 0; | ||
596 | writel(val, base + ULPI_TIMING_CTRL_1); | ||
597 | |||
598 | val |= ULPI_DATA_TRIMMER_SEL(4); | ||
599 | val |= ULPI_STPDIRNXT_TRIMMER_SEL(4); | ||
600 | val |= ULPI_DIR_TRIMMER_SEL(4); | ||
601 | writel(val, base + ULPI_TIMING_CTRL_1); | ||
602 | udelay(10); | ||
603 | |||
604 | val |= ULPI_DATA_TRIMMER_LOAD; | ||
605 | val |= ULPI_STPDIRNXT_TRIMMER_LOAD; | ||
606 | val |= ULPI_DIR_TRIMMER_LOAD; | ||
607 | writel(val, base + ULPI_TIMING_CTRL_1); | ||
608 | |||
609 | /* Fix VbusInvalid due to floating VBUS */ | ||
610 | ret = otg_io_write(phy->ulpi, 0x40, 0x08); | ||
611 | if (ret) { | ||
612 | pr_err("%s: ulpi write failed\n", __func__); | ||
613 | return ret; | ||
614 | } | ||
615 | |||
616 | ret = otg_io_write(phy->ulpi, 0x80, 0x0B); | ||
617 | if (ret) { | ||
618 | pr_err("%s: ulpi write failed\n", __func__); | ||
619 | return ret; | ||
620 | } | ||
621 | |||
622 | val = readl(base + USB_PORTSC1); | ||
623 | val |= USB_PORTSC1_WKOC | USB_PORTSC1_WKDS | USB_PORTSC1_WKCN; | ||
624 | writel(val, base + USB_PORTSC1); | ||
625 | |||
626 | val = readl(base + USB_SUSP_CTRL); | ||
627 | val |= USB_SUSP_CLR; | ||
628 | writel(val, base + USB_SUSP_CTRL); | ||
629 | udelay(100); | ||
630 | |||
631 | val = readl(base + USB_SUSP_CTRL); | ||
632 | val &= ~USB_SUSP_CLR; | ||
633 | writel(val, base + USB_SUSP_CTRL); | ||
634 | |||
635 | return 0; | ||
636 | } | ||
637 | |||
638 | static void ulpi_phy_power_off(struct tegra_usb_phy *phy) | ||
639 | { | ||
640 | unsigned long val; | ||
641 | void __iomem *base = phy->regs; | ||
642 | struct tegra_ulpi_config *config = phy->config; | ||
643 | |||
644 | /* Clear WKCN/WKDS/WKOC wake-on events that can cause the USB | ||
645 | * Controller to immediately bring the ULPI PHY out of low power | ||
646 | */ | ||
647 | val = readl(base + USB_PORTSC1); | ||
648 | val &= ~(USB_PORTSC1_WKOC | USB_PORTSC1_WKDS | USB_PORTSC1_WKCN); | ||
649 | writel(val, base + USB_PORTSC1); | ||
650 | |||
651 | gpio_direction_output(config->reset_gpio, 0); | ||
652 | clk_disable(phy->clk); | ||
653 | } | ||
654 | |||
655 | struct tegra_usb_phy *tegra_usb_phy_open(int instance, void __iomem *regs, | ||
656 | void *config, enum tegra_usb_phy_mode phy_mode) | ||
657 | { | ||
658 | struct tegra_usb_phy *phy; | ||
659 | struct tegra_ulpi_config *ulpi_config; | ||
660 | unsigned long parent_rate; | ||
661 | int i; | ||
662 | int err; | ||
663 | |||
664 | phy = kmalloc(sizeof(struct tegra_usb_phy), GFP_KERNEL); | ||
665 | if (!phy) | ||
666 | return ERR_PTR(-ENOMEM); | ||
667 | |||
668 | phy->instance = instance; | ||
669 | phy->regs = regs; | ||
670 | phy->config = config; | ||
671 | phy->mode = phy_mode; | ||
672 | |||
673 | if (!phy->config) { | ||
674 | if (phy_is_ulpi(phy)) { | ||
675 | pr_err("%s: ulpi phy configuration missing", __func__); | ||
676 | err = -EINVAL; | ||
677 | goto err0; | ||
678 | } else { | ||
679 | phy->config = &utmip_default[instance]; | ||
680 | } | ||
681 | } | ||
682 | |||
683 | phy->pll_u = clk_get_sys(NULL, "pll_u"); | ||
684 | if (IS_ERR(phy->pll_u)) { | ||
685 | pr_err("Can't get pll_u clock\n"); | ||
686 | err = PTR_ERR(phy->pll_u); | ||
687 | goto err0; | ||
688 | } | ||
689 | clk_enable(phy->pll_u); | ||
690 | |||
691 | parent_rate = clk_get_rate(clk_get_parent(phy->pll_u)); | ||
692 | for (i = 0; i < ARRAY_SIZE(tegra_freq_table); i++) { | ||
693 | if (tegra_freq_table[i].freq == parent_rate) { | ||
694 | phy->freq = &tegra_freq_table[i]; | ||
695 | break; | ||
696 | } | ||
697 | } | ||
698 | if (!phy->freq) { | ||
699 | pr_err("invalid pll_u parent rate %ld\n", parent_rate); | ||
700 | err = -EINVAL; | ||
701 | goto err1; | ||
702 | } | ||
703 | |||
704 | if (phy_is_ulpi(phy)) { | ||
705 | ulpi_config = config; | ||
706 | phy->clk = clk_get_sys(NULL, ulpi_config->clk); | ||
707 | if (IS_ERR(phy->clk)) { | ||
708 | pr_err("%s: can't get ulpi clock\n", __func__); | ||
709 | err = -ENXIO; | ||
710 | goto err1; | ||
711 | } | ||
712 | tegra_gpio_enable(ulpi_config->reset_gpio); | ||
713 | gpio_request(ulpi_config->reset_gpio, "ulpi_phy_reset_b"); | ||
714 | gpio_direction_output(ulpi_config->reset_gpio, 0); | ||
715 | phy->ulpi = otg_ulpi_create(&ulpi_viewport_access_ops, 0); | ||
716 | phy->ulpi->io_priv = regs + ULPI_VIEWPORT; | ||
717 | } else { | ||
718 | err = utmip_pad_open(phy); | ||
719 | if (err < 0) | ||
720 | goto err1; | ||
721 | } | ||
722 | |||
723 | return phy; | ||
724 | |||
725 | err1: | ||
726 | clk_disable(phy->pll_u); | ||
727 | clk_put(phy->pll_u); | ||
728 | err0: | ||
729 | kfree(phy); | ||
730 | return ERR_PTR(err); | ||
731 | } | ||
732 | |||
733 | int tegra_usb_phy_power_on(struct tegra_usb_phy *phy) | ||
734 | { | ||
735 | if (phy_is_ulpi(phy)) | ||
736 | return ulpi_phy_power_on(phy); | ||
737 | else | ||
738 | return utmi_phy_power_on(phy); | ||
739 | } | ||
740 | |||
741 | void tegra_usb_phy_power_off(struct tegra_usb_phy *phy) | ||
742 | { | ||
743 | if (phy_is_ulpi(phy)) | ||
744 | ulpi_phy_power_off(phy); | ||
745 | else | ||
746 | utmi_phy_power_off(phy); | ||
747 | } | ||
748 | |||
749 | void tegra_usb_phy_preresume(struct tegra_usb_phy *phy) | ||
750 | { | ||
751 | if (!phy_is_ulpi(phy)) | ||
752 | utmi_phy_preresume(phy); | ||
753 | } | ||
754 | |||
755 | void tegra_usb_phy_postresume(struct tegra_usb_phy *phy) | ||
756 | { | ||
757 | if (!phy_is_ulpi(phy)) | ||
758 | utmi_phy_postresume(phy); | ||
759 | } | ||
760 | |||
761 | void tegra_ehci_phy_restore_start(struct tegra_usb_phy *phy, | ||
762 | enum tegra_usb_phy_port_speed port_speed) | ||
763 | { | ||
764 | if (!phy_is_ulpi(phy)) | ||
765 | utmi_phy_restore_start(phy, port_speed); | ||
766 | } | ||
767 | |||
768 | void tegra_ehci_phy_restore_end(struct tegra_usb_phy *phy) | ||
769 | { | ||
770 | if (!phy_is_ulpi(phy)) | ||
771 | utmi_phy_restore_end(phy); | ||
772 | } | ||
773 | |||
774 | void tegra_usb_phy_clk_disable(struct tegra_usb_phy *phy) | ||
775 | { | ||
776 | if (!phy_is_ulpi(phy)) | ||
777 | utmi_phy_clk_disable(phy); | ||
778 | } | ||
779 | |||
780 | void tegra_usb_phy_clk_enable(struct tegra_usb_phy *phy) | ||
781 | { | ||
782 | if (!phy_is_ulpi(phy)) | ||
783 | utmi_phy_clk_enable(phy); | ||
784 | } | ||
785 | |||
786 | void tegra_usb_phy_close(struct tegra_usb_phy *phy) | ||
787 | { | ||
788 | if (phy_is_ulpi(phy)) | ||
789 | clk_put(phy->clk); | ||
790 | else | ||
791 | utmip_pad_close(phy); | ||
792 | clk_disable(phy->pll_u); | ||
793 | clk_put(phy->pll_u); | ||
794 | kfree(phy); | ||
795 | } | ||