Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 332ceddb authored by Greg Kroah-Hartman's avatar Greg Kroah-Hartman
Browse files

Merge branch 'for-usb' of...

Merge branch 'for-usb' of git://git.kernel.org/pub/scm/linux/kernel/git/geoff/ps3-linux into usb-next

* 'for-usb' of git://git.kernel.org/pub/scm/linux/kernel/git/geoff/ps3-linux:
  usb: PS3 EHCI QH read work-around
  usb: Fix PS3 EHCI suspend
  usb: PS3 EHCI HC reset work-around
  usb: Remove ehci_reset call from ehci_run
parents a36ae95c aaa0ef28
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -23,6 +23,7 @@ static int au1xxx_ehci_setup(struct usb_hcd *hcd)
	int ret = ehci_init(hcd);

	ehci->need_io_watchdog = 0;
	ehci_reset(ehci);
	return ret;
}

+52 −10
Original line number Diff line number Diff line
@@ -48,6 +48,10 @@
#include <asm/system.h>
#include <asm/unaligned.h>

#if defined(CONFIG_PPC_PS3)
#include <asm/firmware.h>
#endif

/*-------------------------------------------------------------------------*/

/*
@@ -230,12 +234,58 @@ static int ehci_halt (struct ehci_hcd *ehci)
			  STS_HALT, STS_HALT, 16 * 125);
}

#if defined(CONFIG_USB_SUSPEND) && defined(CONFIG_PPC_PS3)

/*
 * The EHCI controller of the Cell Super Companion Chip used in the
 * PS3 will stop the root hub after all root hub ports are suspended.
 * When in this condition handshake will return -ETIMEDOUT.  The
 * STS_HLT bit will not be set, so inspection of the frame index is
 * used here to test for the condition.  If the condition is found
 * return success to allow the USB suspend to complete.
 */

static int handshake_for_broken_root_hub(struct ehci_hcd *ehci,
					 void __iomem *ptr, u32 mask, u32 done,
					 int usec)
{
	unsigned int old_index;
	int error;

	if (!firmware_has_feature(FW_FEATURE_PS3_LV1))
		return -ETIMEDOUT;

	old_index = ehci_read_frame_index(ehci);

	error = handshake(ehci, ptr, mask, done, usec);

	if (error == -ETIMEDOUT && ehci_read_frame_index(ehci) == old_index)
		return 0;

	return error;
}

#else

static int handshake_for_broken_root_hub(struct ehci_hcd *ehci,
					 void __iomem *ptr, u32 mask, u32 done,
					 int usec)
{
	return -ETIMEDOUT;
}

#endif

static int handshake_on_error_set_halt(struct ehci_hcd *ehci, void __iomem *ptr,
				       u32 mask, u32 done, int usec)
{
	int error;

	error = handshake(ehci, ptr, mask, done, usec);
	if (error == -ETIMEDOUT)
		error = handshake_for_broken_root_hub(ehci, ptr, mask, done,
						      usec);

	if (error) {
		ehci_halt(ehci);
		ehci->rh_state = EHCI_RH_HALTED;
@@ -620,6 +670,7 @@ static int ehci_init(struct usb_hcd *hcd)
	hw = ehci->async->hw;
	hw->hw_next = QH_NEXT(ehci, ehci->async->qh_dma);
	hw->hw_info1 = cpu_to_hc32(ehci, QH_HEAD);
	hw->hw_info1 |= cpu_to_hc32(ehci, (1 << 7));	/* I = 1 */
	hw->hw_token = cpu_to_hc32(ehci, QTD_STS_HALT);
	hw->hw_qtd_next = EHCI_LIST_END(ehci);
	ehci->async->qh_state = QH_STATE_LINKED;
@@ -677,22 +728,13 @@ static int ehci_init(struct usb_hcd *hcd)
static int ehci_run (struct usb_hcd *hcd)
{
	struct ehci_hcd		*ehci = hcd_to_ehci (hcd);
	int			retval;
	u32			temp;
	u32			hcc_params;

	hcd->uses_new_polling = 1;

	/* EHCI spec section 4.1 */
	/*
	 * TDI driver does the ehci_reset in their reset callback.
	 * Don't reset here, because configuration settings will
	 * vanish.
	 */
	if (!ehci_is_TDI(ehci) && (retval = ehci_reset(ehci)) != 0) {
		ehci_mem_cleanup(ehci);
		return retval;
	}

	ehci_writel(ehci, ehci->periodic_dma, &ehci->regs->frame_list);
	ehci_writel(ehci, (u32)ehci->async->qh_dma, &ehci->regs->async_next);

+2 −0
Original line number Diff line number Diff line
@@ -155,6 +155,8 @@ static int ehci_octeon_drv_probe(struct platform_device *pdev)
	/* cache this readonly data; minimize chip reads */
	ehci->hcs_params = ehci_readl(ehci, &ehci->caps->hcs_params);

	ehci_reset(ehci);

	ret = usb_add_hcd(hcd, irq, IRQF_SHARED);
	if (ret) {
		dev_dbg(&pdev->dev, "failed to add hcd with err %d\n", ret);
+2 −0
Original line number Diff line number Diff line
@@ -228,6 +228,8 @@ static int ehci_hcd_omap_probe(struct platform_device *pdev)
	/* cache this readonly data; minimize chip reads */
	omap_ehci->hcs_params = readl(&omap_ehci->caps->hcs_params);

	ehci_reset(omap_ehci);

	ret = usb_add_hcd(hcd, irq, IRQF_SHARED);
	if (ret) {
		dev_err(dev, "failed to add hcd with err %d\n", ret);
+30 −0
Original line number Diff line number Diff line
@@ -21,6 +21,34 @@
#include <asm/firmware.h>
#include <asm/ps3.h>

static void ps3_ehci_setup_insnreg(struct ehci_hcd *ehci)
{
	/* PS3 HC internal setup register offsets. */

	enum ps3_ehci_hc_insnreg {
		ps3_ehci_hc_insnreg01 = 0x084,
		ps3_ehci_hc_insnreg02 = 0x088,
		ps3_ehci_hc_insnreg03 = 0x08c,
	};

	/* PS3 EHCI HC errata fix 316 - The PS3 EHCI HC will reset its
	 * internal INSNREGXX setup regs back to the chip default values
	 * on Host Controller Reset (CMD_RESET) or Light Host Controller
	 * Reset (CMD_LRESET).  The work-around for this is for the HC
	 * driver to re-initialise these regs when ever the HC is reset.
	 */

	/* Set burst transfer counts to 256 out, 32 in. */

	writel_be(0x01000020, (void __iomem *)ehci->regs +
		ps3_ehci_hc_insnreg01);

	/* Enable burst transfer counts. */

	writel_be(0x00000001, (void __iomem *)ehci->regs +
		ps3_ehci_hc_insnreg03);
}

static int ps3_ehci_hc_reset(struct usb_hcd *hcd)
{
	int result;
@@ -49,6 +77,8 @@ static int ps3_ehci_hc_reset(struct usb_hcd *hcd)

	ehci_reset(ehci);

	ps3_ehci_setup_insnreg(ehci);

	return result;
}

Loading