[Armadeus-commitlog] armadeus/u-boot branch, opos6ul-2018.05, updated. 27dbcd82ccfcf1d2e72b237176c
Brought to you by:
sszy
|
From: sszy <ss...@us...> - 2023-10-16 16:18:48
|
This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project "armadeus/u-boot".
The branch, opos6ul-2018.05 has been updated
via 27dbcd82ccfcf1d2e72b237176c0392f9a04754f (commit)
via c165aa831e10015680ab923f738c1f28adbb99b1 (commit)
via 7948e293a59f484397318bfb9b40d4dd2890ca90 (commit)
via f5ab41acbc02401210fddfbee1c34e96972190e2 (commit)
via 92980c03846bf97d307690200837cf29fec4472a (commit)
via 21ec8b0dd62cbd82932df5bc5b1be9e25d1400be (commit)
via add1e026f72969c57c93f265190d68fd0108bfb2 (commit)
via 2e1712740b7912fcc5fb94da879b263ccd3a20f2 (commit)
via 61639ff85eb12f29f20e0f6f80081a93cf5ac043 (commit)
from dd82cef7c8679adcbc1d1e5701e06e1735b02a22 (commit)
Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.
- Log -----------------------------------------------------------------
commit 27dbcd82ccfcf1d2e72b237176c0392f9a04754f
Author: Sébastien Szymanski <seb...@ar...>
Date: Mon Oct 16 15:59:39 2023 +0200
opos6ul{,nano,sp}dev: use load instead of fatload
commit c165aa831e10015680ab923f738c1f28adbb99b1
Author: Sébastien Szymanski <seb...@ar...>
Date: Mon Oct 16 15:44:55 2023 +0200
opos6ul{,nano,sp}dev: load rootfs at 32KiB offset instead of 32MiB
commit 7948e293a59f484397318bfb9b40d4dd2890ca90
Author: Ye Li <ye...@nx...>
Date: Mon Mar 8 19:26:57 2021 -0800
usb: ehci-hcd: Add IAA handshake for removing async QH
According to EHCI spec, software needs to do handshake with HC for
safely removing QH from async list. This handshake is implemented by
setting IAAD (Interrupt on Async Advance Doorbell) bit in USB_USBCMD
register and poll the IAA (Interrupt on Async Advance bit) in the
USB_USBSTS to ensure the HC has released all on-chip state that may
potentially reference one of the data structures just removed.
Current codes only check active status of the last QTD, but this can't
ensure the QH is released from HC. We can meet unrecoverable
"EHCI timed out on TD" errors when running UEFI SCT tests on USB disk.
The USB_ASYNCLISTADDR register is changed to a invalid address when the
issue happens. It is fixed after adding the IAA handshake.
Steps to reproduce the issue:
1. Build the UEFI SCT from https://github.com/tianocore/edk2-test
2. Build the EDK2 UEFI Shell from https://github.com/tianocore/edk2
3. Copy SCT files and Shell.efi to USB disk FAT partition
4. Load the Shell.efi from USB FAT, and run bootefi to execute it
5. After booting into Shell, enter the SCT directory and run "sct -a"
to execute all tests.
6. Tests run about 1 hour and stop with many EHCI timeout errors like
EHCI timed out on TD - token=0x801f8c80
Signed-off-by: Ye Li <ye...@nx...>
(cherry picked from commit e1769da17ed339bc937d30c49176bc3664b261af)
commit f5ab41acbc02401210fddfbee1c34e96972190e2
Author: Marek Vasut <mar...@gm...>
Date: Mon Apr 6 14:29:44 2020 +0200
usb: Keep async schedule running only across mass storage xfers
Rather than keeping the asynchronous schedule running always, keep it
running only across USB mass storage transfers for now, as it seems
that keeping it running all the time interferes with certain control
transfers during device enumeration.
Note that running the async schedule all the time should not be an
issue, especially on EHCI HCD, as that one implements most of the
transfers using async schedule.
Note that we have usb_disable_asynch(), which however is utterly broken.
The usb_disable_asynch() blocks the USB core from doing async transfers
by setting a global flag. The async schedule should however be disabled
per USB controller. Moreover, setting a global flag does not prevent the
controller from using the async schedule, which e.g. the EHCI HCD does.
This patch implements additional callback to the controller, which
permits it to lock the async schedule and keep it running across
multiple transfers. Once the schedule is unlocked, it must also be
disabled. This thus prevents the async schedule from running outside
of the USB mass storage transfers.
Signed-off-by: Marek Vasut <mar...@gm...>
Cc: Lukasz Majewski <lu...@de...>
Cc: Tom Rini <tr...@ko...>
Tested-by: Tom Rini <tr...@ko...> [omap3_beagle, previously failing]
(cherry picked from commit 31232de07ef2bd97ff67625976eecd97eeb1bd3d)
commit 92980c03846bf97d307690200837cf29fec4472a
Author: Marek Vasut <mar...@gm...>
Date: Sun Oct 6 16:13:38 2019 +0200
usb: ehci-hcd: Keep async schedule running
Profiling the EHCI driver shows a significant performance problem in
ehci_submit_async(). Specifically, this function keeps enabling and
disabling async schedule back and forth for every single transaction.
However, enabling/disabling the async schedule does not take effect
immediatelly, but instead may take up to 1 mS (8 uFrames) to complete.
This impacts USB storage significantly, esp. since the recent reduction
of maximum transfer size to support more USB storage devices. This in
turn results in sharp increase in the number of ehci_submit_async()
calls. Since one USB storage BBB transfer does three such calls and
the maximum transfer size is 120 kiB, the overhead is 6 mS per 120 kiB,
which is unacceptable.
However, this overhead can be removed simply by keeping the async
schedule running. Specifically, the first transfer starts the async
schedule and then each and every subsequent transfer only adds a new
QH into that schedule, waits until the QH is completed and does NOT
disable the async schedule. The async schedule is stopped only by
shutting down the controller, which must happen before moving out
of U-Boot, otherwise the controller will corrupt memory.
Signed-off-by: Marek Vasut <mar...@gm...>
Cc: Bin Meng <bme...@gm...>
Cc: Simon Glass <sj...@ch...>
(cherry picked from commit 02b0e1a36c5bc20174299312556ec4e266872bd6)
commit 21ec8b0dd62cbd82932df5bc5b1be9e25d1400be
Author: Chris Packham <jud...@gm...>
Date: Thu Oct 4 20:03:53 2018 +1300
fsl/usb: Workaround for USB erratum-A005275
Workaround makes FS as default mode on all affected socs.
Add support to check erratum-A005275 validity for an soc. This info is
required to determine whether a given soc is affected by this erratum.
Add quirk for this erratum "has_fsl_erratum_a005275" . This quirk is used
to enable workaround for the errata
Force FS mode as default by:
- making EPS as FS
- setting PFSC bit to disable HS chirping
This workaround can be disabled by mentioning "no_erratum_a005275" in
hwconfig string
Signed-off-by: Chris Packham <jud...@gm...>
Reviewed-by: York Sun <yor...@nx...>
(cherry picked from commit 4eaf7f525a0874a1eff0f5666004896cc5c89fa3)
commit add1e026f72969c57c93f265190d68fd0108bfb2
Author: Marek Vasut <mar...@gm...>
Date: Wed Aug 8 14:29:55 2018 +0200
usb: ehci: Make the PHY handling generic
Pull out the EHCI PHY functions into the ehci-hcd.c to let other
EHCI drivers use them.
Signed-off-by: Marek Vasut <mar...@gm...>
(cherry picked from commit b43cdf9b3fe246a8920d2b62ee41fc1722315ef0)
commit 2e1712740b7912fcc5fb94da879b263ccd3a20f2
Author: Marek Vasut <mar...@gm...>
Date: Sat Oct 5 19:18:38 2019 +0200
usb: storage: Only clear READY flag on error
Clear the USB_READY flag in the storage driver only in case there
is an error, otherwise usb_stor_BBB_transport() waits 5 mS before
doing anything every single time.
This is because the USB_READY flag is only ever set in
usb_test_unit_ready(), which is called only upon storage device
probe, not between each and every request. However, the device
cannot move out of USB_READY state once it was initialized.
Signed-off-by: Marek Vasut <mar...@gm...>
Cc: Bin Meng <bme...@gm...>
Cc: Simon Glass <sj...@ch...>
(cherry picked from commit da3d1c499fbb7cfe1c1dc1bc47699a2f30df4384)
commit 61639ff85eb12f29f20e0f6f80081a93cf5ac043
Author: Marek Vasut <mar...@gm...>
Date: Mon Sep 16 00:16:25 2019 +0200
usb: storage: Limit transfer size to 120 kiB
Due to constant influx of more and more weird and broken USB sticks,
do as Linux does in commit 779b457f66e10de3471479373463b27fd308dc85
usb: storage: scsiglue: further describe our 240 sector limit
Just so we have some sort of documentation as to why
we limit our Mass Storage transfers to 240 sectors,
let's update the comment to make clearer that
devices were found that would choke with larger
transfers.
While at that, also make sure to clarify that other
operating systems have similar, albeit different,
limits on mass storage transfers.
And reduce the maximum transfer length of USB storage to 120 kiB.
Signed-off-by: Marek Vasut <mar...@gm...>
Reviewed-by: Bin Meng <bme...@gm...>
Cc: Bin Meng <bme...@gm...>
Cc: Simon Glass <sj...@ch...>
(cherry picked from commit 7d6fd7f0ba71cd93d94079132f958d9630f27a89)
-----------------------------------------------------------------------
Summary of changes:
arch/powerpc/cpu/mpc85xx/Kconfig | 8 ++
arch/powerpc/cpu/mpc85xx/cmd_errata.c | 4 +
common/usb.c | 6 +
common/usb_storage.c | 53 ++++----
drivers/usb/common/fsl-errata.c | 28 +++++
drivers/usb/host/ehci-fsl.c | 7 ++
drivers/usb/host/ehci-generic.c | 56 +--------
drivers/usb/host/ehci-hcd.c | 223 +++++++++++++++++++++++++++++-----
drivers/usb/host/ehci.h | 11 ++
drivers/usb/host/usb-uclass.c | 11 ++
include/configs/opos6uldev.h | 15 +--
include/fsl_usb.h | 1 +
include/usb.h | 11 ++
13 files changed, 317 insertions(+), 117 deletions(-)
diff --git a/arch/powerpc/cpu/mpc85xx/Kconfig b/arch/powerpc/cpu/mpc85xx/Kconfig
index 19e8d02bf4..ea347ad474 100644
--- a/arch/powerpc/cpu/mpc85xx/Kconfig
+++ b/arch/powerpc/cpu/mpc85xx/Kconfig
@@ -659,6 +659,7 @@ config ARCH_P1010
select SYS_FSL_ERRATUM_A004477
select SYS_FSL_ERRATUM_A004508
select SYS_FSL_ERRATUM_A005125
+ select SYS_FSL_ERRATUM_A005275
select SYS_FSL_ERRATUM_A006261
select SYS_FSL_ERRATUM_A007075
select SYS_FSL_ERRATUM_ESDHC111
@@ -821,6 +822,7 @@ config ARCH_P2041
select FSL_LAW
select SYS_FSL_ERRATUM_A004510
select SYS_FSL_ERRATUM_A004849
+ select SYS_FSL_ERRATUM_A005275
select SYS_FSL_ERRATUM_A006261
select SYS_FSL_ERRATUM_CPU_A003999
select SYS_FSL_ERRATUM_DDR_A003
@@ -845,6 +847,7 @@ config ARCH_P3041
select SYS_FSL_DDR_VER_44
select SYS_FSL_ERRATUM_A004510
select SYS_FSL_ERRATUM_A004849
+ select SYS_FSL_ERRATUM_A005275
select SYS_FSL_ERRATUM_A005812
select SYS_FSL_ERRATUM_A006261
select SYS_FSL_ERRATUM_CPU_A003999
@@ -910,6 +913,7 @@ config ARCH_P5020
select FSL_LAW
select SYS_FSL_DDR_VER_44
select SYS_FSL_ERRATUM_A004510
+ select SYS_FSL_ERRATUM_A005275
select SYS_FSL_ERRATUM_A006261
select SYS_FSL_ERRATUM_DDR_A003
select SYS_FSL_ERRATUM_DDR_A003474
@@ -935,6 +939,7 @@ config ARCH_P5040
select SYS_FSL_DDR_VER_44
select SYS_FSL_ERRATUM_A004510
select SYS_FSL_ERRATUM_A004699
+ select SYS_FSL_ERRATUM_A005275
select SYS_FSL_ERRATUM_A005812
select SYS_FSL_ERRATUM_A006261
select SYS_FSL_ERRATUM_DDR_A003
@@ -1299,6 +1304,9 @@ config SYS_FSL_ERRATUM_A005812
config SYS_FSL_ERRATUM_A005871
bool
+config SYS_FSL_ERRATUM_A005275
+ bool
+
config SYS_FSL_ERRATUM_A006261
bool
diff --git a/arch/powerpc/cpu/mpc85xx/cmd_errata.c b/arch/powerpc/cpu/mpc85xx/cmd_errata.c
index eda2e7e63d..e455d8baf5 100644
--- a/arch/powerpc/cpu/mpc85xx/cmd_errata.c
+++ b/arch/powerpc/cpu/mpc85xx/cmd_errata.c
@@ -307,6 +307,10 @@ static int do_errata(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
(SVR_REV(svr) <= CONFIG_SYS_FSL_A004447_SVR_REV))
puts("Work-around for Erratum I2C-A004447 enabled\n");
#endif
+#ifdef CONFIG_SYS_FSL_ERRATUM_A005275
+ if (has_erratum_a005275())
+ puts("Work-around for Erratum A005275 enabled\n");
+#endif
#ifdef CONFIG_SYS_FSL_ERRATUM_A006261
if (has_erratum_a006261())
puts("Work-around for Erratum A006261 enabled\n");
diff --git a/common/usb.c b/common/usb.c
index 78178c54c8..2b8b01a7c3 100644
--- a/common/usb.c
+++ b/common/usb.c
@@ -171,6 +171,12 @@ int usb_detect_change(void)
return change;
}
+/* Lock or unlock async schedule on the controller */
+__weak int usb_lock_async(struct usb_device *dev, int lock)
+{
+ return 0;
+}
+
/*
* disables the asynch behaviour of the control message. This is used for data
* transfers that uses the exclusiv access to the control and bulk messages.
diff --git a/common/usb_storage.c b/common/usb_storage.c
index 9cd64744f8..722097ced6 100644
--- a/common/usb_storage.c
+++ b/common/usb_storage.c
@@ -941,31 +941,32 @@ do_retry:
static void usb_stor_set_max_xfer_blk(struct usb_device *udev,
struct us_data *us)
{
- unsigned short blk;
- size_t __maybe_unused size;
- int __maybe_unused ret;
-
-#ifndef CONFIG_DM_USB
-#ifdef CONFIG_USB_EHCI_HCD
/*
- * The U-Boot EHCI driver can handle any transfer length as long as
- * there is enough free heap space left, but the SCSI READ(10) and
- * WRITE(10) commands are limited to 65535 blocks.
+ * Limit the total size of a transfer to 120 KB.
+ *
+ * Some devices are known to choke with anything larger. It seems like
+ * the problem stems from the fact that original IDE controllers had
+ * only an 8-bit register to hold the number of sectors in one transfer
+ * and even those couldn't handle a full 256 sectors.
+ *
+ * Because we want to make sure we interoperate with as many devices as
+ * possible, we will maintain a 240 sector transfer size limit for USB
+ * Mass Storage devices.
+ *
+ * Tests show that other operating have similar limits with Microsoft
+ * Windows 7 limiting transfers to 128 sectors for both USB2 and USB3
+ * and Apple Mac OS X 10.11 limiting transfers to 256 sectors for USB2
+ * and 2048 for USB3 devices.
*/
- blk = USHRT_MAX;
-#else
- blk = 20;
-#endif
-#else
+ unsigned short blk = 240;
+
+#if CONFIG_IS_ENABLED(DM_USB)
+ size_t size;
+ int ret;
+
ret = usb_get_max_xfer_size(udev, (size_t *)&size);
- if (ret < 0) {
- /* unimplemented, let's use default 20 */
- blk = 20;
- } else {
- if (size > USHRT_MAX * 512)
- size = USHRT_MAX * 512;
+ if ((ret >= 0) && (size < blk * 512))
blk = size / 512;
- }
#endif
us->max_xfer_blk = blk;
@@ -1159,6 +1160,7 @@ static unsigned long usb_stor_read(struct blk_desc *block_dev, lbaint_t blknr,
ss = (struct us_data *)udev->privptr;
usb_disable_asynch(1); /* asynch transfer not allowed */
+ usb_lock_async(udev, 1);
srb->lun = block_dev->lun;
buf_addr = (uintptr_t)buffer;
start = blknr;
@@ -1182,6 +1184,7 @@ retry_it:
srb->pdata = (unsigned char *)buf_addr;
if (usb_read_10(srb, ss, start, smallblks)) {
debug("Read ERROR\n");
+ ss->flags &= ~USB_READY;
usb_request_sense(srb, ss);
if (retry--)
goto retry_it;
@@ -1192,12 +1195,12 @@ retry_it:
blks -= smallblks;
buf_addr += srb->datalen;
} while (blks != 0);
- ss->flags &= ~USB_READY;
debug("usb_read: end startblk " LBAF
", blccnt %x buffer %" PRIxPTR "\n",
start, smallblks, buf_addr);
+ usb_lock_async(udev, 0);
usb_disable_asynch(0); /* asynch transfer allowed */
if (blkcnt >= ss->max_xfer_blk)
debug("\n");
@@ -1242,6 +1245,7 @@ static unsigned long usb_stor_write(struct blk_desc *block_dev, lbaint_t blknr,
ss = (struct us_data *)udev->privptr;
usb_disable_asynch(1); /* asynch transfer not allowed */
+ usb_lock_async(udev, 1);
srb->lun = block_dev->lun;
buf_addr = (uintptr_t)buffer;
@@ -1268,6 +1272,7 @@ retry_it:
srb->pdata = (unsigned char *)buf_addr;
if (usb_write_10(srb, ss, start, smallblks)) {
debug("Write ERROR\n");
+ ss->flags &= ~USB_READY;
usb_request_sense(srb, ss);
if (retry--)
goto retry_it;
@@ -1278,11 +1283,11 @@ retry_it:
blks -= smallblks;
buf_addr += srb->datalen;
} while (blks != 0);
- ss->flags &= ~USB_READY;
debug("usb_write: end startblk " LBAF ", blccnt %x buffer %"
PRIxPTR "\n", start, smallblks, buf_addr);
+ usb_lock_async(udev, 0);
usb_disable_asynch(0); /* asynch transfer allowed */
if (blkcnt >= ss->max_xfer_blk)
debug("\n");
@@ -1473,10 +1478,10 @@ int usb_stor_get_info(struct usb_device *dev, struct us_data *ss,
memset(pccb->pdata, 0, 8);
if (usb_read_capacity(pccb, ss) != 0) {
printf("READ_CAP ERROR\n");
+ ss->flags &= ~USB_READY;
cap[0] = 2880;
cap[1] = 0x200;
}
- ss->flags &= ~USB_READY;
debug("Read Capacity returns: 0x%08x, 0x%08x\n", cap[0], cap[1]);
#if 0
if (cap[0] > (0x200000 * 10)) /* greater than 10 GByte */
diff --git a/drivers/usb/common/fsl-errata.c b/drivers/usb/common/fsl-errata.c
index 386130d7a1..9eb1d23067 100644
--- a/drivers/usb/common/fsl-errata.c
+++ b/drivers/usb/common/fsl-errata.c
@@ -6,6 +6,7 @@
*/
#include <common.h>
+#include <hwconfig.h>
#include <fsl_errata.h>
#include<fsl_usb.h>
#if defined(CONFIG_FSL_LSCH2) || defined(CONFIG_FSL_LSCH3) || \
@@ -44,6 +45,33 @@ bool has_dual_phy(void)
return false;
}
+bool has_erratum_a005275(void)
+{
+ u32 svr = get_svr();
+ u32 soc = SVR_SOC_VER(svr);
+
+ if (hwconfig("no_erratum_a005275"))
+ return false;
+
+ switch (soc) {
+#ifdef CONFIG_PPC
+ case SVR_P3041:
+ case SVR_P2041:
+ case SVR_P2040:
+ return IS_SVR_REV(svr, 1, 0) || IS_SVR_REV(svr, 1, 1);
+ case SVR_P5010:
+ case SVR_P5020:
+ case SVR_P5021:
+ return IS_SVR_REV(svr, 1, 0) || IS_SVR_REV(svr, 2, 0);
+ case SVR_P5040:
+ case SVR_P1010:
+ return IS_SVR_REV(svr, 1, 0);
+#endif
+ }
+
+ return false;
+}
+
bool has_erratum_a006261(void)
{
u32 svr = get_svr();
diff --git a/drivers/usb/host/ehci-fsl.c b/drivers/usb/host/ehci-fsl.c
index a04f6a31c8..a8fb2b8ac3 100644
--- a/drivers/usb/host/ehci-fsl.c
+++ b/drivers/usb/host/ehci-fsl.c
@@ -93,6 +93,7 @@ static int ehci_fsl_probe(struct udevice *dev)
struct usb_ehci *ehci = NULL;
struct ehci_hccr *hccr;
struct ehci_hcor *hcor;
+ struct ehci_ctrl *ehci_ctrl = &priv->ehci;
/*
* Get the base address for EHCI controller from the device node
@@ -107,6 +108,8 @@ static int ehci_fsl_probe(struct udevice *dev)
hcor = (struct ehci_hcor *)
((void *)hccr + HC_LENGTH(ehci_readl(&hccr->cr_capbase)));
+ ehci_ctrl->has_fsl_erratum_a005275 = has_erratum_a005275();
+
if (ehci_fsl_init(priv, ehci, hccr, hcor) < 0)
return -ENXIO;
@@ -145,6 +148,8 @@ U_BOOT_DRIVER(ehci_fsl) = {
int ehci_hcd_init(int index, enum usb_init_type init,
struct ehci_hccr **hccr, struct ehci_hcor **hcor)
{
+ struct ehci_ctrl *ehci_ctrl = container_of(hccr,
+ struct ehci_ctrl, hccr);
struct usb_ehci *ehci = NULL;
switch (index) {
@@ -163,6 +168,8 @@ int ehci_hcd_init(int index, enum usb_init_type init,
*hcor = (struct ehci_hcor *)((uint32_t) *hccr +
HC_LENGTH(ehci_readl(&(*hccr)->cr_capbase)));
+ ehci_ctrl->has_fsl_erratum_a005275 = has_erratum_a005275();
+
return ehci_fsl_init(index, ehci, *hccr, *hcor);
}
diff --git a/drivers/usb/host/ehci-generic.c b/drivers/usb/host/ehci-generic.c
index 5a56f66cfa..cc2f33826a 100644
--- a/drivers/usb/host/ehci-generic.c
+++ b/drivers/usb/host/ehci-generic.c
@@ -26,56 +26,6 @@ struct generic_ehci {
int reset_count;
};
-static int ehci_setup_phy(struct udevice *dev, int index)
-{
- struct generic_ehci *priv = dev_get_priv(dev);
- int ret;
-
- ret = generic_phy_get_by_index(dev, index, &priv->phy);
- if (ret) {
- if (ret != -ENOENT) {
- dev_err(dev, "failed to get usb phy\n");
- return ret;
- }
- } else {
- ret = generic_phy_init(&priv->phy);
- if (ret) {
- dev_err(dev, "failed to init usb phy\n");
- return ret;
- }
-
- ret = generic_phy_power_on(&priv->phy);
- if (ret) {
- dev_err(dev, "failed to power on usb phy\n");
- return generic_phy_exit(&priv->phy);
- }
- }
-
- return 0;
-}
-
-static int ehci_shutdown_phy(struct udevice *dev)
-{
- struct generic_ehci *priv = dev_get_priv(dev);
- int ret = 0;
-
- if (generic_phy_valid(&priv->phy)) {
- ret = generic_phy_power_off(&priv->phy);
- if (ret) {
- dev_err(dev, "failed to power off usb phy\n");
- return ret;
- }
-
- ret = generic_phy_exit(&priv->phy);
- if (ret) {
- dev_err(dev, "failed to power off usb phy\n");
- return ret;
- }
- }
-
- return 0;
-}
-
static int ehci_usb_probe(struct udevice *dev)
{
struct generic_ehci *priv = dev_get_priv(dev);
@@ -145,7 +95,7 @@ static int ehci_usb_probe(struct udevice *dev)
}
}
- err = ehci_setup_phy(dev, 0);
+ err = ehci_setup_phy(dev, &priv->phy, 0);
if (err)
goto reset_err;
@@ -160,7 +110,7 @@ static int ehci_usb_probe(struct udevice *dev)
return 0;
phy_err:
- ret = ehci_shutdown_phy(dev);
+ ret = ehci_shutdown_phy(dev, &priv->phy);
if (ret)
dev_err(dev, "failed to shutdown usb phy\n");
@@ -185,7 +135,7 @@ static int ehci_usb_remove(struct udevice *dev)
if (ret)
return ret;
- ret = ehci_shutdown_phy(dev);
+ ret = ehci_shutdown_phy(dev, &priv->phy);
if (ret)
return ret;
diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c
index 663f748ffc..7d2d72f1fc 100644
--- a/drivers/usb/host/ehci-hcd.c
+++ b/drivers/usb/host/ehci-hcd.c
@@ -296,6 +296,73 @@ static void ehci_update_endpt2_dev_n_port(struct usb_device *udev,
QH_ENDPT2_HUBADDR(hubaddr));
}
+static int ehci_enable_async(struct ehci_ctrl *ctrl)
+{
+ u32 cmd;
+ int ret;
+
+ /* Enable async. schedule. */
+ cmd = ehci_readl(&ctrl->hcor->or_usbcmd);
+ if (cmd & CMD_ASE)
+ return 0;
+
+ cmd |= CMD_ASE;
+ ehci_writel(&ctrl->hcor->or_usbcmd, cmd);
+
+ ret = handshake((uint32_t *)&ctrl->hcor->or_usbsts, STS_ASS, STS_ASS,
+ 100 * 1000);
+ if (ret < 0)
+ printf("EHCI fail timeout STS_ASS set\n");
+
+ return ret;
+}
+
+static int ehci_disable_async(struct ehci_ctrl *ctrl)
+{
+ u32 cmd;
+ int ret;
+
+ if (ctrl->async_locked)
+ return 0;
+
+ /* Disable async schedule. */
+ cmd = ehci_readl(&ctrl->hcor->or_usbcmd);
+ if (!(cmd & CMD_ASE))
+ return 0;
+
+ cmd &= ~CMD_ASE;
+ ehci_writel(&ctrl->hcor->or_usbcmd, cmd);
+
+ ret = handshake((uint32_t *)&ctrl->hcor->or_usbsts, STS_ASS, 0,
+ 100 * 1000);
+ if (ret < 0)
+ printf("EHCI fail timeout STS_ASS reset\n");
+
+ return ret;
+}
+
+static int ehci_iaa_cycle(struct ehci_ctrl *ctrl)
+{
+ u32 cmd, status;
+ int ret;
+
+ /* Enable Interrupt on Async Advance Doorbell. */
+ cmd = ehci_readl(&ctrl->hcor->or_usbcmd);
+ cmd |= CMD_IAAD;
+ ehci_writel(&ctrl->hcor->or_usbcmd, cmd);
+
+ ret = handshake(&ctrl->hcor->or_usbsts, STS_IAA, STS_IAA,
+ 10 * 1000); /* 10ms timeout */
+ if (ret < 0)
+ printf("EHCI fail timeout STS_IAA set\n");
+
+ status = ehci_readl(&ctrl->hcor->or_usbsts);
+ if (status & STS_IAA)
+ ehci_writel(&ctrl->hcor->or_usbsts, STS_IAA);
+
+ return ret;
+}
+
static int
ehci_submit_async(struct usb_device *dev, unsigned long pipe, void *buffer,
int length, struct devrequest *req)
@@ -307,9 +374,8 @@ ehci_submit_async(struct usb_device *dev, unsigned long pipe, void *buffer,
volatile struct qTD *vtd;
unsigned long ts;
uint32_t *tdp;
- uint32_t endpt, maxpacket, token, usbsts;
+ uint32_t endpt, maxpacket, token, usbsts, qhtoken;
uint32_t c, toggle;
- uint32_t cmd;
int timeout;
int ret = 0;
struct ehci_ctrl *ctrl = ehci_get_ctrl(dev);
@@ -409,9 +475,15 @@ ehci_submit_async(struct usb_device *dev, unsigned long pipe, void *buffer,
endpt = QH_ENDPT1_RL(8) | QH_ENDPT1_C(c) |
QH_ENDPT1_MAXPKTLEN(maxpacket) | QH_ENDPT1_H(0) |
QH_ENDPT1_DTC(QH_ENDPT1_DTC_DT_FROM_QTD) |
- QH_ENDPT1_EPS(ehci_encode_speed(dev->speed)) |
QH_ENDPT1_ENDPT(usb_pipeendpoint(pipe)) | QH_ENDPT1_I(0) |
QH_ENDPT1_DEVADDR(usb_pipedevice(pipe));
+
+ /* Force FS for fsl HS quirk */
+ if (!ctrl->has_fsl_erratum_a005275)
+ endpt |= QH_ENDPT1_EPS(ehci_encode_speed(dev->speed));
+ else
+ endpt |= QH_ENDPT1_EPS(ehci_encode_speed(QH_FULL_SPEED));
+
qh->qh_endpt1 = cpu_to_hc32(endpt);
endpt = QH_ENDPT2_MULT(1) | QH_ENDPT2_UFCMASK(0) | QH_ENDPT2_UFSMASK(0);
qh->qh_endpt2 = cpu_to_hc32(endpt);
@@ -545,23 +617,12 @@ ehci_submit_async(struct usb_device *dev, unsigned long pipe, void *buffer,
flush_dcache_range((unsigned long)qtd,
ALIGN_END_ADDR(struct qTD, qtd, qtd_count));
- /* Set async. queue head pointer. */
- ehci_writel(&ctrl->hcor->or_asynclistaddr, virt_to_phys(&ctrl->qh_list));
-
usbsts = ehci_readl(&ctrl->hcor->or_usbsts);
ehci_writel(&ctrl->hcor->or_usbsts, (usbsts & 0x3f));
- /* Enable async. schedule. */
- cmd = ehci_readl(&ctrl->hcor->or_usbcmd);
- cmd |= CMD_ASE;
- ehci_writel(&ctrl->hcor->or_usbcmd, cmd);
-
- ret = handshake((uint32_t *)&ctrl->hcor->or_usbsts, STS_ASS, STS_ASS,
- 100 * 1000);
- if (ret < 0) {
- printf("EHCI fail timeout STS_ASS set\n");
+ ret = ehci_enable_async(ctrl);
+ if (ret)
goto fail;
- }
/* Wait for TDs to be processed. */
ts = get_timer(0);
@@ -581,6 +642,16 @@ ehci_submit_async(struct usb_device *dev, unsigned long pipe, void *buffer,
break;
WATCHDOG_RESET();
} while (get_timer(ts) < timeout);
+ qhtoken = hc32_to_cpu(qh->qh_overlay.qt_token);
+
+ ctrl->qh_list.qh_link = cpu_to_hc32(virt_to_phys(&ctrl->qh_list) | QH_LINK_TYPE_QH);
+ flush_dcache_range((unsigned long)&ctrl->qh_list,
+ ALIGN_END_ADDR(struct QH, &ctrl->qh_list, 1));
+
+ /* Set IAAD, poll IAA */
+ ret = ehci_iaa_cycle(ctrl);
+ if (ret)
+ goto fail;
/*
* Invalidate the memory area occupied by buffer
@@ -599,25 +670,16 @@ ehci_submit_async(struct usb_device *dev, unsigned long pipe, void *buffer,
if (QT_TOKEN_GET_STATUS(token) & QT_TOKEN_STATUS_ACTIVE)
printf("EHCI timed out on TD - token=%#x\n", token);
- /* Disable async schedule. */
- cmd = ehci_readl(&ctrl->hcor->or_usbcmd);
- cmd &= ~CMD_ASE;
- ehci_writel(&ctrl->hcor->or_usbcmd, cmd);
-
- ret = handshake((uint32_t *)&ctrl->hcor->or_usbsts, STS_ASS, 0,
- 100 * 1000);
- if (ret < 0) {
- printf("EHCI fail timeout STS_ASS reset\n");
+ ret = ehci_disable_async(ctrl);
+ if (ret)
goto fail;
- }
- token = hc32_to_cpu(qh->qh_overlay.qt_token);
- if (!(QT_TOKEN_GET_STATUS(token) & QT_TOKEN_STATUS_ACTIVE)) {
- debug("TOKEN=%#x\n", token);
- switch (QT_TOKEN_GET_STATUS(token) &
+ if (!(QT_TOKEN_GET_STATUS(qhtoken) & QT_TOKEN_STATUS_ACTIVE)) {
+ debug("TOKEN=%#x\n", qhtoken);
+ switch (QT_TOKEN_GET_STATUS(qhtoken) &
~(QT_TOKEN_STATUS_SPLITXSTATE | QT_TOKEN_STATUS_PERR)) {
case 0:
- toggle = QT_TOKEN_GET_DT(token);
+ toggle = QT_TOKEN_GET_DT(qhtoken);
usb_settoggle(dev, usb_pipeendpoint(pipe),
usb_pipeout(pipe), toggle);
dev->status = 0;
@@ -635,11 +697,11 @@ ehci_submit_async(struct usb_device *dev, unsigned long pipe, void *buffer,
break;
default:
dev->status = USB_ST_CRC_ERR;
- if (QT_TOKEN_GET_STATUS(token) & QT_TOKEN_STATUS_HALTED)
+ if (QT_TOKEN_GET_STATUS(qhtoken) & QT_TOKEN_STATUS_HALTED)
dev->status |= USB_ST_STALLED;
break;
}
- dev->act_len = length - QT_TOKEN_GET_TOTALBYTES(token);
+ dev->act_len = length - QT_TOKEN_GET_TOTALBYTES(qhtoken);
} else {
dev->act_len = 0;
#ifndef CONFIG_USB_EHCI_FARADAY
@@ -832,6 +894,10 @@ static int ehci_submit_root(struct usb_device *dev, unsigned long pipe,
} else {
int ret;
+ /* Disable chirp for HS erratum */
+ if (ctrl->has_fsl_erratum_a005275)
+ reg |= PORTSC_FSL_PFSC;
+
reg |= EHCI_PS_PR;
reg &= ~EHCI_PS_PE;
ehci_writel(status_reg, reg);
@@ -1508,6 +1574,16 @@ static int _ehci_submit_int_msg(struct usb_device *dev, unsigned long pipe,
return result;
}
+static int _ehci_lock_async(struct ehci_ctrl *ctrl, int lock)
+{
+ ctrl->async_locked = lock;
+
+ if (lock)
+ return 0;
+
+ return ehci_disable_async(ctrl);
+}
+
#ifndef CONFIG_DM_USB
int submit_bulk_msg(struct usb_device *dev, unsigned long pipe,
void *buffer, int length)
@@ -1544,6 +1620,13 @@ int destroy_int_queue(struct usb_device *dev, struct int_queue *queue)
{
return _ehci_destroy_int_queue(dev, queue);
}
+
+int usb_lock_async(struct usb_device *dev, int lock)
+{
+ struct ehci_ctrl *ctrl = ehci_get_ctrl(dev);
+
+ return _ehci_lock_async(ctrl, lock);
+}
#endif
#ifdef CONFIG_DM_USB
@@ -1606,6 +1689,13 @@ static int ehci_get_max_xfer_size(struct udevice *dev, size_t *size)
return 0;
}
+static int ehci_lock_async(struct udevice *dev, int lock)
+{
+ struct ehci_ctrl *ctrl = dev_get_priv(dev);
+
+ return _ehci_lock_async(ctrl, lock);
+}
+
int ehci_register(struct udevice *dev, struct ehci_hccr *hccr,
struct ehci_hcor *hcor, const struct ehci_ops *ops,
uint tweaks, enum usb_init_type init)
@@ -1672,6 +1762,73 @@ struct dm_usb_ops ehci_usb_ops = {
.poll_int_queue = ehci_poll_int_queue,
.destroy_int_queue = ehci_destroy_int_queue,
.get_max_xfer_size = ehci_get_max_xfer_size,
+ .lock_async = ehci_lock_async,
};
#endif
+
+#ifdef CONFIG_PHY
+int ehci_setup_phy(struct udevice *dev, struct phy *phy, int index)
+{
+ int ret;
+
+ if (!phy)
+ return 0;
+
+ ret = generic_phy_get_by_index(dev, index, phy);
+ if (ret) {
+ if (ret != -ENOENT) {
+ dev_err(dev, "failed to get usb phy\n");
+ return ret;
+ }
+ } else {
+ ret = generic_phy_init(phy);
+ if (ret) {
+ dev_err(dev, "failed to init usb phy\n");
+ return ret;
+ }
+
+ ret = generic_phy_power_on(phy);
+ if (ret) {
+ dev_err(dev, "failed to power on usb phy\n");
+ return generic_phy_exit(phy);
+ }
+ }
+
+ return 0;
+}
+
+int ehci_shutdown_phy(struct udevice *dev, struct phy *phy)
+{
+ int ret = 0;
+
+ if (!phy)
+ return 0;
+
+ if (generic_phy_valid(phy)) {
+ ret = generic_phy_power_off(phy);
+ if (ret) {
+ dev_err(dev, "failed to power off usb phy\n");
+ return ret;
+ }
+
+ ret = generic_phy_exit(phy);
+ if (ret) {
+ dev_err(dev, "failed to power off usb phy\n");
+ return ret;
+ }
+ }
+
+ return 0;
+}
+#else
+int ehci_setup_phy(struct udevice *dev, struct phy *phy, int index)
+{
+ return 0;
+}
+
+int ehci_shutdown_phy(struct udevice *dev, struct phy *phy)
+{
+ return 0;
+}
+#endif
diff --git a/drivers/usb/host/ehci.h b/drivers/usb/host/ehci.h
index 07de472f91..83d1da9372 100644
--- a/drivers/usb/host/ehci.h
+++ b/drivers/usb/host/ehci.h
@@ -8,7 +8,9 @@
#ifndef USB_EHCI_H
#define USB_EHCI_H
+#include <stdbool.h>
#include <usb.h>
+#include <generic-phy.h>
/* Section 2.2.3 - N_PORTS */
#define MAX_HC_PORTS 15
@@ -42,6 +44,7 @@ struct ehci_hcor {
#define STS_ASS (1 << 15)
#define STS_PSS (1 << 14)
#define STS_HALT (1 << 12)
+#define STS_IAA (1 << 5)
uint32_t or_usbintr;
#define INTR_UE (1 << 0) /* USB interrupt enable */
#define INTR_UEE (1 << 1) /* USB error interrupt enable */
@@ -65,6 +68,8 @@ struct ehci_hcor {
#define PORTSC_PSPD_FS 0x0
#define PORTSC_PSPD_LS 0x1
#define PORTSC_PSPD_HS 0x2
+#define PORTSC_FSL_PFSC BIT(24) /* PFSC bit to disable HS chirping */
+
uint32_t or_systune;
} __attribute__ ((packed, aligned(4)));
@@ -250,6 +255,8 @@ struct ehci_ctrl {
uint32_t *periodic_list;
int periodic_schedules;
int ntds;
+ bool has_fsl_erratum_a005275; /* Freescale HS silicon quirk */
+ bool async_locked;
struct ehci_ops ops;
void *priv; /* client's private data */
};
@@ -288,4 +295,8 @@ int ehci_register(struct udevice *dev, struct ehci_hccr *hccr,
int ehci_deregister(struct udevice *dev);
extern struct dm_usb_ops ehci_usb_ops;
+/* EHCI PHY functions */
+int ehci_setup_phy(struct udevice *dev, struct phy *phy, int index);
+int ehci_shutdown_phy(struct udevice *dev, struct phy *phy);
+
#endif /* USB_EHCI_H */
diff --git a/drivers/usb/host/usb-uclass.c b/drivers/usb/host/usb-uclass.c
index 611ea97a72..da54ac690e 100644
--- a/drivers/usb/host/usb-uclass.c
+++ b/drivers/usb/host/usb-uclass.c
@@ -22,6 +22,17 @@ struct usb_uclass_priv {
int companion_device_count;
};
+int usb_lock_async(struct usb_device *udev, int lock)
+{
+ struct udevice *bus = udev->controller_dev;
+ struct dm_usb_ops *ops = usb_get_ops(bus);
+
+ if (!ops->lock_async)
+ return -ENOSYS;
+
+ return ops->lock_async(bus, lock);
+}
+
int usb_disable_asynch(int disable)
{
int old_value = asynch_allowed;
diff --git a/include/configs/opos6uldev.h b/include/configs/opos6uldev.h
index 326258d1de..f79d73bc39 100644
--- a/include/configs/opos6uldev.h
+++ b/include/configs/opos6uldev.h
@@ -128,6 +128,7 @@
"mmcroot=/dev/mmcblk0p2 ro\0" \
"mmcrootfstype=ext4 rootwait\0" \
"kernelimg=" __stringify(CONFIG_BOARD_NAME) "-linux.bin\0" \
+ "rootfs_loadaddr=0x80008000\0" \
"videomode=video=ctfb:x:800,y:480,depth:18,pclk:30030,le:30,ri:210,up:23,lo:22,hs:16,vs:1,sync:1073741824,vmode:0\0" \
"check_env=if test -n ${flash_env_version}; " \
"then env default env_version; " \
@@ -176,12 +177,12 @@
"else echo dtb update in failed; " \
"fi;\0" \
"update_dtb=run download_dtb flash_dtb\0" \
- "download_rootfs=tftpboot ${loadaddr} ${board_name}-rootfs.ext4\0" \
+ "download_rootfs=tftpboot ${rootfs_loadaddr} ${board_name}-rootfs.ext4\0" \
"flash_rootfs=" \
"if mmc dev 0 0; then " \
"setexpr nbblocks ${filesize} / 0x200; " \
"setexpr nbblocks ${nbblocks} + 1; " \
- "if mmc write ${loadaddr} 0x40800 ${nbblocks}; then " \
+ "if mmc write ${rootfs_loadaddr} 0x40800 ${nbblocks}; then " \
"echo Flashing of rootfs image succeed; " \
"else echo Flashing of rootfs image failed; " \
"fi; " \
@@ -191,18 +192,18 @@
"if mmc dev 0 0; then " \
"setexpr nbblocks ${filesize} / 0x200; " \
"setexpr nbblocks ${nbblocks} + 1; " \
- "if mmc write ${loadaddr} 0x800 ${nbblocks}; then " \
+ "if mmc write ${rootfs_loadaddr} 0x800 ${nbblocks}; then " \
"echo Flashing of rootfs image in failsafe partition succeed; " \
"else echo Flashing of rootfs image in failsafe partition failed; " \
"fi; " \
"fi;\0" \
"update_failsafe=run download_rootfs flash_failsafe\0" \
- "download_userdata=tftpboot ${loadaddr} ${board_name}-user_data.ext4\0" \
+ "download_userdata=tftpboot ${rootfs_loadaddr} ${board_name}-user_data.ext4\0" \
"flash_userdata=" \
"if mmc dev 0 0; then " \
"setexpr nbblocks ${filesize} / 0x200; " \
"setexpr nbblocks ${nbblocks} + 1; " \
- "if mmc write ${loadaddr} 0 ${nbblocks}; then " \
+ "if mmc write ${rootfs_loadaddr} 0 ${nbblocks}; then " \
"echo Flashing of user_data image succeed; " \
"else echo Flashing of user_data image failed; " \
"fi; " \
@@ -235,9 +236,9 @@
"nfs ${loadaddr} ${serverip}:${rootpath}/boot/${kernelimg} && " \
"nfs ${fdt_addr} ${serverip}:${rootpath}/boot/${cpu_type}-${fdt_name}.dtb && " \
"bootz ${loadaddr} - ${fdt_addr};\0" \
- "show_update_logo=if fatload usb 0:1 ${loadaddr} /update/update.bmp; " \
+ "show_update_logo=if load usb 0:1 ${loadaddr} /update/update.bmp; " \
"then bmp display ${loadaddr}; fi\0" \
- "usb_update_rootfs=if fatload usb 0:1 ${loadaddr} /update/${board_name}-rootfs.ext4; " \
+ "usb_update_rootfs=if load usb 0:1 ${rootfs_loadaddr} /update/${board_name}-rootfs.ext4; " \
"then run flash_rootfs; fi\0" \
"usb_update=usb start 1; run show_update_logo; run usb_update_rootfs;\0" \
EXTRA_ENV_SETTINGS_OPOS6UL_SP
diff --git a/include/fsl_usb.h b/include/fsl_usb.h
index e9e1dd6905..c0f076b06d 100644
--- a/include/fsl_usb.h
+++ b/include/fsl_usb.h
@@ -87,6 +87,7 @@ struct ccsr_usb_phy {
/* USB Erratum Checking code */
#if defined(CONFIG_PPC) || defined(CONFIG_ARM)
bool has_dual_phy(void);
+bool has_erratum_a005275(void);
bool has_erratum_a006261(void);
bool has_erratum_a007075(void);
bool has_erratum_a007798(void);
diff --git a/include/usb.h b/include/usb.h
index b6b48a8c60..c01a09dd63 100644
--- a/include/usb.h
+++ b/include/usb.h
@@ -263,6 +263,7 @@ int usb_bulk_msg(struct usb_device *dev, unsigned int pipe,
void *data, int len, int *actual_length, int timeout);
int usb_submit_int_msg(struct usb_device *dev, unsigned long pipe,
void *buffer, int transfer_len, int interval);
+int usb_lock_async(struct usb_device *dev, int lock);
int usb_disable_asynch(int disable);
int usb_maxpacket(struct usb_device *dev, unsigned long pipe);
int usb_get_configuration_no(struct usb_device *dev, int cfgno,
@@ -785,6 +786,16 @@ struct dm_usb_ops {
* in a USB transfer. USB class driver needs to be aware of this.
*/
int (*get_max_xfer_size)(struct udevice *bus, size_t *size);
+
+ /**
+ * lock_async() - Keep async schedule after a transfer
+ *
+ * It may be desired to keep the asynchronous schedule running even
+ * after a transfer finishes, usually when doing multiple transfers
+ * back-to-back. This callback allows signalling the USB controller
+ * driver to do just that.
+ */
+ int (*lock_async)(struct udevice *udev, int lock);
};
#define usb_get_ops(dev) ((struct dm_usb_ops *)(dev)->driver->ops)
hooks/post-receive
--
armadeus/u-boot
|