Re: [PATCH 15/17] usb: isp1760: Initialize the bus interface in core code

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



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


[Index of Archives]     [Linux Media]     [Linux Input]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]     [Old Linux USB Devel Archive]

  Powered by Linux