d4565813504e62828975736430124150dff000e3
[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
25 #define DEFAULT_PORTBASE            0x3f8   //< COM1 port
26 #define DEFAULT_IRQ                 4       //< COM1 IRQ
27
28 struct serial_lpuart {
29     struct serial_common m;
30     struct lpuart_t uart;
31
32 };
33 __attribute__((__unused__))
34 // CALL THIS FUNCTION IN INIT
35 static void serial_poll(struct serial_lpuart *spc)
36 {   while(lpuart_stat_rdrf_rdf(&spc->uart)){
37         char c = lpuart_data_buf_rdf(&spc->uart);
38         debug_printf("read %c from uart\n", c);
39         serial_input(&spc->m, &c, 1);
40      }
41      
42 }
43 // __attribute__((__unused__))
44 // static void serial_interrupt(void *m)
45 // {
46 //     // Figure out which interrupt happened
47 //     // -> we have data to read -> call serial_poll
48 //     // 
49 // }
50
51 static void hw_init(struct serial_lpuart *spc)
52 {   // Disable transceiver
53     lpuart_ctrl_t ctrl = lpuart_ctrl_rawrd(&spc->uart);
54     ctrl = lpuart_ctrl_te_insert(ctrl, 0);
55     ctrl = lpuart_ctrl_re_insert(ctrl, 0);
56     lpuart_ctrl_rawwr(&spc->uart, ctrl);
57     // Set baudrate
58     // baudrate = clock rate / (over sampling rate * SBR)
59     // TODO: Currently we assume UART clock is set to 8MHz
60     lpuart_baud_t baud = lpuart_baud_default;
61     baud = lpuart_baud_osr_insert(baud, lpuart_ratio5);
62     // OSR of 5 needs bothedge set
63     baud = lpuart_baud_bothedge_insert(baud, 1);
64     baud = lpuart_baud_sbr_insert(baud, 139);
65     lpuart_baud_rawwr(&spc->uart, baud);
66     //enable FIFOs
67     lpuart_fifo_t fcr = lpuart_fifo_default;
68     fcr = lpuart_fifo_txfe_insert(fcr, 1);
69     fcr = lpuart_fifo_rxfe_insert(fcr, 1);
70     
71     // Transmit FIFO/Buffer depth is 256 datawords
72     fcr = lpuart_fifo_txfifosize_insert(fcr, 0x3);
73     lpuart_fifo_wr(&spc->uart, fcr);
74     fcr = lpuart_fifo_rxfifosize_insert(fcr, 0x3);
75     lpuart_fifo_wr(&spc->uart, fcr);
76    // lpuart_fifo_t lcr = lpuart_fifo_default;
77     // lcr = pc16550d_lcr_wls_insert(lcr, pc16550d_bits8); // 8 data bits
78     // lcr = pc16550d_lcr_stb_insert(lcr, 1); // 1 stop bit
79     // lcr = pc16550d_lcr_pen_insert(lcr, 0); // no parity
80     // lpuart_fifo_wr(&spc->uart, lcr);
81
82     // Enable transceiver
83     ctrl = lpuart_ctrl_default;
84     ctrl = lpuart_ctrl_te_insert(ctrl, 1);
85     ctrl = lpuart_ctrl_re_insert(ctrl, 1);
86     lpuart_ctrl_rawwr(&spc->uart, ctrl);
87
88     // ENABLE INTERRUPTS
89     /*
90     //transmit interrupt enable
91      lpuart_ctrl_tie_wrf(&spc->uart,1);
92     //Transmission Complete Interrupt Enable
93     lpuart_ctrl_tcie_wrf(&spc->uart,1);
94     //Receiver Interrupt Enable
95     lpuart_ctrl_rie_wrf(&spc->uart,1);
96     //Overrun Interrupt Enable
97      lpuart_ctrl_orie_wrf(&spc->uart,1);
98      //noise error interrupt enable
99      lpuart_ctrl_neie_wrf(&spc->uart,1);
100      //framing error interrupt enable
101      lpuart_ctrl_feie_wrf(&spc->uart,1);
102      //Parity Error Interrupt Enable
103      lpuart_ctrl_peie_wrf(&spc->uart,1);
104       */
105 }
106
107 __attribute__((__unused__))
108 static void serial_putc(struct serial_lpuart *spc,char c)
109 {
110     // // Wait until FIFO can hold more characters
111     // while(!pc16550d_lsr_thre_rdf(&spc->uart));
112     // // Write character
113     // pc16550d_thr_wr(&spc->uart, c);
114    
115     lpuart_t *u = &spc->uart;
116     assert(u->base != 0);
117
118     while(lpuart_stat_tdre_rdf(u) == 0);
119     lpuart_data_buf_wrf(u, c);
120    
121
122 }
123
124 static void serial_write(void * m, const char *c, size_t len)
125 {
126     struct serial_lpuart * spc = m;
127     for (int i = 0; i < len; i++) {
128         serial_putc(spc, c[i]);
129     }
130 }
131
132 // #define MAX_NUM_UARTS 1
133 // lpaddr_t platform_uart_base[MAX_NUM_UARTS] =
134 // {
135 //         0x5A090000
136 // };
137
138 // errval_t serial_early_init(unsigned n)
139 // {unsigned serial_num_physical_ports = 1;
140 //     assert(!paging_mmu_enabled());
141 //     assert(n < serial_num_physical_ports);
142
143 //     lpuart_initialize(&uarts[n],
144 //         (mackerel_addr_t)local_phys_to_mem(platform_uart_base[n]));
145
146 //     // Make sure that the UART is enabled and transmitting - not all platforms
147 //     // do this for us.serial_putc
148 //    hw_init(&uarts[n]);serial_putc
149
150 //     return SYS_ERR_OK;serial_putc
151 // }
152
153 /**
154  * \brief Configure the serial interface, from a caller that knows
155  * that this i__attribute__((__unused__))s a bunch of PL011s, and furthermore where they are in
156  * the physical address space.
157  */
158 // errval_t serial_early_init_mmu_enabled(unsigned n)
159 // {
160 //     assert(paging_mmu_enabled());serial_putc
161 //     assert(n < serial_num_physicaserial_putcorts);
162
163 //     lpuart_initialize(&uarts[n],
164 //         (mackerel_addr_t)local_phys_to_mem(platform_uart_base[n]));
165
166 //     // Make sure that the UART is enabled and transmitting - not all platforms
167 //     // do this for us.
168 //     lpuart_hw_init(&uarts[n]);
169
170 //     return SYS_ERR_OK;
171 // }
172
173 static errval_t
174 serial_lpuart_init(struct serial_lpuart *spc, struct capref irq_src)
175 {   debug_printf("Hello world from serial lpuart driver\n");
176     
177     //errval_t err;
178
179     // if(capref_is_null(irq_src))
180     //     USER_PANIC("serial_kernel requires an irq cap");
181
182     spc->m.output = serial_write;
183     spc->m.output_arg = spc;
184
185     //Register interrupt handler
186     //err = int_route_client_route_and_connect(irq_src, 0,
187     //        get_default_waitset(), serial_interrupt, spc);
188     //if (err_is_fail(err)) {
189     //    USER_PANIC_ERR(err, "interrupt setup failed.");
190     // }
191
192     hw_init(spc);
193
194     // offer service now we're up
195     start_service(&spc->m);
196     return SYS_ERR_OK;
197 }
198 // static errval_t serial_lpuart_init(unsigned port, lvaddr_t base, bool hwinit)
199 // {   errval_t err;
200 //     assert(paging_mmu_enabled());
201 //     assert(port < serial_num_physical_ports);
202
203 //     lpuart_t *u = &uarts[port];
204
205 //     // [Re]initialize the Mackerel state for the UART
206 //     lpuart_initialize(u, (mackerel_addr_t) base);
207
208 //     if (hwinit) {
209 //         lpuart_hw_init(u);
210 //     }
211 //     return SYS_ERR_OK;
212 // }
213
214
215
216 static errval_t
217 init(struct bfdriver_instance* bfi, uint64_t flags, iref_t *dev)
218 {
219     errval_t err;
220     struct serial_lpuart *spc = malloc(sizeof(struct serial_lpuart));
221     init_serial_common(&spc->m);
222     //copy
223     lvaddr_t vbase;
224     struct capref devframe_cap = {
225         .slot = DRIVERKIT_ARGCN_SLOT_BAR0,
226         .cnode = bfi->argcn
227     };
228     err = map_device_cap(devframe_cap, &vbase);
229     debug_printf("vbase = %p\n", vbase);
230
231     lpuart_initialize (&spc->uart,(mackerel_addr_t) vbase);
232    //paste
233
234     /*  struct capref irq_src;
235     irq_src.cnode = bfi->argcn;
236     irq_src.slot = PCIARG_SLOT_INT; */
237     err = serial_lpuart_init(spc, NULL_CAP);
238     assert(err_is_ok(err));
239     bfi->dstate = spc;
240
241     SERIAL_DEBUG("lpuart Serial driver initialized.\n");
242     debug_printf("reading from uart\n");
243     while(1)
244     {
245     serial_poll(spc);
246     }
247     return SYS_ERR_OK;
248 }
249
250 static errval_t attach(struct bfdriver_instance* bfi) {
251     return SYS_ERR_OK;
252 }
253
254 static errval_t detach(struct bfdriver_instance* bfi) {
255     return SYS_ERR_OK;
256 }
257
258 static errval_t set_sleep_level(struct bfdriver_instance* bfi, uint32_t level) {
259     return SYS_ERR_OK;
260 }
261
262 static errval_t destroy(struct bfdriver_instance* bfi) {
263     struct lpuart_t * spc = bfi->dstate;
264     free(spc);
265     bfi->dstate = NULL;
266     // XXX: Tear-down the service
267     bfi->device = 0x0;
268     return SYS_ERR_OK;
269 }
270
271 static errval_t get_ep(struct bfdriver_instance* bfi, bool lmp, struct capref* ret_cap)
272 {   
273     USER_PANIC("NIY \n");
274     return SYS_ERR_OK;
275 }
276
277 DEFINE_MODULE(serial_lpuart, init, attach, detach, set_sleep_level, destroy, get_ep);