From 2296774af67f2fd728c662d5120e29b849b4d685 Mon Sep 17 00:00:00 2001 From: Furquan Shaikh Date: Wed, 6 Aug 2014 09:53:55 -0700 Subject: [PATCH] tegra: Clean up USB code Pull out the common usb setup utmip functions from t124 into tegra usb.h. These can be reused for t132 as well. BUG=chrome-os-partner:31293 BRANCH=None TEST=Compiles successfully for nyan, big and blaze Change-Id: Idddd40e409b56875436db6918d05f2889d83870b Signed-off-by: Patrick Georgi Original-Commit-Id: 12f12cb30a033cce645f53457d13a987aeec22a1 Original-Change-Id: I83f83bafad0f52ad651fe5989430f41142803f2b Original-Signed-off-by: Furquan Shaikh Original-Reviewed-on: https://chromium-review.googlesource.com/211200 Original-Tested-by: Furquan Shaikh Original-Reviewed-by: Aaron Durbin Original-Commit-Queue: Furquan Shaikh Reviewed-on: http://review.coreboot.org/8927 Tested-by: build bot (Jenkins) Reviewed-by: Stefan Reinauer --- src/mainboard/google/nyan/mainboard.c | 6 +- src/mainboard/google/nyan_big/mainboard.c | 6 +- src/mainboard/google/nyan_blaze/mainboard.c | 8 +- src/soc/nvidia/tegra/usb.c | 156 ++++++++++++++++---- src/soc/nvidia/tegra/usb.h | 93 +----------- src/soc/nvidia/tegra124/usb.h | 50 ------- 6 files changed, 139 insertions(+), 180 deletions(-) delete mode 100644 src/soc/nvidia/tegra124/usb.h diff --git a/src/mainboard/google/nyan/mainboard.c b/src/mainboard/google/nyan/mainboard.c index 682fdc4db4..b534ea908d 100644 --- a/src/mainboard/google/nyan/mainboard.c +++ b/src/mainboard/google/nyan/mainboard.c @@ -29,7 +29,7 @@ #include #include #include -#include +#include #include static struct clk_rst_ctlr *clk_rst = (void *)TEGRA_CLK_RST_BASE; @@ -232,9 +232,9 @@ static void mainboard_init(device_t dev) CLK_X_AFC2 | CLK_X_AFC3 | CLK_X_AFC4 | CLK_X_AFC5); - usb_setup_utmip1(); + usb_setup_utmip((void*)TEGRA_USBD_BASE); /* USB2 is the camera, we don't need it in firmware */ - usb_setup_utmip3(); + usb_setup_utmip((void*)TEGRA_USB3_BASE); setup_pinmux(); diff --git a/src/mainboard/google/nyan_big/mainboard.c b/src/mainboard/google/nyan_big/mainboard.c index ff147e2c15..86d9fe3b37 100644 --- a/src/mainboard/google/nyan_big/mainboard.c +++ b/src/mainboard/google/nyan_big/mainboard.c @@ -29,7 +29,7 @@ #include #include #include -#include +#include #include static struct clk_rst_ctlr *clk_rst = (void *)TEGRA_CLK_RST_BASE; @@ -230,9 +230,9 @@ static void mainboard_init(device_t dev) CLK_X_AFC2 | CLK_X_AFC3 | CLK_X_AFC4 | CLK_X_AFC5); - usb_setup_utmip1(); + usb_setup_utmip((void*)TEGRA_USBD_BASE); /* USB2 is the camera, we don't need it in firmware */ - usb_setup_utmip3(); + usb_setup_utmip((void*)TEGRA_USB3_BASE); setup_pinmux(); diff --git a/src/mainboard/google/nyan_blaze/mainboard.c b/src/mainboard/google/nyan_blaze/mainboard.c index 8d4f553cef..ccbaf63f94 100644 --- a/src/mainboard/google/nyan_blaze/mainboard.c +++ b/src/mainboard/google/nyan_blaze/mainboard.c @@ -29,7 +29,7 @@ #include #include #include -#include +#include #include static struct clk_rst_ctlr *clk_rst = (void *)TEGRA_CLK_RST_BASE; @@ -230,9 +230,9 @@ static void mainboard_init(device_t dev) CLK_X_AFC2 | CLK_X_AFC3 | CLK_X_AFC4 | CLK_X_AFC5); - usb_setup_utmip1(); - usb_setup_utmip2(); - usb_setup_utmip3(); + usb_setup_utmip((void*)TEGRA_USBD_BASE); + usb_setup_utmip((void*)TEGRA_USB2_BASE); + usb_setup_utmip((void*)TEGRA_USB3_BASE); setup_pinmux(); diff --git a/src/soc/nvidia/tegra/usb.c b/src/soc/nvidia/tegra/usb.c index e0455ed05c..3268ee1a74 100644 --- a/src/soc/nvidia/tegra/usb.c +++ b/src/soc/nvidia/tegra/usb.c @@ -24,9 +24,131 @@ #include "usb.h" -/* Assume USBx clocked, out of reset, UTMI+ PLL set up, SAMP_x out of pwrdn */ -void usb_setup_utmip(struct usb_ctlr *usb) +struct utmip_ctlr { + u32 pll0; + u32 pll1; + u32 xcvr0; + u32 bias0; + u32 hsrx0; + u32 hsrx1; + u32 fslsrx0; + u32 fslsrx1; + u32 tx; + u32 misc0; + u32 misc1; + u32 debounce; + u32 batchrgr; + u32 spare; + u32 xcvr1; + u32 bias1; + u32 bias_sts; + u32 chrgr_debounce; + u32 misc_sts; + u32 pmc_wakeup; +}; +check_member(utmip_ctlr, pmc_wakeup, 0x84c - 0x800); + +struct usb_ctlr { + u32 id; + u32 _rsv0; + u32 host; + u32 device; + u32 txbuf; /* 0x010 */ + u32 rxbuf; + u32 _rsv1[58]; + u16 ehci_caplen; /* 0x100 */ + u16 ehci_version; + u32 ehci_hcsp; + u32 ehci_hccp; + u32 _rsv2[5]; + u32 dci_version; /* 0x120 */ + u32 dcc_params; + u32 extsts; + u32 extintr; + u32 ehci_usbcmd; /* 0x130 */ + u32 ehci_usbsts; + u32 ehci_usbintr; + u32 ehci_frindex; + u32 _rsv3; /* 0x140 */ + u32 ehci_periodic_base; + u32 ehci_async_base; + u32 async_ttsts; + u32 burst_size; /* 0x150 */ + u32 tx_fill_tuning; + u32 _rsv4; + u32 icusb_ctrl; + u32 ulpi_viewport; /* 0x160 */ + u32 _rsv5[4]; + u32 ehci_portsc; + u32 _rsv6[15]; + u32 lpm_ctrl; + u32 _rsv7[15]; + u32 otgsc; + u32 usb_mode; + u32 _rsv8; + u32 ep_nak; /* 0x200 */ + u32 ep_nak_enable; + u32 ep_setup; + u32 ep_init; + u32 ep_deinit; + u32 ep_sts; + u32 ep_complete; + u32 ep_ctrl[16]; + u32 _rsv9[105]; + u32 suspend_ctrl; /* 0x400 */ + u32 vbus_sensors; + u32 vbus_wakeup_id; + u32 alt_vbus_sts; + u32 legacy_ctrl; + u32 _rsv10[3]; + u32 interpacket_delay; + u32 _rsv11[27]; + u32 resume_delay; + u32 _rsv12; + u32 spare; + u32 _rsv13[9]; + u32 new_ctrl; + u32 _rsv14[207]; + struct utmip_ctlr utmip; /* 0x800 */ +}; +check_member(usb_ctlr, utmip, 0x800); + +/* + * Tegra EHCI controllers need their usb_mode, lpm_ctrl and tx_fill_tuning + * registers initialized after every EHCI reset and before any other actions + * (such as Run/Stop bit) are taken. We reset the controller here, set those + * registers and rely on the fact that libpayload doesn't reset EHCI controllers + * on initialization for whatever weird reason. This is ugly, fragile, and I + * really don't like it, but making this work will require an ugly hack one way + * or another so we might as well take the path of least resistance for now. + */ +static void usb_ehci_reset_and_prepare(struct usb_ctlr *usb, enum usb_phy_type type) { + int timeout = 1000; + + write32(1 << 1, &usb->ehci_usbcmd); /* Host Controller Reset */ + /* TODO: Resets are long, find way to parallelize... or just use XHCI */ + while (--timeout && (read32(&usb->ehci_usbcmd) & 1 << 1)) + /* wait for HC to reset */; + + if (!timeout) { + printk(BIOS_ERR, "ERROR: EHCI(%p) reset timeout", usb); + return; + } + + /* Controller mode: HOST */ + write32(3 << 0, &usb->usb_mode); + /* Parallel transceiver selct */ + write32(type << 29, &usb->lpm_ctrl); + /* Tx FIFO Burst thresh */ + write32(0x10 << 16, &usb->tx_fill_tuning); +} + +/* Assume USBx clocked, out of reset, UTMI+ PLL set up, SAMP_x out of pwrdn */ +void usb_setup_utmip(void *usb_base) +{ + struct usb_ctlr *usb = (struct usb_ctlr *)usb_base; + /* KHz formulas were guessed from U-Boot constants. Formats unclear. */ int khz = clock_get_pll_input_khz(); @@ -90,32 +212,8 @@ void usb_setup_utmip(struct usb_ctlr *usb) write32(1 << 12 | /* UTMI+ enable */ 0 << 11 | /* UTMI+ reset */ 0, &usb->suspend_ctrl); + + usb_ehci_reset_and_prepare(usb, USB_PHY_UTMIP); + printk(BIOS_DEBUG, "USB controller @ %p set up with UTMI+ PHY\n",usb_base); } -/* - * Tegra EHCI controllers need their usb_mode, lpm_ctrl and tx_fill_tuning - * registers initialized after every EHCI reset and before any other actions - * (such as Run/Stop bit) are taken. We reset the controller here, set those - * registers and rely on the fact that libpayload doesn't reset EHCI controllers - * on initialization for whatever weird reason. This is ugly, fragile, and I - * really don't like it, but making this work will require an ugly hack one way - * or another so we might as well take the path of least resistance for now. - */ -void usb_ehci_reset_and_prepare(struct usb_ctlr *usb, enum usb_phy_type type) -{ - int timeout = 1000; - - write32(1 << 1, &usb->ehci_usbcmd); /* Host Controller Reset */ - /* TODO: Resets are long, find way to parallelize... or just use XHCI */ - while (--timeout && (read32(&usb->ehci_usbcmd) & 1 << 1)) - /* wait for HC to reset */; - - if (!timeout) { - printk(BIOS_ERR, "ERROR: EHCI(%p) reset timeout", usb); - return; - } - - write32(3 << 0, &usb->usb_mode); /* Controller mode: HOST */ - write32(type << 29, &usb->lpm_ctrl); /* Parallel transceiver selct */ - write32(0x10 << 16, &usb->tx_fill_tuning); /* Tx FIFO Burst thresh */ -} diff --git a/src/soc/nvidia/tegra/usb.h b/src/soc/nvidia/tegra/usb.h index f720c2aab3..9d22b0b867 100644 --- a/src/soc/nvidia/tegra/usb.h +++ b/src/soc/nvidia/tegra/usb.h @@ -22,95 +22,6 @@ #include -struct utmip_ctlr { - u32 pll0; - u32 pll1; - u32 xcvr0; - u32 bias0; - u32 hsrx0; - u32 hsrx1; - u32 fslsrx0; - u32 fslsrx1; - u32 tx; - u32 misc0; - u32 misc1; - u32 debounce; - u32 batchrgr; - u32 spare; - u32 xcvr1; - u32 bias1; - u32 bias_sts; - u32 chrgr_debounce; - u32 misc_sts; - u32 pmc_wakeup; -}; -check_member(utmip_ctlr, pmc_wakeup, 0x84c - 0x800); - -struct usb_ctlr { - u32 id; - u32 _rsv0; - u32 host; - u32 device; - u32 txbuf; /* 0x010 */ - u32 rxbuf; - u32 _rsv1[58]; - u16 ehci_caplen; /* 0x100 */ - u16 ehci_version; - u32 ehci_hcsp; - u32 ehci_hccp; - u32 _rsv2[5]; - u32 dci_version; /* 0x120 */ - u32 dcc_params; - u32 extsts; - u32 extintr; - u32 ehci_usbcmd; /* 0x130 */ - u32 ehci_usbsts; - u32 ehci_usbintr; - u32 ehci_frindex; - u32 _rsv3; /* 0x140 */ - u32 ehci_periodic_base; - u32 ehci_async_base; - u32 async_ttsts; - u32 burst_size; /* 0x150 */ - u32 tx_fill_tuning; - u32 _rsv4; - u32 icusb_ctrl; - u32 ulpi_viewport; /* 0x160 */ - u32 _rsv5[4]; - u32 ehci_portsc; - u32 _rsv6[15]; - u32 lpm_ctrl; - u32 _rsv7[15]; - u32 otgsc; - u32 usb_mode; - u32 _rsv8; - u32 ep_nak; /* 0x200 */ - u32 ep_nak_enable; - u32 ep_setup; - u32 ep_init; - u32 ep_deinit; - u32 ep_sts; - u32 ep_complete; - u32 ep_ctrl[16]; - u32 _rsv9[105]; - u32 suspend_ctrl; /* 0x400 */ - u32 vbus_sensors; - u32 vbus_wakeup_id; - u32 alt_vbus_sts; - u32 legacy_ctrl; - u32 _rsv10[3]; - u32 interpacket_delay; - u32 _rsv11[27]; - u32 resume_delay; - u32 _rsv12; - u32 spare; - u32 _rsv13[9]; - u32 new_ctrl; - u32 _rsv14[207]; - struct utmip_ctlr utmip; /* 0x800 */ -}; -check_member(usb_ctlr, utmip, 0x800); - enum usb_phy_type { /* For use in lpm_ctrl[31:29] */ USB_PHY_UTMIP = 0, USB_PHY_ULPI = 2, @@ -118,6 +29,6 @@ enum usb_phy_type { /* For use in lpm_ctrl[31:29] */ USB_PHY_HSIC = 4, }; -void usb_setup_utmip(struct usb_ctlr *usb); -void usb_ehci_reset_and_prepare(struct usb_ctlr *usb, enum usb_phy_type type); +void usb_setup_utmip(void *usb_base); + #endif diff --git a/src/soc/nvidia/tegra124/usb.h b/src/soc/nvidia/tegra124/usb.h deleted file mode 100644 index ec5a14464e..0000000000 --- a/src/soc/nvidia/tegra124/usb.h +++ /dev/null @@ -1,50 +0,0 @@ -/* - * This file is part of the coreboot project. - * - * Copyright 2013, Google Inc. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, - * version 2, as published by the Free Software Foundation. - * - * This program is distributed in the hope it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#ifndef __SOC_NVIDIA_TEGRA124_USB_H_ -#define __SOC_NVIDIA_TEGRA124_USB_H_ - -#include -#include -#include - -static inline void usb_setup_utmip1(void) -{ - struct usb_ctlr *usb = (void *)TEGRA_USBD_BASE; - usb_setup_utmip(usb); - usb_ehci_reset_and_prepare(usb, USB_PHY_UTMIP); - printk(BIOS_DEBUG, "USBD controller set up with UTMI+ PHY\n"); -} - -static inline void usb_setup_utmip2(void) -{ - struct usb_ctlr *usb = (void *)TEGRA_USB2_BASE; - usb_setup_utmip(usb); - usb_ehci_reset_and_prepare(usb, USB_PHY_UTMIP); - printk(BIOS_DEBUG, "USB2 controller set up with UTMI+ PHY\n"); -} - -static inline void usb_setup_utmip3(void) -{ - struct usb_ctlr *usb = (void *)TEGRA_USB3_BASE; - usb_setup_utmip(usb); - usb_ehci_reset_and_prepare(usb, USB_PHY_UTMIP); - printk(BIOS_DEBUG, "USB3 controller set up with UTMI+ PHY\n"); -} - -#endif /* __SOC_NVIDIA_TEGRA124_USB_H_ */