static void r8a66597_usb_connect(struct r8a66597 *r8a66597) { r8a66597_bset(r8a66597, CTRE, INTENB0); r8a66597_bset(r8a66597, BEMPE | BRDYE, INTENB0); r8a66597_bset(r8a66597, DPRPU, SYSCFG0); }
static int send_status_packet(struct r8a66597 *r8a66597, unsigned long pipe) { r8a66597_bset(r8a66597, SQSET, DCPCTR); r8a66597_mdfy(r8a66597, PID_NAK, PID, DCPCTR); if (usb_pipein(pipe)) { r8a66597_bset(r8a66597, R8A66597_DIR, DCPCFG); r8a66597_mdfy(r8a66597, ISEL, ISEL | CURPIPE, CFIFOSEL); r8a66597_reg_wait(r8a66597, CFIFOSEL, CURPIPE, 0); r8a66597_write(r8a66597, ~BEMP0, BEMPSTS); r8a66597_write(r8a66597, BCLR | BVAL, CFIFOCTR); } else { r8a66597_bclr(r8a66597, R8A66597_DIR, DCPCFG); r8a66597_mdfy(r8a66597, 0, ISEL | CURPIPE, CFIFOSEL); r8a66597_reg_wait(r8a66597, CFIFOSEL, CURPIPE, 0); r8a66597_write(r8a66597, BCLR, CFIFOCTR); } r8a66597_mdfy(r8a66597, PID_BUF, PID, DCPCTR); while (!(r8a66597_read(r8a66597, BEMPSTS) & 0x0001)) if (ctrlc()) return -1; return 0; }
/* this function must be called with interrupt disabled */ static void r8a66597_pipe_toggle(struct r8a66597 *r8a66597, struct r8a66597_pipe *pipe, int toggle) { if (toggle) r8a66597_bset(r8a66597, SQSET, pipe->pipectr); else r8a66597_bset(r8a66597, SQCLR, pipe->pipectr); }
static int r8a66597_clock_enable(struct r8a66597 *r8a66597) { u16 tmp; int i = 0; #if defined(CONFIG_SUPERH_ON_CHIP_R8A66597) do { r8a66597_write(r8a66597, SCKE, SYSCFG0); tmp = r8a66597_read(r8a66597, SYSCFG0); if (i++ > 1000) { printf("register access fail.\n"); return -1; } } while ((tmp & SCKE) != SCKE); r8a66597_write(r8a66597, 0x04, 0x02); #else do { r8a66597_write(r8a66597, USBE, SYSCFG0); tmp = r8a66597_read(r8a66597, SYSCFG0); if (i++ > 1000) { printf("register access fail.\n"); return -1; } } while ((tmp & USBE) != USBE); r8a66597_bclr(r8a66597, USBE, SYSCFG0); #if !defined(CONFIG_RZA_USB) r8a66597_mdfy(r8a66597, CONFIG_R8A66597_XTAL, XTAL, SYSCFG0); i = 0; r8a66597_bset(r8a66597, XCKE, SYSCFG0); do { udelay(1000); tmp = r8a66597_read(r8a66597, SYSCFG0); if (i++ > 500) { printf("register access fail.\n"); return -1; } } while ((tmp & SCKE) != SCKE); #else /* * RZ/A Only: * Bits XTAL(UCKSEL) and UPLLE in SYSCFG0 for USB0 controls both USB0 * and USB1, so we must always set the USB0 register */ #if (CONFIG_R8A66597_XTAL == 1) setbits(le16, R8A66597_BASE0, XTAL); #endif mdelay(1); setbits(le16, R8A66597_BASE0, UPLLE); mdelay(1); r8a66597_bset(r8a66597, SUSPM, SUSPMODE0); #endif /* CONFIG_RZA_USB */ #endif /* #if defined(CONFIG_SUPERH_ON_CHIP_R8A66597) */ return 0; }
static void r8a66597_enable_port(struct r8a66597 *r8a66597, int port) { u16 val; val = port ? DRPD : DCFM | DRPD; r8a66597_bset(r8a66597, val, get_syscfg_reg(port)); r8a66597_bset(r8a66597, HSE, get_syscfg_reg(port)); r8a66597_write(r8a66597, BURST | CPU_ADR_RD_WR, get_dmacfg_reg(port)); }
static int enable_controller(struct r8a66597 *r8a66597) { int ret, port; ret = r8a66597_clock_enable(r8a66597); if (ret < 0) return ret; #if !defined(CONFIG_RZA_USB) r8a66597_bset(r8a66597, CONFIG_R8A66597_LDRV & LDRV, PINCFG); #endif r8a66597_bset(r8a66597, USBE, SYSCFG0); r8a66597_bset(r8a66597, INTL, SOFCFG); r8a66597_write(r8a66597, 0, INTENB0); for (port = 0; port < R8A66597_MAX_ROOT_HUB; port++) r8a66597_write(r8a66597, 0, get_intenb_reg(port)); r8a66597_bset(r8a66597, CONFIG_R8A66597_ENDIAN & BIGEND, CFIFOSEL); r8a66597_bset(r8a66597, CONFIG_R8A66597_ENDIAN & BIGEND, D0FIFOSEL); r8a66597_bset(r8a66597, CONFIG_R8A66597_ENDIAN & BIGEND, D1FIFOSEL); r8a66597_bset(r8a66597, TRNENSEL, SOFCFG); for (port = 0; port < R8A66597_MAX_ROOT_HUB; port++) r8a66597_enable_port(r8a66597, port); return 0; }
static int receive_bulk_packet(struct r8a66597 *r8a66597, struct usb_device *dev, unsigned long pipe, void *buffer, int transfer_len) { u16 tmp; u16 *buf; const u16 pipenum = BULK_IN_PIPENUM; int rcv_len; int maxpacket = dev->epmaxpacketin[usb_pipeendpoint(pipe)]; R8A66597_DPRINT("%s\n", __func__); /* prepare */ if (dev->act_len == 0) { r8a66597_mdfy(r8a66597, PID_NAK, PID, get_pipectr_addr(pipenum)); r8a66597_write(r8a66597, ~(1 << pipenum), BRDYSTS); r8a66597_write(r8a66597, TRCLR, get_pipetre_addr(pipenum)); r8a66597_write(r8a66597, (transfer_len + maxpacket - 1) / maxpacket, get_pipetrn_addr(pipenum)); r8a66597_bset(r8a66597, TRENB, get_pipetre_addr(pipenum)); r8a66597_mdfy(r8a66597, PID_BUF, PID, get_pipectr_addr(pipenum)); } r8a66597_mdfy(r8a66597, MBW | pipenum, MBW | CURPIPE, CFIFOSEL); r8a66597_reg_wait(r8a66597, CFIFOSEL, CURPIPE, pipenum); while (!(r8a66597_read(r8a66597, BRDYSTS) & (1 << pipenum))) if (ctrlc()) return -1; r8a66597_write(r8a66597, ~(1 << pipenum), BRDYSTS); tmp = r8a66597_read(r8a66597, CFIFOCTR); if ((tmp & FRDY) == 0) { printf("%s FRDY is not set. (%x)\n", __func__, tmp); return -1; } buf = (u16 *)(buffer + dev->act_len); rcv_len = tmp & DTLN; dev->act_len += rcv_len; if (buffer) { if (rcv_len == 0) r8a66597_write(r8a66597, BCLR, CFIFOCTR); else r8a66597_read_fifo(r8a66597, CFIFO, buf, rcv_len); } return 0; }
/* this function must be called with interrupt disabled */ static void enable_pipe_irq(struct r8a66597 *r8a66597, u16 pipenum, unsigned long reg) { u16 tmp; tmp = r8a66597_read(r8a66597, INTENB0); r8a66597_bclr(r8a66597, BEMPE | NRDYE | BRDYE, INTENB0); r8a66597_bset(r8a66597, 1 << pipenum, reg); r8a66597_write(r8a66597, tmp, INTENB0); }
/* this function must be called with interrupt disabled */ static void clear_all_buffer(struct r8a66597 *r8a66597, struct r8a66597_pipe *pipe) { u16 tmp; if (!pipe || pipe->info.pipenum == 0) return; pipe_stop(r8a66597, pipe); r8a66597_bset(r8a66597, ACLRM, pipe->pipectr); tmp = r8a66597_read(r8a66597, pipe->pipectr); tmp = r8a66597_read(r8a66597, pipe->pipectr); tmp = r8a66597_read(r8a66597, pipe->pipectr); r8a66597_bclr(r8a66597, ACLRM, pipe->pipectr); }
static int r8a66597_clock_enable(struct r8a66597 *r8a66597) { u16 tmp; int i = 0; 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: reg access fail.\n"); return -ENXIO; } } while ((tmp & SCKE) != SCKE); r8a66597_write(r8a66597, 0x04, 0x02); } else { do { r8a66597_write(r8a66597, USBE, SYSCFG0); tmp = r8a66597_read(r8a66597, SYSCFG0); if (i++ > 1000) { 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); i = 0; r8a66597_bset(r8a66597, XCKE, SYSCFG0); do { msleep(1); tmp = r8a66597_read(r8a66597, SYSCFG0); if (i++ > 500) { printk(KERN_ERR "r8a66597: reg access fail.\n"); return -ENXIO; } } while ((tmp & SCKE) != SCKE); } return 0; }
static int receive_control_packet(struct r8a66597 *r8a66597, struct usb_device *dev, void *buffer, int transfer_len) { u16 tmp; int rcv_len; /* FIXME: limit transfer size : 64byte or less */ r8a66597_bclr(r8a66597, R8A66597_DIR, DCPCFG); r8a66597_mdfy(r8a66597, 0, ISEL | CURPIPE, CFIFOSEL); r8a66597_reg_wait(r8a66597, CFIFOSEL, CURPIPE, 0); r8a66597_bset(r8a66597, SQSET, DCPCTR); r8a66597_write(r8a66597, BCLR, CFIFOCTR); r8a66597_mdfy(r8a66597, PID_BUF, PID, DCPCTR); while (!(r8a66597_read(r8a66597, BRDYSTS) & 0x0001)) if (ctrlc()) return -1; r8a66597_write(r8a66597, ~0x0001, BRDYSTS); r8a66597_mdfy(r8a66597, MBW, MBW | CURPIPE, CFIFOSEL); r8a66597_reg_wait(r8a66597, CFIFOSEL, CURPIPE, 0); tmp = r8a66597_read(r8a66597, CFIFOCTR); if ((tmp & FRDY) == 0) { printf("%s FRDY is not set. (%x)\n", __func__, tmp); return -1; } rcv_len = tmp & DTLN; dev->act_len += rcv_len; r8a66597_mdfy(r8a66597, PID_NAK, PID, DCPCTR); if (buffer) { if (rcv_len == 0) r8a66597_write(r8a66597, BCLR, DCPCTR); else r8a66597_read_fifo(r8a66597, CFIFO, buffer, rcv_len); } return 0; }
static int r8a66597_clock_enable(struct r8a66597 *r8a66597) { u16 tmp; int i = 0; #if defined(CONFIG_SUPERH_ON_CHIP_R8A66597) do { r8a66597_write(r8a66597, SCKE, SYSCFG0); tmp = r8a66597_read(r8a66597, SYSCFG0); if (i++ > 1000) { printf("register access fail.\n"); return -1; } } while ((tmp & SCKE) != SCKE); r8a66597_write(r8a66597, 0x04, 0x02); #else do { r8a66597_write(r8a66597, USBE, SYSCFG0); tmp = r8a66597_read(r8a66597, SYSCFG0); if (i++ > 1000) { printf("register access fail.\n"); return -1; } } while ((tmp & USBE) != USBE); r8a66597_bclr(r8a66597, USBE, SYSCFG0); r8a66597_mdfy(r8a66597, CONFIG_R8A66597_XTAL, XTAL, SYSCFG0); i = 0; r8a66597_bset(r8a66597, XCKE, SYSCFG0); do { udelay(1000); tmp = r8a66597_read(r8a66597, SYSCFG0); if (i++ > 500) { printf("register access fail.\n"); return -1; } } while ((tmp & SCKE) != SCKE); #endif /* #if defined(CONFIG_SUPERH_ON_CHIP_R8A66597) */ return 0; }
/* this function must be called with interrupt disabled */ static void enable_r8a66597_pipe_dma(struct r8a66597 *r8a66597, struct r8a66597_device *dev, struct r8a66597_pipe *pipe, struct urb *urb) { 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++) { if ((r8a66597->dma_map & (1 << i)) != 0) continue; dev_info(&dev->udev->dev, "address %d, EndpointAddress 0x%02x use " "DMA FIFO\n", usb_pipedevice(urb->pipe), info->dir_in ? USB_ENDPOINT_DIR_MASK + info->epnum : info->epnum); r8a66597->dma_map |= 1 << i; dev->dma_map |= 1 << i; set_pipe_reg_addr(pipe, i); cfifo_change(r8a66597, 0); r8a66597_mdfy(r8a66597, mbw | pipe->info.pipenum, mbw | CURPIPE, pipe->fifosel); r8a66597_reg_wait(r8a66597, pipe->fifosel, CURPIPE, pipe->info.pipenum); r8a66597_bset(r8a66597, BCLR, pipe->fifoctr); break; } } }
static void pipe_buffer_setting(struct r8a66597 *r8a66597, struct usb_device *dev, unsigned long pipe) { u16 val = 0; u16 pipenum, bufnum, maxpacket; if (usb_pipein(pipe)) { pipenum = BULK_IN_PIPENUM; bufnum = BULK_IN_BUFNUM; maxpacket = dev->epmaxpacketin[usb_pipeendpoint(pipe)]; } else { pipenum = BULK_OUT_PIPENUM; bufnum = BULK_OUT_BUFNUM; maxpacket = dev->epmaxpacketout[usb_pipeendpoint(pipe)]; } if (r8a66597->pipe_config & (1 << pipenum)) return; r8a66597->pipe_config |= (1 << pipenum); r8a66597_bset(r8a66597, ACLRM, get_pipectr_addr(pipenum)); r8a66597_bclr(r8a66597, ACLRM, get_pipectr_addr(pipenum)); r8a66597_write(r8a66597, pipenum, PIPESEL); /* FIXME: This driver support bulk transfer only. */ if (!usb_pipein(pipe)) val |= R8A66597_DIR; else val |= R8A66597_SHTNAK; val |= R8A66597_BULK | R8A66597_DBLB | usb_pipeendpoint(pipe); r8a66597_write(r8a66597, val, PIPECFG); r8a66597_write(r8a66597, (8 << 10) | bufnum, PIPEBUF); r8a66597_write(r8a66597, make_devsel(usb_pipedevice(pipe)) | maxpacket, PIPEMAXP); r8a66597_write(r8a66597, 0, PIPEPERI); r8a66597_write(r8a66597, SQCLR, get_pipectr_addr(pipenum)); }
/* this function must be called with interrupt disabled */ static void pipe_buffer_setting(struct r8a66597 *r8a66597, struct r8a66597_pipe_info *info) { u16 val = 0; if (info->pipenum == 0) return; r8a66597_bset(r8a66597, ACLRM, get_pipectr_addr(info->pipenum)); r8a66597_bclr(r8a66597, ACLRM, get_pipectr_addr(info->pipenum)); r8a66597_write(r8a66597, info->pipenum, PIPESEL); if (!info->dir_in) val |= R8A66597_DIR; if (info->type == R8A66597_BULK && info->dir_in) val |= R8A66597_DBLB | R8A66597_SHTNAK; val |= info->type | info->epnum; r8a66597_write(r8a66597, val, PIPECFG); r8a66597_write(r8a66597, (info->buf_bsize << 10) | (info->bufnum), PIPEBUF); r8a66597_write(r8a66597, make_devsel(info->address) | info->maxpacket, PIPEMAXP); r8a66597_write(r8a66597, info->interval, PIPEPERI); }
static int enable_controller(struct r8a66597 *r8a66597) { int ret, port; u16 vif = r8a66597->pdata->vif ? LDRV : 0; u16 irq_sense = r8a66597->irq_sense_low ? INTL : 0; u16 endian = r8a66597->pdata->endian ? BIGEND : 0; ret = r8a66597_clock_enable(r8a66597); if (ret < 0) return ret; r8a66597_bset(r8a66597, vif & LDRV, PINCFG); r8a66597_bset(r8a66597, USBE, SYSCFG0); r8a66597_bset(r8a66597, BEMPE | NRDYE | BRDYE, INTENB0); r8a66597_bset(r8a66597, irq_sense & INTL, SOFCFG); r8a66597_bset(r8a66597, BRDY0, BRDYENB); r8a66597_bset(r8a66597, BEMP0, BEMPENB); r8a66597_bset(r8a66597, endian & BIGEND, CFIFOSEL); r8a66597_bset(r8a66597, endian & BIGEND, D0FIFOSEL); r8a66597_bset(r8a66597, endian & BIGEND, D1FIFOSEL); r8a66597_bset(r8a66597, TRNENSEL, SOFCFG); r8a66597_bset(r8a66597, SIGNE | SACKE, INTENB1); for (port = 0; port < r8a66597->max_root_hub; port++) r8a66597_enable_port(r8a66597, port); return 0; }