From c8b62ab41f76218efca5e4baa5c22ef52a9fe3a5 Mon Sep 17 00:00:00 2001 From: Allen Martin Date: Fri, 10 Sep 2010 09:17:33 -0500 Subject: [PATCH 1/7] ARM: tegra: Add pllc clock init table pll_c will be used as a clock source. Fill in tegra_pll_c_freq_table[] so that it's possible to explicitly initialize the PLL. NVIDIA's downstream nv-3.1 kernel and the ChromeOS kernel have different pll_c tables. nv-3.1 contains entries for 522MHz and 598MHz output, whereas the ChromeOS kernel contains entries for 600MHz output. I chose to upstream the ChromeOS values for now, since the 600MHz rate appears to match the default rate of this PLL when the HW boots, and it's not clear to me why 522 or 598MHz are more useful. Signed-off-by: Allen Martin Signed-off-by: Olof Johansson Signed-off-by: Stephen Warren [swarren: wrote commit description] --- arch/arm/mach-tegra/tegra2_clocks.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/arch/arm/mach-tegra/tegra2_clocks.c b/arch/arm/mach-tegra/tegra2_clocks.c index 592a4eeb5328..a357ad2a8cf7 100644 --- a/arch/arm/mach-tegra/tegra2_clocks.c +++ b/arch/arm/mach-tegra/tegra2_clocks.c @@ -1486,6 +1486,10 @@ static struct clk tegra_clk_m = { }; static struct clk_pll_freq_table tegra_pll_c_freq_table[] = { + { 12000000, 600000000, 600, 12, 1, 8 }, + { 13000000, 600000000, 600, 13, 1, 8 }, + { 19200000, 600000000, 500, 16, 1, 6 }, + { 26000000, 600000000, 600, 26, 1, 8 }, { 0, 0, 0, 0, 0, 0 }, }; From 60f975b98cf41476ba0e156f7523b197b046cf2b Mon Sep 17 00:00:00 2001 From: Stephen Warren Date: Thu, 12 Apr 2012 14:09:39 -0600 Subject: [PATCH 2/7] ARM: tegra: reparent sclk to pll_c_out1 pll_p_out4 needs to be used for other purposes. Reparent sclk so that it runs from pll_c. Change sclk's rate to 120MHz from 108MHz since this is the lowest precise rate that can be achieved by dividing the pll_c rate without reducing the sclk rate. (600/5=120, 600/5.5=109.0909..., 600/6=100). Signed-off-by: Stephen Warren --- arch/arm/mach-tegra/common.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/arch/arm/mach-tegra/common.c b/arch/arm/mach-tegra/common.c index 22df10fb9972..e96900418682 100644 --- a/arch/arm/mach-tegra/common.c +++ b/arch/arm/mach-tegra/common.c @@ -83,8 +83,10 @@ static __initdata struct tegra_clk_init_table tegra20_clk_init_table[] = { { "pll_p_out2", "pll_p", 48000000, true }, { "pll_p_out3", "pll_p", 72000000, true }, { "pll_p_out4", "pll_p", 108000000, true }, - { "sclk", "pll_p_out4", 108000000, true }, - { "hclk", "sclk", 108000000, true }, + { "pll_c", "clk_m", 600000000, true }, + { "pll_c_out1", "pll_c", 120000000, true }, + { "sclk", "pll_c_out1", 120000000, true }, + { "hclk", "sclk", 120000000, true }, { "pclk", "hclk", 54000000, true }, { "csite", NULL, 0, true }, { "emc", NULL, 0, true }, From 7ff4db0967bd7d617c77dc5a66c0d95166277817 Mon Sep 17 00:00:00 2001 From: Stephen Warren Date: Fri, 20 Apr 2012 16:58:18 -0600 Subject: [PATCH 3/7] ARM: tegra: fix pclk rate Commit 40f9cf0 "ARM: tegra: reparent sclk to pll_c_out1" changed the rate of hclk. Since pclk is derived from that, and only has integer dividers, the pclk rate needs to change in the same fashion, from 54MHz to 60MHz. Signed-off-by: Stephen Warren --- arch/arm/mach-tegra/common.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm/mach-tegra/common.c b/arch/arm/mach-tegra/common.c index e96900418682..a4fba8835136 100644 --- a/arch/arm/mach-tegra/common.c +++ b/arch/arm/mach-tegra/common.c @@ -87,7 +87,7 @@ static __initdata struct tegra_clk_init_table tegra20_clk_init_table[] = { { "pll_c_out1", "pll_c", 120000000, true }, { "sclk", "pll_c_out1", 120000000, true }, { "hclk", "sclk", 120000000, true }, - { "pclk", "hclk", 54000000, true }, + { "pclk", "hclk", 60000000, true }, { "csite", NULL, 0, true }, { "emc", NULL, 0, true }, { "cpu", NULL, 0, true }, From 9abafa021e223f04d6589ee2b977bbaf2e1f1367 Mon Sep 17 00:00:00 2001 From: Stephen Warren Date: Thu, 12 Apr 2012 14:13:05 -0600 Subject: [PATCH 4/7] ARM: tegra: change pll_p_out4's rate to 24MHz pll_p_out4 is used on all/most Tegra boards to drive the cdev2 output pin to provide a reference clock to a ULPI USB PHY. This reference clock must run at 24MHz, and the cdev2 output has no additional dividers. Remove board-paz00.c's now-duplicate initialization of this clock. Reported-by: Marc Dietrich Signed-off-by: Stephen Warren --- arch/arm/mach-tegra/board-paz00.c | 1 - arch/arm/mach-tegra/common.c | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/arch/arm/mach-tegra/board-paz00.c b/arch/arm/mach-tegra/board-paz00.c index 330afdfa2475..aebfa4003813 100644 --- a/arch/arm/mach-tegra/board-paz00.c +++ b/arch/arm/mach-tegra/board-paz00.c @@ -176,7 +176,6 @@ static __initdata struct tegra_clk_init_table paz00_clk_init_table[] = { { "uarta", "pll_p", 216000000, true }, { "uartc", "pll_p", 216000000, true }, - { "pll_p_out4", "pll_p", 24000000, true }, { "usbd", "clk_m", 12000000, false }, { "usb2", "clk_m", 12000000, false }, { "usb3", "clk_m", 12000000, false }, diff --git a/arch/arm/mach-tegra/common.c b/arch/arm/mach-tegra/common.c index a4fba8835136..f18f615aa93a 100644 --- a/arch/arm/mach-tegra/common.c +++ b/arch/arm/mach-tegra/common.c @@ -82,7 +82,7 @@ static __initdata struct tegra_clk_init_table tegra20_clk_init_table[] = { { "pll_p_out1", "pll_p", 28800000, true }, { "pll_p_out2", "pll_p", 48000000, true }, { "pll_p_out3", "pll_p", 72000000, true }, - { "pll_p_out4", "pll_p", 108000000, true }, + { "pll_p_out4", "pll_p", 24000000, true }, { "pll_c", "clk_m", 600000000, true }, { "pll_c_out1", "pll_c", 120000000, true }, { "sclk", "pll_c_out1", 120000000, true }, From 60d148b9f838b718e4808061ee6d5833de77fd9c Mon Sep 17 00:00:00 2001 From: Stephen Warren Date: Thu, 12 Apr 2012 15:03:52 -0600 Subject: [PATCH 5/7] ARM: tegra: don't hard-code USB ULPI PHY reset_gpio Not all boards use GPIO_PV0 as the ULPI PHY reset signal. Instead of hard-coding this GPIO into devices.c, make the board files set it explicitly. This will allow the PHY code to differentiate between set and unset values, and hence know when to read the value from device tree. Signed-off-by: Stephen Warren --- arch/arm/mach-tegra/board-paz00.c | 2 ++ arch/arm/mach-tegra/board-trimslice.c | 2 ++ arch/arm/mach-tegra/devices.c | 5 ++--- arch/arm/mach-tegra/devices.h | 4 ++++ 4 files changed, 10 insertions(+), 3 deletions(-) diff --git a/arch/arm/mach-tegra/board-paz00.c b/arch/arm/mach-tegra/board-paz00.c index aebfa4003813..e31317deec21 100644 --- a/arch/arm/mach-tegra/board-paz00.c +++ b/arch/arm/mach-tegra/board-paz00.c @@ -159,6 +159,8 @@ static void paz00_i2c_init(void) static void paz00_usb_init(void) { + tegra_ehci2_ulpi_phy_config.reset_gpio = TEGRA_ULPI_RST; + platform_device_register(&tegra_ehci2_device); platform_device_register(&tegra_ehci3_device); } diff --git a/arch/arm/mach-tegra/board-trimslice.c b/arch/arm/mach-tegra/board-trimslice.c index f6f5b6a11325..24f1678098dd 100644 --- a/arch/arm/mach-tegra/board-trimslice.c +++ b/arch/arm/mach-tegra/board-trimslice.c @@ -117,6 +117,8 @@ static void trimslice_usb_init(void) pdata = tegra_ehci1_device.dev.platform_data; pdata->vbus_gpio = TRIMSLICE_GPIO_USB1_MODE; + tegra_ehci2_ulpi_phy_config.reset_gpio = TEGRA_GPIO_PV0; + platform_device_register(&tegra_ehci3_device); platform_device_register(&tegra_ehci2_device); platform_device_register(&tegra_ehci1_device); diff --git a/arch/arm/mach-tegra/devices.c b/arch/arm/mach-tegra/devices.c index bd3035e0cea1..9fcb9a522276 100644 --- a/arch/arm/mach-tegra/devices.c +++ b/arch/arm/mach-tegra/devices.c @@ -439,9 +439,8 @@ static struct resource tegra_usb3_resources[] = { }, }; -static struct tegra_ulpi_config tegra_ehci2_ulpi_phy_config = { - /* All existing boards use GPIO PV0 for phy reset */ - .reset_gpio = TEGRA_GPIO_PV0, +struct tegra_ulpi_config tegra_ehci2_ulpi_phy_config = { + .reset_gpio = -1, .clk = "cdev2", }; diff --git a/arch/arm/mach-tegra/devices.h b/arch/arm/mach-tegra/devices.h index ec455679b219..4290ea0063ac 100644 --- a/arch/arm/mach-tegra/devices.h +++ b/arch/arm/mach-tegra/devices.h @@ -22,6 +22,10 @@ #include #include +#include + +extern struct tegra_ulpi_config tegra_ehci2_ulpi_phy_config; + extern struct tegra_ehci_platform_data tegra_ehci1_pdata; extern struct tegra_ehci_platform_data tegra_ehci2_pdata; extern struct tegra_ehci_platform_data tegra_ehci3_pdata; From aa607ebf93a5fc26275a575781399df971dd1b91 Mon Sep 17 00:00:00 2001 From: Stephen Warren Date: Thu, 12 Apr 2012 15:46:49 -0600 Subject: [PATCH 6/7] ARM: tegra: add USB ULPI PHY reset GPIO to device tree ULPI PHYs have a reset signal, and different boards use a different GPIO for this task. Add a property to device tree to represent this. I'm not sure if adding this property to the EHCI controller node is entirely correct; perhaps eventually we should have explicit separate nodes for the various PHYs. However, we don't have that right now, so this binding seems like a reasonable choice. Cc: Cc: Greg Kroah-Hartman Cc: Signed-off-by: Stephen Warren --- .../devicetree/bindings/usb/tegra-usb.txt | 3 +++ arch/arm/boot/dts/tegra-harmony.dts | 4 ++++ arch/arm/boot/dts/tegra-paz00.dts | 4 ++++ arch/arm/boot/dts/tegra-seaboard.dts | 4 ++++ arch/arm/boot/dts/tegra-trimslice.dts | 4 ++++ arch/arm/boot/dts/tegra-ventana.dts | 4 ++++ arch/arm/mach-tegra/include/mach/usb_phy.h | 4 ++-- arch/arm/mach-tegra/usb_phy.c | 15 +++++++++++++-- drivers/usb/host/ehci-tegra.c | 5 +++-- 9 files changed, 41 insertions(+), 6 deletions(-) diff --git a/Documentation/devicetree/bindings/usb/tegra-usb.txt b/Documentation/devicetree/bindings/usb/tegra-usb.txt index 007005ddbe12..e9b005dc7625 100644 --- a/Documentation/devicetree/bindings/usb/tegra-usb.txt +++ b/Documentation/devicetree/bindings/usb/tegra-usb.txt @@ -12,6 +12,9 @@ Required properties : - nvidia,vbus-gpio : If present, specifies a gpio that needs to be activated for the bus to be powered. +Required properties for phy_type == ulpi: + - nvidia,phy-reset-gpio : The GPIO used to reset the PHY. + Optional properties: - dr_mode : dual role mode. Indicates the working mode for nvidia,tegra20-ehci compatible controllers. Can be "host", "peripheral", diff --git a/arch/arm/boot/dts/tegra-harmony.dts b/arch/arm/boot/dts/tegra-harmony.dts index 1a0b1f182944..59bf1cf6a65c 100644 --- a/arch/arm/boot/dts/tegra-harmony.dts +++ b/arch/arm/boot/dts/tegra-harmony.dts @@ -336,4 +336,8 @@ power-gpios = <&gpio 70 0>; /* gpio PI6 */ support-8bit; }; + + usb@c5004000 { + nvidia,phy-reset-gpio = <&gpio 169 0>; /* gpio PV1 */ + }; }; diff --git a/arch/arm/boot/dts/tegra-paz00.dts b/arch/arm/boot/dts/tegra-paz00.dts index 10943fb2561c..fad92f2dbff0 100644 --- a/arch/arm/boot/dts/tegra-paz00.dts +++ b/arch/arm/boot/dts/tegra-paz00.dts @@ -351,4 +351,8 @@ linux,default-trigger = "rfkill0"; }; }; + + usb@c5004000 { + nvidia,phy-reset-gpio = <&gpio 168 0>; /* gpio PV0 */ + }; }; diff --git a/arch/arm/boot/dts/tegra-seaboard.dts b/arch/arm/boot/dts/tegra-seaboard.dts index ec33116f5df9..ed0a2f5bf918 100644 --- a/arch/arm/boot/dts/tegra-seaboard.dts +++ b/arch/arm/boot/dts/tegra-seaboard.dts @@ -415,4 +415,8 @@ 0x00000000 0x00000000 0x00000000 0x00000000 >; }; }; + + usb@c5004000 { + nvidia,phy-reset-gpio = <&gpio 169 0>; /* gpio PV1 */ + }; }; diff --git a/arch/arm/boot/dts/tegra-trimslice.dts b/arch/arm/boot/dts/tegra-trimslice.dts index 98efd5b0d7f9..71b73aab87ff 100644 --- a/arch/arm/boot/dts/tegra-trimslice.dts +++ b/arch/arm/boot/dts/tegra-trimslice.dts @@ -304,4 +304,8 @@ cd-gpios = <&gpio 121 0>; wp-gpios = <&gpio 122 0>; }; + + usb@c5004000 { + nvidia,phy-reset-gpio = <&gpio 168 0>; /* gpio PV0 */ + }; }; diff --git a/arch/arm/boot/dts/tegra-ventana.dts b/arch/arm/boot/dts/tegra-ventana.dts index 71eb2e50a668..bd074cfb338f 100644 --- a/arch/arm/boot/dts/tegra-ventana.dts +++ b/arch/arm/boot/dts/tegra-ventana.dts @@ -335,4 +335,8 @@ sdhci@c8000600 { support-8bit; }; + + usb@c5004000 { + nvidia,phy-reset-gpio = <&gpio 169 0>; /* gpio PV1 */ + }; }; diff --git a/arch/arm/mach-tegra/include/mach/usb_phy.h b/arch/arm/mach-tegra/include/mach/usb_phy.h index de1a0f602b28..935ce9f65590 100644 --- a/arch/arm/mach-tegra/include/mach/usb_phy.h +++ b/arch/arm/mach-tegra/include/mach/usb_phy.h @@ -61,8 +61,8 @@ struct tegra_usb_phy { struct usb_phy *ulpi; }; -struct tegra_usb_phy *tegra_usb_phy_open(int instance, void __iomem *regs, - void *config, enum tegra_usb_phy_mode phy_mode); +struct tegra_usb_phy *tegra_usb_phy_open(struct device *dev, int instance, + void __iomem *regs, void *config, enum tegra_usb_phy_mode phy_mode); int tegra_usb_phy_power_on(struct tegra_usb_phy *phy); diff --git a/arch/arm/mach-tegra/usb_phy.c b/arch/arm/mach-tegra/usb_phy.c index d71d2fed6721..54e353c8e304 100644 --- a/arch/arm/mach-tegra/usb_phy.c +++ b/arch/arm/mach-tegra/usb_phy.c @@ -26,6 +26,7 @@ #include #include #include +#include #include #include #include @@ -654,8 +655,8 @@ static void ulpi_phy_power_off(struct tegra_usb_phy *phy) clk_disable(phy->clk); } -struct tegra_usb_phy *tegra_usb_phy_open(int instance, void __iomem *regs, - void *config, enum tegra_usb_phy_mode phy_mode) +struct tegra_usb_phy *tegra_usb_phy_open(struct device *dev, int instance, + void __iomem *regs, void *config, enum tegra_usb_phy_mode phy_mode) { struct tegra_usb_phy *phy; struct tegra_ulpi_config *ulpi_config; @@ -711,6 +712,16 @@ struct tegra_usb_phy *tegra_usb_phy_open(int instance, void __iomem *regs, err = -ENXIO; goto err1; } + if (!gpio_is_valid(ulpi_config->reset_gpio)) + ulpi_config->reset_gpio = + of_get_named_gpio(dev->of_node, + "nvidia,phy-reset-gpio", 0); + if (!gpio_is_valid(ulpi_config->reset_gpio)) { + pr_err("%s: invalid reset gpio: %d\n", __func__, + ulpi_config->reset_gpio); + err = -EINVAL; + goto err1; + } gpio_request(ulpi_config->reset_gpio, "ulpi_phy_reset_b"); gpio_direction_output(ulpi_config->reset_gpio, 0); phy->ulpi = otg_ulpi_create(&ulpi_viewport_access_ops, 0); diff --git a/drivers/usb/host/ehci-tegra.c b/drivers/usb/host/ehci-tegra.c index 9692bef159f5..14532fe04f5e 100644 --- a/drivers/usb/host/ehci-tegra.c +++ b/drivers/usb/host/ehci-tegra.c @@ -708,8 +708,9 @@ static int tegra_ehci_probe(struct platform_device *pdev) } } - tegra->phy = tegra_usb_phy_open(instance, hcd->regs, pdata->phy_config, - TEGRA_USB_PHY_MODE_HOST); + tegra->phy = tegra_usb_phy_open(&pdev->dev, instance, hcd->regs, + pdata->phy_config, + TEGRA_USB_PHY_MODE_HOST); if (IS_ERR(tegra->phy)) { dev_err(&pdev->dev, "Failed to open USB phy\n"); err = -ENXIO; From 563da21b1d1878736905bbff0f096fcd960d57c5 Mon Sep 17 00:00:00 2001 From: Stephen Warren Date: Fri, 13 Apr 2012 16:35:20 -0600 Subject: [PATCH 7/7] ARM: dt: tegra: pinmux changes for USB ULPI Ensure that the USB ULPI signals are not tri-stated, and have no pull- up or pull-down. Ensure that the pingroup hosting the USB ULPI reset signal (GPIO PV0 or PV1 depending on the board, so UAC) is not tri-stated, and has no pull- up or pull-down. This change appears larger than it is due to the grouping and sorting of the pin configuration data. Signed-off-by: Stephen Warren --- arch/arm/boot/dts/tegra-harmony.dts | 20 ++++++++++---------- arch/arm/boot/dts/tegra-paz00.dts | 14 +++++--------- arch/arm/boot/dts/tegra-trimslice.dts | 18 +++++++++--------- 3 files changed, 24 insertions(+), 28 deletions(-) diff --git a/arch/arm/boot/dts/tegra-harmony.dts b/arch/arm/boot/dts/tegra-harmony.dts index 59bf1cf6a65c..6857cec8382d 100644 --- a/arch/arm/boot/dts/tegra-harmony.dts +++ b/arch/arm/boot/dts/tegra-harmony.dts @@ -167,28 +167,28 @@ }; conf_ata { nvidia,pins = "ata", "atb", "atc", "atd", "ate", - "cdev1", "dap1", "dtb", "gma", "gmb", - "gmc", "gmd", "gme", "gpu7", "gpv", - "i2cp", "pta", "rm", "slxa", "slxk", - "spia", "spib"; + "cdev1", "cdev2", "dap1", "dtb", "gma", + "gmb", "gmc", "gmd", "gme", "gpu7", + "gpv", "i2cp", "pta", "rm", "slxa", + "slxk", "spia", "spib", "uac"; nvidia,pull = <0>; nvidia,tristate = <0>; }; - conf_cdev2 { - nvidia,pins = "cdev2", "csus", "spid", "spif"; - nvidia,pull = <1>; - nvidia,tristate = <1>; - }; conf_ck32 { nvidia,pins = "ck32", "ddrc", "pmca", "pmcb", "pmcc", "pmcd", "pmce", "xm2c", "xm2d"; nvidia,pull = <0>; }; + conf_csus { + nvidia,pins = "csus", "spid", "spif"; + nvidia,pull = <1>; + nvidia,tristate = <1>; + }; conf_crtp { nvidia,pins = "crtp", "dap2", "dap3", "dap4", "dtc", "dte", "dtf", "gpu", "sdio1", "slxc", "slxd", "spdi", "spdo", "spig", - "uac", "uda"; + "uda"; nvidia,pull = <0>; nvidia,tristate = <1>; }; diff --git a/arch/arm/boot/dts/tegra-paz00.dts b/arch/arm/boot/dts/tegra-paz00.dts index fad92f2dbff0..34a917710e09 100644 --- a/arch/arm/boot/dts/tegra-paz00.dts +++ b/arch/arm/boot/dts/tegra-paz00.dts @@ -159,18 +159,14 @@ }; conf_ata { nvidia,pins = "ata", "atb", "atc", "atd", "ate", - "cdev1", "dap1", "dap2", "dtf", "gma", - "gmb", "gmc", "gmd", "gme", "gpu", - "gpu7", "gpv", "i2cp", "pta", "rm", - "sdio1", "slxk", "spdo", "uac", "uda"; + "cdev1", "cdev2", "dap1", "dap2", "dtf", + "gma", "gmb", "gmc", "gmd", "gme", + "gpu", "gpu7", "gpv", "i2cp", "pta", + "rm", "sdio1", "slxk", "spdo", "uac", + "uda"; nvidia,pull = <0>; nvidia,tristate = <0>; }; - conf_cdev2 { - nvidia,pins = "cdev2"; - nvidia,pull = <1>; - nvidia,tristate = <0>; - }; conf_ck32 { nvidia,pins = "ck32", "ddrc", "pmca", "pmcb", "pmcc", "pmcd", "pmce", "xm2c", "xm2d"; diff --git a/arch/arm/boot/dts/tegra-trimslice.dts b/arch/arm/boot/dts/tegra-trimslice.dts index 71b73aab87ff..e4fcf9a8178a 100644 --- a/arch/arm/boot/dts/tegra-trimslice.dts +++ b/arch/arm/boot/dts/tegra-trimslice.dts @@ -182,23 +182,23 @@ nvidia,tristate = <1>; }; conf_atb { - nvidia,pins = "atb", "cdev1", "dap1", "gma", - "gmc", "gmd", "gpu", "gpu7", "gpv", - "sdio1", "slxa", "slxk", "uac"; + nvidia,pins = "atb", "cdev1", "cdev2", "dap1", + "gma", "gmc", "gmd", "gpu", "gpu7", + "gpv", "sdio1", "slxa", "slxk", "uac"; nvidia,pull = <0>; nvidia,tristate = <0>; }; - conf_cdev2 { - nvidia,pins = "cdev2", "csus", "spia", "spib", - "spid", "spif"; - nvidia,pull = <1>; - nvidia,tristate = <1>; - }; conf_ck32 { nvidia,pins = "ck32", "ddrc", "pmca", "pmcb", "pmcc", "pmcd", "pmce", "xm2c", "xm2d"; nvidia,pull = <0>; }; + conf_csus { + nvidia,pins = "csus", "spia", "spib", + "spid", "spif"; + nvidia,pull = <1>; + nvidia,tristate = <1>; + }; conf_ddc { nvidia,pins = "ddc", "dtf", "rm", "sdc", "sdd"; nvidia,pull = <2>;