1 /* $OpenBSD: pckbc_ebus.c,v 1.12 2010/11/23 04:07:55 shadchin Exp $ */ 2 3 /* 4 * Copyright (c) 2002 Jason L. Wright (jason@thought.net) 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 17 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 19 * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, 20 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 22 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 24 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 25 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 26 * POSSIBILITY OF SUCH DAMAGE. 27 */ 28 29 /* 30 * Driver for i8042 keyboard controller found on some PCI based 31 * UltraSPARCs 32 * 33 * Effort sponsored in part by the Defense Advanced Research Projects 34 * Agency (DARPA) and Air Force Research Laboratory, Air Force 35 * Materiel Command, USAF, under agreement number F30602-01-2-0537. 36 * 37 */ 38 39 #include <sys/types.h> 40 #include <sys/param.h> 41 #include <sys/systm.h> 42 #include <sys/device.h> 43 #include <sys/conf.h> 44 #include <sys/malloc.h> 45 46 #include <machine/bus.h> 47 #include <machine/autoconf.h> 48 #include <machine/openfirm.h> 49 50 #include <sparc64/dev/ebusreg.h> 51 #include <sparc64/dev/ebusvar.h> 52 53 #include <dev/ic/i8042reg.h> 54 #include <dev/ic/pckbcvar.h> 55 56 struct pckbc_ebus_softc { 57 struct pckbc_softc sc_pckbc; 58 bus_space_tag_t sc_iot; 59 bus_space_handle_t sc_ioh; 60 bus_space_handle_t sc_ioh_c; 61 bus_space_handle_t sc_ioh_d; 62 void *sc_irq[2]; 63 int sc_node; 64 }; 65 66 int pckbc_ebus_match(struct device *, void *, void *); 67 void pckbc_ebus_attach(struct device *, struct device *, void *); 68 69 struct cfattach pckbc_ebus_ca = { 70 sizeof(struct pckbc_ebus_softc), pckbc_ebus_match, pckbc_ebus_attach 71 }; 72 73 void pckbc_ebus_intr_establish(struct pckbc_softc *, pckbc_slot_t); 74 int pckbc_ebus_is_console(struct pckbc_ebus_softc *); 75 76 int 77 pckbc_ebus_match(parent, match, aux) 78 struct device *parent; 79 void *match; 80 void *aux; 81 { 82 struct ebus_attach_args *ea = aux; 83 84 if (strcmp(ea->ea_name, "8042") == 0) 85 return (1); 86 return (0); 87 } 88 89 void 90 pckbc_ebus_attach(parent, self, aux) 91 struct device *parent, *self; 92 void *aux; 93 { 94 struct pckbc_ebus_softc *sc = (void *)self; 95 struct pckbc_softc *psc = &sc->sc_pckbc; 96 struct ebus_attach_args *ea = aux; 97 struct pckbc_internal *t = NULL; 98 int console; 99 int flags = 0; 100 101 sc->sc_node = ea->ea_node; 102 console = pckbc_ebus_is_console(sc); 103 104 /* Use prom address if available, otherwise map it. */ 105 if (ea->ea_nvaddrs && bus_space_map(ea->ea_iotag, ea->ea_vaddrs[0], 0, 106 0, &sc->sc_ioh) == 0) { 107 sc->sc_iot = ea->ea_iotag; 108 } else if (ebus_bus_map(ea->ea_iotag, 0, 109 EBUS_PADDR_FROM_REG(&ea->ea_regs[0]), ea->ea_regs[0].size, 110 0, 0, &sc->sc_ioh) == 0) { 111 sc->sc_iot = ea->ea_iotag; 112 } else if (ebus_bus_map(ea->ea_memtag, 0, 113 EBUS_PADDR_FROM_REG(&ea->ea_regs[0]), ea->ea_regs[0].size, 114 0, 0, &sc->sc_ioh) == 0) { 115 sc->sc_iot = ea->ea_memtag; 116 } else { 117 printf(": can't map register space\n"); 118 return; 119 } 120 121 /* 122 * The 8042 controller found on the Tadpole SPARCLE doesn't 123 * implement XT scan code translation. 124 * XXX I have not checked the value of the model property on 125 * XXX UltraAXe boards... 126 */ 127 { 128 char model[128]; 129 OF_getprop(ea->ea_node, "model", &model, sizeof model); 130 if (strcmp(model, "INTC,80c42") == 0) 131 flags = PCKBC_CANT_TRANSLATE | PCKBC_NEED_AUXWRITE; 132 } 133 134 if (console) { 135 if (pckbc_cnattach(sc->sc_iot, 136 EBUS_PADDR_FROM_REG(&ea->ea_regs[0]), KBCMDP, flags) == 0) { 137 t = &pckbc_consdata; 138 pckbc_console_attached = 1; 139 sc->sc_ioh_c = t->t_ioh_c; 140 sc->sc_ioh_d = t->t_ioh_d; 141 } else 142 console = 0; 143 } 144 145 if (console == 0) { 146 if (bus_space_subregion(sc->sc_iot, sc->sc_ioh, 147 KBCMDP, sizeof(u_int32_t), &sc->sc_ioh_c) != 0) { 148 printf(": couldn't get cmd subregion\n"); 149 return; 150 } 151 if (bus_space_subregion(sc->sc_iot, sc->sc_ioh, 152 KBDATAP, sizeof(u_int32_t), &sc->sc_ioh_d) != 0) { 153 printf(": couldn't get data subregion\n"); 154 return; 155 } 156 157 t = malloc(sizeof(*t), M_DEVBUF, M_NOWAIT | M_ZERO); 158 t->t_flags = flags; 159 } 160 161 psc->intr_establish = pckbc_ebus_intr_establish; 162 163 sc->sc_irq[0] = bus_intr_establish(sc->sc_iot, ea->ea_intrs[0], 164 IPL_TTY, 0, pckbcintr, psc, self->dv_xname); 165 if (sc->sc_irq[0] == NULL) { 166 printf(": couldn't get intr0\n"); 167 return; 168 } 169 170 sc->sc_irq[1] = bus_intr_establish(sc->sc_iot, ea->ea_intrs[1], 171 IPL_TTY, 0, pckbcintr, psc, self->dv_xname); 172 if (sc->sc_irq[1] == NULL) { 173 printf(": couldn't get intr1\n"); 174 return; 175 } 176 177 t->t_iot = sc->sc_iot; 178 t->t_ioh_c = sc->sc_ioh_c; 179 t->t_ioh_d = sc->sc_ioh_d; 180 t->t_cmdbyte = KC8_CPU; 181 t->t_sc = psc; 182 183 psc->id = t; 184 185 printf("\n"); 186 pckbc_attach(psc, 0); 187 } 188 189 int 190 pckbc_ebus_is_console(sc) 191 struct pckbc_ebus_softc *sc; 192 { 193 char *name; 194 int node; 195 196 /* 197 * Loop through the children of 8042 and see if the keyboard 198 * exists, and further, whether it is the console input device. 199 * This is almost redundant because 8042 doesn't show up in 200 * device tree unless a keyboard is in fact attached. 201 */ 202 for (node = OF_child(sc->sc_node); node; node = OF_peer(node)) { 203 name = getpropstring(node, "name"); 204 if (name == NULL) 205 continue; 206 if (strcmp("kb_ps2", name) == 0 || 207 strcmp("keyboard", name) == 0) { 208 if (node == OF_instance_to_package(OF_stdin())) 209 return (1); 210 } 211 } 212 return (0); 213 } 214 215 void 216 pckbc_ebus_intr_establish(psc, slot) 217 struct pckbc_softc *psc; 218 pckbc_slot_t slot; 219 { 220 /* Nothing to do, interrupts were mapped in attach. */ 221 } 222