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

Commit 719a72b7 authored by Magnus Damm's avatar Magnus Damm Committed by Paul Mundt
Browse files

usb: r8a66597-hcd platform data on_chip support



Convert the r8a66597-hcd driver to use the on_chip flag
from platform data to enable on chip behaviour instead
of relying on CONFIG_SUPERH_ON_CHIP_R8A66597 ugliness.

This makes the code cleaner and also allows us to support
both external and internal r8a66597 with the same kernel.

It also makes the Kconfig part more future proof since
we with this patch can add support for new processors
with on-chip r8a66597 without modifying the Kconfig.

Signed-off-by: default avatarMagnus Damm <damm@igel.co.jp>
Signed-off-by: default avatarPaul Mundt <lethal@linux-sh.org>
parent ae1cef6e
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -304,6 +304,7 @@ static struct platform_device sh_eth_device = {
};

static struct r8a66597_platdata sh7724_usb0_host_data = {
	.on_chip = 1,
};

static struct resource sh7724_usb0_host_resources[] = {
+1 −1
Original line number Diff line number Diff line
@@ -40,7 +40,7 @@ static struct platform_device iic_device = {
};

static struct r8a66597_platdata r8a66597_data = {
	/* This set zero to all members */
	.on_chip = 1,
};

static struct resource usb_host_resources[] = {
+1 −1
Original line number Diff line number Diff line
@@ -398,7 +398,7 @@ static struct platform_device rtc_device = {
};

static struct r8a66597_platdata r8a66597_data = {
	/* This set zero to all members */
	.on_chip = 1,
};

static struct resource sh7723_usb_host_resources[] = {
+0 −7
Original line number Diff line number Diff line
@@ -336,13 +336,6 @@ config USB_R8A66597_HCD
	  To compile this driver as a module, choose M here: the
	  module will be called r8a66597-hcd.

config SUPERH_ON_CHIP_R8A66597
	boolean "Enable SuperH on-chip R8A66597 USB"
	depends on USB_R8A66597_HCD && (CPU_SUBTYPE_SH7366 || CPU_SUBTYPE_SH7723 || CPU_SUBTYPE_SH7724)
	help
	   This driver enables support for the on-chip R8A66597 in the
	   SH7366, SH7723 and SH7724 processors.

config USB_WHCI_HCD
	tristate "Wireless USB Host Controller Interface (WHCI) driver (EXPERIMENTAL)"
	depends on EXPERIMENTAL
+106 −81
Original line number Diff line number Diff line
@@ -91,31 +91,31 @@ static int r8a66597_clock_enable(struct r8a66597 *r8a66597)
	u16 tmp;
	int i = 0;

#if defined(CONFIG_SUPERH_ON_CHIP_R8A66597)
#if defined(CONFIG_HAVE_CLK)
	if (r8a66597->pdata->on_chip) {
#ifdef CONFIG_HAVE_CLK
		clk_enable(r8a66597->clk);
#endif
		do {
			r8a66597_write(r8a66597, SCKE, SYSCFG0);
			tmp = r8a66597_read(r8a66597, SYSCFG0);
			if (i++ > 1000) {
			printk(KERN_ERR "r8a66597: register access fail.\n");
				printk(KERN_ERR "r8a66597: reg access fail.\n");
				return -ENXIO;
			}
		} while ((tmp & SCKE) != SCKE);
		r8a66597_write(r8a66597, 0x04, 0x02);
#else
	} else {
		do {
			r8a66597_write(r8a66597, USBE, SYSCFG0);
			tmp = r8a66597_read(r8a66597, SYSCFG0);
			if (i++ > 1000) {
			printk(KERN_ERR "r8a66597: register access fail.\n");
				printk(KERN_ERR "r8a66597: reg access fail.\n");
				return -ENXIO;
			}
		} while ((tmp & USBE) != USBE);
		r8a66597_bclr(r8a66597, USBE, SYSCFG0);
	r8a66597_mdfy(r8a66597, get_xtal_from_pdata(r8a66597->pdata), XTAL,
			SYSCFG0);
		r8a66597_mdfy(r8a66597, get_xtal_from_pdata(r8a66597->pdata),
			      XTAL, SYSCFG0);

		i = 0;
		r8a66597_bset(r8a66597, XCKE, SYSCFG0);
@@ -123,11 +123,11 @@ static int r8a66597_clock_enable(struct r8a66597 *r8a66597)
			msleep(1);
			tmp = r8a66597_read(r8a66597, SYSCFG0);
			if (i++ > 500) {
			printk(KERN_ERR "r8a66597: register access fail.\n");
				printk(KERN_ERR "r8a66597: reg access fail.\n");
				return -ENXIO;
			}
		} while ((tmp & SCKE) != SCKE);
#endif	/* #if defined(CONFIG_SUPERH_ON_CHIP_R8A66597) */
	}

