1a9643ea8Slogwang /*-
2a9643ea8Slogwang * Copyright (c) 2016 Michael Zhilin <[email protected]>
3a9643ea8Slogwang *
4a9643ea8Slogwang * All rights reserved.
5a9643ea8Slogwang *
6a9643ea8Slogwang * Redistribution and use in source and binary forms, with or without
7a9643ea8Slogwang * modification, are permitted provided that the following conditions
8a9643ea8Slogwang * are met:
9a9643ea8Slogwang * 1. Redistributions of source code must retain the above copyright
10a9643ea8Slogwang * notice, this list of conditions and the following disclaimer.
11a9643ea8Slogwang * 2. Redistributions in binary form must reproduce the above copyright
12a9643ea8Slogwang * notice, this list of conditions and the following disclaimer in the
13a9643ea8Slogwang * documentation and/or other materials provided with the distribution.
14a9643ea8Slogwang *
15a9643ea8Slogwang * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16a9643ea8Slogwang * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17a9643ea8Slogwang * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18a9643ea8Slogwang * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19a9643ea8Slogwang * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20a9643ea8Slogwang * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21a9643ea8Slogwang * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22a9643ea8Slogwang * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23a9643ea8Slogwang * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24a9643ea8Slogwang * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25a9643ea8Slogwang * SUCH DAMAGE.
26a9643ea8Slogwang */
27a9643ea8Slogwang
28a9643ea8Slogwang #include <sys/cdefs.h>
29a9643ea8Slogwang __FBSDID("$FreeBSD$");
30a9643ea8Slogwang
31a9643ea8Slogwang #include "opt_uart.h"
32a9643ea8Slogwang
33a9643ea8Slogwang #include <sys/param.h>
34a9643ea8Slogwang #include <sys/systm.h>
35a9643ea8Slogwang #include <sys/bus.h>
36a9643ea8Slogwang #include <sys/cons.h>
37a9643ea8Slogwang #include <sys/lock.h>
38a9643ea8Slogwang #include <sys/mutex.h>
39a9643ea8Slogwang
40a9643ea8Slogwang #include <machine/bus.h>
41a9643ea8Slogwang
42a9643ea8Slogwang #include <dev/bhnd/cores/chipc/chipcreg.h>
43a9643ea8Slogwang
44a9643ea8Slogwang #include <dev/uart/uart.h>
45a9643ea8Slogwang #include <dev/uart/uart_bus.h>
46a9643ea8Slogwang #include <dev/uart/uart_cpu.h>
47a9643ea8Slogwang
48*22ce4affSfengbojiang #ifdef CFE
49*22ce4affSfengbojiang #include <dev/cfe/cfe_api.h>
50*22ce4affSfengbojiang #include <dev/cfe/cfe_ioctl.h>
51*22ce4affSfengbojiang #include <dev/cfe/cfe_error.h>
52*22ce4affSfengbojiang #endif
53*22ce4affSfengbojiang
54*22ce4affSfengbojiang #include "bcm_machdep.h"
55a9643ea8Slogwang
56a9643ea8Slogwang bus_space_tag_t uart_bus_space_io;
57a9643ea8Slogwang bus_space_tag_t uart_bus_space_mem;
58a9643ea8Slogwang
59a9643ea8Slogwang static struct uart_class *chipc_uart_class = &uart_ns8250_class;
60a9643ea8Slogwang
61a9643ea8Slogwang #define CHIPC_UART_BAUDRATE 115200
62a9643ea8Slogwang
63a9643ea8Slogwang int
uart_cpu_eqres(struct uart_bas * b1,struct uart_bas * b2)64a9643ea8Slogwang uart_cpu_eqres(struct uart_bas *b1, struct uart_bas *b2)
65a9643ea8Slogwang {
66a9643ea8Slogwang return ((b1->bsh == b2->bsh && b1->bst == b2->bst) ? 1 : 0);
67a9643ea8Slogwang }
68a9643ea8Slogwang
69a9643ea8Slogwang static int
uart_cpu_init(struct uart_devinfo * di,u_int uart,int baudrate)70*22ce4affSfengbojiang uart_cpu_init(struct uart_devinfo *di, u_int uart, int baudrate)
71a9643ea8Slogwang {
72a9643ea8Slogwang if (uart >= CHIPC_UART_MAX)
73a9643ea8Slogwang return (EINVAL);
74a9643ea8Slogwang
75a9643ea8Slogwang di->ops = uart_getops(chipc_uart_class);
76a9643ea8Slogwang di->bas.chan = 0;
77a9643ea8Slogwang di->bas.bst = uart_bus_space_mem;
78*22ce4affSfengbojiang di->bas.bsh = (bus_space_handle_t) BCM_CORE_ADDR(bcm_get_platform(),
79*22ce4affSfengbojiang cc_addr, CHIPC_UART(uart));
80a9643ea8Slogwang di->bas.regshft = 0;
81*22ce4affSfengbojiang di->bas.rclk = bcm_get_uart_rclk(bcm_get_platform());
82a9643ea8Slogwang di->baudrate = baudrate;
83a9643ea8Slogwang di->databits = 8;
84a9643ea8Slogwang di->stopbits = 1;
85a9643ea8Slogwang di->parity = UART_PARITY_NONE;
86a9643ea8Slogwang
87a9643ea8Slogwang return (0);
88a9643ea8Slogwang }
89a9643ea8Slogwang
90*22ce4affSfengbojiang #ifdef CFE
91*22ce4affSfengbojiang static int
uart_getenv_cfe(int devtype,struct uart_devinfo * di)92*22ce4affSfengbojiang uart_getenv_cfe(int devtype, struct uart_devinfo *di)
93*22ce4affSfengbojiang {
94*22ce4affSfengbojiang char device[sizeof("uartXX")];
95*22ce4affSfengbojiang int baud, fd, len;
96*22ce4affSfengbojiang int ret;
97*22ce4affSfengbojiang u_int uart;
98*22ce4affSfengbojiang
99*22ce4affSfengbojiang /* CFE only vends console configuration */
100*22ce4affSfengbojiang if (devtype != UART_DEV_CONSOLE)
101*22ce4affSfengbojiang return (ENODEV);
102*22ce4affSfengbojiang
103*22ce4affSfengbojiang /* Fetch console device */
104*22ce4affSfengbojiang ret = cfe_getenv("BOOT_CONSOLE", device, sizeof(device));
105*22ce4affSfengbojiang if (ret != CFE_OK)
106*22ce4affSfengbojiang return (ENXIO);
107*22ce4affSfengbojiang
108*22ce4affSfengbojiang /* Parse serial console unit. Fails on non-uart devices. */
109*22ce4affSfengbojiang if (sscanf(device, "uart%u", &uart) != 1)
110*22ce4affSfengbojiang return (ENXIO);
111*22ce4affSfengbojiang
112*22ce4affSfengbojiang /* Fetch device handle */
113*22ce4affSfengbojiang fd = bcm_get_platform()->cfe_console;
114*22ce4affSfengbojiang if (fd < 0)
115*22ce4affSfengbojiang return (ENXIO);
116*22ce4affSfengbojiang
117*22ce4affSfengbojiang /* Fetch serial configuration */
118*22ce4affSfengbojiang ret = cfe_ioctl(fd, IOCTL_SERIAL_GETSPEED, (unsigned char *)&baud,
119*22ce4affSfengbojiang sizeof(baud), &len, 0);
120*22ce4affSfengbojiang if (ret != CFE_OK)
121*22ce4affSfengbojiang baud = CHIPC_UART_BAUDRATE;
122*22ce4affSfengbojiang
123*22ce4affSfengbojiang /* Initialize device info */
124*22ce4affSfengbojiang return (uart_cpu_init(di, uart, baud));
125*22ce4affSfengbojiang }
126*22ce4affSfengbojiang #endif /* CFE */
127*22ce4affSfengbojiang
128a9643ea8Slogwang int
uart_cpu_getdev(int devtype,struct uart_devinfo * di)129a9643ea8Slogwang uart_cpu_getdev(int devtype, struct uart_devinfo *di)
130a9643ea8Slogwang {
131a9643ea8Slogwang int ivar;
132a9643ea8Slogwang
133a9643ea8Slogwang uart_bus_space_io = NULL;
134a9643ea8Slogwang uart_bus_space_mem = mips_bus_space_generic;
135a9643ea8Slogwang
136*22ce4affSfengbojiang #ifdef CFE
137*22ce4affSfengbojiang /* Check the CFE environment */
138*22ce4affSfengbojiang if (uart_getenv_cfe(devtype, di) == 0)
139*22ce4affSfengbojiang return (0);
140*22ce4affSfengbojiang #endif /* CFE */
141*22ce4affSfengbojiang
142*22ce4affSfengbojiang /* Check the kernel environment. */
143a9643ea8Slogwang if (uart_getenv(devtype, di, chipc_uart_class) == 0)
144a9643ea8Slogwang return (0);
145a9643ea8Slogwang
146a9643ea8Slogwang /* Scan the device hints for the first matching device */
147*22ce4affSfengbojiang for (u_int i = 0; i < CHIPC_UART_MAX; i++) {
148a9643ea8Slogwang if (resource_int_value("uart", i, "flags", &ivar))
149a9643ea8Slogwang continue;
150a9643ea8Slogwang
151a9643ea8Slogwang /* Check usability */
152a9643ea8Slogwang if (devtype == UART_DEV_CONSOLE && !UART_FLAGS_CONSOLE(ivar))
153a9643ea8Slogwang continue;
154a9643ea8Slogwang
155a9643ea8Slogwang if (devtype == UART_DEV_DBGPORT && !UART_FLAGS_DBGPORT(ivar))
156a9643ea8Slogwang continue;
157a9643ea8Slogwang
158a9643ea8Slogwang if (resource_int_value("uart", i, "disabled", &ivar) == 0 &&
159a9643ea8Slogwang ivar == 0)
160a9643ea8Slogwang continue;
161a9643ea8Slogwang
162a9643ea8Slogwang /* Found */
163a9643ea8Slogwang if (resource_int_value("uart", i, "baud", &ivar) != 0)
164a9643ea8Slogwang ivar = CHIPC_UART_BAUDRATE;
165a9643ea8Slogwang
166a9643ea8Slogwang return (uart_cpu_init(di, i, ivar));
167a9643ea8Slogwang }
168a9643ea8Slogwang
169a9643ea8Slogwang /* Default to uart0/115200 */
170a9643ea8Slogwang return (uart_cpu_init(di, 0, CHIPC_UART_BAUDRATE));
171a9643ea8Slogwang }
172