diff options
Diffstat (limited to 'firmware/target/mips')
3 files changed, 406 insertions, 61 deletions
diff --git a/firmware/target/mips/ingenic_jz47xx/onda_vx747/lcd-onda_vx747.c b/firmware/target/mips/ingenic_jz47xx/onda_vx747/lcd-onda_vx747.c index 40d9bb6106..faed5ecda2 100644 --- a/firmware/target/mips/ingenic_jz47xx/onda_vx747/lcd-onda_vx747.c +++ b/firmware/target/mips/ingenic_jz47xx/onda_vx747/lcd-onda_vx747.c | |||
@@ -203,7 +203,7 @@ static void _set_lcd_clock(void) | |||
203 | 203 | ||
204 | __cpm_stop_lcd(); | 204 | __cpm_stop_lcd(); |
205 | pll_div = ( REG_CPM_CPCCR & CPM_CPCCR_PCS ); /* clock source, 0:pllout/2 1: pllout */ | 205 | pll_div = ( REG_CPM_CPCCR & CPM_CPCCR_PCS ); /* clock source, 0:pllout/2 1: pllout */ |
206 | pll_div = pll_div ? 1 : 2 ; | 206 | pll_div = pll_div ? 1 : 2; |
207 | val = ( __cpm_get_pllout()/pll_div ) / __cpm_get_pclk(); | 207 | val = ( __cpm_get_pllout()/pll_div ) / __cpm_get_pclk(); |
208 | val--; | 208 | val--; |
209 | if ( val > 0x1ff ) | 209 | if ( val > 0x1ff ) |
diff --git a/firmware/target/mips/ingenic_jz47xx/system-jz4740.c b/firmware/target/mips/ingenic_jz47xx/system-jz4740.c index 48fb192810..c741d9f311 100644 --- a/firmware/target/mips/ingenic_jz47xx/system-jz4740.c +++ b/firmware/target/mips/ingenic_jz47xx/system-jz4740.c | |||
@@ -663,6 +663,168 @@ void dma_disable(void) | |||
663 | } | 663 | } |
664 | } | 664 | } |
665 | 665 | ||
666 | static inline void pll_convert(unsigned int pllin, unsigned int *pll_cfcr, unsigned int *pll_plcr1) | ||
667 | { | ||
668 | register unsigned int cfcr, plcr1; | ||
669 | int div[5] = {1, 3, 3, 3, 3}; /* divisors of I:S:P:L:M */ | ||
670 | int nf; | ||
671 | |||
672 | cfcr = CPM_CPCCR_CLKOEN | | ||
673 | (div[0] << CPM_CPCCR_CDIV_BIT) | | ||
674 | (div[1] << CPM_CPCCR_HDIV_BIT) | | ||
675 | (div[2] << CPM_CPCCR_PDIV_BIT) | | ||
676 | (div[3] << CPM_CPCCR_MDIV_BIT) | | ||
677 | (div[4] << CPM_CPCCR_LDIV_BIT); | ||
678 | |||
679 | //nf = pllin * 2 / CFG_EXTAL; | ||
680 | nf = pllin * 2 / 375299969; | ||
681 | plcr1 = ((nf - 2) << CPM_CPPCR_PLLM_BIT) | /* FD */ | ||
682 | (0 << CPM_CPPCR_PLLN_BIT) | /* RD=0, NR=2 */ | ||
683 | (0 << CPM_CPPCR_PLLOD_BIT) | /* OD=0, NO=1 */ | ||
684 | (0xa << CPM_CPPCR_PLLST_BIT) | /* PLL stable time */ | ||
685 | CPM_CPPCR_PLLEN; /* enable PLL */ | ||
686 | |||
687 | /* init PLL */ | ||
688 | *pll_cfcr = cfcr; | ||
689 | *pll_plcr1 = plcr1; | ||
690 | } | ||
691 | |||
692 | static inline void sdram_convert(unsigned int pllin, unsigned int *sdram_freq) | ||
693 | { | ||
694 | register unsigned int ns, tmp; | ||
695 | |||
696 | ns = 1000000000 / pllin; | ||
697 | tmp = 15625 / ns; | ||
698 | |||
699 | /* Set refresh registers */ | ||
700 | tmp = tmp / 64 + 1; | ||
701 | |||
702 | if(tmp > 0xff) | ||
703 | tmp = 0xff; | ||
704 | |||
705 | *sdram_freq = tmp; | ||
706 | } | ||
707 | |||
708 | static inline void set_cpu_freq(unsigned int pllin, unsigned int div) | ||
709 | { | ||
710 | unsigned int sdram_freq; | ||
711 | unsigned int pll_cfcr, pll_plcr1; | ||
712 | int div_preq[] = {1, 2, 3, 4, 6, 8, 12, 16, 24, 32}; | ||
713 | |||
714 | if(pllin < 25000000 || pllin > 420000000) | ||
715 | panicf("PLL should be >25000000 and <420000000 !"); | ||
716 | |||
717 | unsigned long t = read_c0_status(); | ||
718 | write_c0_status(t & ~1); | ||
719 | |||
720 | pll_convert(pllin, &pll_cfcr, &pll_plcr1); | ||
721 | |||
722 | sdram_convert(pllin / div_preq[div], &sdram_freq); | ||
723 | |||
724 | REG_CPM_CPCCR &= ~CPM_CPCCR_CE; | ||
725 | |||
726 | REG_CPM_CPCCR = pll_cfcr; | ||
727 | REG_CPM_CPPCR = pll_plcr1; | ||
728 | |||
729 | REG_EMC_RTCOR = sdram_freq; | ||
730 | REG_EMC_RTCNT = sdram_freq; | ||
731 | |||
732 | REG_CPM_CPCCR |= CPM_CPCCR_CE; | ||
733 | |||
734 | detect_clock(); | ||
735 | |||
736 | write_c0_status(t); | ||
737 | } | ||
738 | |||
739 | static void OF_init_clocks(void) | ||
740 | { | ||
741 | unsigned int prog_entry = ((unsigned int)OF_init_clocks >> 5) << 5; | ||
742 | unsigned int i, prog_size = 1024; | ||
743 | |||
744 | for(i = prog_entry; i < prog_entry + prog_size; i += 32) | ||
745 | __asm__ __volatile__("cache 0x1c, 0x00(%0) \n" | ||
746 | : | ||
747 | : "r" (i) | ||
748 | ); | ||
749 | |||
750 | /* disable PLL clock */ | ||
751 | REG_CPM_CPPCR &= ~CPM_CPPCR_PLLEN; | ||
752 | REG_CPM_CPCCR |= CPM_CPCCR_CE; | ||
753 | |||
754 | unsigned long old_clocks = REG_CPM_CLKGR; | ||
755 | /* | ||
756 | REG_CPM_CLKGR = ~( CPM_CLKGR_UART0 | CPM_CLKGR_TCU | | ||
757 | CPM_CLKGR_RTC | CPM_CLKGR_SADC | | ||
758 | CPM_CLKGR_LCD ); | ||
759 | */ | ||
760 | |||
761 | unsigned long old_scr = REG_CPM_SCR; | ||
762 | REG_CPM_SCR &= ~CPM_SCR_OSC_ENABLE; /* O1SE: 12M oscillator is disabled in Sleep mode */ | ||
763 | |||
764 | REG_EMC_DMCR |= (EMC_DMCR_RMODE | EMC_DMCR_RFSH); /* self refresh + refresh is performed */ | ||
765 | REG_EMC_DMCR = (REG_EMC_DMCR & ~EMC_DMCR_RMODE) | 1; /* -> RMODE = auto refresh | ||
766 | -> CAS mode = 2 cycles */ | ||
767 | __asm__ __volatile__("wait \n"); | ||
768 | |||
769 | REG_CPM_CLKGR = old_clocks; | ||
770 | REG_CPM_SCR = old_scr; | ||
771 | |||
772 | for(i=0; i<90; i++); | ||
773 | |||
774 | set_cpu_freq(336000000, 1); | ||
775 | |||
776 | for(i=0; i<60; i++); | ||
777 | } | ||
778 | |||
779 | static void my_init_clocks(void) | ||
780 | { | ||
781 | unsigned long t = read_c0_status(); | ||
782 | write_c0_status(t & ~1); | ||
783 | |||
784 | unsigned int prog_entry = ((unsigned int)my_init_clocks / 32 - 1) * 32; | ||
785 | unsigned int i, prog_size = 1024; | ||
786 | |||
787 | for(i = prog_entry; i < prog_entry + prog_size; i += 32) | ||
788 | __asm__ __volatile__("cache 0x1c, 0x00(%0) \n" | ||
789 | : | ||
790 | : "r" (i) | ||
791 | ); | ||
792 | |||
793 | unsigned int sdram_freq, plcr1, cfcr; | ||
794 | |||
795 | sdram_convert(336000000/3, &sdram_freq); | ||
796 | |||
797 | cfcr = CPM_CPCCR_CLKOEN | | ||
798 | (6 << CPM_CPCCR_UDIV_BIT) | | ||
799 | CPM_CPCCR_UCS | | ||
800 | CPM_CPCCR_PCS | | ||
801 | (0 << CPM_CPCCR_CDIV_BIT) | | ||
802 | (2 << CPM_CPCCR_HDIV_BIT) | | ||
803 | (2 << CPM_CPCCR_PDIV_BIT) | | ||
804 | (2 << CPM_CPCCR_MDIV_BIT) | | ||
805 | (2 << CPM_CPCCR_LDIV_BIT); | ||
806 | |||
807 | plcr1 = (54 << CPM_CPPCR_PLLM_BIT) | /* FD */ | ||
808 | (0 << CPM_CPPCR_PLLN_BIT) | /* RD=0, NR=2 */ | ||
809 | (0 << CPM_CPPCR_PLLOD_BIT) | /* OD=0, NO=1 */ | ||
810 | (0x20 << CPM_CPPCR_PLLST_BIT)| /* PLL stable time */ | ||
811 | CPM_CPPCR_PLLEN; /* enable PLL */ | ||
812 | |||
813 | REG_CPM_CPCCR &= ~CPM_CPCCR_CE; | ||
814 | |||
815 | REG_CPM_CPCCR = cfcr; | ||
816 | REG_CPM_CPPCR = plcr1; | ||
817 | |||
818 | REG_EMC_RTCOR = sdram_freq; | ||
819 | REG_EMC_RTCNT = sdram_freq; | ||
820 | |||
821 | REG_CPM_CPCCR |= CPM_CPCCR_CE; | ||
822 | |||
823 | REG_CPM_LPCDR = (REG_CPM_LPCDR & ~CPM_LPCDR_PIXDIV_MASK) | (11 << CPM_LPCDR_PIXDIV_BIT); | ||
824 | |||
825 | write_c0_status(t); | ||
826 | } | ||
827 | |||
666 | extern int main(void); | 828 | extern int main(void); |
667 | extern void except_common_entry(void); | 829 | extern void except_common_entry(void); |
668 | 830 | ||
@@ -696,6 +858,15 @@ void system_main(void) | |||
696 | 858 | ||
697 | /* Disable unneeded clocks, clocks are enabled when needed */ | 859 | /* Disable unneeded clocks, clocks are enabled when needed */ |
698 | __cpm_stop_all(); | 860 | __cpm_stop_all(); |
861 | __cpm_suspend_usbhost(); | ||
862 | |||
863 | #if 0 | ||
864 | my_init_clocks(); | ||
865 | /*__cpm_stop_udc(); | ||
866 | REG_CPM_CPCCR |= CPM_CPCCR_UCS; | ||
867 | REG_CPM_CPCCR = (REG_CPM_CPCCR & ~CPM_CPCCR_UDIV_MASK) | (3 << CPM_CPCCR_UDIV_BIT); | ||
868 | __cpm_start_udc();*/ | ||
869 | #endif | ||
699 | 870 | ||
700 | /* Enable interrupts at core level */ | 871 | /* Enable interrupts at core level */ |
701 | sti(); | 872 | sti(); |
diff --git a/firmware/target/mips/ingenic_jz47xx/usb-jz4740.c b/firmware/target/mips/ingenic_jz47xx/usb-jz4740.c index f06e796e05..eda3fb3b88 100644 --- a/firmware/target/mips/ingenic_jz47xx/usb-jz4740.c +++ b/firmware/target/mips/ingenic_jz47xx/usb-jz4740.c | |||
@@ -34,11 +34,12 @@ | |||
34 | #define USB_EP0_RX 1 | 34 | #define USB_EP0_RX 1 |
35 | #define USB_EP0_TX 2 | 35 | #define USB_EP0_TX 2 |
36 | 36 | ||
37 | #define EP_BUF_LEFT(ep) (ep->length - ep->sent) | 37 | #define EP_BUF_LEFT(ep) ((ep)->length - (ep)->sent) |
38 | #define EP_PTR(ep) ((void*)((unsigned int)ep->buf + ep->sent)) | 38 | #define EP_PTR(ep) ((void*)((unsigned int)(ep)->buf + (ep)->sent)) |
39 | #define EP_NUMBER(ep) (((int)ep - (int)&endpoints[0])/sizeof(struct usb_endpoint)) | 39 | #define EP_NUMBER(ep) (((int)(ep) - (int)&endpoints[0])/sizeof(struct usb_endpoint)) |
40 | #define EP_NUMBER2(ep) (EP_NUMBER((ep))/2) | ||
40 | #define TOTAL_EP() (sizeof(endpoints)/sizeof(struct usb_endpoint)) | 41 | #define TOTAL_EP() (sizeof(endpoints)/sizeof(struct usb_endpoint)) |
41 | #define EP_IS_IN(ep) (EP_NUMBER(ep)%2) | 42 | #define EP_IS_IN(ep) (EP_NUMBER((ep))%2) |
42 | 43 | ||
43 | enum ep_type | 44 | enum ep_type |
44 | { | 45 | { |
@@ -66,11 +67,11 @@ static unsigned char ep0_rx_buf[64]; | |||
66 | static unsigned char ep0state = USB_EP0_IDLE; | 67 | static unsigned char ep0state = USB_EP0_IDLE; |
67 | static struct usb_endpoint endpoints[] = | 68 | static struct usb_endpoint endpoints[] = |
68 | { | 69 | { |
69 | /* buf length sent type use_dma fifo_addr fifo_size */ | 70 | /* buf length sent type use_dma fifo_addr fifo_size */ |
70 | {&ep0_rx_buf, 0, {0}, ep_control, false, USB_FIFO_EP0, 64 }, | 71 | {&ep0_rx_buf, 0, {0}, ep_control, false, USB_FIFO_EP0, 64 }, |
71 | {NULL, 0, {0}, ep_control, false, USB_FIFO_EP0, 64 }, | 72 | {NULL, 0, {0}, ep_control, false, USB_FIFO_EP0, 64 }, |
72 | {NULL, 0, {0}, ep_bulk, true, USB_FIFO_EP1, 512}, | 73 | {NULL, 0, {0}, ep_bulk, false, USB_FIFO_EP1, 512}, |
73 | {NULL, 0, {0}, ep_bulk, true, USB_FIFO_EP1, 512}, | 74 | {NULL, 0, {0}, ep_bulk, false, USB_FIFO_EP1, 512}, |
74 | {NULL, 0, {0}, ep_interrupt, false, USB_FIFO_EP2, 64 } | 75 | {NULL, 0, {0}, ep_interrupt, false, USB_FIFO_EP2, 64 } |
75 | }; | 76 | }; |
76 | 77 | ||
@@ -81,7 +82,7 @@ static inline void select_endpoint(int ep) | |||
81 | 82 | ||
82 | static void readFIFO(struct usb_endpoint *ep, unsigned int size) | 83 | static void readFIFO(struct usb_endpoint *ep, unsigned int size) |
83 | { | 84 | { |
84 | logf("readFIFO(EP%d, %d)", EP_NUMBER(ep), size); | 85 | logf("readFIFO(EP%d, %d)", EP_NUMBER2(ep), size); |
85 | 86 | ||
86 | register unsigned char *ptr = (unsigned char*)EP_PTR(ep); | 87 | register unsigned char *ptr = (unsigned char*)EP_PTR(ep); |
87 | register unsigned int *ptr32 = (unsigned int*)ptr; | 88 | register unsigned int *ptr32 = (unsigned int*)ptr; |
@@ -117,19 +118,19 @@ static void readFIFO(struct usb_endpoint *ep, unsigned int size) | |||
117 | 118 | ||
118 | static void writeFIFO(struct usb_endpoint *ep, unsigned int size) | 119 | static void writeFIFO(struct usb_endpoint *ep, unsigned int size) |
119 | { | 120 | { |
120 | logf("writeFIFO(EP%d, %d)", EP_NUMBER(ep), size); | 121 | //logf("writeFIFO(EP%d, %d)", EP_NUMBER2(ep), size); |
121 | 122 | ||
122 | register unsigned int *d = (unsigned int *)EP_PTR(ep); | 123 | register unsigned int *d = (unsigned int *)EP_PTR(ep); |
123 | register unsigned char *c; | 124 | register unsigned char *c; |
124 | register int s; | 125 | register int s; |
125 | 126 | ||
126 | if (size > 0) | 127 | if(size > 0) |
127 | { | 128 | { |
128 | s = size >> 2; | 129 | s = size >> 2; |
129 | while (s--) | 130 | while (s--) |
130 | REG32(ep->fifo_addr) = *d++; | 131 | REG32(ep->fifo_addr) = *d++; |
131 | 132 | ||
132 | if ( (s = size & 3) ) | 133 | if( (s = size & 3) ) |
133 | { | 134 | { |
134 | c = (unsigned char *)d; | 135 | c = (unsigned char *)d; |
135 | while (s--) | 136 | while (s--) |
@@ -140,18 +141,43 @@ static void writeFIFO(struct usb_endpoint *ep, unsigned int size) | |||
140 | REG32(ep->fifo_addr) = 0; | 141 | REG32(ep->fifo_addr) = 0; |
141 | } | 142 | } |
142 | 143 | ||
144 | static void flushFIFO(struct usb_endpoint *ep) | ||
145 | { | ||
146 | //logf("flushFIFO(%d)", EP_NUMBER(ep)); | ||
147 | |||
148 | switch (ep->type) | ||
149 | { | ||
150 | case ep_control: | ||
151 | break; | ||
152 | |||
153 | case ep_bulk: | ||
154 | case ep_interrupt: | ||
155 | if(EP_IS_IN(ep)) | ||
156 | REG_USB_REG_INCSR |= USB_INCSR_FF; | ||
157 | else | ||
158 | REG_USB_REG_OUTCSR |= USB_OUTCSR_FF; | ||
159 | break; | ||
160 | } | ||
161 | } | ||
162 | |||
143 | static void EP0_send(void) | 163 | static void EP0_send(void) |
144 | { | 164 | { |
145 | register struct usb_endpoint* ep = &endpoints[1]; | 165 | register struct usb_endpoint* ep = &endpoints[1]; |
146 | register unsigned int length; | 166 | register unsigned int length; |
147 | 167 | ||
168 | if(ep->length == 0) | ||
169 | { | ||
170 | select_endpoint(0); | ||
171 | REG_USB_REG_CSR0 |= (USB_CSR0_SVDOUTPKTRDY | USB_CSR0_DATAEND); | ||
172 | return; | ||
173 | } | ||
174 | |||
148 | if(ep->sent == 0) | 175 | if(ep->sent == 0) |
149 | length = (ep->length <= ep->fifo_size ? ep->length : ep->fifo_size); | 176 | length = (ep->length <= ep->fifo_size ? ep->length : ep->fifo_size); |
150 | else | 177 | else |
151 | length = (EP_BUF_LEFT(ep) <= ep->fifo_size ? EP_BUF_LEFT(ep) : ep->fifo_size); | 178 | length = (EP_BUF_LEFT(ep) <= ep->fifo_size ? EP_BUF_LEFT(ep) : ep->fifo_size); |
152 | 179 | ||
153 | select_endpoint(0); | 180 | select_endpoint(0); |
154 | |||
155 | writeFIFO(ep, length); | 181 | writeFIFO(ep, length); |
156 | ep->sent += length; | 182 | ep->sent += length; |
157 | 183 | ||
@@ -166,6 +192,7 @@ static void EP0_send(void) | |||
166 | 192 | ||
167 | static void EP0_handler(void) | 193 | static void EP0_handler(void) |
168 | { | 194 | { |
195 | logf("EP0_handler"); | ||
169 | register unsigned char csr0; | 196 | register unsigned char csr0; |
170 | 197 | ||
171 | /* Read CSR0 */ | 198 | /* Read CSR0 */ |
@@ -208,46 +235,127 @@ static void EP0_handler(void) | |||
208 | EP0_send(); | 235 | EP0_send(); |
209 | } | 236 | } |
210 | 237 | ||
238 | static void EPIN_handler(unsigned int endpoint) | ||
239 | { | ||
240 | logf("EPIN_handler(%d)", endpoint); | ||
241 | struct usb_endpoint* ep = &endpoints[endpoint*2+1]; | ||
242 | unsigned int length, csr; | ||
243 | |||
244 | select_endpoint(endpoint); | ||
245 | csr = REG_USB_REG_INCSR; | ||
246 | |||
247 | if(ep->length == 0) | ||
248 | { | ||
249 | REG_USB_REG_INCSR = csr | USB_INCSR_INPKTRDY; | ||
250 | return; | ||
251 | } | ||
252 | |||
253 | if(csr & USB_INCSR_SENTSTALL) | ||
254 | { | ||
255 | REG_USB_REG_INCSR = csr & ~USB_INCSR_SENTSTALL; | ||
256 | return; | ||
257 | } | ||
258 | |||
259 | if(ep->sent == 0) | ||
260 | length = (ep->length <= ep->fifo_size ? ep->length : ep->fifo_size); | ||
261 | else | ||
262 | length = (EP_BUF_LEFT(ep) <= ep->fifo_size ? EP_BUF_LEFT(ep) : ep->fifo_size); | ||
263 | |||
264 | writeFIFO(ep, length); | ||
265 | ep->sent += length; | ||
266 | |||
267 | REG_USB_REG_INCSR = csr | USB_INCSR_INPKTRDY; | ||
268 | if(ep->sent >= ep->length) | ||
269 | usb_core_transfer_complete(endpoint|USB_DIR_IN, USB_DIR_IN, 0, ep->sent); | ||
270 | } | ||
271 | |||
272 | static void EPOUT_handler(unsigned int endpoint) | ||
273 | { | ||
274 | logf("EPOUT_handler(%d)", endpoint); | ||
275 | struct usb_endpoint* ep = &endpoints[endpoint*2]; | ||
276 | unsigned int size, csr; | ||
277 | |||
278 | select_endpoint(endpoint); | ||
279 | csr = REG_USB_REG_OUTCSR; | ||
280 | |||
281 | if(ep->buf == NULL && ep->length == 0) | ||
282 | { | ||
283 | REG_USB_REG_OUTCSR = csr & ~USB_OUTCSR_OUTPKTRDY; | ||
284 | return; | ||
285 | } | ||
286 | |||
287 | if(csr & USB_OUTCSR_SENTSTALL) | ||
288 | { | ||
289 | REG_USB_REG_OUTCSR = csr & ~USB_OUTCSR_SENTSTALL; | ||
290 | return; | ||
291 | } | ||
292 | |||
293 | size = REG_USB_REG_OUTCOUNT; | ||
294 | ep->received += size; | ||
295 | |||
296 | readFIFO(ep, size); | ||
297 | |||
298 | REG_USB_REG_OUTCSR = csr & ~USB_OUTCSR_OUTPKTRDY; | ||
299 | |||
300 | logf("received: %d length: %d", ep->received, ep->length); | ||
301 | |||
302 | //if(ep->received >= ep->length) | ||
303 | usb_core_transfer_complete(endpoint|USB_DIR_OUT, USB_DIR_OUT, 0, ep->received); | ||
304 | } | ||
305 | |||
211 | static void setup_endpoint(struct usb_endpoint *ep) | 306 | static void setup_endpoint(struct usb_endpoint *ep) |
212 | { | 307 | { |
308 | int csr; | ||
213 | ep->sent = 0; | 309 | ep->sent = 0; |
214 | ep->length = 0; | 310 | ep->length = 0; |
215 | 311 | ||
312 | select_endpoint(EP_NUMBER2(ep)); | ||
313 | |||
314 | if(ep->type == ep_bulk) | ||
315 | { | ||
316 | if(REG_USB_REG_POWER & USB_POWER_HSMODE) | ||
317 | ep->fifo_size = 512; | ||
318 | else | ||
319 | ep->fifo_size = 64; | ||
320 | } | ||
321 | |||
216 | if(EP_IS_IN(ep)) | 322 | if(EP_IS_IN(ep)) |
217 | { | 323 | { |
218 | if(ep->type == ep_bulk) | 324 | REG_USB_REG_INMAXP = ep->fifo_size; |
219 | { | 325 | csr = (USB_INCSR_FF | USB_INCSR_CDT | USB_INCSRH_MODE); |
220 | register int size; | 326 | if(ep->use_dma) |
221 | 327 | csr |= (USB_INCSRH_DMAREQENAB | USB_INCSRH_AUTOSET); | |
222 | if((REG_USB_REG_POWER & USB_POWER_HSMODE) == 0) | ||
223 | size = 64; | ||
224 | else | ||
225 | size = 512; | ||
226 | |||
227 | REG_USB_REG_INMAXP = size; | ||
228 | ep->fifo_size = size; | ||
229 | } | ||
230 | else | 328 | else |
231 | REG_USB_REG_INMAXP = ep->fifo_size; | 329 | REG_USB_REG_INTRINE |= USB_INTR_EP(EP_NUMBER2(ep)); |
232 | 330 | ||
233 | REG_USB_REG_INCSR = (USB_INCSR_FF | USB_INCSR_CDT | USB_INCSRH_MODE); | 331 | REG_USB_REG_INCSR = csr; |
234 | REG_USB_REG_INTRINE |= USB_INTR_EP(EP_NUMBER(ep)); | ||
235 | } | 332 | } |
236 | else | 333 | else |
237 | { | 334 | { |
238 | REG_USB_REG_OUTMAXP = ep->fifo_size; | 335 | REG_USB_REG_OUTMAXP = ep->fifo_size; |
239 | REG_USB_REG_OUTCSR = (USB_OUTCSR_FF | USB_OUTCSR_CDT); | 336 | csr = (USB_OUTCSR_FF | USB_OUTCSR_CDT); |
240 | REG_USB_REG_INTROUTE |= USB_INTR_EP(EP_NUMBER(ep)); | 337 | |
338 | if(ep->type == ep_interrupt) | ||
339 | csr |= USB_OUTCSRH_DNYT; | ||
340 | |||
341 | if(ep->use_dma) | ||
342 | csr |= (USB_OUTCSRH_DMAREQENAB | USB_OUTCSRH_AUTOCLR | USB_OUTCSRH_DMAREQMODE); | ||
343 | else | ||
344 | REG_USB_REG_INTROUTE |= USB_INTR_EP(EP_NUMBER2(ep)); | ||
345 | |||
346 | csr = REG_USB_REG_OUTCSR; | ||
241 | } | 347 | } |
348 | |||
349 | //flushFIFO(ep); | ||
242 | } | 350 | } |
243 | 351 | ||
244 | static void udc_reset(void) | 352 | static void udc_reset(void) |
245 | { | 353 | { |
246 | logf("udc_reset"); | 354 | logf("udc_reset()"); |
247 | 355 | ||
248 | register unsigned int i; | 356 | register unsigned int i; |
249 | 357 | ||
250 | /* data init */ | 358 | /* EP0 init */ |
251 | ep0state = USB_EP0_IDLE; | 359 | ep0state = USB_EP0_IDLE; |
252 | 360 | ||
253 | /* Disable interrupts */ | 361 | /* Disable interrupts */ |
@@ -261,19 +369,20 @@ static void udc_reset(void) | |||
261 | 369 | ||
262 | /* Reset address */ | 370 | /* Reset address */ |
263 | REG_USB_REG_FADDR = 0; | 371 | REG_USB_REG_FADDR = 0; |
264 | //REG_USB_REG_POWER = (USB_POWER_SOFTCONN | USB_POWER_HSENAB); /* High speed and softconnect */ | 372 | |
373 | /* High speed and softconnect */ | ||
374 | //REG_USB_REG_POWER = (USB_POWER_SOFTCONN | USB_POWER_HSENAB); | ||
265 | REG_USB_REG_POWER = USB_POWER_SOFTCONN; | 375 | REG_USB_REG_POWER = USB_POWER_SOFTCONN; |
376 | |||
266 | /* Enable SUSPEND */ | 377 | /* Enable SUSPEND */ |
267 | /* REG_USB_REG_POWER |= USB_POWER_SUSPENDM; */ | 378 | /* REG_USB_REG_POWER |= USB_POWER_SUSPENDM; */ |
268 | 379 | ||
380 | /* Reset EP0 */ | ||
269 | select_endpoint(0); | 381 | select_endpoint(0); |
270 | REG_USB_REG_CSR0 = (USB_CSR0_SVDOUTPKTRDY | USB_CSR0_SVDSETUPEND); | 382 | REG_USB_REG_CSR0 = (USB_CSR0_SVDOUTPKTRDY | USB_CSR0_SVDSETUPEND); |
271 | 383 | ||
272 | for(i=2; i<TOTAL_EP(); i++) /* Skip EP0 */ | 384 | for(i=2; i<TOTAL_EP(); i++) /* Skip EP0 */ |
273 | { | ||
274 | select_endpoint(i); | ||
275 | setup_endpoint(&endpoints[i]); | 385 | setup_endpoint(&endpoints[i]); |
276 | } | ||
277 | 386 | ||
278 | /* Enable interrupts */ | 387 | /* Enable interrupts */ |
279 | REG_USB_REG_INTRINE |= USB_INTR_EP0; | 388 | REG_USB_REG_INTRINE |= USB_INTR_EP0; |
@@ -297,19 +406,31 @@ void UDC(void) | |||
297 | /* EPIN & EPOUT are all handled in DMA */ | 406 | /* EPIN & EPOUT are all handled in DMA */ |
298 | if(intrIn & USB_INTR_EP0) | 407 | if(intrIn & USB_INTR_EP0) |
299 | EP0_handler(); | 408 | EP0_handler(); |
409 | if(intrIn & USB_INTR_INEP1) | ||
410 | EPIN_handler(1); | ||
411 | if(intrIn & USB_INTR_INEP2) | ||
412 | EPIN_handler(2); | ||
413 | if(intrOut & USB_INTR_OUTEP1) | ||
414 | EPOUT_handler(1); | ||
415 | if(intrOut & USB_INTR_OUTEP2) | ||
416 | EPOUT_handler(2); | ||
300 | if(intrUSB & USB_INTR_RESET) | 417 | if(intrUSB & USB_INTR_RESET) |
301 | udc_reset(); | 418 | udc_reset(); |
302 | if(intrUSB & USB_INTR_SUSPEND); | 419 | //if(intrUSB & USB_INTR_SUSPEND); |
303 | if(intrUSB & USB_INTR_RESUME); | 420 | //if(intrUSB & USB_INTR_RESUME); |
304 | if(intrDMA & USB_INTR_DMA_BULKIN) | 421 | if(intrDMA & USB_INTR_DMA_BULKIN) |
305 | { | 422 | { |
306 | logf("DMA_BULKIN %d", ((REG_USB_REG_CNTL1 >> 4) & 0xF)); | 423 | logf("DMA_BULKIN %d", ((REG_USB_REG_CNTL1 >> 4) & 0xF)); |
307 | usb_core_transfer_complete(((REG_USB_REG_CNTL1 >> 4) & 0xF) | USB_DIR_IN, USB_DIR_IN, 0, 0); | 424 | usb_core_transfer_complete(1 | USB_DIR_IN, USB_DIR_IN, 0, 0); |
308 | } | 425 | } |
309 | if(intrDMA & USB_INTR_DMA_BULKOUT) | 426 | if(intrDMA & USB_INTR_DMA_BULKOUT) |
310 | { | 427 | { |
311 | logf("DMA_BULKOUT %d", ((REG_USB_REG_CNTL2 >> 4) & 0xF)); | 428 | logf("DMA_BULKOUT %d", ((REG_USB_REG_CNTL2 >> 4) & 0xF)); |
312 | usb_core_transfer_complete(((REG_USB_REG_CNTL2 >> 4) & 0xF) | USB_DIR_OUT, USB_DIR_OUT, 0, 0); | 429 | |
430 | select_endpoint(1); | ||
431 | REG_USB_REG_OUTCSR &= ~(USB_OUTCSRH_DMAREQENAB | USB_OUTCSR_OUTPKTRDY); | ||
432 | |||
433 | usb_core_transfer_complete(1 | USB_DIR_OUT, USB_DIR_OUT, 0, 0); | ||
313 | } | 434 | } |
314 | } | 435 | } |
315 | 436 | ||
@@ -317,7 +438,7 @@ bool usb_drv_stalled(int endpoint, bool in) | |||
317 | { | 438 | { |
318 | logf("usb_drv_stalled(%d, %s)", endpoint, in?"IN":"OUT"); | 439 | logf("usb_drv_stalled(%d, %s)", endpoint, in?"IN":"OUT"); |
319 | 440 | ||
320 | select_endpoint(endpoint); | 441 | select_endpoint(endpoint & 0x7F); |
321 | 442 | ||
322 | if(endpoint == 0) | 443 | if(endpoint == 0) |
323 | return (REG_USB_REG_CSR0 & USB_CSR0_SENDSTALL) != 0; | 444 | return (REG_USB_REG_CSR0 & USB_CSR0_SENDSTALL) != 0; |
@@ -332,7 +453,7 @@ bool usb_drv_stalled(int endpoint, bool in) | |||
332 | 453 | ||
333 | void usb_drv_stall(int endpoint, bool stall, bool in) | 454 | void usb_drv_stall(int endpoint, bool stall, bool in) |
334 | { | 455 | { |
335 | logf("usb_drv_stall(%d,%s,%s)", endpoint, stall?"y":"n", in?"IN":"OUT"); | 456 | logf("usb_drv_stall(%d,%s,%s)", endpoint, stall?"Y":"N", in?"IN":"OUT"); |
336 | 457 | ||
337 | select_endpoint(endpoint); | 458 | select_endpoint(endpoint); |
338 | 459 | ||
@@ -350,14 +471,14 @@ void usb_drv_stall(int endpoint, bool stall, bool in) | |||
350 | if(stall) | 471 | if(stall) |
351 | REG_USB_REG_INCSR |= USB_INCSR_SENDSTALL; | 472 | REG_USB_REG_INCSR |= USB_INCSR_SENDSTALL; |
352 | else | 473 | else |
353 | REG_USB_REG_INCSR &= ~USB_INCSR_SENDSTALL; | 474 | REG_USB_REG_INCSR = (REG_USB_REG_INCSR & ~USB_INCSR_SENDSTALL) | USB_INCSR_CDT; |
354 | } | 475 | } |
355 | else | 476 | else |
356 | { | 477 | { |
357 | if(stall) | 478 | if(stall) |
358 | REG_USB_REG_OUTCSR |= USB_OUTCSR_SENDSTALL; | 479 | REG_USB_REG_OUTCSR |= USB_OUTCSR_SENDSTALL; |
359 | else | 480 | else |
360 | REG_USB_REG_OUTCSR &= ~USB_OUTCSR_SENDSTALL; | 481 | REG_USB_REG_OUTCSR = (REG_USB_REG_OUTCSR & ~USB_OUTCSR_SENDSTALL) | USB_OUTCSR_CDT; |
361 | } | 482 | } |
362 | } | 483 | } |
363 | } | 484 | } |
@@ -388,12 +509,13 @@ void usb_enable(bool on) | |||
388 | 509 | ||
389 | void usb_drv_init(void) | 510 | void usb_drv_init(void) |
390 | { | 511 | { |
512 | logf("usb_drv_init()"); | ||
513 | |||
391 | /* Set this bit to allow the UDC entering low-power mode when | 514 | /* Set this bit to allow the UDC entering low-power mode when |
392 | * there are no actions on the USB bus. | 515 | * there are no actions on the USB bus. |
393 | * UDC still works during this bit was set. | 516 | * UDC still works during this bit was set. |
394 | */ | 517 | */ |
395 | //__cpm_stop_udc(); | 518 | //__cpm_stop_udc(); |
396 | |||
397 | __cpm_start_udc(); | 519 | __cpm_start_udc(); |
398 | 520 | ||
399 | /* Enable the USB PHY */ | 521 | /* Enable the USB PHY */ |
@@ -404,6 +526,8 @@ void usb_drv_init(void) | |||
404 | 526 | ||
405 | void usb_drv_exit(void) | 527 | void usb_drv_exit(void) |
406 | { | 528 | { |
529 | logf("usb_drv_exit()"); | ||
530 | |||
407 | /* Disable interrupts */ | 531 | /* Disable interrupts */ |
408 | REG_USB_REG_INTRINE = 0; | 532 | REG_USB_REG_INTRINE = 0; |
409 | REG_USB_REG_INTROUTE = 0; | 533 | REG_USB_REG_INTROUTE = 0; |
@@ -413,7 +537,7 @@ void usb_drv_exit(void) | |||
413 | REG_USB_REG_CNTL1 = 0; | 537 | REG_USB_REG_CNTL1 = 0; |
414 | REG_USB_REG_CNTL2 = 0; | 538 | REG_USB_REG_CNTL2 = 0; |
415 | 539 | ||
416 | /* Disconnect from usb */ | 540 | /* Disconnect from USB */ |
417 | REG_USB_REG_POWER &= ~USB_POWER_SOFTCONN; | 541 | REG_USB_REG_POWER &= ~USB_POWER_SOFTCONN; |
418 | 542 | ||
419 | /* Disable the USB PHY */ | 543 | /* Disable the USB PHY */ |
@@ -431,32 +555,71 @@ void usb_drv_set_address(int address) | |||
431 | 555 | ||
432 | int usb_drv_send(int endpoint, void* ptr, int length) | 556 | int usb_drv_send(int endpoint, void* ptr, int length) |
433 | { | 557 | { |
434 | logf("usb_drv_send(%d, 0x%x, %d)", endpoint, (int)ptr, length); | 558 | int flags; |
435 | 559 | endpoint &= 0x7F; | |
436 | if(endpoint == EP_CONTROL && ptr == NULL && length == 0) /* ACK request */ | ||
437 | return 0; | ||
438 | 560 | ||
561 | logf("usb_drv_send(%d, 0x%x, %d)", endpoint, (int)ptr, length); | ||
562 | |||
439 | if(endpoint == EP_CONTROL) | 563 | if(endpoint == EP_CONTROL) |
440 | { | 564 | { |
565 | flags = disable_irq_save(); | ||
441 | endpoints[1].buf = ptr; | 566 | endpoints[1].buf = ptr; |
442 | endpoints[1].sent = 0; | 567 | endpoints[1].sent = 0; |
443 | endpoints[1].length = length; | 568 | endpoints[1].length = length; |
444 | ep0state = USB_EP0_TX; | 569 | ep0state = USB_EP0_TX; |
445 | EP0_send(); | 570 | EP0_send(); |
571 | |||
572 | restore_irq(flags); | ||
446 | return 0; | 573 | return 0; |
447 | } | 574 | } |
448 | else | 575 | else if(endpoint == 1) |
576 | { | ||
577 | #if 0 | ||
578 | select_endpoint(endpoint); | ||
579 | |||
580 | REG_USB_REG_ADDR2 = ((unsigned long)ptr) & 0x7fffffff; | ||
581 | REG_USB_REG_COUNT2 = length; | ||
582 | REG_USB_REG_CNTL2 = 1; | ||
583 | #else | ||
584 | flags = disable_irq_save(); | ||
585 | endpoints[3].buf = ptr; | ||
586 | endpoints[3].sent = 0; | ||
587 | endpoints[3].length = length; | ||
588 | EPIN_handler(1); | ||
589 | restore_irq(flags); | ||
590 | #endif | ||
449 | return 0; | 591 | return 0; |
592 | } | ||
593 | else | ||
594 | return -1; | ||
595 | } | ||
596 | |||
597 | int usb_drv_send_nonblocking(int endpoint, void* ptr, int length) | ||
598 | { | ||
599 | return usb_drv_send(endpoint, ptr, length); | ||
450 | } | 600 | } |
451 | 601 | ||
452 | int usb_drv_recv(int endpoint, void* ptr, int length) | 602 | int usb_drv_recv(int endpoint, void* ptr, int length) |
453 | { | 603 | { |
604 | int flags; | ||
605 | endpoint &= 0x7F; | ||
606 | |||
454 | logf("usb_drv_recv(%d, 0x%x, %d)", endpoint, (int)ptr, length); | 607 | logf("usb_drv_recv(%d, 0x%x, %d)", endpoint, (int)ptr, length); |
455 | 608 | ||
456 | if(endpoint == EP_CONTROL && ptr == NULL && length == 0) /* ACK request */ | 609 | if(endpoint == EP_CONTROL && ptr == NULL && length == 0) |
610 | return 0; /* ACK request, handled by the USB controller */ | ||
611 | else if(endpoint == 1) | ||
612 | { | ||
613 | logf("EP1 handled: %d", length); | ||
614 | flags = disable_irq_save(); | ||
615 | endpoints[2].buf = ptr; | ||
616 | endpoints[2].received = 0; | ||
617 | endpoints[2].length = length; | ||
618 | restore_irq(flags); | ||
457 | return 0; | 619 | return 0; |
458 | 620 | } | |
459 | return -1; | 621 | else |
622 | return -1; | ||
460 | } | 623 | } |
461 | 624 | ||
462 | void usb_drv_set_test_mode(int mode) | 625 | void usb_drv_set_test_mode(int mode) |
@@ -492,13 +655,18 @@ void usb_drv_cancel_all_transfers(void) | |||
492 | { | 655 | { |
493 | logf("usb_drv_cancel_all_transfers()"); | 656 | logf("usb_drv_cancel_all_transfers()"); |
494 | 657 | ||
495 | unsigned int i; | 658 | unsigned int i, flags; |
659 | flags = disable_irq_save(); | ||
660 | |||
496 | for(i=0; i<TOTAL_EP(); i++) | 661 | for(i=0; i<TOTAL_EP(); i++) |
497 | { | 662 | { |
498 | endpoints[i].sent = 0; | 663 | endpoints[i].sent = 0; |
499 | endpoints[i].length = 0; | 664 | endpoints[i].length = 0; |
500 | /* TODO: flush FIFO's ? */ | 665 | |
666 | select_endpoint(i/2); | ||
667 | flushFIFO(&endpoints[i]); | ||
501 | } | 668 | } |
669 | restore_irq(flags); | ||
502 | 670 | ||
503 | ep0state = USB_EP0_IDLE; | 671 | ep0state = USB_EP0_IDLE; |
504 | } | 672 | } |
@@ -512,8 +680,14 @@ void usb_drv_release_endpoint(int ep) | |||
512 | 680 | ||
513 | int usb_drv_request_endpoint(int dir) | 681 | int usb_drv_request_endpoint(int dir) |
514 | { | 682 | { |
515 | logf("usb_drv_request_endpoint(%d)", dir); | 683 | logf("usb_drv_request_endpoint(%s)", dir == USB_DIR_IN ? "IN" : "OUT"); |
516 | 684 | ||
517 | (void)dir; | 685 | /* There are only 3+2 endpoints, so hardcode this ... */ |
518 | return -1; | 686 | /* Currently only BULK endpoints ... */ |
687 | if(dir == USB_DIR_OUT) | ||
688 | return (1 | USB_DIR_OUT); | ||
689 | else if(dir == USB_DIR_IN) | ||
690 | return (1 | USB_DIR_IN); | ||
691 | else | ||
692 | return -1; | ||
519 | } | 693 | } |