	return 0;
}
@@ -136,15 +136,16 @@ static void r8a66597_clock_disable(struct r8a66597 *r8a66597)
{
	r8a66597_bclr(r8a66597, SCKE, SYSCFG0);
	udelay(1);
#if defined(CONFIG_SUPERH_ON_CHIP_R8A66597)
#if defined(CONFIG_HAVE_CLK)

	if (r8a66597->pdata->on_chip) {
#ifdef CONFIG_HAVE_CLK
		clk_disable(r8a66597->clk);
#endif
#else
	} else {
		r8a66597_bclr(r8a66597, PLLC, SYSCFG0);
		r8a66597_bclr(r8a66597, XCKE, SYSCFG0);
		r8a66597_bclr(r8a66597, USBE, SYSCFG0);
#endif
	}
}

static void r8a66597_enable_port(struct r8a66597 *r8a66597, int port)
@@ -205,7 +206,7 @@ static int enable_controller(struct r8a66597 *r8a66597)

	r8a66597_bset(r8a66597, SIGNE | SACKE, INTENB1);

	for (port = 0; port < R8A66597_MAX_ROOT_HUB; port++)
	for (port = 0; port < r8a66597->max_root_hub; port++)
		r8a66597_enable_port(r8a66597, port);

	return 0;
@@ -218,7 +219,7 @@ static void disable_controller(struct r8a66597 *r8a66597)
	r8a66597_write(r8a66597, 0, INTENB0);
	r8a66597_write(r8a66597, 0, INTSTS0);

	for (port = 0; port < R8A66597_MAX_ROOT_HUB; port++)
	for (port = 0; port < r8a66597->max_root_hub; port++)
		r8a66597_disable_port(r8a66597, port);

	r8a66597_clock_disable(r8a66597);
@@ -249,11 +250,12 @@ static int is_hub_limit(char *devpath)
	return ((strlen(devpath) >= 4) ? 1 : 0);
}

