imx8x: Remove hacks from serial_lpuart driver
[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 DELAY  10000
28 //#define LPUART_DEBUG_ON
29
30 #if defined(LPUART_DEBUG_ON) || defined(GLOBAL_DEBUG)
31 #    define LPUART_DEBUG(x...) debug_printf(x)
32 #else
33 #    define LPUART_DEBUG(x...) ((void)0)
34 #endif
35
36 struct serial_lpuart {
37     struct serial_common m;
38     struct lpuart_t uart;
39 };
40
41 static void print_regvalues(struct serial_lpuart *spc)
42 {
43     char buffer[10000];
44     lpuart_pr(buffer, 10000, &spc->uart);
45     LPUART_DEBUG("printing lpuart  %s\n", buffer);
46 }
47
48 static void serial_poll(struct serial_lpuart *spc)
49 {
50     while (lpuart_stat_rdrf_rdf(&spc->uart)) {
51         char c = lpuart_rxdata_buf_rdf((&spc->uart));
52         if (c)
53             LPUART_DEBUG("Read char=%c\n", c);
54         else
55             LPUART_DEBUG("Read NULL char\n");
56         serial_input(&spc->m, &c, 1);
57         uint8_t or = lpuart_stat_or_rdf(&spc->uart);
58         if (or == 1) {
59             LPUART_DEBUG("OR FLAG IS SET\n");
60             lpuart_stat_or_wrf(&spc->uart, 1);
61         }
62     }
63 }
64
65 static void serial_poll_ev(void *arg)
66 {
67     serial_poll((struct serial_lpuart *)arg);
68
69     struct deferred_event *de = malloc(sizeof(struct deferred_event));
70     deferred_event_init(de);
71     errval_t err = deferred_event_register(de, get_default_waitset(), DELAY,
72                                            MKCLOSURE(serial_poll_ev, arg));
73     if (err_is_fail(err)) {
74         USER_PANIC_ERR(err, "deferred event register failed.");
75     }
76 }
77
78
79 static void hw_init(struct serial_lpuart *spc)
80 {  // Disable transceiver
81     lpuart_ctrl_t ctrl = lpuart_ctrl_rawrd(&spc->uart);
82     ctrl = lpuart_ctrl_te_insert(ctrl, 0);
83     ctrl = lpuart_ctrl_re_insert(ctrl, 0);
84     lpuart_ctrl_rawwr(&spc->uart, ctrl);
85     // Set baudrate
86     // baudrate = clock rate / (over sampling rate * SBR)
87     // TODO: Currently we assume UART clock is set to 8MHz
88     lpuart_baud_t baud = lpuart_baud_default;
89     baud = lpuart_baud_osr_insert(baud, lpuart_ratio5);
90     // OSR of 5 needs bothedge set
91     baud = lpuart_baud_bothedge_insert(baud, 1);
92     baud = lpuart_baud_sbr_insert(baud, 139);
93     lpuart_baud_rawwr(&spc->uart, baud);
94     // enable FIFOs
95     lpuart_fifo_t fcr = lpuart_fifo_default;
96     ctrl = lpuart_ctrl_default;
97     ctrl = lpuart_ctrl_te_insert(ctrl, 0);
98     ctrl = lpuart_ctrl_re_insert(ctrl, 0);
99     lpuart_ctrl_wr(&spc->uart, ctrl);
100     // enable fifo
101     fcr = lpuart_fifo_rxfe_insert(fcr, 1);
102     lpuart_fifo_wr(&spc->uart, fcr);
103     fcr = lpuart_fifo_txfe_insert(fcr, 1);
104     lpuart_fifo_wr(&spc->uart, fcr);
105     lpuart_water_rxwater_wrf(&spc->uart, 0);
106     // Enable transceiver
107     ctrl = lpuart_ctrl_default;
108     ctrl = lpuart_ctrl_te_insert(ctrl, 1);
109     ctrl = lpuart_ctrl_re_insert(ctrl, 1);
110     lpuart_ctrl_wr(&spc->uart, ctrl);
111     print_regvalues(spc);
112     // ENABLE INTERRUPTS
113     /*
114     //transmit interrupt enable
115      lpuart_ctrl_tie_wrf(&spc->uart,1);
116     //Transmission Complete Interrupt Enable
117     lpuart_ctrl_tcie_wrf(&spc->uart,1);
118     //Receiver Interrupt Enable
119     lpuart_ctrl_rie_wrf(&spc->uart,1);
120     //Overrun Interrupt Enable
121      lpuart_ctrl_orie_wrf(&spc->uart,1);
122      //noise error interrupt enable
123      lpuart_ctrl_neie_wrf(&spc->uart,1);
124      //framing error interrupt enable
125      lpuart_ctrl_feie_wrf(&spc->uart,1);
126      //Parity Error Interrupt Enable
127      lpuart_ctrl_peie_wrf(&spc->uart,1);
128      */
129 }
130
131 static void serial_putc(struct serial_lpuart *spc, char c)
132 {
133     lpuart_t *u = &spc->uart;
134     assert(u->base != 0);
135
136     while (lpuart_stat_tdre_rdf(u) == 0)
137         ;
138     lpuart_txdata_wr(u, c);
139 }
140
141 static void serial_write(void *m, const char *c, size_t len)
142 {
143     struct serial_lpuart *spc = m;
144     for (int i = 0; i < len; i++) {
145         serial_putc(spc, c[i]);
146     }
147 }
148
149 static errval_t serial_lpuart_init(struct serial_lpuart *spc, struct capref irq_src)
150 {
151     debug_printf("Hello world from serial lpuart driver\n");
152
153     // errval_t err;
154
155     // if(capref_is_null(irq_src))
156     //     USER_PANIC("serial_kernel requires an irq cap");
157
158     spc->m.output = serial_write;
159     spc->m.output_arg = spc;
160
161     // Register interrupt handler
162     // err = int_route_client_route_and_connect(irq_src, 0,
163     //        get_default_waitset(), serial_interrupt, spc);
164     // if (err_is_fail(err)) {
165     //    USER_PANIC_ERR(err, "interrupt setup failed.");
166     // }
167
168     hw_init(spc);
169
170     // offer service now we're up
171     start_service(&spc->m);
172     return SYS_ERR_OK;
173 }
174
175 static errval_t init(struct bfdriver_instance *bfi, uint64_t flags, iref_t *dev)
176 {
177     errval_t err;
178     struct serial_lpuart *spc = malloc(sizeof(struct serial_lpuart));
179     init_serial_common(&spc->m);
180     // copy
181     lvaddr_t vbase;
182     struct capref devframe_cap = { .slot = DRIVERKIT_ARGCN_SLOT_BAR0,
183                                    .cnode = bfi->argcn };
184     err = map_device_cap(devframe_cap, &vbase);
185     debug_printf("vbase = %p\n", vbase);
186     lpuart_initialize(&spc->uart, (mackerel_addr_t)vbase);
187
188     /*  struct capref irq_src;
189     irq_src.cnode = bfi->argcn;
190     irq_src.slot = PCIARG_SLOT_INT; */
191     err = serial_lpuart_init(spc, NULL_CAP);
192     assert(err_is_ok(err));
193     bfi->dstate = spc;
194
195     SERIAL_DEBUG("lpuart Serial driver initialized.\n");
196     debug_printf("installing handler, spc=%p\n", spc);
197     serial_poll_ev(spc);
198     return SYS_ERR_OK;
199 }
200
201 static errval_t attach(struct bfdriver_instance *bfi)
202 {
203     return SYS_ERR_OK;
204 }
205
206 static errval_t detach(struct bfdriver_instance *bfi)
207 {
208     return SYS_ERR_OK;
209 }
210
211 static errval_t set_sleep_level(struct bfdriver_instance *bfi, uint32_t level)
212 {
213     return SYS_ERR_OK;
214 }
215
216 static errval_t destroy(struct bfdriver_instance *bfi)
217 {
218     struct lpuart_t *spc = bfi->dstate;
219     free(spc);
220     bfi->dstate = NULL;
221     // XXX: Tear-down the service
222     bfi->device = 0x0;
223     return SYS_ERR_OK;
224 }
225
226 static errval_t get_ep(struct bfdriver_instance *bfi, bool lmp, struct capref *ret_cap)
227 {
228     USER_PANIC("NIY \n");
229     return SYS_ERR_OK;
230 }
231
232 DEFINE_MODULE(serial_lpuart, init, attach, detach, set_sleep_level, destroy, get_ep);