1/*-
2 * SPDX-License-Identifier: BSD-2-Clause
3 *
4 * Copyright (c) 2006 Juniper Networks
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 *
11 * 1. Redistributions of source code must retain the above copyright
12 *    notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 *    notice, this list of conditions and the following disclaimer in the
15 *    documentation and/or other materials provided with the distribution.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
29#include <sys/param.h>
30#include <sys/systm.h>
31#include <sys/bus.h>
32#include <sys/conf.h>
33#include <sys/endian.h>
34#include <machine/bus.h>
35
36#include <dev/ic/quicc.h>
37
38#include <dev/uart/uart.h>
39#include <dev/uart/uart_cpu.h>
40#include <dev/uart/uart_bus.h>
41
42#include "uart_if.h"
43
44#define	DEFAULT_RCLK	((266000000 * 2) / 16)
45
46#define	quicc_read2(bas, reg)		\
47	bus_space_read_2((bas)->bst, (bas)->bsh, reg)
48#define	quicc_read4(bas, reg)		\
49	bus_space_read_4((bas)->bst, (bas)->bsh, reg)
50
51#define	quicc_write2(bas, reg, val)	\
52	bus_space_write_2((bas)->bst, (bas)->bsh, reg, val)
53#define	quicc_write4(bas, reg, val)	\
54	bus_space_write_4((bas)->bst, (bas)->bsh, reg, val)
55
56static int
57quicc_divisor(int rclk, int baudrate)
58{
59	int act_baud, divisor, error;
60
61	if (baudrate == 0)
62		return (-1);
63
64	divisor = rclk / baudrate / 16;
65	if (divisor > 4096)
66		divisor = ((divisor >> 3) - 2) | 1;
67	else if (divisor >= 0)
68		divisor = (divisor - 1) << 1;
69	if (divisor < 0 || divisor >= 8192)
70		return (-1);
71	act_baud = rclk / (((divisor >> 1) + 1) << ((divisor & 1) ? 8 : 4));
72
73	/* 10 times error in percent: */
74	error = ((act_baud - baudrate) * 2000 / baudrate + 1) >> 1;
75
76	/* 3.0% maximum error tolerance: */
77	if (error < -30 || error > 30)
78		return (-1);
79
80	return (divisor);
81}
82
83static int
84quicc_param(struct uart_bas *bas, int baudrate, int databits, int stopbits,
85    int parity)
86{
87	int divisor;
88	uint16_t psmr;
89
90	if (baudrate > 0) {
91		divisor = quicc_divisor(bas->rclk, baudrate);
92		if (divisor == -1)
93			return (EINVAL);
94		quicc_write4(bas, QUICC_REG_BRG(bas->chan - 1),
95		    divisor | 0x10000);
96	}
97
98	psmr = 0;
99	switch (databits) {
100	case 5:		psmr |= 0x0000; break;
101	case 6:		psmr |= 0x1000; break;
102	case 7:		psmr |= 0x2000; break;
103	case 8:		psmr |= 0x3000; break;
104	default:	return (EINVAL);
105	}
106	switch (stopbits) {
107	case 1:		psmr |= 0x0000; break;
108	case 2:		psmr |= 0x4000; break;
109	default:	return (EINVAL);
110	}
111	switch (parity) {
112	case UART_PARITY_EVEN:	psmr |= 0x1a; break;
113	case UART_PARITY_MARK:	psmr |= 0x1f; break;
114	case UART_PARITY_NONE:	psmr |= 0x00; break;
115	case UART_PARITY_ODD:	psmr |= 0x10; break;
116	case UART_PARITY_SPACE:	psmr |= 0x15; break;
117	default:		return (EINVAL);
118	}
119	quicc_write2(bas, QUICC_REG_SCC_PSMR(bas->chan - 1), psmr);
120	return (0);
121}
122
123static void
124quicc_setup(struct uart_bas *bas, int baudrate, int databits, int stopbits,
125    int parity)
126{
127
128	if (bas->rclk == 0)
129		bas->rclk = DEFAULT_RCLK;
130
131	/*
132	 * GSMR_L = 0x00028034
133	 * GSMR_H = 0x00000020
134	 */
135	quicc_param(bas, baudrate, databits, stopbits, parity);
136
137	quicc_write2(bas, QUICC_REG_SCC_SCCE(bas->chan - 1), ~0);
138	quicc_write2(bas, QUICC_REG_SCC_SCCM(bas->chan - 1), 0x0027);
139}
140
141/*
142 * Low-level UART interface.
143 */
144static int quicc_probe(struct uart_bas *bas);
145static void quicc_init(struct uart_bas *bas, int, int, int, int);
146static void quicc_term(struct uart_bas *bas);
147static void quicc_putc(struct uart_bas *bas, int);
148static int quicc_rxready(struct uart_bas *bas);
149static int quicc_getc(struct uart_bas *bas, struct mtx *);
150
151static struct uart_ops uart_quicc_ops = {
152	.probe = quicc_probe,
153	.init = quicc_init,
154	.term = quicc_term,
155	.putc = quicc_putc,
156	.rxready = quicc_rxready,
157	.getc = quicc_getc,
158};
159
160static int
161quicc_probe(struct uart_bas *bas)
162{
163
164	return (0);
165}
166
167static void
168quicc_init(struct uart_bas *bas, int baudrate, int databits, int stopbits,
169    int parity)
170{
171
172	quicc_setup(bas, baudrate, databits, stopbits, parity);
173}
174
175static void
176quicc_term(struct uart_bas *bas)
177{
178}
179
180static void
181quicc_putc(struct uart_bas *bas, int c)
182{
183	int unit;
184	uint16_t toseq;
185
186	unit = bas->chan - 1;
187	while (quicc_read2(bas, QUICC_PRAM_SCC_UART_TOSEQ(unit)) & 0x2000)
188		DELAY(10);
189
190	toseq = 0x2000 | (c & 0xff);
191	quicc_write2(bas, QUICC_PRAM_SCC_UART_TOSEQ(unit), toseq);
192}
193
194static int
195quicc_rxready(struct uart_bas *bas)
196{
197	uint16_t rb;
198
199	rb = quicc_read2(bas, QUICC_PRAM_SCC_RBASE(bas->chan - 1));
200	return ((quicc_read2(bas, rb) & 0x8000) ? 0 : 1);
201}
202
203static int
204quicc_getc(struct uart_bas *bas, struct mtx *hwmtx)
205{
206	volatile char *buf;
207	int c;
208	uint16_t rb, sc;
209
210	uart_lock(hwmtx);
211
212	rb = quicc_read2(bas, QUICC_PRAM_SCC_RBASE(bas->chan - 1));
213
214	while ((sc = quicc_read2(bas, rb)) & 0x8000) {
215		uart_unlock(hwmtx);
216		DELAY(4);
217		uart_lock(hwmtx);
218	}
219
220	buf = (void *)(uintptr_t)quicc_read4(bas, rb + 4);
221	c = *buf;
222	quicc_write2(bas, rb, sc | 0x8000);
223
224	uart_unlock(hwmtx);
225
226	return (c);
227}
228
229/*
230 * High-level UART interface.
231 */
232struct quicc_softc {
233	struct uart_softc base;
234};
235
236static int quicc_bus_attach(struct uart_softc *);
237static int quicc_bus_detach(struct uart_softc *);
238static int quicc_bus_flush(struct uart_softc *, int);
239static int quicc_bus_getsig(struct uart_softc *);
240static int quicc_bus_ioctl(struct uart_softc *, int, intptr_t);
241static int quicc_bus_ipend(struct uart_softc *);
242static int quicc_bus_param(struct uart_softc *, int, int, int, int);
243static int quicc_bus_probe(struct uart_softc *);
244static int quicc_bus_receive(struct uart_softc *);
245static int quicc_bus_setsig(struct uart_softc *, int);
246static int quicc_bus_transmit(struct uart_softc *);
247static void quicc_bus_grab(struct uart_softc *);
248static void quicc_bus_ungrab(struct uart_softc *);
249
250static kobj_method_t quicc_methods[] = {
251	KOBJMETHOD(uart_attach,		quicc_bus_attach),
252	KOBJMETHOD(uart_detach,		quicc_bus_detach),
253	KOBJMETHOD(uart_flush,		quicc_bus_flush),
254	KOBJMETHOD(uart_getsig,		quicc_bus_getsig),
255	KOBJMETHOD(uart_ioctl,		quicc_bus_ioctl),
256	KOBJMETHOD(uart_ipend,		quicc_bus_ipend),
257	KOBJMETHOD(uart_param,		quicc_bus_param),
258	KOBJMETHOD(uart_probe,		quicc_bus_probe),
259	KOBJMETHOD(uart_receive,	quicc_bus_receive),
260	KOBJMETHOD(uart_setsig,		quicc_bus_setsig),
261	KOBJMETHOD(uart_transmit,	quicc_bus_transmit),
262	KOBJMETHOD(uart_grab,		quicc_bus_grab),
263	KOBJMETHOD(uart_ungrab,		quicc_bus_ungrab),
264	{ 0, 0 }
265};
266
267struct uart_class uart_quicc_class = {
268	"quicc",
269	quicc_methods,
270	sizeof(struct quicc_softc),
271	.uc_ops = &uart_quicc_ops,
272	.uc_range = 2,
273	.uc_rclk = DEFAULT_RCLK,
274	.uc_rshift = 0
275};
276UART_CLASS(uart_quicc_class);
277
278#define	SIGCHG(c, i, s, d)				\
279	if (c) {					\
280		i |= (i & s) ? s : s | d;		\
281	} else {					\
282		i = (i & s) ? (i & ~s) | d : i;		\
283	}
284
285static int
286quicc_bus_attach(struct uart_softc *sc)
287{
288	struct uart_bas *bas;
289	struct uart_devinfo *di;
290	uint16_t st, rb;
291
292	bas = &sc->sc_bas;
293	if (sc->sc_sysdev != NULL) {
294		di = sc->sc_sysdev;
295		quicc_param(bas, di->baudrate, di->databits, di->stopbits,
296		    di->parity);
297	} else {
298		quicc_setup(bas, 9600, 8, 1, UART_PARITY_NONE);
299	}
300
301	/* Enable interrupts on the receive buffer. */
302	rb = quicc_read2(bas, QUICC_PRAM_SCC_RBASE(bas->chan - 1));
303	st = quicc_read2(bas, rb);
304	quicc_write2(bas, rb, st | 0x9000);
305
306	(void)quicc_bus_getsig(sc);
307
308	return (0);
309}
310
311static int
312quicc_bus_detach(struct uart_softc *sc)
313{
314
315	return (0);
316}
317
318static int
319quicc_bus_flush(struct uart_softc *sc, int what)
320{
321
322	return (0);
323}
324
325static int
326quicc_bus_getsig(struct uart_softc *sc)
327{
328	uint32_t new, old, sig;
329	uint32_t dummy;
330
331	do {
332		old = sc->sc_hwsig;
333		sig = old;
334		uart_lock(sc->sc_hwmtx);
335		/* XXX SIGNALS */
336		dummy = 0;
337		uart_unlock(sc->sc_hwmtx);
338		SIGCHG(dummy, sig, SER_CTS, SER_DCTS);
339		SIGCHG(dummy, sig, SER_DCD, SER_DDCD);
340		SIGCHG(dummy, sig, SER_DSR, SER_DDSR);
341		new = sig & ~SER_MASK_DELTA;
342	} while (!atomic_cmpset_32(&sc->sc_hwsig, old, new));
343	return (sig);
344}
345
346static int
347quicc_bus_ioctl(struct uart_softc *sc, int request, intptr_t data)
348{
349	struct uart_bas *bas;
350	uint32_t brg;
351	int baudrate, error;
352
353	bas = &sc->sc_bas;
354	error = 0;
355	uart_lock(sc->sc_hwmtx);
356	switch (request) {
357	case UART_IOCTL_BREAK:
358		break;
359	case UART_IOCTL_BAUD:
360		brg = quicc_read4(bas, QUICC_REG_BRG(bas->chan - 1)) & 0x1fff;
361		brg = (brg & 1) ? (brg + 1) << 3 : (brg + 2) >> 1;
362		baudrate = bas->rclk / (brg * 16);
363		*(int*)data = baudrate;
364		break;
365	default:
366		error = EINVAL;
367		break;
368	}
369	uart_unlock(sc->sc_hwmtx);
370	return (error);
371}
372
373static int
374quicc_bus_ipend(struct uart_softc *sc)
375{
376	struct uart_bas *bas;
377	int ipend;
378	uint16_t scce;
379
380	bas = &sc->sc_bas;
381	ipend = 0;
382
383	uart_lock(sc->sc_hwmtx);
384	scce = quicc_read2(bas, QUICC_REG_SCC_SCCE(bas->chan - 1));
385	quicc_write2(bas, QUICC_REG_SCC_SCCE(bas->chan - 1), ~0);
386	uart_unlock(sc->sc_hwmtx);
387	if (scce & 0x0001)
388		ipend |= SER_INT_RXREADY;
389	if (scce & 0x0002)
390		ipend |= SER_INT_TXIDLE;
391	if (scce & 0x0004)
392		ipend |= SER_INT_OVERRUN;
393	if (scce & 0x0020)
394		ipend |= SER_INT_BREAK;
395	/* XXX SIGNALS */
396	return (ipend);
397}
398
399static int
400quicc_bus_param(struct uart_softc *sc, int baudrate, int databits,
401    int stopbits, int parity)
402{
403	int error;
404
405	uart_lock(sc->sc_hwmtx);
406	error = quicc_param(&sc->sc_bas, baudrate, databits, stopbits,
407	    parity);
408	uart_unlock(sc->sc_hwmtx);
409	return (error);
410}
411
412static int
413quicc_bus_probe(struct uart_softc *sc)
414{
415	int error;
416
417	error = quicc_probe(&sc->sc_bas);
418	if (error)
419		return (error);
420
421	sc->sc_rxfifosz = 1;
422	sc->sc_txfifosz = 1;
423
424	device_set_descf(sc->sc_dev, "quicc, channel %d", sc->sc_bas.chan);
425	return (0);
426}
427
428static int
429quicc_bus_receive(struct uart_softc *sc)
430{
431	struct uart_bas *bas;
432	volatile char *buf;
433	uint16_t st, rb;
434
435	bas = &sc->sc_bas;
436	uart_lock(sc->sc_hwmtx);
437	rb = quicc_read2(bas, QUICC_PRAM_SCC_RBASE(bas->chan - 1));
438	st = quicc_read2(bas, rb);
439	buf = (void *)(uintptr_t)quicc_read4(bas, rb + 4);
440	uart_rx_put(sc, *buf);
441	quicc_write2(bas, rb, st | 0x9000);
442	uart_unlock(sc->sc_hwmtx);
443	return (0);
444}
445
446static int
447quicc_bus_setsig(struct uart_softc *sc, int sig)
448{
449	uint32_t new, old;
450
451	do {
452		old = sc->sc_hwsig;
453		new = old;
454		if (sig & SER_DDTR) {
455			SIGCHG(sig & SER_DTR, new, SER_DTR,
456			    SER_DDTR);
457		}
458		if (sig & SER_DRTS) {
459			SIGCHG(sig & SER_RTS, new, SER_RTS,
460			    SER_DRTS);
461		}
462	} while (!atomic_cmpset_32(&sc->sc_hwsig, old, new));
463
464	uart_lock(sc->sc_hwmtx);
465	/* XXX SIGNALS */
466	uart_unlock(sc->sc_hwmtx);
467	return (0);
468}
469
470static int
471quicc_bus_transmit(struct uart_softc *sc)
472{
473	volatile char *buf;
474	struct uart_bas *bas;
475	uint16_t st, tb;
476
477	bas = &sc->sc_bas;
478	uart_lock(sc->sc_hwmtx);
479	tb = quicc_read2(bas, QUICC_PRAM_SCC_TBASE(bas->chan - 1));
480	st = quicc_read2(bas, tb);
481	buf = (void *)(uintptr_t)quicc_read4(bas, tb + 4);
482	*buf = sc->sc_txbuf[0];
483	quicc_write2(bas, tb + 2, 1);
484	quicc_write2(bas, tb, st | 0x9000);
485	sc->sc_txbusy = 1;
486	uart_unlock(sc->sc_hwmtx);
487	return (0);
488}
489
490static void
491quicc_bus_grab(struct uart_softc *sc)
492{
493	struct uart_bas *bas;
494	uint16_t st, rb;
495
496	/* Disable interrupts on the receive buffer. */
497	bas = &sc->sc_bas;
498	uart_lock(sc->sc_hwmtx);
499	rb = quicc_read2(bas, QUICC_PRAM_SCC_RBASE(bas->chan - 1));
500	st = quicc_read2(bas, rb);
501	quicc_write2(bas, rb, st & ~0x9000);
502	uart_unlock(sc->sc_hwmtx);
503}
504
505static void
506quicc_bus_ungrab(struct uart_softc *sc)
507{
508	struct uart_bas *bas;
509	uint16_t st, rb;
510
511	/* Enable interrupts on the receive buffer. */
512	bas = &sc->sc_bas;
513	uart_lock(sc->sc_hwmtx);
514	rb = quicc_read2(bas, QUICC_PRAM_SCC_RBASE(bas->chan - 1));
515	st = quicc_read2(bas, rb);
516	quicc_write2(bas, rb, st | 0x9000);
517	uart_unlock(sc->sc_hwmtx);
518}
519