1 /* $NetBSD: stasc.c,v 1.3 2024/02/08 10:30:25 andvar Exp $ */
2 /*
3 * Copyright (c) 2020 Valery Ushakov
4 * 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 /*
28 * STMicroelectronics ST40 Asynchronous Serial Controller
29 */
30 #include <sys/cdefs.h>
31 __KERNEL_RCSID(0, "$NetBSD: stasc.c,v 1.3 2024/02/08 10:30:25 andvar Exp $");
32
33 #include <sys/param.h>
34 #include <sys/systm.h>
35 #include <sys/conf.h>
36 #include <sys/device.h>
37 #include <sys/kernel.h>
38
39 #include <dev/cons.h>
40
41
42 #define STM_ASC_BASE 0xfd032000
43
44 #define ASC_BAUDRATE_OFFSET 0x00
45 #define ASC_TX_BUFF_OFFSET 0x04
46 #define ASC_RX_BUFF_OFFSET 0x08
47 #define ASC_CTRL_OFFSET 0x0C
48 #define ASC_INT_EN_OFFSET 0x10
49 #define ASC_INT_STA_OFFSET 0x14
50 #define ASC_GUARDTIME_OFFSET 0x18
51 #define ASC_TIMEOUT_OFFSET 0x1C
52 #define ASC_TX_RST_OFFSET 0x20
53 #define ASC_RX_RST_OFFSET 0x24
54 #define ASC_RETRIES_OFFSET 0x28
55
56 #define ASC_TX_BUFF (*(volatile uint32_t *)(STM_ASC_BASE + ASC_TX_BUFF_OFFSET))
57 #define ASC_RX_BUFF (*(volatile uint32_t *)(STM_ASC_BASE + ASC_RX_BUFF_OFFSET))
58 #define ASC_INT_EN (*(volatile uint32_t *)(STM_ASC_BASE + ASC_INT_EN_OFFSET))
59 #define ASC_INT_STA (*(volatile uint32_t *)(STM_ASC_BASE + ASC_INT_STA_OFFSET))
60
61
62 #define ASC_CTRL_NACK_DISABLE 0x2000
63 #define ASC_CTRL_BAUDMODE 0x1000
64 #define ASC_CTRL_CTS_EN 0x0800
65 #define ASC_CTRL_FIFO_EN 0x0400
66 #define ASC_CTRL_SC_EN 0x0200
67 #define ASC_CTRL_RX_EN 0x0100
68 #define ASC_CTRL_RUN 0x0080
69 #define ASC_CTRL_LOOPBACK 0x0040
70 #define ASC_CTRL_PARITYODD 0x0020
71 #define ASC_CTRL_STOPBITS_MASK 0x0018
72 #define ASC_CTRL_STOPBITS_0_5 0x0000
73 #define ASC_CTRL_STOPBITS_1_0 0x0008
74 #define ASC_CTRL_STOPBITS_1_5 0x0010
75 #define ASC_CTRL_STOPBITS_2_0 0x0018
76 #define ASC_CTRL_MODE_MASK 0x0007
77 #define ASC_CTRL_MODE_8N 0x0001 /* 8 bit */
78 #define ASC_CTRL_MODE_7P 0x0003 /* 7 bit + parity */
79 #define ASC_CTRL_MODE_9N 0x0004 /* 9 bit */
80 #define ASC_CTRL_MODE_8W 0x0005 /* 8 bit + wakeup */
81 #define ASC_CTRL_MODE_8P 0x0007 /* 8 bit + parity */
82
83
84 #define ASC_INT_EN_RHF 0x0100 /* ASC_INT_STA_RHF */
85 #define ASC_INT_EN_TOE 0x0080 /* ASC_INT_STA_TOE */
86 #define ASC_INT_EN_TNE 0x0040 /* ASC_INT_STA_TNE */
87 #define ASC_INT_EN_OE 0x0020 /* ASC_INT_STA_OE */
88 #define ASC_INT_EN_FE 0x0010 /* ASC_INT_STA_FE */
89 #define ASC_INT_EN_PE 0x0008 /* ASC_INT_STA_PE */
90 #define ASC_INT_EN_THE 0x0004 /* ASC_INT_STA_THE */
91 #define ASC_INT_EN_TE 0x0002 /* ASC_INT_STA_TE */
92 #define ASC_INT_EN_RBF 0x0001 /* ASC_INT_STA_RBF */
93
94 #define ASC_INT_STA_NKD 0x0400 /* Tx: NACK Data */
95 #define ASC_INT_STA_TF 0x0200 /* Tx: Transmitter Full */
96 #define ASC_INT_STA_RHF 0x0100 /* Rx: Receiver FIFO Half Full */
97 #define ASC_INT_STA_TOE 0x0080 /* Rx: Timeout Or Empty */
98 #define ASC_INT_STA_TNE 0x0040 /* Rx: Timeout Or Not Empty */
99 #define ASC_INT_STA_OE 0x0020 /* Rx: Overrun Error */
100 #define ASC_INT_STA_FE 0x0010 /* Rx: Frame Error */
101 #define ASC_INT_STA_PE 0x0008 /* Rx: Parity Error */
102 #define ASC_INT_STA_THE 0x0004 /* Tx: Transmitter FIFO Half Empty */
103 #define ASC_INT_STA_TE 0x0002 /* Tx: Transmitter Empty */
104 #define ASC_INT_STA_RBF 0x0001 /* Rx: Receiver Buffer Full */
105
106
107
108 struct stasc_softc {
109 device_t sc_dev;
110 };
111
112
113 static int stasc_match(device_t, cfdata_t, void *);
114 static void stasc_attach(device_t, device_t, void *);
115
116 CFATTACH_DECL_NEW(stasc, sizeof(struct stasc_softc),
117 stasc_match, stasc_attach, NULL, NULL);
118
119
120 /* console */
121 cons_decl(stasc_)
122
123 /* assign to cn_tab after cleaning bss to get printf early for the cpu setup */
124 struct consdev stasc_earlycons = cons_init(stasc_);
125
126 extern struct cfdriver stasc_cd;
127
128 const struct cdevsw stasc_cdevsw = {
129 .d_open = noopen,
130 .d_close = noclose,
131 .d_read = noread,
132 .d_write = nowrite,
133 .d_ioctl = noioctl,
134 .d_stop = nostop,
135 .d_tty = notty,
136 .d_poll = nopoll,
137 .d_mmap = nommap,
138 .d_kqfilter = nokqfilter,
139 .d_discard = nodiscard,
140 .d_flag = D_TTY
141 };
142
143
144
145 static int
stasc_match(device_t parent,cfdata_t cfp,void * aux)146 stasc_match(device_t parent, cfdata_t cfp, void *aux)
147 {
148
149 if (strcmp(cfp->cf_name, "stasc") != 0)
150 return 0;
151
152 return 0; /* just stub it out for now */
153 }
154
155
156 static void
stasc_attach(device_t parent,device_t self,void * aux)157 stasc_attach(device_t parent, device_t self, void *aux)
158 {
159 struct stasc_softc *sc;
160
161 sc = device_private(self);
162 sc->sc_dev = self;
163
164 aprint_normal("\n");
165 }
166
167
168 void
stasc_cnprobe(struct consdev * cp)169 stasc_cnprobe(struct consdev *cp)
170 {
171
172 cp->cn_pri = CN_NORMAL;
173 }
174
175
176 void
stasc_cninit(struct consdev * cp)177 stasc_cninit(struct consdev *cp)
178 {
179
180 return;
181 }
182
183
184 int
stasc_cngetc(dev_t dev)185 stasc_cngetc(dev_t dev)
186 {
187 int s = splserial();
188 uint32_t status;
189 int c;
190
191 /* don't block if Rx buffer is empty */
192 status = ASC_INT_STA;
193 if (!ISSET(status, ASC_INT_STA_RBF)) {
194 splx(s);
195 return -1;
196 }
197
198 /* can read the character now */
199 c = ASC_RX_BUFF;
200 splx(s);
201 return (unsigned char)c;
202 }
203
204
205 void
stasc_cnputc(dev_t dev,int c)206 stasc_cnputc(dev_t dev, int c)
207 {
208 int s = splserial();
209 uint32_t timo, status;
210
211 /* wait for Tx Full to become clear */
212 timo = 150000;
213 do {
214 status = ASC_INT_STA;
215 } while (ISSET(status, ASC_INT_STA_TF) && --timo);
216
217 /* can write the character now */
218 ASC_TX_BUFF = c;
219 splx(s);
220 }
221
222
223 void
stasc_cnpollc(dev_t dev,int on)224 stasc_cnpollc(dev_t dev, int on)
225 {
226
227 return;
228 }
229