| @@ -1,14 +1,14 @@ | | | @@ -1,14 +1,14 @@ |
1 | /* $NetBSD: amlogic_com.c,v 1.3 2015/03/01 23:39:28 jmcneill Exp $ */ | | 1 | /* $NetBSD: amlogic_com.c,v 1.4 2015/03/03 21:56:25 jmcneill Exp $ */ |
2 | | | 2 | |
3 | /*- | | 3 | /*- |
4 | * Copyright (c) 2013 The NetBSD Foundation, Inc. | | 4 | * Copyright (c) 2013 The NetBSD Foundation, Inc. |
5 | * All rights reserved. | | 5 | * All rights reserved. |
6 | * | | 6 | * |
7 | * This code is derived from software contributed to The NetBSD Foundation | | 7 | * This code is derived from software contributed to The NetBSD Foundation |
8 | * by Matt Thomas of 3am Software Foundry. | | 8 | * by Matt Thomas of 3am Software Foundry. |
9 | * | | 9 | * |
10 | * Redistribution and use in source and binary forms, with or without | | 10 | * Redistribution and use in source and binary forms, with or without |
11 | * modification, are permitted provided that the following conditions | | 11 | * modification, are permitted provided that the following conditions |
12 | * are met: | | 12 | * are met: |
13 | * 1. Redistributions of source code must retain the above copyright | | 13 | * 1. Redistributions of source code must retain the above copyright |
14 | * notice, this list of conditions and the following disclaimer. | | 14 | * notice, this list of conditions and the following disclaimer. |
| @@ -23,84 +23,73 @@ | | | @@ -23,84 +23,73 @@ |
23 | * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | | 23 | * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR |
24 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | | 24 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
25 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | | 25 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
26 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | | 26 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
27 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | | 27 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
28 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | | 28 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
29 | * POSSIBILITY OF SUCH DAMAGE. | | 29 | * POSSIBILITY OF SUCH DAMAGE. |
30 | */ | | 30 | */ |
31 | | | 31 | |
32 | #include "locators.h" | | 32 | #include "locators.h" |
33 | | | 33 | |
34 | #include <sys/cdefs.h> | | 34 | #include <sys/cdefs.h> |
35 | | | 35 | |
36 | __KERNEL_RCSID(1, "$NetBSD: amlogic_com.c,v 1.3 2015/03/01 23:39:28 jmcneill Exp $"); | | 36 | __KERNEL_RCSID(1, "$NetBSD: amlogic_com.c,v 1.4 2015/03/03 21:56:25 jmcneill Exp $"); |
37 | | | | |
38 | #define AMLOGIC_COM_INTRPOLL | | | |
39 | #define AMLOGIC_COM_INTRPOLL_RATE 10 | | | |
40 | | | 37 | |
41 | #include <sys/param.h> | | 38 | #include <sys/param.h> |
42 | #include <sys/bus.h> | | 39 | #include <sys/bus.h> |
43 | #include <sys/device.h> | | 40 | #include <sys/device.h> |
44 | #include <sys/conf.h> | | 41 | #include <sys/conf.h> |
45 | #include <sys/intr.h> | | 42 | #include <sys/intr.h> |
46 | #include <sys/systm.h> | | 43 | #include <sys/systm.h> |
47 | #include <sys/time.h> | | 44 | #include <sys/time.h> |
48 | #include <sys/termios.h> | | 45 | #include <sys/termios.h> |
49 | #include <sys/kauth.h> | | 46 | #include <sys/kauth.h> |
50 | #include <sys/lwp.h> | | 47 | #include <sys/lwp.h> |
51 | #include <sys/tty.h> | | 48 | #include <sys/tty.h> |
52 | | | 49 | |
53 | #include <dev/cons.h> | | 50 | #include <dev/cons.h> |
54 | | | 51 | |
55 | #include <arm/amlogic/amlogic_reg.h> | | 52 | #include <arm/amlogic/amlogic_reg.h> |
56 | #include <arm/amlogic/amlogic_var.h> | | 53 | #include <arm/amlogic/amlogic_var.h> |
57 | #include <arm/amlogic/amlogic_comreg.h> | | 54 | #include <arm/amlogic/amlogic_comreg.h> |
58 | #include <arm/amlogic/amlogic_comvar.h> | | 55 | #include <arm/amlogic/amlogic_comvar.h> |
59 | | | 56 | |
60 | static int amlogic_com_match(device_t, cfdata_t, void *); | | 57 | static int amlogic_com_match(device_t, cfdata_t, void *); |
61 | static void amlogic_com_attach(device_t, device_t, void *); | | 58 | static void amlogic_com_attach(device_t, device_t, void *); |
62 | | | 59 | |
63 | static int amlogic_com_intr(void *); | | 60 | static int amlogic_com_intr(void *); |
64 | | | 61 | |
65 | #ifdef AMLOGIC_COM_INTRPOLL | | | |
66 | static void amlogic_com_intrpoll(void *); | | | |
67 | #endif | | | |
68 | | | | |
69 | static int amlogic_com_cngetc(dev_t); | | 62 | static int amlogic_com_cngetc(dev_t); |
70 | static void amlogic_com_cnputc(dev_t, int); | | 63 | static void amlogic_com_cnputc(dev_t, int); |
71 | static void amlogic_com_cnpollc(dev_t, int); | | 64 | static void amlogic_com_cnpollc(dev_t, int); |
72 | | | 65 | |
73 | static void amlogic_com_start(struct tty *); | | 66 | static void amlogic_com_start(struct tty *); |
74 | static int amlogic_com_param(struct tty *, struct termios *); | | 67 | static int amlogic_com_param(struct tty *, struct termios *); |
75 | | | 68 | |
76 | extern struct cfdriver amlogiccom_cd; | | 69 | extern struct cfdriver amlogiccom_cd; |
77 | | | 70 | |
78 | struct amlogic_com_softc { | | 71 | struct amlogic_com_softc { |
79 | device_t sc_dev; | | 72 | device_t sc_dev; |
80 | bus_space_tag_t sc_bst; | | 73 | bus_space_tag_t sc_bst; |
81 | bus_space_handle_t sc_bsh; | | 74 | bus_space_handle_t sc_bsh; |
82 | void *sc_ih; | | 75 | void *sc_ih; |
83 | | | 76 | |
84 | struct tty *sc_tty; | | 77 | struct tty *sc_tty; |
85 | | | 78 | |
86 | int sc_ospeed; | | 79 | int sc_ospeed; |
87 | tcflag_t sc_cflag; | | 80 | tcflag_t sc_cflag; |
88 | | | 81 | |
89 | u_char sc_buf[1024]; | | 82 | u_char sc_buf[1024]; |
90 | | | | |
91 | #ifdef AMLOGIC_COM_INTRPOLL | | | |
92 | callout_t sc_intrpoll_ch; | | | |
93 | #endif | | | |
94 | }; | | 83 | }; |
95 | | | 84 | |
96 | static struct amlogic_com_softc amlogic_com_cnsc; | | 85 | static struct amlogic_com_softc amlogic_com_cnsc; |
97 | | | 86 | |
98 | static struct cnm_state amlogic_com_cnm_state; | | 87 | static struct cnm_state amlogic_com_cnm_state; |
99 | | | 88 | |
100 | struct consdev amlogic_com_consdev = { | | 89 | struct consdev amlogic_com_consdev = { |
101 | .cn_getc = amlogic_com_cngetc, | | 90 | .cn_getc = amlogic_com_cngetc, |
102 | .cn_putc = amlogic_com_cnputc, | | 91 | .cn_putc = amlogic_com_cnputc, |
103 | .cn_pollc = amlogic_com_cnpollc, | | 92 | .cn_pollc = amlogic_com_cnpollc, |
104 | .cn_dev = NODEV, | | 93 | .cn_dev = NODEV, |
105 | .cn_pri = CN_NORMAL, | | 94 | .cn_pri = CN_NORMAL, |
106 | }; | | 95 | }; |
| @@ -146,38 +135,33 @@ amlogic_com_attach(device_t parent, devi | | | @@ -146,38 +135,33 @@ amlogic_com_attach(device_t parent, devi |
146 | struct amlogic_com_softc * const sc = device_private(self); | | 135 | struct amlogic_com_softc * const sc = device_private(self); |
147 | struct amlogicio_attach_args * const aio = aux; | | 136 | struct amlogicio_attach_args * const aio = aux; |
148 | const struct amlogic_locators * const loc = &aio->aio_loc; | | 137 | const struct amlogic_locators * const loc = &aio->aio_loc; |
149 | const bus_addr_t iobase = AMLOGIC_CORE_BASE + loc->loc_offset; | | 138 | const bus_addr_t iobase = AMLOGIC_CORE_BASE + loc->loc_offset; |
150 | struct tty *tp; | | 139 | struct tty *tp; |
151 | int major, minor; | | 140 | int major, minor; |
152 | uint32_t misc, control; | | 141 | uint32_t misc, control; |
153 | | | 142 | |
154 | sc->sc_dev = self; | | 143 | sc->sc_dev = self; |
155 | sc->sc_bst = aio->aio_core_bst; | | 144 | sc->sc_bst = aio->aio_core_bst; |
156 | bus_space_subregion(aio->aio_core_bst, aio->aio_bsh, | | 145 | bus_space_subregion(aio->aio_core_bst, aio->aio_bsh, |
157 | loc->loc_offset, loc->loc_size, &sc->sc_bsh); | | 146 | loc->loc_offset, loc->loc_size, &sc->sc_bsh); |
158 | | | 147 | |
159 | #ifdef AMLOGIC_COM_INTRPOLL | | | |
160 | callout_init(&sc->sc_intrpoll_ch, CALLOUT_MPSAFE); | | | |
161 | callout_setfunc(&sc->sc_intrpoll_ch, amlogic_com_intrpoll, sc); | | | |
162 | #else | | | |
163 | sc->sc_ih = intr_establish(loc->loc_intr, IPL_SERIAL, | | 148 | sc->sc_ih = intr_establish(loc->loc_intr, IPL_SERIAL, |
164 | IST_EDGE | IST_MPSAFE, amlogic_com_intr, sc); | | 149 | IST_EDGE | IST_MPSAFE, amlogic_com_intr, sc); |
165 | if (sc->sc_ih == NULL) { | | 150 | if (sc->sc_ih == NULL) { |
166 | aprint_error(": failed to establish interrupt %d\n", | | 151 | aprint_error(": failed to establish interrupt %d\n", |
167 | loc->loc_intr); | | 152 | loc->loc_intr); |
168 | return; | | 153 | return; |
169 | } | | 154 | } |
170 | #endif | | | |
171 | | | 155 | |
172 | if (amlogic_com_cmajor == -1) { | | 156 | if (amlogic_com_cmajor == -1) { |
173 | /* allocate a major number */ | | 157 | /* allocate a major number */ |
174 | int bmajor = -1, cmajor = -1; | | 158 | int bmajor = -1, cmajor = -1; |
175 | int error = devsw_attach("amlogiccom", NULL, &bmajor, | | 159 | int error = devsw_attach("amlogiccom", NULL, &bmajor, |
176 | &amlogiccom_cdevsw, &cmajor); | | 160 | &amlogiccom_cdevsw, &cmajor); |
177 | if (error) { | | 161 | if (error) { |
178 | aprint_error(": couldn't allocate major number\n"); | | 162 | aprint_error(": couldn't allocate major number\n"); |
179 | return; | | 163 | return; |
180 | } | | 164 | } |
181 | amlogic_com_cmajor = cmajor; | | 165 | amlogic_com_cmajor = cmajor; |
182 | } | | 166 | } |
183 | | | 167 | |
| @@ -188,51 +172,39 @@ amlogic_com_attach(device_t parent, devi | | | @@ -188,51 +172,39 @@ amlogic_com_attach(device_t parent, devi |
188 | tp->t_oproc = amlogic_com_start; | | 172 | tp->t_oproc = amlogic_com_start; |
189 | tp->t_param = amlogic_com_param; | | 173 | tp->t_param = amlogic_com_param; |
190 | tp->t_dev = makedev(major, minor); | | 174 | tp->t_dev = makedev(major, minor); |
191 | tp->t_sc = sc; | | 175 | tp->t_sc = sc; |
192 | tty_attach(tp); | | 176 | tty_attach(tp); |
193 | | | 177 | |
194 | aprint_naive("\n"); | | 178 | aprint_naive("\n"); |
195 | if (amlogic_com_is_console(iobase)) { | | 179 | if (amlogic_com_is_console(iobase)) { |
196 | cn_tab->cn_dev = tp->t_dev; | | 180 | cn_tab->cn_dev = tp->t_dev; |
197 | aprint_normal(": console"); | | 181 | aprint_normal(": console"); |
198 | } | | 182 | } |
199 | aprint_normal("\n"); | | 183 | aprint_normal("\n"); |
200 | | | 184 | |
201 | #ifdef AMLOGIC_COM_INTRPOLL | | | |
202 | aprint_normal_dev(self, "polling\n"); | | | |
203 | #else | | | |
204 | aprint_normal_dev(self, "interrupting at irq %d\n", loc->loc_intr); | | 185 | aprint_normal_dev(self, "interrupting at irq %d\n", loc->loc_intr); |
205 | #endif | | | |
206 | | | 186 | |
207 | misc = bus_space_read_4(sc->sc_bst, sc->sc_bsh, UART_MISC_REG); | | 187 | misc = bus_space_read_4(sc->sc_bst, sc->sc_bsh, UART_MISC_REG); |
208 | misc &= ~UART_MISC_TX_IRQ_CNT; | | 188 | misc &= ~UART_MISC_TX_IRQ_CNT; |
209 | misc |= __SHIFTIN(0, UART_MISC_TX_IRQ_CNT); | | 189 | misc |= __SHIFTIN(0, UART_MISC_TX_IRQ_CNT); |
210 | misc &= ~UART_MISC_RX_IRQ_CNT; | | 190 | misc &= ~UART_MISC_RX_IRQ_CNT; |
211 | misc |= __SHIFTIN(1, UART_MISC_RX_IRQ_CNT); | | 191 | misc |= __SHIFTIN(1, UART_MISC_RX_IRQ_CNT); |
212 | bus_space_write_4(sc->sc_bst, sc->sc_bsh, UART_MISC_REG, misc); | | 192 | bus_space_write_4(sc->sc_bst, sc->sc_bsh, UART_MISC_REG, misc); |
213 | | | 193 | |
214 | control = bus_space_read_4(sc->sc_bst, sc->sc_bsh, UART_CONTROL_REG); | | 194 | control = bus_space_read_4(sc->sc_bst, sc->sc_bsh, UART_CONTROL_REG); |
215 | control &= ~UART_CONTROL_TX_INT_EN; | | 195 | control &= ~UART_CONTROL_TX_INT_EN; |
216 | #ifdef AMLOGIC_COM_INTRPOLL | | | |
217 | control &= ~UART_CONTROL_RX_INT_EN; | | | |
218 | #else | | | |
219 | control |= UART_CONTROL_RX_INT_EN; | | 196 | control |= UART_CONTROL_RX_INT_EN; |
220 | #endif | | | |
221 | bus_space_write_4(sc->sc_bst, sc->sc_bsh, UART_CONTROL_REG, control); | | 197 | bus_space_write_4(sc->sc_bst, sc->sc_bsh, UART_CONTROL_REG, control); |
222 | | | | |
223 | #ifdef AMLOGIC_COM_INTRPOLL | | | |
224 | callout_schedule(&sc->sc_intrpoll_ch, AMLOGIC_COM_INTRPOLL_RATE); | | | |
225 | #endif | | | |
226 | } | | 198 | } |
227 | | | 199 | |
228 | static int | | 200 | static int |
229 | amlogic_com_cngetc(dev_t dev) | | 201 | amlogic_com_cngetc(dev_t dev) |
230 | { | | 202 | { |
231 | bus_space_tag_t bst = amlogic_com_cnsc.sc_bst; | | 203 | bus_space_tag_t bst = amlogic_com_cnsc.sc_bst; |
232 | bus_space_handle_t bsh = amlogic_com_cnsc.sc_bsh; | | 204 | bus_space_handle_t bsh = amlogic_com_cnsc.sc_bsh; |
233 | uint32_t status; | | 205 | uint32_t status; |
234 | int s, c; | | 206 | int s, c; |
235 | | | 207 | |
236 | s = splserial(); | | 208 | s = splserial(); |
237 | | | 209 | |
238 | status = bus_space_read_4(bst, bsh, UART_STATUS_REG); | | 210 | status = bus_space_read_4(bst, bsh, UART_STATUS_REG); |
| @@ -461,28 +433,13 @@ amlogic_com_intr(void *priv) | | | @@ -461,28 +433,13 @@ amlogic_com_intr(void *priv) |
461 | status = bus_space_read_4(sc->sc_bst, sc->sc_bsh, | | 433 | status = bus_space_read_4(sc->sc_bst, sc->sc_bsh, |
462 | UART_STATUS_REG); | | 434 | UART_STATUS_REG); |
463 | if (status & UART_STATUS_RX_EMPTY) { | | 435 | if (status & UART_STATUS_RX_EMPTY) { |
464 | break; | | 436 | break; |
465 | } | | 437 | } |
466 | | | 438 | |
467 | c = bus_space_read_4(sc->sc_bst, sc->sc_bsh, UART_RFIFO_REG); | | 439 | c = bus_space_read_4(sc->sc_bst, sc->sc_bsh, UART_RFIFO_REG); |
468 | cn_check_magic(tp->t_dev, c, amlogic_com_cnm_state); | | 440 | cn_check_magic(tp->t_dev, c, amlogic_com_cnm_state); |
469 | tp->t_linesw->l_rint(c & 0xff, tp); | | 441 | tp->t_linesw->l_rint(c & 0xff, tp); |
470 | } | | 442 | } |
471 | | | 443 | |
472 | return 0; | | 444 | return 0; |
473 | } | | 445 | } |
474 | | | | |
475 | #ifdef AMLOGIC_COM_INTRPOLL | | | |
476 | static void | | | |
477 | amlogic_com_intrpoll(void *priv) | | | |
478 | { | | | |
479 | struct amlogic_com_softc *sc = priv; | | | |
480 | int s; | | | |
481 | | | | |
482 | s = splserial(); | | | |
483 | amlogic_com_intr(sc); | | | |
484 | splx(s); | | | |
485 | | | | |
486 | callout_schedule(&sc->sc_intrpoll_ch, AMLOGIC_COM_INTRPOLL_RATE); | | | |
487 | } | | | |
488 | #endif | | | |