1/*	$NetBSD: zs.c,v 1.4 2024/05/03 21:38:15 andvar Exp $	*/
2
3/*-
4 * Copyright (c) 2008 Izumi Tsutsui. All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 * 1. Redistributions of source code must retain the above copyright
10 *    notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 *    notice, this list of conditions and the following disclaimer in the
13 *    documentation and/or other materials provided with the distribution.
14 *
15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
16 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
17 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
18 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
19 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
20 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
21 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
22 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
24 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25 */
26
27#ifdef CONS_ZS
28/*
29 * optional Z85C30 serial support for Qube 2700
30 */
31
32#include <lib/libsa/stand.h>
33#include <lib/libkern/libkern.h>
34
35#include <dev/ic/z8530reg.h>
36
37#include <machine/cpu.h>
38
39#include "boot.h"
40#include "zs.h"
41
42#define ZSCLOCK		11059200	/* 19200 * 576 */
43
44#define ZS_DELAY()	delay(2)
45
46static uint8_t zs_read(void *, uint8_t);
47static void zs_write(void *, uint8_t, uint8_t);
48static void zs_write_reg(void *, uint8_t, uint8_t);
49static void zs_reset(void *);
50
51static uint8_t
52zs_read(void *dev, uint8_t reg)
53{
54	volatile uint8_t *zs = dev;
55	uint8_t val;
56
57	val = *(volatile uint8_t *)(zs + reg);
58	ZS_DELAY();
59
60	return val;
61}
62
63static void
64zs_write(void *dev, uint8_t reg, uint8_t val)
65{
66	volatile uint8_t *zs = dev;
67
68        *(volatile uint8_t *)(zs + reg) = val;
69	ZS_DELAY();
70}
71
72static void
73zs_write_reg(void *dev, uint8_t reg, uint8_t val)
74{
75
76	zs_write(dev, ZS_CSR, reg);
77	zs_write(dev, ZS_CSR, val);
78}
79
80static void
81zs_reset(void *dev)
82{
83
84	/* clear errors */
85	zs_write_reg(dev,  9, 0);
86	/* hardware reset */
87	zs_write_reg(dev,  9, ZSWR9_HARD_RESET);
88	delay(1000);
89
90	/* disable all interrupts */
91	zs_write_reg(dev,  1, 0);
92
93	/* set TX/RX misc parameters and modes */
94	zs_write_reg(dev,  4, ZSWR4_CLK_X16 | ZSWR4_ONESB | ZSWR4_EVENP);
95	zs_write_reg(dev, 10, ZSWR10_NRZ);
96	zs_write_reg(dev,  3, ZSWR3_RX_8);
97	zs_write_reg(dev,  5, ZSWR5_TX_8 | ZSWR5_DTR | ZSWR5_RTS);
98
99	/* sync registers unused */
100	zs_write_reg(dev,  6, 0);
101	zs_write_reg(dev,  7, 0);
102
103	/* set baud rate generator mode */
104	zs_write_reg(dev, 14, ZSWR14_BAUD_FROM_PCLK);
105	/* set clock mode */
106	zs_write_reg(dev, 11, ZSWR11_RXCLK_BAUD | ZSWR11_TXCLK_BAUD);
107	/* set baud rate constant */
108	zs_write_reg(dev, 12, BPS_TO_TCONST(ZSCLOCK / 16, ZSSPEED));
109	zs_write_reg(dev, 13, 0);
110
111	/* enable baud rate generator */
112	zs_write_reg(dev, 14, ZSWR14_BAUD_FROM_PCLK | ZSWR14_BAUD_ENA);
113	/* disable all external interrupts */
114	zs_write_reg(dev, 15, 0);
115
116	/* reset external status twice (see src/sys/dev/ic/z8530sc.c) */
117	zs_write(dev, ZS_CSR, ZSWR0_RESET_STATUS);
118	zs_write(dev, ZS_CSR, ZSWR0_RESET_STATUS);
119
120	/* enable TX and RX */
121	zs_write_reg(dev,  3, ZSWR3_RX_8 | ZSWR3_RX_ENABLE);
122	zs_write_reg(dev,  5,
123	    ZSWR5_TX_8 | ZSWR5_DTR | ZSWR5_RTS | ZSWR5_TX_ENABLE);
124}
125
126void *
127zs_init(int addr, int speed)
128{
129	void *zs;
130
131	zs = (void *)MIPS_PHYS_TO_KSEG1(ZS_BASE + addr);
132	zs_reset(zs);
133
134	return zs;
135}
136
137void
138zs_putc(void *dev, int c)
139{
140	uint8_t csr;
141
142	do {
143		csr = zs_read(dev, ZS_CSR);
144	} while ((csr & ZSRR0_TX_READY) == 0);
145
146	zs_write(dev, ZS_DATA, c);
147}
148
149int
150zs_getc(void *dev)
151{
152	uint8_t csr, data;
153
154	do {
155		csr = zs_read(dev, ZS_CSR);
156	} while ((csr & ZSRR0_RX_READY) == 0);
157
158	data = zs_read(dev, ZS_DATA);
159	return data;
160}
161
162int
163zs_scan(void *dev)
164{
165	uint8_t csr, data;
166
167	csr = zs_read(dev, ZS_CSR);
168	if ((csr & ZSRR0_RX_READY) == 0)
169		return -1;
170
171	data = zs_read(dev, ZS_DATA);
172	return data;
173}
174#endif /* CONS_ZS */
175