1 1.32 isaki /* $NetBSD: mfp.c,v 1.32 2024/01/06 05:31:19 isaki Exp $ */ 2 1.2 minoura 3 1.5 minoura /*- 4 1.2 minoura * Copyright (c) 1998 NetBSD Foundation, Inc. 5 1.2 minoura * All rights reserved. 6 1.2 minoura * 7 1.2 minoura * Redistribution and use in source and binary forms, with or without 8 1.2 minoura * modification, are permitted provided that the following conditions 9 1.2 minoura * are met: 10 1.2 minoura * 1. Redistributions of source code must retain the above copyright 11 1.2 minoura * notice, this list of conditions and the following disclaimer. 12 1.2 minoura * 2. Redistributions in binary form must reproduce the above copyright 13 1.2 minoura * notice, this list of conditions and the following disclaimer in the 14 1.2 minoura * documentation and/or other materials provided with the distribution. 15 1.2 minoura * 16 1.5 minoura * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 17 1.5 minoura * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 18 1.5 minoura * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 19 1.5 minoura * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 20 1.5 minoura * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 21 1.5 minoura * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 22 1.5 minoura * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 23 1.5 minoura * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 24 1.5 minoura * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 25 1.5 minoura * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 26 1.5 minoura * POSSIBILITY OF SUCH DAMAGE. 27 1.2 minoura */ 28 1.2 minoura 29 1.2 minoura /* 30 1.2 minoura * MC68901 MFP (multi function periferal) driver for NetBSD/x68k 31 1.2 minoura */ 32 1.2 minoura 33 1.2 minoura /* 34 1.11 wiz * MFP is used as keyboard controller, which may be used before 35 1.2 minoura * ordinary initialization. 36 1.2 minoura */ 37 1.10 lukem 38 1.10 lukem #include <sys/cdefs.h> 39 1.32 isaki __KERNEL_RCSID(0, "$NetBSD: mfp.c,v 1.32 2024/01/06 05:31:19 isaki Exp $"); 40 1.2 minoura 41 1.2 minoura #include <sys/param.h> 42 1.2 minoura #include <sys/systm.h> 43 1.2 minoura #include <sys/device.h> 44 1.2 minoura 45 1.2 minoura #include <machine/bus.h> 46 1.2 minoura #include <machine/cpu.h> 47 1.22 isaki #include <machine/autoconf.h> 48 1.2 minoura 49 1.2 minoura #include <arch/x68k/dev/intiovar.h> 50 1.2 minoura #include <arch/x68k/dev/mfp.h> 51 1.2 minoura 52 1.23 isaki static int mfp_match(device_t, cfdata_t, void *); 53 1.23 isaki static void mfp_attach(device_t, device_t, void *); 54 1.21 isaki static int mfp_search(device_t, cfdata_t, const int *, void *); 55 1.14 chs static void mfp_init(void); 56 1.14 chs static void mfp_calibrate_delay(void); 57 1.2 minoura 58 1.23 isaki CFATTACH_DECL_NEW(mfp, sizeof(struct mfp_softc), 59 1.9 thorpej mfp_match, mfp_attach, NULL, NULL); 60 1.2 minoura 61 1.12 chs static int mfp_attached; 62 1.12 chs 63 1.18 isaki static int 64 1.23 isaki mfp_match(device_t parent, cfdata_t cf, void *aux) 65 1.2 minoura { 66 1.2 minoura struct intio_attach_args *ia = aux; 67 1.2 minoura 68 1.2 minoura /* mfp0 */ 69 1.19 isaki if (strcmp(ia->ia_name, "mfp") != 0) 70 1.2 minoura return 0; 71 1.12 chs if (mfp_attached) 72 1.2 minoura return (0); 73 1.2 minoura 74 1.2 minoura if (ia->ia_addr == INTIOCF_ADDR_DEFAULT) 75 1.2 minoura ia->ia_addr = MFP_ADDR; 76 1.2 minoura if (ia->ia_intr == INTIOCF_INTR_DEFAULT) 77 1.2 minoura ia->ia_addr = MFP_INTR; 78 1.2 minoura 79 1.2 minoura /* fixed address */ 80 1.2 minoura if (ia->ia_addr != MFP_ADDR) 81 1.2 minoura return (0); 82 1.2 minoura if (ia->ia_intr != MFP_INTR) 83 1.2 minoura return (0); 84 1.2 minoura 85 1.2 minoura return (1); 86 1.2 minoura } 87 1.2 minoura 88 1.2 minoura 89 1.18 isaki static void 90 1.23 isaki mfp_attach(device_t parent, device_t self, void *aux) 91 1.2 minoura { 92 1.23 isaki struct mfp_softc *sc = device_private(self); 93 1.2 minoura struct intio_attach_args *ia = aux; 94 1.26 christos int r __diagused; 95 1.22 isaki 96 1.23 isaki aprint_normal("\n"); 97 1.22 isaki mfp_attached = 1; 98 1.2 minoura 99 1.25 tsutsui /* mfp_init() is already called via early config_console() */ 100 1.22 isaki sc->sc_bst = ia->ia_bst; 101 1.22 isaki sc->sc_intr = ia->ia_intr; 102 1.22 isaki ia->ia_size = 0x30; 103 1.22 isaki r = intio_map_allocate_region(parent, ia, INTIO_MAP_ALLOCATE); 104 1.2 minoura #ifdef DIAGNOSTIC 105 1.22 isaki if (r) 106 1.22 isaki panic("IO map for MFP corruption??"); 107 1.2 minoura #endif 108 1.22 isaki bus_space_map(ia->ia_bst, ia->ia_addr, 0x2000, 0, &sc->sc_bht); 109 1.28 thorpej config_search(self, NULL, 110 1.29 thorpej CFARGS(.search = mfp_search)); 111 1.2 minoura } 112 1.2 minoura 113 1.21 isaki static int 114 1.21 isaki mfp_search(device_t parent, cfdata_t cf, const int *loc, void *aux) 115 1.21 isaki { 116 1.28 thorpej if (config_probe(parent, cf, __UNCONST(cf->cf_name))) 117 1.28 thorpej config_attach(parent, cf, __UNCONST(cf->cf_name), NULL, 118 1.29 thorpej CFARGS_NONE); 119 1.21 isaki return 0; 120 1.21 isaki } 121 1.21 isaki 122 1.22 isaki void 123 1.22 isaki mfp_config_console(void) 124 1.22 isaki { 125 1.22 isaki mfp_init(); 126 1.22 isaki mfp_calibrate_delay(); 127 1.22 isaki } 128 1.22 isaki 129 1.2 minoura static void 130 1.14 chs mfp_init(void) 131 1.2 minoura { 132 1.2 minoura mfp_set_vr(MFP_INTR); 133 1.2 minoura 134 1.2 minoura /* stop all interrupts */ 135 1.2 minoura mfp_set_iera(0); 136 1.2 minoura mfp_set_ierb(0); 137 1.20 isaki 138 1.20 isaki /* make MSCTRL 'High', XXX where should I do it? */ 139 1.20 isaki mfp_send_usart(0x41); 140 1.2 minoura 141 1.2 minoura /* Timer A settings */ 142 1.2 minoura mfp_set_tacr(MFP_TIMERA_RESET | MFP_TIMERA_STOP); 143 1.2 minoura 144 1.2 minoura /* Timer B settings: used for USART clock */ 145 1.2 minoura mfp_set_tbcr(MFP_TIMERB_RESET | MFP_TIMERB_STOP); 146 1.2 minoura 147 1.2 minoura /* Timer C/D settings */ 148 1.2 minoura mfp_set_tcdcr(0); 149 1.4 minoura } 150 1.4 minoura 151 1.4 minoura extern int delay_divisor; 152 1.4 minoura 153 1.4 minoura static void 154 1.4 minoura mfp_calibrate_delay(void) 155 1.4 minoura { 156 1.4 minoura /* 157 1.4 minoura * Stolen from mvme68k. 158 1.4 minoura */ 159 1.4 minoura /* 160 1.4 minoura * X68k provides 4MHz clock (= 0.25usec) for MFP timer C. 161 1.4 minoura * 10000usec = 0.25usec * 200 * 200 162 1.4 minoura * Our slowest clock is 20MHz (?). Its delay_divisor value 163 1.4 minoura * should be about 102. Start from 140 here. 164 1.4 minoura */ 165 1.4 minoura for (delay_divisor = 140; delay_divisor > 0; delay_divisor--) { 166 1.4 minoura mfp_set_tcdr(255-0); 167 1.4 minoura mfp_set_tcdcr(0x70); /* 1/200 delay mode */ 168 1.32 isaki _delay(10000); 169 1.4 minoura mfp_set_tcdcr(0); /* stop timer */ 170 1.4 minoura if ((255 - mfp_get_tcdr()) > 200) 171 1.4 minoura break; /* got it! */ 172 1.4 minoura /* retry! */ 173 1.4 minoura } 174 1.2 minoura } 175 1.2 minoura 176 1.2 minoura /* 177 1.2 minoura * MFP utility functions 178 1.2 minoura */ 179 1.2 minoura 180 1.2 minoura /* 181 1.2 minoura * wait for built-in display hsync. 182 1.2 minoura * should be called before writing to frame buffer. 183 1.2 minoura * might be called before realconfig. 184 1.2 minoura */ 185 1.2 minoura void 186 1.14 chs mfp_wait_for_hsync(void) 187 1.2 minoura { 188 1.2 minoura /* wait for CRT HSYNC */ 189 1.2 minoura while (mfp_get_gpip() & MFP_GPIP_HSYNC) 190 1.17 perry __asm("nop"); 191 1.2 minoura while (!(mfp_get_gpip() & MFP_GPIP_HSYNC)) 192 1.17 perry __asm("nop"); 193 1.2 minoura } 194 1.2 minoura 195 1.2 minoura /* 196 1.2 minoura * send COMMAND to the MFP USART. 197 1.2 minoura * USART is attached to the keyboard. 198 1.2 minoura * might be called before realconfig. 199 1.2 minoura */ 200 1.18 isaki int 201 1.14 chs mfp_send_usart(int command) 202 1.2 minoura { 203 1.2 minoura while (!(mfp_get_tsr() & MFP_TSR_BE)); 204 1.2 minoura mfp_set_udr(command); 205 1.2 minoura 206 1.2 minoura return 0; 207 1.2 minoura } 208 1.2 minoura 209 1.2 minoura int 210 1.6 wiz mfp_receive_usart(void) 211 1.2 minoura { 212 1.2 minoura while (!(mfp_get_rsr() & MFP_RSR_BF)) 213 1.17 perry __asm("nop"); 214 1.2 minoura return mfp_get_udr(); 215 1.2 minoura } 216