1 1.5 thorpej /* $NetBSD: lpc_com.c,v 1.5 2018/12/08 17:46:09 thorpej Exp $ */ 2 1.1 cliff 3 1.1 cliff /* adapted from: 4 1.1 cliff * NetBSD: gemini_com.c,v 1.1 2008/10/24 04:23:18 matt Exp 5 1.1 cliff */ 6 1.1 cliff 7 1.1 cliff /* 8 1.1 cliff * Based on arch/arm/xscale/pxa2x0_com.c 9 1.1 cliff * 10 1.1 cliff * Copyright 2003 Wasabi Systems, Inc. 11 1.1 cliff * All rights reserved. 12 1.1 cliff * 13 1.1 cliff * Written by Steve C. Woodford for Wasabi Systems, Inc. 14 1.1 cliff * 15 1.1 cliff * Redistribution and use in source and binary forms, with or without 16 1.1 cliff * modification, are permitted provided that the following conditions 17 1.1 cliff * are met: 18 1.1 cliff * 1. Redistributions of source code must retain the above copyright 19 1.1 cliff * notice, this list of conditions and the following disclaimer. 20 1.1 cliff * 2. Redistributions in binary form must reproduce the above copyright 21 1.1 cliff * notice, this list of conditions and the following disclaimer in the 22 1.1 cliff * documentation and/or other materials provided with the distribution. 23 1.1 cliff * 3. All advertising materials mentioning features or use of this software 24 1.1 cliff * must display the following acknowledgement: 25 1.1 cliff * This product includes software developed for the NetBSD Project by 26 1.1 cliff * Wasabi Systems, Inc. 27 1.1 cliff * 4. The name of Wasabi Systems, Inc. may not be used to endorse 28 1.1 cliff * or promote products derived from this software without specific prior 29 1.1 cliff * written permission. 30 1.1 cliff * 31 1.1 cliff * THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``AS IS'' AND 32 1.1 cliff * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 33 1.1 cliff * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 34 1.1 cliff * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL WASABI SYSTEMS, INC 35 1.1 cliff * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 36 1.1 cliff * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 37 1.1 cliff * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 38 1.1 cliff * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 39 1.1 cliff * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 40 1.1 cliff * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 41 1.1 cliff * POSSIBILITY OF SUCH DAMAGE. 42 1.1 cliff */ 43 1.1 cliff 44 1.1 cliff #include <sys/cdefs.h> 45 1.5 thorpej __KERNEL_RCSID(0, "$NetBSD: lpc_com.c,v 1.5 2018/12/08 17:46:09 thorpej Exp $"); 46 1.1 cliff 47 1.1 cliff #include "opt_com.h" 48 1.1 cliff #include "locators.h" 49 1.1 cliff 50 1.1 cliff #include <sys/param.h> 51 1.1 cliff #include <sys/systm.h> 52 1.1 cliff #include <sys/device.h> 53 1.1 cliff #include <sys/termios.h> 54 1.1 cliff #include <sys/callout.h> 55 1.1 cliff #include <sys/kernel.h> 56 1.1 cliff 57 1.1 cliff #include <machine/intr.h> 58 1.4 dyoung #include <sys/bus.h> 59 1.1 cliff 60 1.1 cliff #include <dev/ic/comreg.h> 61 1.1 cliff #include <dev/ic/comvar.h> 62 1.1 cliff 63 1.1 cliff #include <arm/gemini/gemini_obiovar.h> 64 1.1 cliff #include <arm/gemini/gemini_lpchcvar.h> 65 1.1 cliff #include <arm/gemini/gemini_lpcvar.h> 66 1.1 cliff #include <arm/gemini/gemini_reg.h> 67 1.1 cliff 68 1.1 cliff #include <arm/gemini/lpc_com.h> 69 1.1 cliff 70 1.1 cliff typedef struct lpc_com_softc { 71 1.1 cliff struct com_softc sc_com; 72 1.1 cliff bus_addr_t sc_addr; 73 1.1 cliff bus_size_t sc_size; 74 1.1 cliff int sc_intr; 75 1.1 cliff bus_space_tag_t sc_iot; 76 1.1 cliff bus_space_handle_t sc_ioh; 77 1.1 cliff struct callout sc_callout; 78 1.1 cliff } lpc_com_softc_t; 79 1.1 cliff 80 1.1 cliff static int lpc_com_match(device_t, cfdata_t , void *); 81 1.1 cliff static void lpc_com_attach(device_t, device_t, void *); 82 1.1 cliff static int lpc_com_intr(void *); 83 1.1 cliff static void lpc_com_time(void *); 84 1.1 cliff 85 1.1 cliff CFATTACH_DECL_NEW(lpc_com, sizeof(struct lpc_com_softc), 86 1.1 cliff lpc_com_match, lpc_com_attach, NULL, NULL); 87 1.1 cliff 88 1.1 cliff static int 89 1.1 cliff lpc_com_match(device_t parent, cfdata_t cf, void *aux) 90 1.1 cliff { 91 1.1 cliff struct gemini_lpc_attach_args *lpc = aux; 92 1.1 cliff lpctag_t lpctag; 93 1.1 cliff bus_space_tag_t iot; 94 1.1 cliff bus_space_handle_t ioh; 95 1.1 cliff bus_addr_t iobase; 96 1.1 cliff int rv; 97 1.1 cliff 98 1.1 cliff if (lpc->lpc_addr == LPCCF_LDN_DEFAULT 99 1.1 cliff || lpc->lpc_addr == LPCCF_ADDR_DEFAULT) 100 1.1 cliff panic("lpc_com must have ldn and addr" 101 1.1 cliff " in config."); 102 1.1 cliff 103 1.1 cliff if ((lpc->lpc_intr != LPCCF_INTR_DEFAULT) && (lpc->lpc_intr > 0xff)) 104 1.1 cliff panic("lpc_com: bad intr %d", lpc->lpc_intr); 105 1.1 cliff 106 1.1 cliff if (lpc->lpc_size == LPCCF_SIZE_DEFAULT) 107 1.1 cliff lpc->lpc_size = IT8712F_UART_SIZE; 108 1.1 cliff 109 1.1 cliff iobase = lpc->lpc_base + lpc->lpc_addr; 110 1.1 cliff if (com_is_console(lpc->lpc_iot, iobase, NULL)) 111 1.1 cliff return 1; 112 1.1 cliff 113 1.1 cliff lpctag = lpc->lpc_tag; 114 1.3 cliff 115 1.3 cliff lpc_pnp_enter(lpctag); 116 1.1 cliff 117 1.1 cliff /* Activate */ 118 1.3 cliff lpc_pnp_write(lpctag, lpc->lpc_ldn, 0x30, 0x01); 119 1.1 cliff 120 1.1 cliff /* Set address */ 121 1.3 cliff lpc_pnp_write(lpctag, lpc->lpc_ldn, 0x60, 122 1.1 cliff (lpc->lpc_addr % 0xff00) >> 8); 123 1.3 cliff lpc_pnp_write(lpctag, lpc->lpc_ldn, 0x61, 124 1.1 cliff (lpc->lpc_addr % 0x00ff) >> 0); 125 1.1 cliff 126 1.1 cliff /* Set Interrupt Level */ 127 1.3 cliff lpc_pnp_write(lpctag, lpc->lpc_ldn, 0x70, lpc->lpc_intr); 128 1.1 cliff 129 1.1 cliff /* Set Special Configuration Regs */ 130 1.3 cliff lpc_pnp_write(lpctag, lpc->lpc_ldn, 0xf0, 0x00); 131 1.1 cliff #if 0 132 1.3 cliff lpc_pnp_write(lpctag, lpc->lpc_ldn, 0xf1, 0x50); 133 1.1 cliff #else 134 1.3 cliff lpc_pnp_write(lpctag, lpc->lpc_ldn, 0xf1, 0x58); /* LO */ 135 1.1 cliff #endif 136 1.3 cliff lpc_pnp_write(lpctag, lpc->lpc_ldn, 0xf2, 0x00); 137 1.3 cliff lpc_pnp_write(lpctag, lpc->lpc_ldn, 0xf3, 0x7f); 138 1.1 cliff 139 1.3 cliff lpc_pnp_exit(lpctag); 140 1.1 cliff 141 1.1 cliff iot = lpc->lpc_iot; 142 1.1 cliff if (bus_space_map(iot, iobase, lpc->lpc_size, 0, &ioh)) 143 1.1 cliff return 0; 144 1.1 cliff 145 1.1 cliff rv = comprobe1(iot, ioh); 146 1.1 cliff 147 1.1 cliff bus_space_unmap(iot, ioh, lpc->lpc_size); 148 1.1 cliff 149 1.1 cliff return rv; 150 1.1 cliff } 151 1.1 cliff 152 1.1 cliff static void 153 1.1 cliff lpc_com_attach(device_t parent, device_t self, void *aux) 154 1.1 cliff { 155 1.1 cliff struct lpc_com_softc *sc = device_private(self); 156 1.1 cliff struct gemini_lpc_attach_args *lpc = aux; 157 1.1 cliff bus_space_tag_t iot; 158 1.1 cliff bus_space_handle_t ioh; 159 1.1 cliff bus_addr_t iobase; 160 1.1 cliff 161 1.1 cliff sc->sc_com.sc_dev = self; 162 1.1 cliff iot = lpc->lpc_iot; 163 1.1 cliff iobase = lpc->lpc_base + lpc->lpc_addr; 164 1.1 cliff sc->sc_com.sc_frequency = IT8712F_COM_FREQ; 165 1.1 cliff sc->sc_com.sc_type = COM_TYPE_NORMAL; 166 1.1 cliff 167 1.1 cliff if (com_is_console(iot, iobase, &ioh) == 0 && 168 1.1 cliff bus_space_map(iot, iobase, lpc->lpc_size, 0, &ioh)) { 169 1.1 cliff panic(": can't map registers\n"); 170 1.1 cliff return; 171 1.1 cliff } 172 1.1 cliff 173 1.5 thorpej com_init_regs(&sc->sc_com.sc_regs, iot, ioh, iobase); 174 1.1 cliff 175 1.1 cliff com_attach_subr(&sc->sc_com); 176 1.1 cliff aprint_naive("\n"); 177 1.1 cliff 178 1.1 cliff if (lpc->lpc_intr == LPCCF_INTR_DEFAULT) { 179 1.1 cliff /* callout based polliung */ 180 1.1 cliff callout_init(&sc->sc_callout, 0); 181 1.1 cliff callout_setfunc(&sc->sc_callout, lpc_com_time, sc); 182 1.2 cliff callout_schedule(&sc->sc_callout, hz/16); 183 1.1 cliff aprint_normal("%s: callout polling mode\n", device_xname(self)); 184 1.1 cliff } else { 185 1.1 cliff /* interrupting */ 186 1.1 cliff #if 0 187 1.3 cliff lpc_intr_establish(lpc->lpc_tag, lpc->lpc_intr, 188 1.1 cliff IPL_SERIAL, IST_LEVEL_HIGH, comintr, &sc->sc_com); 189 1.1 cliff #else 190 1.3 cliff lpc_intr_establish(lpc->lpc_tag, lpc->lpc_intr, 191 1.1 cliff IPL_SERIAL, IST_LEVEL_LOW, lpc_com_intr, &sc->sc_com); 192 1.1 cliff #endif 193 1.1 cliff } 194 1.1 cliff } 195 1.1 cliff 196 1.1 cliff int 197 1.1 cliff lpc_com_intr(void *arg) 198 1.1 cliff { 199 1.1 cliff printf("."); 200 1.1 cliff return comintr(arg); 201 1.1 cliff } 202 1.1 cliff 203 1.1 cliff void 204 1.1 cliff lpc_com_time(void *arg) 205 1.1 cliff { 206 1.1 cliff lpc_com_softc_t *sc = arg; 207 1.1 cliff int s; 208 1.1 cliff 209 1.1 cliff s = splserial(); 210 1.1 cliff (void)comintr(&sc->sc_com); 211 1.2 cliff callout_schedule(&sc->sc_callout, hz/16); 212 1.1 cliff splx(s); 213 1.1 cliff } 214