diff options
author | Yoshihiro Shimoda <shimoda.yoshihiro@renesas.com> | 2008-04-10 08:05:58 -0400 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@suse.de> | 2008-04-25 00:16:49 -0400 |
commit | 9424ea29658ce5bcdcf527ddf9617b9507ddf1aa (patch) | |
tree | b733f3cd7991d964810b32d7a555bdf9826a63e8 /drivers/usb/host | |
parent | 29fab0cd897519be9009ba8c898410ab83b378e9 (diff) |
USB: r8a66597-hcd: Add support for SH7366 USB host
R8A66597 is similar to SH7366 USB 2.0 Host/Function module. It can
support SH7366 USB host by changing several R8A66597 code.
Signed-off-by: Yoshihiro Shimoda <shimoda.yoshihiro@renesas.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'drivers/usb/host')
-rw-r--r-- | drivers/usb/host/Kconfig | 6 | ||||
-rw-r--r-- | drivers/usb/host/r8a66597-hcd.c | 115 | ||||
-rw-r--r-- | drivers/usb/host/r8a66597.h | 45 |
3 files changed, 129 insertions, 37 deletions
diff --git a/drivers/usb/host/Kconfig b/drivers/usb/host/Kconfig index 27f295b78055..0b87480dd713 100644 --- a/drivers/usb/host/Kconfig +++ b/drivers/usb/host/Kconfig | |||
@@ -260,3 +260,9 @@ config USB_R8A66597_HCD | |||
260 | To compile this driver as a module, choose M here: the | 260 | To compile this driver as a module, choose M here: the |
261 | module will be called r8a66597-hcd. | 261 | module will be called r8a66597-hcd. |
262 | 262 | ||
263 | config SUPERH_ON_CHIP_R8A66597 | ||
264 | boolean "Enable SuperH on-chip USB like the R8A66597" | ||
265 | depends on USB_R8A66597_HCD && CPU_SUBTYPE_SH7366 | ||
266 | help | ||
267 | Renesas SuperH processor has USB like the R8A66597. | ||
268 | This driver supported processor is SH7366. | ||
diff --git a/drivers/usb/host/r8a66597-hcd.c b/drivers/usb/host/r8a66597-hcd.c index bb48f42bd7ce..f4fa93dabdde 100644 --- a/drivers/usb/host/r8a66597-hcd.c +++ b/drivers/usb/host/r8a66597-hcd.c | |||
@@ -51,10 +51,12 @@ MODULE_ALIAS("platform:r8a66597_hcd"); | |||
51 | static const char hcd_name[] = "r8a66597_hcd"; | 51 | static const char hcd_name[] = "r8a66597_hcd"; |
52 | 52 | ||
53 | /* module parameters */ | 53 | /* module parameters */ |
54 | #if !defined(CONFIG_SUPERH_ON_CHIP_R8A66597) | ||
54 | static unsigned short clock = XTAL12; | 55 | static unsigned short clock = XTAL12; |
55 | module_param(clock, ushort, 0644); | 56 | module_param(clock, ushort, 0644); |
56 | MODULE_PARM_DESC(clock, "input clock: 48MHz=32768, 24MHz=16384, 12MHz=0 " | 57 | MODULE_PARM_DESC(clock, "input clock: 48MHz=32768, 24MHz=16384, 12MHz=0 " |
57 | "(default=0)"); | 58 | "(default=0)"); |
59 | #endif | ||
58 | 60 | ||
59 | static unsigned short vif = LDRV; | 61 | static unsigned short vif = LDRV; |
60 | module_param(vif, ushort, 0644); | 62 | module_param(vif, ushort, 0644); |
@@ -106,11 +108,22 @@ static void set_devadd_reg(struct r8a66597 *r8a66597, u8 r8a66597_address, | |||
106 | r8a66597_write(r8a66597, val, devadd_reg); | 108 | r8a66597_write(r8a66597, val, devadd_reg); |
107 | } | 109 | } |
108 | 110 | ||
109 | static int enable_controller(struct r8a66597 *r8a66597) | 111 | static int r8a66597_clock_enable(struct r8a66597 *r8a66597) |
110 | { | 112 | { |
111 | u16 tmp; | 113 | u16 tmp; |
112 | int i = 0; | 114 | int i = 0; |
113 | 115 | ||
116 | #if defined(CONFIG_SUPERH_ON_CHIP_R8A66597) | ||
117 | do { | ||
118 | r8a66597_write(r8a66597, SCKE, SYSCFG0); | ||
119 | tmp = r8a66597_read(r8a66597, SYSCFG0); | ||
120 | if (i++ > 1000) { | ||
121 | err("register access fail."); | ||
122 | return -ENXIO; | ||
123 | } | ||
124 | } while ((tmp & SCKE) != SCKE); | ||
125 | r8a66597_write(r8a66597, 0x04, 0x02); | ||
126 | #else | ||
114 | do { | 127 | do { |
115 | r8a66597_write(r8a66597, USBE, SYSCFG0); | 128 | r8a66597_write(r8a66597, USBE, SYSCFG0); |
116 | tmp = r8a66597_read(r8a66597, SYSCFG0); | 129 | tmp = r8a66597_read(r8a66597, SYSCFG0); |
@@ -132,13 +145,63 @@ static int enable_controller(struct r8a66597 *r8a66597) | |||
132 | return -ENXIO; | 145 | return -ENXIO; |
133 | } | 146 | } |
134 | } while ((tmp & SCKE) != SCKE); | 147 | } while ((tmp & SCKE) != SCKE); |
148 | #endif /* #if defined(CONFIG_SUPERH_ON_CHIP_R8A66597) */ | ||
149 | |||
150 | return 0; | ||
151 | } | ||
152 | |||
153 | static void r8a66597_clock_disable(struct r8a66597 *r8a66597) | ||
154 | { | ||
155 | r8a66597_bclr(r8a66597, SCKE, SYSCFG0); | ||
156 | udelay(1); | ||
157 | #if !defined(CONFIG_SUPERH_ON_CHIP_R8A66597) | ||
158 | r8a66597_bclr(r8a66597, PLLC, SYSCFG0); | ||
159 | r8a66597_bclr(r8a66597, XCKE, SYSCFG0); | ||
160 | r8a66597_bclr(r8a66597, USBE, SYSCFG0); | ||
161 | #endif | ||
162 | } | ||
163 | |||
164 | static void r8a66597_enable_port(struct r8a66597 *r8a66597, int port) | ||
165 | { | ||
166 | u16 val; | ||
167 | |||
168 | val = port ? DRPD : DCFM | DRPD; | ||
169 | r8a66597_bset(r8a66597, val, get_syscfg_reg(port)); | ||
170 | r8a66597_bset(r8a66597, HSE, get_syscfg_reg(port)); | ||
171 | |||
172 | r8a66597_write(r8a66597, BURST | CPU_ADR_RD_WR, get_dmacfg_reg(port)); | ||
173 | r8a66597_bclr(r8a66597, DTCHE, get_intenb_reg(port)); | ||
174 | r8a66597_bset(r8a66597, ATTCHE, get_intenb_reg(port)); | ||
175 | } | ||
176 | |||
177 | static void r8a66597_disable_port(struct r8a66597 *r8a66597, int port) | ||
178 | { | ||
179 | u16 val, tmp; | ||
135 | 180 | ||
136 | r8a66597_bset(r8a66597, DCFM | DRPD, SYSCFG0); | 181 | r8a66597_write(r8a66597, 0, get_intenb_reg(port)); |
137 | r8a66597_bset(r8a66597, DRPD, SYSCFG1); | 182 | r8a66597_write(r8a66597, 0, get_intsts_reg(port)); |
183 | |||
184 | r8a66597_port_power(r8a66597, port, 0); | ||
185 | |||
186 | do { | ||
187 | tmp = r8a66597_read(r8a66597, SOFCFG) & EDGESTS; | ||
188 | udelay(640); | ||
189 | } while (tmp == EDGESTS); | ||
190 | |||
191 | val = port ? DRPD : DCFM | DRPD; | ||
192 | r8a66597_bclr(r8a66597, val, get_syscfg_reg(port)); | ||
193 | r8a66597_bclr(r8a66597, HSE, get_syscfg_reg(port)); | ||
194 | } | ||
195 | |||
196 | static int enable_controller(struct r8a66597 *r8a66597) | ||
197 | { | ||
198 | int ret, port; | ||
199 | |||
200 | ret = r8a66597_clock_enable(r8a66597); | ||
201 | if (ret < 0) | ||
202 | return ret; | ||
138 | 203 | ||
139 | r8a66597_bset(r8a66597, vif & LDRV, PINCFG); | 204 | r8a66597_bset(r8a66597, vif & LDRV, PINCFG); |
140 | r8a66597_bset(r8a66597, HSE, SYSCFG0); | ||
141 | r8a66597_bset(r8a66597, HSE, SYSCFG1); | ||
142 | r8a66597_bset(r8a66597, USBE, SYSCFG0); | 205 | r8a66597_bset(r8a66597, USBE, SYSCFG0); |
143 | 206 | ||
144 | r8a66597_bset(r8a66597, BEMPE | NRDYE | BRDYE, INTENB0); | 207 | r8a66597_bset(r8a66597, BEMPE | NRDYE | BRDYE, INTENB0); |
@@ -146,53 +209,30 @@ static int enable_controller(struct r8a66597 *r8a66597) | |||
146 | r8a66597_bset(r8a66597, BRDY0, BRDYENB); | 209 | r8a66597_bset(r8a66597, BRDY0, BRDYENB); |
147 | r8a66597_bset(r8a66597, BEMP0, BEMPENB); | 210 | r8a66597_bset(r8a66597, BEMP0, BEMPENB); |
148 | 211 | ||
149 | r8a66597_write(r8a66597, BURST | CPU_ADR_RD_WR, DMA0CFG); | ||
150 | r8a66597_write(r8a66597, BURST | CPU_ADR_RD_WR, DMA1CFG); | ||
151 | |||
152 | r8a66597_bset(r8a66597, endian & BIGEND, CFIFOSEL); | 212 | r8a66597_bset(r8a66597, endian & BIGEND, CFIFOSEL); |
153 | r8a66597_bset(r8a66597, endian & BIGEND, D0FIFOSEL); | 213 | r8a66597_bset(r8a66597, endian & BIGEND, D0FIFOSEL); |
154 | r8a66597_bset(r8a66597, endian & BIGEND, D1FIFOSEL); | 214 | r8a66597_bset(r8a66597, endian & BIGEND, D1FIFOSEL); |
155 | |||
156 | r8a66597_bset(r8a66597, TRNENSEL, SOFCFG); | 215 | r8a66597_bset(r8a66597, TRNENSEL, SOFCFG); |
157 | 216 | ||
158 | r8a66597_bset(r8a66597, SIGNE | SACKE, INTENB1); | 217 | r8a66597_bset(r8a66597, SIGNE | SACKE, INTENB1); |
159 | r8a66597_bclr(r8a66597, DTCHE, INTENB1); | 218 | |
160 | r8a66597_bset(r8a66597, ATTCHE, INTENB1); | 219 | for (port = 0; port < R8A66597_MAX_ROOT_HUB; port++) |
161 | r8a66597_bclr(r8a66597, DTCHE, INTENB2); | 220 | r8a66597_enable_port(r8a66597, port); |
162 | r8a66597_bset(r8a66597, ATTCHE, INTENB2); | ||
163 | 221 | ||
164 | return 0; | 222 | return 0; |
165 | } | 223 | } |
166 | 224 | ||
167 | static void disable_controller(struct r8a66597 *r8a66597) | 225 | static void disable_controller(struct r8a66597 *r8a66597) |
168 | { | 226 | { |
169 | u16 tmp; | 227 | int port; |
170 | 228 | ||
171 | r8a66597_write(r8a66597, 0, INTENB0); | 229 | r8a66597_write(r8a66597, 0, INTENB0); |
172 | r8a66597_write(r8a66597, 0, INTENB1); | ||
173 | r8a66597_write(r8a66597, 0, INTENB2); | ||
174 | r8a66597_write(r8a66597, 0, INTSTS0); | 230 | r8a66597_write(r8a66597, 0, INTSTS0); |
175 | r8a66597_write(r8a66597, 0, INTSTS1); | ||
176 | r8a66597_write(r8a66597, 0, INTSTS2); | ||
177 | |||
178 | r8a66597_port_power(r8a66597, 0, 0); | ||
179 | r8a66597_port_power(r8a66597, 1, 0); | ||
180 | |||
181 | do { | ||
182 | tmp = r8a66597_read(r8a66597, SOFCFG) & EDGESTS; | ||
183 | udelay(640); | ||
184 | } while (tmp == EDGESTS); | ||
185 | 231 | ||
186 | r8a66597_bclr(r8a66597, DCFM | DRPD, SYSCFG0); | 232 | for (port = 0; port < R8A66597_MAX_ROOT_HUB; port++) |
187 | r8a66597_bclr(r8a66597, DRPD, SYSCFG1); | 233 | r8a66597_disable_port(r8a66597, port); |
188 | r8a66597_bclr(r8a66597, HSE, SYSCFG0); | ||
189 | r8a66597_bclr(r8a66597, HSE, SYSCFG1); | ||
190 | 234 | ||
191 | r8a66597_bclr(r8a66597, SCKE, SYSCFG0); | 235 | r8a66597_clock_disable(r8a66597); |
192 | udelay(1); | ||
193 | r8a66597_bclr(r8a66597, PLLC, SYSCFG0); | ||
194 | r8a66597_bclr(r8a66597, XCKE, SYSCFG0); | ||
195 | r8a66597_bclr(r8a66597, USBE, SYSCFG0); | ||
196 | } | 236 | } |
197 | 237 | ||
198 | static int get_parent_r8a66597_address(struct r8a66597 *r8a66597, | 238 | static int get_parent_r8a66597_address(struct r8a66597 *r8a66597, |
@@ -711,6 +751,7 @@ static void enable_r8a66597_pipe_dma(struct r8a66597 *r8a66597, | |||
711 | struct r8a66597_pipe *pipe, | 751 | struct r8a66597_pipe *pipe, |
712 | struct urb *urb) | 752 | struct urb *urb) |
713 | { | 753 | { |
754 | #if !defined(CONFIG_SUPERH_ON_CHIP_R8A66597) | ||
714 | int i; | 755 | int i; |
715 | struct r8a66597_pipe_info *info = &pipe->info; | 756 | struct r8a66597_pipe_info *info = &pipe->info; |
716 | 757 | ||
@@ -738,6 +779,7 @@ static void enable_r8a66597_pipe_dma(struct r8a66597 *r8a66597, | |||
738 | break; | 779 | break; |
739 | } | 780 | } |
740 | } | 781 | } |
782 | #endif /* #if defined(CONFIG_SUPERH_ON_CHIP_R8A66597) */ | ||
741 | } | 783 | } |
742 | 784 | ||
743 | /* this function must be called with interrupt disabled */ | 785 | /* this function must be called with interrupt disabled */ |
@@ -1054,8 +1096,7 @@ static void prepare_status_packet(struct r8a66597 *r8a66597, | |||
1054 | r8a66597_mdfy(r8a66597, ISEL, ISEL | CURPIPE, CFIFOSEL); | 1096 | r8a66597_mdfy(r8a66597, ISEL, ISEL | CURPIPE, CFIFOSEL); |
1055 | r8a66597_reg_wait(r8a66597, CFIFOSEL, CURPIPE, 0); | 1097 | r8a66597_reg_wait(r8a66597, CFIFOSEL, CURPIPE, 0); |
1056 | r8a66597_write(r8a66597, ~BEMP0, BEMPSTS); | 1098 | r8a66597_write(r8a66597, ~BEMP0, BEMPSTS); |
1057 | r8a66597_write(r8a66597, BCLR, CFIFOCTR); | 1099 | r8a66597_write(r8a66597, BCLR | BVAL, CFIFOCTR); |
1058 | r8a66597_write(r8a66597, BVAL, CFIFOCTR); | ||
1059 | enable_irq_empty(r8a66597, 0); | 1100 | enable_irq_empty(r8a66597, 0); |
1060 | } else { | 1101 | } else { |
1061 | r8a66597_bclr(r8a66597, R8A66597_DIR, DCPCFG); | 1102 | r8a66597_bclr(r8a66597, R8A66597_DIR, DCPCFG); |
diff --git a/drivers/usb/host/r8a66597.h b/drivers/usb/host/r8a66597.h index f46f7dd944a1..84ee01417315 100644 --- a/drivers/usb/host/r8a66597.h +++ b/drivers/usb/host/r8a66597.h | |||
@@ -187,7 +187,11 @@ | |||
187 | #define REW 0x4000 /* b14: Buffer rewind */ | 187 | #define REW 0x4000 /* b14: Buffer rewind */ |
188 | #define DCLRM 0x2000 /* b13: DMA buffer clear mode */ | 188 | #define DCLRM 0x2000 /* b13: DMA buffer clear mode */ |
189 | #define DREQE 0x1000 /* b12: DREQ output enable */ | 189 | #define DREQE 0x1000 /* b12: DREQ output enable */ |
190 | #if defined(CONFIG_SUPERH_ON_CHIP_R8A66597) | ||
191 | #define MBW 0x0800 | ||
192 | #else | ||
190 | #define MBW 0x0400 /* b10: Maximum bit width for FIFO access */ | 193 | #define MBW 0x0400 /* b10: Maximum bit width for FIFO access */ |
194 | #endif | ||
191 | #define MBW_8 0x0000 /* 8bit */ | 195 | #define MBW_8 0x0000 /* 8bit */ |
192 | #define MBW_16 0x0400 /* 16bit */ | 196 | #define MBW_16 0x0400 /* 16bit */ |
193 | #define BIGEND 0x0100 /* b8: Big endian mode */ | 197 | #define BIGEND 0x0100 /* b8: Big endian mode */ |
@@ -395,7 +399,11 @@ | |||
395 | #define R8A66597_MAX_NUM_PIPE 10 | 399 | #define R8A66597_MAX_NUM_PIPE 10 |
396 | #define R8A66597_BUF_BSIZE 8 | 400 | #define R8A66597_BUF_BSIZE 8 |
397 | #define R8A66597_MAX_DEVICE 10 | 401 | #define R8A66597_MAX_DEVICE 10 |
402 | #if defined(CONFIG_SUPERH_ON_CHIP_R8A66597) | ||
403 | #define R8A66597_MAX_ROOT_HUB 1 | ||
404 | #else | ||
398 | #define R8A66597_MAX_ROOT_HUB 2 | 405 | #define R8A66597_MAX_ROOT_HUB 2 |
406 | #endif | ||
399 | #define R8A66597_MAX_SAMPLING 5 | 407 | #define R8A66597_MAX_SAMPLING 5 |
400 | #define R8A66597_RH_POLL_TIME 10 | 408 | #define R8A66597_RH_POLL_TIME 10 |
401 | #define R8A66597_MAX_DMA_CHANNEL 2 | 409 | #define R8A66597_MAX_DMA_CHANNEL 2 |
@@ -530,8 +538,21 @@ static inline void r8a66597_read_fifo(struct r8a66597 *r8a66597, | |||
530 | unsigned long offset, u16 *buf, | 538 | unsigned long offset, u16 *buf, |
531 | int len) | 539 | int len) |
532 | { | 540 | { |
541 | #if defined(CONFIG_SUPERH_ON_CHIP_R8A66597) | ||
542 | unsigned long fifoaddr = r8a66597->reg + offset; | ||
543 | unsigned long count; | ||
544 | |||
545 | count = len / 4; | ||
546 | insl(fifoaddr, buf, count); | ||
547 | |||
548 | if (len & 0x00000003) { | ||
549 | unsigned long tmp = inl(fifoaddr); | ||
550 | memcpy((unsigned char *)buf + count * 4, &tmp, len & 0x03); | ||
551 | } | ||
552 | #else | ||
533 | len = (len + 1) / 2; | 553 | len = (len + 1) / 2; |
534 | insw(r8a66597->reg + offset, buf, len); | 554 | insw(r8a66597->reg + offset, buf, len); |
555 | #endif | ||
535 | } | 556 | } |
536 | 557 | ||
537 | static inline void r8a66597_write(struct r8a66597 *r8a66597, u16 val, | 558 | static inline void r8a66597_write(struct r8a66597 *r8a66597, u16 val, |
@@ -545,6 +566,24 @@ static inline void r8a66597_write_fifo(struct r8a66597 *r8a66597, | |||
545 | int len) | 566 | int len) |
546 | { | 567 | { |
547 | unsigned long fifoaddr = r8a66597->reg + offset; | 568 | unsigned long fifoaddr = r8a66597->reg + offset; |
569 | #if defined(CONFIG_SUPERH_ON_CHIP_R8A66597) | ||
570 | unsigned long count; | ||
571 | unsigned char *pb; | ||
572 | int i; | ||
573 | |||
574 | count = len / 4; | ||
575 | outsl(fifoaddr, buf, count); | ||
576 | |||
577 | if (len & 0x00000003) { | ||
578 | pb = (unsigned char *)buf + count * 4; | ||
579 | for (i = 0; i < (len & 0x00000003); i++) { | ||
580 | if (r8a66597_read(r8a66597, CFIFOSEL) & BIGEND) | ||
581 | outb(pb[i], fifoaddr + i); | ||
582 | else | ||
583 | outb(pb[i], fifoaddr + 3 - i); | ||
584 | } | ||
585 | } | ||
586 | #else | ||
548 | int odd = len & 0x0001; | 587 | int odd = len & 0x0001; |
549 | 588 | ||
550 | len = len / 2; | 589 | len = len / 2; |
@@ -553,6 +592,7 @@ static inline void r8a66597_write_fifo(struct r8a66597 *r8a66597, | |||
553 | buf = &buf[len]; | 592 | buf = &buf[len]; |
554 | outb((unsigned char)*buf, fifoaddr); | 593 | outb((unsigned char)*buf, fifoaddr); |
555 | } | 594 | } |
595 | #endif | ||
556 | } | 596 | } |
557 | 597 | ||
558 | static inline void r8a66597_mdfy(struct r8a66597 *r8a66597, | 598 | static inline void r8a66597_mdfy(struct r8a66597 *r8a66597, |
@@ -585,6 +625,11 @@ static inline unsigned long get_dvstctr_reg(int port) | |||
585 | return port == 0 ? DVSTCTR0 : DVSTCTR1; | 625 | return port == 0 ? DVSTCTR0 : DVSTCTR1; |
586 | } | 626 | } |
587 | 627 | ||
628 | static inline unsigned long get_dmacfg_reg(int port) | ||
629 | { | ||
630 | return port == 0 ? DMA0CFG : DMA1CFG; | ||
631 | } | ||
632 | |||
588 | static inline unsigned long get_intenb_reg(int port) | 633 | static inline unsigned long get_intenb_reg(int port) |
589 | { | 634 | { |
590 | return port == 0 ? INTENB1 : INTENB2; | 635 | return port == 0 ? INTENB1 : INTENB2; |