1 /* $NetBSD: stasc.c,v 1.2 2020/07/20 01:06:33 uwe 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.2 2020/07/20 01:06:33 uwe 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: Reciever 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 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 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 169 stasc_cnprobe(struct consdev *cp) 170 { 171 172 cp->cn_pri = CN_NORMAL; 173 } 174 175 176 void 177 stasc_cninit(struct consdev *cp) 178 { 179 180 return; 181 } 182 183 184 int 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 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 224 stasc_cnpollc(dev_t dev, int on) 225 { 226 227 return; 228 } 229