static void get_port_number(char *devpath, u16 *root_port, u16 *hub_port)
static void get_port_number(struct r8a66597 *r8a66597,
			    char *devpath, u16 *root_port, u16 *hub_port)
{
	if (root_port) {
		*root_port = (devpath[0] & 0x0F) - 1;
		if (*root_port >= R8A66597_MAX_ROOT_HUB)
		if (*root_port >= r8a66597->max_root_hub)
			printk(KERN_ERR "r8a66597: Illegal root port number.\n");
	}
	if (hub_port)
@@ -355,7 +357,8 @@ static int make_r8a66597_device(struct r8a66597 *r8a66597,
	INIT_LIST_HEAD(&dev->device_list);
	list_add_tail(&dev->device_list, &r8a66597->child_device);

	get_port_number(urb->dev->devpath, &dev->root_port, &dev->hub_port);
	get_port_number(r8a66597, urb->dev->devpath,
			&dev->root_port, &dev->hub_port);
	if (!is_child_device(urb->dev->devpath))
		r8a66597->root_hub[dev->root_port].dev = dev;

@@ -420,7 +423,7 @@ static void free_usb_address(struct r8a66597 *r8a66597,
	list_del(&dev->device_list);
	kfree(dev);

	for (port = 0; port < R8A66597_MAX_ROOT_HUB; port++) {
	for (port = 0; port < r8a66597->max_root_hub; port++) {
		if (r8a66597->root_hub[port].dev == dev) {
			r8a66597->root_hub[port].dev = NULL;
			break;
@@ -495,10 +498,20 @@ static void r8a66597_pipe_toggle(struct r8a66597 *r8a66597,
		r8a66597_bset(r8a66597, SQCLR, pipe->pipectr);
}

static inline unsigned short mbw_value(struct r8a66597 *r8a66597)
{
	if (r8a66597->pdata->on_chip)
		return MBW_32;
	else
		return MBW_16;
}

/* this function must be called with interrupt disabled */
static inline void cfifo_change(struct r8a66597 *r8a66597, u16 pipenum)
{
	r8a66597_mdfy(r8a66597, MBW | pipenum, MBW | CURPIPE, CFIFOSEL);
	unsigned short mbw = mbw_value(r8a66597);

	r8a66597_mdfy(r8a66597, mbw | pipenum, mbw | CURPIPE, CFIFOSEL);
	r8a66597_reg_wait(r8a66597, CFIFOSEL, CURPIPE, pipenum);
}

@@ -506,11 +519,13 @@ static inline void cfifo_change(struct r8a66597 *r8a66597, u16 pipenum)
static inline void fifo_change_from_pipe(struct r8a66597 *r8a66597,
					 struct r8a66597_pipe *pipe)
{
	unsigned short mbw = mbw_value(r8a66597);

	cfifo_change(r8a66597, 0);
	r8a66597_mdfy(r8a66597, MBW | 0, MBW | CURPIPE, D0FIFOSEL);
	r8a66597_mdfy(r8a66597, MBW | 0, MBW | CURPIPE, D1FIFOSEL);
	r8a66597_mdfy(r8a66597, mbw | 0, mbw | CURPIPE, D0FIFOSEL);
	r8a66597_mdfy(r8a66597, mbw | 0, mbw | CURPIPE, D1FIFOSEL);

	r8a66597_mdfy(r8a66597, MBW | pipe->info.pipenum, MBW | CURPIPE,
	r8a66597_mdfy(r8a66597, mbw | pipe->info.pipenum, mbw | CURPIPE,
		      pipe->fifosel);
	r8a66597_reg_wait(r8a66597, pipe->fifosel, CURPIPE, pipe->info.pipenum);
}
@@ -742,9 +757,13 @@ static void enable_r8a66597_pipe_dma(struct r8a66597 *r8a66597,
				     struct r8a66597_pipe *pipe,
				     struct urb *urb)
{
#if !defined(CONFIG_SUPERH_ON_CHIP_R8A66597)
	int i;
	struct r8a66597_pipe_info *info = &pipe->info;
	unsigned short mbw = mbw_value(r8a66597);

	/* pipe dma is only for external controlles */
	if (r8a66597->pdata->on_chip)
		return;

	if ((pipe->info.pipenum != 0) && (info->type != R8A66597_INT)) {
		for (i = 0; i < R8A66597_MAX_DMA_CHANNEL; i++) {
@@ -763,8 +782,8 @@ static void enable_r8a66597_pipe_dma(struct r8a66597 *r8a66597,
			set_pipe_reg_addr(pipe, i);

			cfifo_change(r8a66597, 0);
			r8a66597_mdfy(r8a66597, MBW | pipe->info.pipenum,
				      MBW | CURPIPE, pipe->fifosel);
			r8a66597_mdfy(r8a66597, mbw | pipe->info.pipenum,
				      mbw | CURPIPE, pipe->fifosel);

			r8a66597_reg_wait(r8a66597, pipe->fifosel, CURPIPE,
					  pipe->info.pipenum);
@@ -772,7 +791,6 @@ static void enable_r8a66597_pipe_dma(struct r8a66597 *r8a66597,
			break;
		}
	}
#endif	/* #if defined(CONFIG_SUPERH_ON_CHIP_R8A66597) */
}

/* this function must be called with interrupt disabled */
@@ -1769,7 +1787,7 @@ static void r8a66597_timer(unsigned long _r8a66597)

	spin_lock_irqsave(&r8a66597->lock, flags);

	for (port = 0; port < R8A66597_MAX_ROOT_HUB; port++)
	for (port = 0; port < r8a66597->max_root_hub; port++)
		r8a66597_root_hub_control(r8a66597, port);

	spin_unlock_irqrestore(&r8a66597->lock, flags);
@@ -1807,7 +1825,7 @@ static void set_address_zero(struct r8a66597 *r8a66597, struct urb *urb)
	u16 root_port, hub_port;

	if (usb_address == 0) {
		get_port_number(urb->dev->devpath,
		get_port_number(r8a66597, urb->dev->devpath,
				&root_port, &hub_port);
		set_devadd_reg(r8a66597, 0,
			       get_r8a66597_usb_speed(urb->dev->speed),
@@ -2082,7 +2100,7 @@ static int r8a66597_hub_status_data(struct usb_hcd *hcd, char *buf)

	*buf = 0;	/* initialize (no change) */

	for (i = 0; i < R8A66597_MAX_ROOT_HUB; i++) {
	for (i = 0; i < r8a66597->max_root_hub; i++) {
		if (r8a66597->root_hub[i].port & 0xffff0000)
			*buf |= 1 << (i + 1);
	}
@@ -2097,11 +2115,11 @@ static void r8a66597_hub_descriptor(struct r8a66597 *r8a66597,
{
	desc->bDescriptorType = 0x29;
	desc->bHubContrCurrent = 0;
	desc->bNbrPorts = R8A66597_MAX_ROOT_HUB;
	desc->bNbrPorts = r8a66597->max_root_hub;
	desc->bDescLength = 9;
	desc->bPwrOn2PwrGood = 0;
	desc->wHubCharacteristics = cpu_to_le16(0x0011);
	desc->bitmap[0] = ((1 << R8A66597_MAX_ROOT_HUB) - 1) << 1;
	desc->bitmap[0] = ((1 << r8a66597->max_root_hub) - 1) << 1;
	desc->bitmap[1] = ~0;
}

@@ -2129,7 +2147,7 @@ static int r8a66597_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue,
		}
		break;
	case ClearPortFeature:
		if (wIndex > R8A66597_MAX_ROOT_HUB)
		if (wIndex > r8a66597->max_root_hub)
			goto error;
		if (wLength != 0)
			goto error;
@@ -2162,12 +2180,12 @@ static int r8a66597_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue,
		*buf = 0x00;
		break;
	case GetPortStatus:
		if (wIndex > R8A66597_MAX_ROOT_HUB)
		if (wIndex > r8a66597->max_root_hub)
			goto error;
		*(__le32 *)buf = cpu_to_le32(rh->port);
		break;
	case SetPortFeature:
		if (wIndex > R8A66597_MAX_ROOT_HUB)
		if (wIndex > r8a66597->max_root_hub)
			goto error;
		if (wLength != 0)
			goto error;
@@ -2216,7 +2234,7 @@ static int r8a66597_bus_suspend(struct usb_hcd *hcd)

	dbg("%s", __func__);

	for (port = 0; port < R8A66597_MAX_ROOT_HUB; port++) {
	for (port = 0; port < r8a66597->max_root_hub; port++) {
		struct r8a66597_root_hub *rh = &r8a66597->root_hub[port];
		unsigned long dvstctr_reg = get_dvstctr_reg(port);

@@ -2247,7 +2265,7 @@ static int r8a66597_bus_resume(struct usb_hcd *hcd)

	dbg("%s", __func__);

	for (port = 0; port < R8A66597_MAX_ROOT_HUB; port++) {
	for (port = 0; port < r8a66597->max_root_hub; port++) {
		struct r8a66597_root_hub *rh = &r8a66597->root_hub[port];
		unsigned long dvstctr_reg = get_dvstctr_reg(port);

@@ -2314,7 +2332,7 @@ static int r8a66597_suspend(struct device *dev)

	disable_controller(r8a66597);

	for (port = 0; port < R8A66597_MAX_ROOT_HUB; port++) {
	for (port = 0; port < r8a66597->max_root_hub; port++) {
		struct r8a66597_root_hub *rh = &r8a66597->root_hub[port];

		rh->port = 0x00000000;
@@ -2354,7 +2372,8 @@ static int __init_or_module r8a66597_remove(struct platform_device *pdev)
	del_timer_sync(&r8a66597->rh_timer);
	usb_remove_hcd(hcd);
	iounmap((void *)r8a66597->reg);
#if defined(CONFIG_SUPERH_ON_CHIP_R8A66597) && defined(CONFIG_HAVE_CLK)
#ifdef CONFIG_HAVE_CLK
	if (r8a66597->pdata->on_chip)
		clk_put(r8a66597->clk);
#endif
	usb_put_hcd(hcd);
@@ -2363,7 +2382,7 @@ static int __init_or_module r8a66597_remove(struct platform_device *pdev)

static int __devinit r8a66597_probe(struct platform_device *pdev)
{
#if defined(CONFIG_SUPERH_ON_CHIP_R8A66597) && defined(CONFIG_HAVE_CLK)
#ifdef CONFIG_HAVE_CLK
	char clk_name[8];
#endif
	struct resource *res = NULL, *ires;
@@ -2425,15 +2444,20 @@ static int __devinit r8a66597_probe(struct platform_device *pdev)
	r8a66597->pdata = pdev->dev.platform_data;
	r8a66597->irq_sense_low = irq_trigger == IRQF_TRIGGER_LOW;

#if defined(CONFIG_SUPERH_ON_CHIP_R8A66597) && defined(CONFIG_HAVE_CLK)
	if (r8a66597->pdata->on_chip) {
#ifdef CONFIG_HAVE_CLK
		snprintf(clk_name, sizeof(clk_name), "usb%d", pdev->id);
		r8a66597->clk = clk_get(&pdev->dev, clk_name);
		if (IS_ERR(r8a66597->clk)) {
		dev_err(&pdev->dev, "cannot get clock \"%s\"\n", clk_name);
			dev_err(&pdev->dev, "cannot get clock \"%s\"\n",
				clk_name);
			ret = PTR_ERR(r8a66597->clk);
			goto clean_up2;
		}
#endif
		r8a66597->max_root_hub = 1;
	} else
		r8a66597->max_root_hub = 2;

	spin_lock_init(&r8a66597->lock);
	init_timer(&r8a66597->rh_timer);
@@ -2463,7 +2487,8 @@ static int __devinit r8a66597_probe(struct platform_device *pdev)
	return 0;

clean_up3:
#if defined(CONFIG_SUPERH_ON_CHIP_R8A66597) && defined(CONFIG_HAVE_CLK)
#ifdef CONFIG_HAVE_CLK
	if (r8a66597->pdata->on_chip)
		clk_put(r8a66597->clk);
clean_up2:
#endif
Loading