On Mon, Oct 06, 2014 at 06:55:03PM +0300, Laurent Pinchart wrote: > Although the corresponding register is part of the HCD register space, > processor bus initialization is not specific to the HCD. To prepare for > device controller support, move bus interface initialization to core > code. > > Signed-off-by: Laurent Pinchart <laurent.pinchart@xxxxxxxxxxxxxxxx> Reviewed-by: Felipe Balbi <balbi@xxxxxx> > --- > drivers/usb/host/isp1760-core.c | 62 ++++++++++++++++++++++++++++++++++++-- > drivers/usb/host/isp1760-core.h | 30 ++++++++++++++++++ > drivers/usb/host/isp1760-hcd.c | 67 ++++++++--------------------------------- > drivers/usb/host/isp1760-hcd.h | 20 +----------- > 4 files changed, 104 insertions(+), 75 deletions(-) > > diff --git a/drivers/usb/host/isp1760-core.c b/drivers/usb/host/isp1760-core.c > index 718fd6c..cde66d3 100644 > --- a/drivers/usb/host/isp1760-core.c > +++ b/drivers/usb/host/isp1760-core.c > @@ -13,6 +13,7 @@ > * version 2 as published by the Free Software Foundation. > */ > > +#include <linux/delay.h> > #include <linux/gpio.h> > #include <linux/io.h> > #include <linux/kernel.h> > @@ -22,6 +23,59 @@ > > #include "isp1760-core.h" > #include "isp1760-hcd.h" > +#include "isp1760-regs.h" > + > +static void isp1760_init_core(struct isp1760_device *isp) > +{ > + u32 hwmode; > + > + /* Low-level chip reset */ > + if (gpio_is_valid(isp->rst_gpio)) { > + unsigned int rst_lvl; > + > + rst_lvl = (isp->devflags & > + ISP1760_FLAG_RESET_ACTIVE_HIGH) ? 1 : 0; > + > + gpio_set_value(isp->rst_gpio, rst_lvl); > + mdelay(50); > + gpio_set_value(isp->rst_gpio, !rst_lvl); > + } > + > + /* > + * Reset the host controller, including the CPU interface > + * configuration. > + */ > + isp1760_write32(isp->regs, HC_RESET_REG, SW_RESET_RESET_ALL); > + msleep(100); > + > + /* Setup HW Mode Control: This assumes a level active-low interrupt */ > + hwmode = HW_DATA_BUS_32BIT; > + > + if (isp->devflags & ISP1760_FLAG_BUS_WIDTH_16) > + hwmode &= ~HW_DATA_BUS_32BIT; > + if (isp->devflags & ISP1760_FLAG_ANALOG_OC) > + hwmode |= HW_ANA_DIGI_OC; > + if (isp->devflags & ISP1760_FLAG_DACK_POL_HIGH) > + hwmode |= HW_DACK_POL_HIGH; > + if (isp->devflags & ISP1760_FLAG_DREQ_POL_HIGH) > + hwmode |= HW_DREQ_POL_HIGH; > + if (isp->devflags & ISP1760_FLAG_INTR_POL_HIGH) > + hwmode |= HW_INTR_HIGH_ACT; > + if (isp->devflags & ISP1760_FLAG_INTR_EDGE_TRIG) > + hwmode |= HW_INTR_EDGE_TRIG; > + > + /* > + * We have to set this first in case we're in 16-bit mode. > + * Write it twice to ensure correct upper bits if switching > + * to 16-bit mode. > + */ > + isp1760_write32(isp->regs, HC_HW_MODE_CTRL, hwmode); > + isp1760_write32(isp->regs, HC_HW_MODE_CTRL, hwmode); > + > + dev_info(isp->dev, "bus width: %u, oc: %s\n", > + isp->devflags & ISP1760_FLAG_BUS_WIDTH_16 ? 16 : 32, > + isp->devflags & ISP1760_FLAG_ANALOG_OC ? "analog" : "digital"); > +} > > int isp1760_register(struct resource *mem, int irq, unsigned long irqflags, > int rst_gpio, struct device *dev, unsigned int devflags) > @@ -39,6 +93,9 @@ int isp1760_register(struct resource *mem, int irq, unsigned long irqflags, > if (!isp) > return -ENOMEM; > > + isp->dev = dev; > + isp->devflags = devflags; > + > if (gpio_is_valid(rst_gpio)) { > ret = gpio_request(rst_gpio, dev_name(dev)); > if (!ret) { > @@ -62,9 +119,10 @@ int isp1760_register(struct resource *mem, int irq, unsigned long irqflags, > goto error; > } > > - isp->hcd.rst_gpio = rst_gpio; > + isp1760_init_core(isp); > + > ret = isp1760_hcd_register(&isp->hcd, isp->regs, mem, irq, > - irqflags | IRQF_SHARED, dev, devflags); > + irqflags | IRQF_SHARED, dev); > if (ret < 0) > goto error; > > diff --git a/drivers/usb/host/isp1760-core.h b/drivers/usb/host/isp1760-core.h > index 8bd997c..862dff4 100644 > --- a/drivers/usb/host/isp1760-core.h > +++ b/drivers/usb/host/isp1760-core.h > @@ -20,11 +20,31 @@ > > #include "isp1760-hcd.h" > > +struct device; > + > +/* > + * Device flags that can vary from board to board. All of these > + * indicate the most "atypical" case, so that a devflags of 0 is > + * a sane default configuration. > + */ > +#define ISP1760_FLAG_BUS_WIDTH_16 0x00000002 /* 16-bit data bus width */ > +#define ISP1760_FLAG_OTG_EN 0x00000004 /* Port 1 supports OTG */ > +#define ISP1760_FLAG_ANALOG_OC 0x00000008 /* Analog overcurrent */ > +#define ISP1760_FLAG_DACK_POL_HIGH 0x00000010 /* DACK active high */ > +#define ISP1760_FLAG_DREQ_POL_HIGH 0x00000020 /* DREQ active high */ > +#define ISP1760_FLAG_ISP1761 0x00000040 /* Chip is ISP1761 */ > +#define ISP1760_FLAG_INTR_POL_HIGH 0x00000080 /* Interrupt polarity active high */ > +#define ISP1760_FLAG_INTR_EDGE_TRIG 0x00000100 /* Interrupt edge triggered */ > +#define ISP1760_FLAG_RESET_ACTIVE_HIGH 0x80000000 /* RESET GPIO active high */ > + > struct isp1760_device { > + struct device *dev; > + > resource_size_t mem_start; > resource_size_t mem_size; > > void __iomem *regs; > + unsigned int devflags; > int rst_gpio; > > struct isp1760_hcd hcd; > @@ -34,4 +54,14 @@ int isp1760_register(struct resource *mem, int irq, unsigned long irqflags, > int rst_gpio, struct device *dev, unsigned int devflags); > void isp1760_unregister(struct device *dev); > > +static inline u32 isp1760_read32(void __iomem *base, u32 reg) > +{ > + return readl(base + reg); > +} > + > +static inline void isp1760_write32(void __iomem *base, u32 reg, u32 val) > +{ > + writel(val, base + reg); > +} > + > #endif > diff --git a/drivers/usb/host/isp1760-hcd.c b/drivers/usb/host/isp1760-hcd.c > index f903ad9..596a1a9 100644 > --- a/drivers/usb/host/isp1760-hcd.c > +++ b/drivers/usb/host/isp1760-hcd.c > @@ -24,8 +24,8 @@ > #include <linux/timer.h> > #include <asm/unaligned.h> > #include <asm/cacheflush.h> > -#include <linux/gpio.h> > > +#include "isp1760-core.h" > #include "isp1760-hcd.h" > #include "isp1760-regs.h" > > @@ -160,12 +160,12 @@ struct urb_listitem { > */ > static u32 reg_read32(void __iomem *base, u32 reg) > { > - return readl(base + reg); > + return isp1760_read32(base, reg); > } > > static void reg_write32(void __iomem *base, u32 reg, u32 val) > { > - writel(val, base + reg); > + isp1760_write32(base, reg, val); > } > > /* > @@ -466,42 +466,6 @@ static int isp1760_hc_setup(struct usb_hcd *hcd) > int result; > u32 scratch, hwmode; > > - /* low-level chip reset */ > - if (gpio_is_valid(priv->rst_gpio)) { > - unsigned int rst_lvl; > - > - rst_lvl = (priv->devflags & > - ISP1760_FLAG_RESET_ACTIVE_HIGH) ? 1 : 0; > - > - gpio_set_value(priv->rst_gpio, rst_lvl); > - mdelay(50); > - gpio_set_value(priv->rst_gpio, !rst_lvl); > - } > - > - /* Setup HW Mode Control: This assumes a level active-low interrupt */ > - hwmode = HW_DATA_BUS_32BIT; > - > - if (priv->devflags & ISP1760_FLAG_BUS_WIDTH_16) > - hwmode &= ~HW_DATA_BUS_32BIT; > - if (priv->devflags & ISP1760_FLAG_ANALOG_OC) > - hwmode |= HW_ANA_DIGI_OC; > - if (priv->devflags & ISP1760_FLAG_DACK_POL_HIGH) > - hwmode |= HW_DACK_POL_HIGH; > - if (priv->devflags & ISP1760_FLAG_DREQ_POL_HIGH) > - hwmode |= HW_DREQ_POL_HIGH; > - if (priv->devflags & ISP1760_FLAG_INTR_POL_HIGH) > - hwmode |= HW_INTR_HIGH_ACT; > - if (priv->devflags & ISP1760_FLAG_INTR_EDGE_TRIG) > - hwmode |= HW_INTR_EDGE_TRIG; > - > - /* > - * We have to set this first in case we're in 16-bit mode. > - * Write it twice to ensure correct upper bits if switching > - * to 16-bit mode. > - */ > - reg_write32(hcd->regs, HC_HW_MODE_CTRL, hwmode); > - reg_write32(hcd->regs, HC_HW_MODE_CTRL, hwmode); > - > reg_write32(hcd->regs, HC_SCRATCH_REG, 0xdeadbabe); > /* Change bus pattern */ > scratch = reg_read32(hcd->regs, HC_CHIP_ID_REG); > @@ -511,31 +475,27 @@ static int isp1760_hc_setup(struct usb_hcd *hcd) > return -ENODEV; > } > > - /* pre reset */ > + /* > + * The RESET_HC bit in the SW_RESET register is supposed to reset the > + * host controller without touching the CPU interface registers, but at > + * least on the ISP1761 it seems to behave as the RESET_ALL bit and > + * reset the whole device. We thus can't use it here, so let's reset > + * the host controller through the EHCI USB Command register. The device > + * has been reset in core code anyway, so this shouldn't matter. > + */ > reg_write32(hcd->regs, HC_BUFFER_STATUS_REG, 0); > reg_write32(hcd->regs, HC_ATL_PTD_SKIPMAP_REG, NO_TRANSFER_ACTIVE); > reg_write32(hcd->regs, HC_INT_PTD_SKIPMAP_REG, NO_TRANSFER_ACTIVE); > reg_write32(hcd->regs, HC_ISO_PTD_SKIPMAP_REG, NO_TRANSFER_ACTIVE); > > - /* reset */ > - reg_write32(hcd->regs, HC_RESET_REG, SW_RESET_RESET_ALL); > - mdelay(100); > - > - reg_write32(hcd->regs, HC_RESET_REG, SW_RESET_RESET_HC); > - mdelay(100); > - > result = ehci_reset(hcd); > if (result) > return result; > > /* Step 11 passed */ > > - dev_info(hcd->self.controller, "bus width: %d, oc: %s\n", > - (priv->devflags & ISP1760_FLAG_BUS_WIDTH_16) ? > - 16 : 32, (priv->devflags & ISP1760_FLAG_ANALOG_OC) ? > - "analog" : "digital"); > - > /* ATL reset */ > + hwmode = reg_read32(hcd->regs, HC_HW_MODE_CTRL) & ~ALL_ATX_RESET; > reg_write32(hcd->regs, HC_HW_MODE_CTRL, hwmode | ALL_ATX_RESET); > mdelay(10); > reg_write32(hcd->regs, HC_HW_MODE_CTRL, hwmode); > @@ -2239,7 +2199,7 @@ void isp1760_deinit_kmem_cache(void) > > int isp1760_hcd_register(struct isp1760_hcd *priv, void __iomem *regs, > struct resource *mem, int irq, unsigned long irqflags, > - struct device *dev, unsigned int devflags) > + struct device *dev) > { > struct usb_hcd *hcd; > int ret; > @@ -2251,7 +2211,6 @@ int isp1760_hcd_register(struct isp1760_hcd *priv, void __iomem *regs, > *(struct isp1760_hcd **)hcd->hcd_priv = priv; > > priv->hcd = hcd; > - priv->devflags = devflags; > > init_memory(priv); > > diff --git a/drivers/usb/host/isp1760-hcd.h b/drivers/usb/host/isp1760-hcd.h > index 51996a2..df7ea36 100644 > --- a/drivers/usb/host/isp1760-hcd.h > +++ b/drivers/usb/host/isp1760-hcd.h > @@ -26,21 +26,6 @@ struct usb_hcd; > #define MAX_PAYLOAD_SIZE BLOCK_3_SIZE > #define PAYLOAD_AREA_SIZE 0xf000 > > -/* > - * Device flags that can vary from board to board. All of these > - * indicate the most "atypical" case, so that a devflags of 0 is > - * a sane default configuration. > - */ > -#define ISP1760_FLAG_BUS_WIDTH_16 0x00000002 /* 16-bit data bus width */ > -#define ISP1760_FLAG_OTG_EN 0x00000004 /* Port 1 supports OTG */ > -#define ISP1760_FLAG_ANALOG_OC 0x00000008 /* Analog overcurrent */ > -#define ISP1760_FLAG_DACK_POL_HIGH 0x00000010 /* DACK active high */ > -#define ISP1760_FLAG_DREQ_POL_HIGH 0x00000020 /* DREQ active high */ > -#define ISP1760_FLAG_ISP1761 0x00000040 /* Chip is ISP1761 */ > -#define ISP1760_FLAG_INTR_POL_HIGH 0x00000080 /* Interrupt polarity active high */ > -#define ISP1760_FLAG_INTR_EDGE_TRIG 0x00000100 /* Interrupt edge triggered */ > -#define ISP1760_FLAG_RESET_ACTIVE_HIGH 0x80000000 /* RESET GPIO active high */ > - > struct isp1760_slotinfo { > struct isp1760_qh *qh; > struct isp1760_qtd *qtd; > @@ -79,14 +64,11 @@ struct isp1760_hcd { > unsigned i_thresh; > unsigned long reset_done; > unsigned long next_statechange; > - unsigned int devflags; > - > - int rst_gpio; > }; > > int isp1760_hcd_register(struct isp1760_hcd *priv, void __iomem *regs, > struct resource *mem, int irq, unsigned long irqflags, > - struct device *dev, unsigned int devflags); > + struct device *dev); > void isp1760_hcd_unregister(struct isp1760_hcd *priv); > > int isp1760_init_kmem_once(void); > -- > 2.0.4 > -- balbi
Attachment:
signature.asc
Description: Digital signature