]> git.lizzy.rs Git - plan9front.git/blob - sys/src/9/bcm/uartmini.c
bcm: move okay() from uartmini.c to devarch.c
[plan9front.git] / sys / src / 9 / bcm / uartmini.c
1 /*
2  * bcm2835 mini uart (UART1)
3  */
4
5 #include "u.h"
6 #include "../port/lib.h"
7 #include "../port/error.h"
8 #include "mem.h"
9 #include "dat.h"
10 #include "fns.h"
11 #include "io.h"
12
13 #define AUXREGS         (VIRTIO+0x215000)
14 #define OkLed           16
15 #define TxPin           14
16 #define RxPin           15
17
18 /* AUX regs */
19 enum {
20         Irq     = 0x00>>2,
21                 UartIrq = 1<<0,
22         Enables = 0x04>>2,
23                 UartEn  = 1<<0,
24         MuIo    = 0x40>>2,
25         MuIer   = 0x44>>2,
26                 RxIen   = 1<<0,
27                 TxIen   = 1<<1,
28         MuIir   = 0x48>>2,
29         MuLcr   = 0x4c>>2,
30                 Bitsmask= 3<<0,
31                 Bits7   = 2<<0,
32                 Bits8   = 3<<0,
33         MuMcr   = 0x50>>2,
34                 RtsN    = 1<<1,
35         MuLsr   = 0x54>>2,
36                 TxDone  = 1<<6,
37                 TxRdy   = 1<<5,
38                 RxRdy   = 1<<0,
39         MuCntl  = 0x60>>2,
40                 CtsFlow = 1<<3,
41                 TxEn    = 1<<1,
42                 RxEn    = 1<<0,
43         MuBaud  = 0x68>>2,
44 };
45
46 extern PhysUart miniphysuart;
47
48 static Uart miniuart = {
49         .regs   = (u32int*)AUXREGS,
50         .name   = "uart0",
51         .freq   = 250000000,
52         .baud   = 115200,
53         .phys   = &miniphysuart,
54 };
55
56 static int baud(Uart*, int);
57
58 static void
59 interrupt(Ureg*, void *arg)
60 {
61         Uart *uart;
62         u32int *ap;
63
64         uart = arg;
65         ap = (u32int*)uart->regs;
66
67         coherence();
68         if(0 && (ap[Irq] & UartIrq) == 0)
69                 return;
70         if(ap[MuLsr] & TxRdy)
71                 uartkick(uart);
72         if(ap[MuLsr] & RxRdy){
73                 do{
74                         uartrecv(uart, ap[MuIo] & 0xFF);
75                 }while(ap[MuLsr] & RxRdy);
76         }
77         coherence();
78 }
79
80 static Uart*
81 pnp(void)
82 {
83         return &miniuart;
84 }
85
86 static void
87 enable(Uart *uart, int ie)
88 {
89         u32int *ap;
90
91         ap = (u32int*)uart->regs;
92         delay(10);
93         gpiosel(TxPin, Alt5);
94         gpiosel(RxPin, Alt5);
95         gpiopulloff(TxPin);
96         gpiopullup(RxPin);
97         ap[Enables] |= UartEn;
98         ap[MuIir] = 6;
99         ap[MuLcr] = Bits8;
100         ap[MuCntl] = TxEn|RxEn;
101         baud(uart, uart->baud);
102         if(ie){
103                 intrenable(IRQaux, interrupt, uart, 0, "uart");
104                 ap[MuIer] = RxIen|TxIen;
105         }else
106                 ap[MuIer] = 0;
107 }
108
109 static void
110 disable(Uart *uart)
111 {
112         u32int *ap;
113
114         ap = (u32int*)uart->regs;
115         ap[MuCntl] = 0;
116         ap[MuIer] = 0;
117 }
118
119 static void
120 kick(Uart *uart)
121 {
122         u32int *ap;
123
124         ap = (u32int*)uart->regs;
125         if(uart->blocked)
126                 return;
127         coherence();
128         while(ap[MuLsr] & TxRdy){
129                 if(uart->op >= uart->oe && uartstageoutput(uart) == 0)
130                         break;
131                 ap[MuIo] = *(uart->op++);
132         }
133         if(ap[MuLsr] & TxDone)
134                 ap[MuIer] &= ~TxIen;
135         else
136                 ap[MuIer] |= TxIen;
137         coherence();
138 }
139
140 /* TODO */
141 static void
142 dobreak(Uart *uart, int ms)
143 {
144         USED(uart, ms);
145 }
146
147 static int
148 baud(Uart *uart, int n)
149 {
150         u32int *ap;
151
152         ap = (u32int*)uart->regs;
153         if(uart->freq == 0 || n <= 0)
154                 return -1;
155         ap[MuBaud] = (uart->freq + 4*n - 1) / (8 * n) - 1;
156         uart->baud = n;
157         return 0;
158 }
159
160 static int
161 bits(Uart *uart, int n)
162 {
163         u32int *ap;
164         int set;
165
166         ap = (u32int*)uart->regs;
167         switch(n){
168         case 7:
169                 set = Bits7;
170                 break;
171         case 8:
172                 set = Bits8;
173                 break;
174         default:
175                 return -1;
176         }
177         ap[MuLcr] = (ap[MuLcr] & ~Bitsmask) | set;
178         uart->bits = n;
179         return 0;
180 }
181
182 static int
183 stop(Uart *uart, int n)
184 {
185         if(n != 1)
186                 return -1;
187         uart->stop = n;
188         return 0;
189 }
190
191 static int
192 parity(Uart *uart, int n)
193 {
194         if(n != 'n')
195                 return -1;
196         uart->parity = n;
197         return 0;
198 }
199
200 /*
201  * cts/rts flow control
202  *   need to bring signals to gpio pins before enabling this
203  */
204
205 static void
206 modemctl(Uart *uart, int on)
207 {
208         u32int *ap;
209
210         ap = (u32int*)uart->regs;
211         if(on)
212                 ap[MuCntl] |= CtsFlow;
213         else
214                 ap[MuCntl] &= ~CtsFlow;
215         uart->modem = on;
216 }
217
218 static void
219 rts(Uart *uart, int on)
220 {
221         u32int *ap;
222
223         ap = (u32int*)uart->regs;
224         if(on)
225                 ap[MuMcr] &= ~RtsN;
226         else
227                 ap[MuMcr] |= RtsN;
228 }
229
230 static long
231 status(Uart *uart, void *buf, long n, long offset)
232 {
233         char *p;
234
235         p = malloc(READSTR);
236         if(p == nil)
237                 error(Enomem);
238         snprint(p, READSTR,
239                 "b%d\n"
240                 "dev(%d) type(%d) framing(%d) overruns(%d) "
241                 "berr(%d) serr(%d)\n",
242
243                 uart->baud,
244                 uart->dev,
245                 uart->type,
246                 uart->ferr,
247                 uart->oerr,
248                 uart->berr,
249                 uart->serr
250         );
251         n = readstr(offset, buf, n, p);
252         free(p);
253
254         return n;
255 }
256
257 static void
258 donothing(Uart*, int)
259 {
260 }
261
262 void
263 putc(Uart*, int c)
264 {
265         u32int *ap;
266
267         ap = (u32int*)AUXREGS;
268         while((ap[MuLsr] & TxRdy) == 0)
269                 ;
270         ap[MuIo] = c;
271         while((ap[MuLsr] & TxRdy) == 0)
272                 ;
273 }
274
275 int
276 getc(Uart*)
277 {
278         u32int *ap;
279
280         ap = (u32int*)AUXREGS;
281         while((ap[MuLsr] & RxRdy) == 0)
282                 ;
283         return ap[MuIo] & 0xFF;
284 }
285
286 void
287 uartconsinit(void)
288 {
289         Uart *uart;
290         int n;
291         char *p, *cmd;
292
293         if((p = getconf("console")) == nil)
294                 return;
295         n = strtoul(p, &cmd, 0);
296         if(p == cmd)
297                 return;
298         switch(n){
299         default:
300                 return;
301         case 0:
302                 uart = &miniuart;
303                 break;
304         }
305
306         if(!uart->enabled)
307                 (*uart->phys->enable)(uart, 0);
308         uartctl(uart, "l8 pn s1");
309         if(*cmd != '\0')
310                 uartctl(uart, cmd);
311
312         consuart = uart;
313         uart->console = 1;
314 }
315
316 PhysUart miniphysuart = {
317         .name           = "miniuart",
318         .pnp            = pnp,
319         .enable         = enable,
320         .disable        = disable,
321         .kick           = kick,
322         .dobreak        = dobreak,
323         .baud           = baud,
324         .bits           = bits,
325         .stop           = stop,
326         .parity         = parity,
327         .modemctl       = donothing,
328         .rts            = rts,
329         .dtr            = donothing,
330         .status         = status,
331         .fifo           = donothing,
332         .getc           = getc,
333         .putc           = putc,
334 };