|
|
|
@@ -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)
|
|
|
|
|
{
|
|
|
|
|
cfifo_change(r8a66597, 0);
|
|
|
|
|
r8a66597_mdfy(r8a66597, MBW | 0, MBW | CURPIPE, D0FIFOSEL);
|
|
|
|
|
r8a66597_mdfy(r8a66597, MBW | 0, MBW | CURPIPE, D1FIFOSEL);
|
|
|
|
|
unsigned short mbw = mbw_value(r8a66597);
|
|
|
|
|
|
|
|
|
|
r8a66597_mdfy(r8a66597, MBW | pipe->info.pipenum, MBW | CURPIPE,
|
|
|
|
|
cfifo_change(r8a66597, 0);
|
|
|
|
|
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,
|
|
|
|
|
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
|
|
|
|
|