serial lpuart driver (reading characters and sending them to the shell)
[barrelfish] / usr / drivers / serial / serial_lpuart.c
1 /**
2  * \file
3  * \brief Serial port driver.
4  */
5
6 /*
7  * Copyright (c) 2007, 2008, 2010, 2011, 2012, ETH Zurich.
8  * All rights reserved.
9  *
10  * This file is distributed under the terms in the attached LICENSE file.
11  * If you do not find this file, copies can be found by writing to:
12  * ETH Zurich D-INFK, CAB F.78, Universitaetstrasse 6, CH-8092 Zurich,
13  * Attn: Systems Group.
14  */
15
16 #include <barrelfish/barrelfish.h>
17 #include <int_route/int_route_client.h>
18 #include <pci/pci.h>
19 #include "serial.h"
20 #include "serial_debug.h"
21 #include "pci/pci.h"
22 #include <dev/lpuart_dev.h>
23 #include <driverkit/driverkit.h>
24 #include <barrelfish/deferred.h>
25 #include <barrelfish/systime.h>
26
27 #define DEFAULT_PORTBASE            0x3f8   //< COM1 port
28 #define DEFAULT_IRQ                 4       //< COM1 IRQ
29
30
31 //#define LPUART_DEBUG_ON
32
33 #if defined(LPUART_DEBUG_ON) || defined(GLOBAL_DEBUG)
34 #define LPUART_DEBUG(x...) debug_printf(x)
35 #else
36 #define LPUART_DEBUG(x...) ((void)0)
37 #endif
38
39 struct serial_lpuart {
40     struct serial_common m;
41     struct lpuart_t uart;
42
43 };
44 __attribute__((__unused__))
45 static void print_regvalues(struct serial_lpuart *spc)
46 {   char buffer[10000];
47     lpuart_pr(buffer,10000,&spc->uart);
48     LPUART_DEBUG("printing lpuart  %s\n",buffer);
49  
50 }
51
52 __attribute__((__unused__))
53 // CALL THIS FUNCTION IN INIT
54 static void serial_poll(struct serial_lpuart *spc)
55 {  
56     while(lpuart_stat_rdrf_rdf(&spc->uart)){
57         LPUART_DEBUG("befohooore\n");
58         char c = lpuart_read_data_buf_rdf((&spc->uart));
59         if(c) LPUART_DEBUG("Read char=%c\n", c); 
60         else LPUART_DEBUG("Read NULL char\n");
61         serial_input(&spc->m, &c, 1);
62         uint8_t or= lpuart_stat_or_rdf(&spc->uart);
63         if(or==1) { 
64             LPUART_DEBUG("OR FLAG IS SET\n");
65             lpuart_stat_or_wrf(&spc->uart,1);
66         }
67     }   
68 }
69 static void serial_poll2(void* arg){
70     LPUART_DEBUG("my call back worked, arg=%p\n", arg);
71     serial_poll((struct serial_lpuart *)arg);
72     struct deferred_event* de= malloc(sizeof(struct deferred_event));
73     deferred_event_init(de);
74     struct event_closure ec;
75     ec.handler = serial_poll2;
76     ec.arg = arg;
77     errval_t err = deferred_event_register(de, get_default_waitset(),
78                                            1000, ec);
79     if (err_is_fail(err)) {
80         USER_PANIC_ERR(err, "deferred event register failed.");
81     }
82 }
83 __attribute__((__unused__))
84 static void install_event(delayus_t delay, struct serial_lpuart *spc) {
85     struct deferred_event* de= malloc(sizeof(struct deferred_event));
86     deferred_event_init(de);
87     errval_t err = deferred_event_register(de, get_default_waitset(),
88                                            delay, MKCLOSURE(serial_poll2, spc));
89     if (err_is_fail(err)) {
90         USER_PANIC_ERR(err, "deferred event register failed.");
91     }
92 }
93
94 // __attribute__((__unused__))
95 // static void serial_interrupt(void *m)
96 // {
97 //     // Figure out which interrupt happened
98 //     // -> we have data to read -> call serial_poll
99 //     // 
100 // }
101
102
103 static void hw_init(struct serial_lpuart *spc)
104 {   // Disable transceiver
105     lpuart_ctrl_t ctrl = lpuart_ctrl_rawrd(&spc->uart);
106     ctrl = lpuart_ctrl_te_insert(ctrl, 0);
107     ctrl = lpuart_ctrl_re_insert(ctrl, 0);
108     lpuart_ctrl_rawwr(&spc->uart, ctrl);
109     // Set baudrate
110     // baudrate = clock rate / (over sampling rate * SBR)
111     // TODO: Currently we assume UART clock is set to 8MHz
112     lpuart_baud_t baud = lpuart_baud_default;
113     baud = lpuart_baud_osr_insert(baud, lpuart_ratio5);
114     // OSR of 5 needs bothedge set
115     baud = lpuart_baud_bothedge_insert(baud, 1);
116     baud = lpuart_baud_sbr_insert(baud, 139);
117     lpuart_baud_rawwr(&spc->uart, baud);
118     //enable FIFOs
119      lpuart_fifo_t fcr = lpuart_fifo_default;
120     ctrl = lpuart_ctrl_default;
121     ctrl = lpuart_ctrl_te_insert(ctrl, 0);
122     ctrl = lpuart_ctrl_re_insert(ctrl, 0);
123     lpuart_ctrl_wr(&spc->uart, ctrl);
124     //enable fifo
125     fcr = lpuart_fifo_rxfe_insert(fcr, 1);
126     lpuart_fifo_wr(&spc->uart, fcr);
127     fcr = lpuart_fifo_txfe_insert(fcr, 1);
128     lpuart_fifo_wr(&spc->uart, fcr);
129     lpuart_water_rxwater_wrf(&spc->uart, 0);
130     // Enable transceiver
131     ctrl = lpuart_ctrl_default;
132     ctrl = lpuart_ctrl_te_insert(ctrl, 1);
133     ctrl = lpuart_ctrl_re_insert(ctrl, 1);
134     lpuart_ctrl_wr(&spc->uart, ctrl);
135     print_regvalues(spc);
136     // ENABLE INTERRUPTS
137     /*
138     //transmit interrupt enable
139      lpuart_ctrl_tie_wrf(&spc->uart,1);
140     //Transmission Complete Interrupt Enable
141     lpuart_ctrl_tcie_wrf(&spc->uart,1);
142     //Receiver Interrupt Enable
143     lpuart_ctrl_rie_wrf(&spc->uart,1);
144     //Overrun Interrupt Enable
145      lpuart_ctrl_orie_wrf(&spc->uart,1);
146      //noise error interrupt enable
147      lpuart_ctrl_neie_wrf(&spc->uart,1);
148      //framing error interrupt enable
149      lpuart_ctrl_feie_wrf(&spc->uart,1);
150      //Parity Error Interrupt Enable
151      lpuart_ctrl_peie_wrf(&spc->uart,1);
152       */
153 }
154
155 __attribute__((__unused__))
156 static void serial_putc(struct serial_lpuart *spc,char c)
157 {
158     // // Wait until FIFO can hold more characters
159     // while(!pc16550d_lsr_thre_rdf(&spc->uart));
160     // // Write character
161     // pc16550d_thr_wr(&spc->uart, c);
162     lpuart_t *u = &spc->uart;
163     assert(u->base != 0);
164
165     while(lpuart_stat_tdre_rdf(u) == 0);
166    lpuart_write_data_wr(u,c);
167 }
168
169 static void serial_write(void * m, const char *c, size_t len)
170 {
171     struct serial_lpuart * spc = m;
172     for (int i = 0; i < len; i++) {
173         serial_putc(spc, c[i]);
174     }
175 }
176
177 // #define MAX_NUM_UARTS 1
178 // lpaddr_t platform_uart_base[MAX_NUM_UARTS] =
179 // {
180 //         0x5A090000
181 // };
182
183 // errval_t serial_early_init(unsigned n)
184 // {unsigned serial_num_physical_ports = 1;
185 //     assert(!paging_mmu_enabled());
186 //     assert(n < serial_num_physical_ports);
187
188 //     lpuart_initialize(&uarts[n],
189 //         (mackerel_addr_t)local_phys_to_mem(platform_uart_base[n]));
190
191 //     // Make sure that the UART is enabled and transmitting - not all platforms
192 //     // do this for us.serial_putc
193 //    hw_init(&uarts[n]);serial_putc
194
195 //     return SYS_ERR_OK;serial_putc
196 // }
197
198 /**
199  * \brief Configure the serial interface, from a caller that knows
200  * that this i__attribute__((__unused__))s a bunch of PL011s, and furthermore where they are in
201  * the physical address space.
202  */
203 // errval_t serial_early_init_mmu_enabled(unsigned n)
204 // {
205 //     assert(paging_mmu_enabled());serial_putc
206 //     assert(n < serial_num_physicaserial_putcorts);
207
208 //     lpuart_initialize(&uarts[n],
209 //         (mackerel_addr_t)local_phys_to_mem(platform_uart_base[n]));
210
211 //     // Make sure that the UART is enabled and transmitting - not all platforms
212 //     // do this for us.
213 //     lpuart_hw_init(&uarts[n]);
214
215 //     return SYS_ERR_OK;
216 // }
217
218 static errval_t
219 serial_lpuart_init(struct serial_lpuart *spc, struct capref irq_src)
220 {   debug_printf("Hello world from serial lpuart driver\n");
221     
222     //errval_t err;
223
224     // if(capref_is_null(irq_src))
225     //     USER_PANIC("serial_kernel requires an irq cap");
226
227     spc->m.output = serial_write;
228     spc->m.output_arg = spc;
229
230     //Register interrupt handler
231     //err = int_route_client_route_and_connect(irq_src, 0,
232     //        get_default_waitset(), serial_interrupt, spc);
233     //if (err_is_fail(err)) {
234     //    USER_PANIC_ERR(err, "interrupt setup failed.");
235     // }
236
237     hw_init(spc);
238
239     // offer service now we're up
240     start_service(&spc->m);
241     return SYS_ERR_OK;
242 }
243 // static errval_t serial_lpuart_init(unsigned port, lvaddr_t base, bool hwinit)
244 // {   errval_t err;
245 //     assert(paging_mmu_enabled());
246 //     assert(port < serial_num_physical_ports);
247
248 //     lpuart_t *u = &uarts[port];
249
250 //     // [Re]initialize the Mackerel state for the UART
251 //     lpuart_initialize(u, (mackerel_addr_t) base);
252
253 //     if (hwinit) {
254 //         lpuart_hw_init(u);
255 //     }
256 //     return SYS_ERR_OK;
257 // }
258
259
260 static errval_t
261 init(struct bfdriver_instance* bfi, uint64_t flags, iref_t *dev)
262 {
263     errval_t err;
264     struct serial_lpuart *spc = malloc(sizeof(struct serial_lpuart));
265     init_serial_common(&spc->m);
266     //copy
267     lvaddr_t vbase;
268     struct capref devframe_cap = {
269         .slot = DRIVERKIT_ARGCN_SLOT_BAR0,
270         .cnode = bfi->argcn
271     };
272     err = map_device_cap(devframe_cap, &vbase);
273     debug_printf("vbase = %p\n", vbase);
274     lpuart_initialize (&spc->uart,(mackerel_addr_t) vbase);
275
276     /*  struct capref irq_src;
277     irq_src.cnode = bfi->argcn;
278     irq_src.slot = PCIARG_SLOT_INT; */
279     err = serial_lpuart_init(spc, NULL_CAP);
280     assert(err_is_ok(err));
281     bfi->dstate = spc;
282
283     SERIAL_DEBUG("lpuart Serial driver initialized.\n");
284     debug_printf("installing handler, spc=%p\n", spc);
285     install_event(1000, spc);
286     return SYS_ERR_OK;
287 }
288
289 static errval_t attach(struct bfdriver_instance* bfi) {
290     return SYS_ERR_OK;
291 }
292
293 static errval_t detach(struct bfdriver_instance* bfi) {
294     return SYS_ERR_OK;
295 }
296
297 static errval_t set_sleep_level(struct bfdriver_instance* bfi, uint32_t level) {
298     return SYS_ERR_OK;
299 }
300
301 static errval_t destroy(struct bfdriver_instance* bfi) {
302     struct lpuart_t * spc = bfi->dstate;
303     free(spc);
304     bfi->dstate = NULL;
305     // XXX: Tear-down the service
306     bfi->device = 0x0;
307     return SYS_ERR_OK;
308 }
309
310 static errval_t get_ep(struct bfdriver_instance* bfi, bool lmp, struct capref* ret_cap)
311 {   
312     USER_PANIC("NIY \n");
313     return SYS_ERR_OK;
314 }
315
316 DEFINE_MODULE(serial_lpuart, init, attach, detach, set_sleep_level, destroy, get_ep);