]> git.lizzy.rs Git - plan9front.git/blob - sys/src/9/zynq/usbehcizynq.c
bootrc: allow kbmap to be set via plan9.ini (thanks Aaron Bieber)
[plan9front.git] / sys / src / 9 / zynq / usbehcizynq.c
1 #include        "u.h"
2 #include        "../port/lib.h"
3 #include        "mem.h"
4 #include        "dat.h"
5 #include        "fns.h"
6 #include        "io.h"
7 #include        "../port/error.h"
8 #include        "../port/usb.h"
9 #include        "usbehci.h"
10
11 enum {
12         USBMODE = 0x1A8/4,
13         USBHOST = 3,
14         OTGSC = 0x1A4/4,
15         ULPI = 0x170/4,
16 };
17
18 static Ctlr ctlrs[3] = {
19         {
20                 .base = USB0_BASE,
21                 .irq = USB0IRQ,
22         },
23         {
24                 .base = USB1_BASE,
25                 .irq = USB1IRQ,
26         },
27 };
28
29 static void
30 ehcireset(Ctlr *ctlr)
31 {
32         int i;
33         Eopio *opio;
34
35         ilock(ctlr);
36         opio = ctlr->opio;
37         ehcirun(ctlr, 0);
38         opio->cmd |= Chcreset;
39         for(i = 0; i < 100; i++){
40                 if((opio->cmd & Chcreset) == 0)
41                         break;
42                 delay(1);
43         }
44         if(i == 100)
45                 print("ehci %#p controller reset timed out\n", ctlr->base);
46         opio->cmd |= Citc1;
47         switch(opio->cmd & Cflsmask){
48         case Cfls1024:
49                 ctlr->nframes = 1024;
50                 break;
51         case Cfls512:
52                 ctlr->nframes = 512;
53                 break;
54         case Cfls256:
55                 ctlr->nframes = 256;
56                 break;
57         default:
58                 panic("ehci: unknown fls %ld", opio->cmd & Cflsmask);
59         }
60         dprint("ehci: %d frames\n", ctlr->nframes);
61         iunlock(ctlr);
62 }
63
64 /* descriptors need to be allocated in uncached memory */
65 static void*
66 tdalloc(ulong size, int, ulong)
67 {
68         return ucalloc(size);
69 }
70
71 static void*
72 dmaalloc(ulong len)
73 {
74         return mallocalign(ROUND(len, BLOCKALIGN), BLOCKALIGN, 0, 0);
75 }
76 static void
77 dmafree(void *data)
78 {
79         free(data);
80 }
81
82 static int (*ehciportstatus)(Hci*,int);
83
84 static int
85 portstatus(Hci *hp, int port)
86 {
87         Ctlr *ctlr;
88         Eopio *opio;
89         int r, sts;
90
91         ctlr = hp->aux;
92         opio = ctlr->opio;
93         r = (*ehciportstatus)(hp, port);
94         if(r & HPpresent){
95                 sts = opio->portsc[port-1];
96                 r &= ~(HPhigh|HPslow);
97                 if(sts & (1<<9))
98                         r |= HPhigh;
99                 else if(sts & 1<<26)
100                         r |= HPslow;
101         }
102         return r;
103 }
104
105 static int
106 reset(Hci *hp)
107 {
108         static Lock resetlck;
109         Ctlr *ctlr;
110         
111         ilock(&resetlck);
112         for(ctlr = ctlrs; ctlr->base != 0; ctlr++)
113                 if(!ctlr->active && (hp->port == 0 || hp->port == ctlr->base)){
114                         ctlr->active = 1;
115                         break;
116                 }
117         iunlock(&resetlck);
118         if(ctlr->base == 0)
119                 return -1;
120         hp->port = ctlr->base;
121         hp->irq = ctlr->irq;
122         hp->aux = ctlr;
123         
124         ctlr->r = vmap(ctlr->base, 0x1F0);
125         ctlr->opio = (Eopio *) ((uchar *) ctlr->r + 0x140);
126         ctlr->capio = (void *) ctlr->base;
127         hp->nports = 1; 
128
129         ctlr->tdalloc = tdalloc;
130         ctlr->dmaalloc = dmaalloc;
131         ctlr->dmafree = dmafree;
132
133         ehcireset(ctlr);
134         ctlr->r[USBMODE] |= USBHOST;
135         ctlr->r[ULPI] = 1<<30 | 1<<29 | 0x0B << 16 | 3<<5;
136         ehcimeminit(ctlr);
137         ehcilinkage(hp);
138
139         /* hook portstatus */
140         ehciportstatus = hp->portstatus;
141         hp->portstatus = portstatus;
142
143         if(hp->interrupt != nil)
144                 intrenable(hp->irq, hp->interrupt, hp, LEVEL, hp->type);
145         return 0;
146 }
147
148 void
149 usbehcilink(void)
150 {
151 //      ehcidebug = 2;
152         addhcitype("ehci", reset);
153 }