1 /* $NetBSD: obio_lpchc.c,v 1.7 2021/08/07 16:18:44 thorpej Exp $ */ 2 3 /* 4 * obio attachment for GEMINI LPC Host Controller 5 */ 6 #include "opt_gemini.h" 7 #include "locators.h" 8 9 #include <sys/cdefs.h> 10 __KERNEL_RCSID(0, "$NetBSD: obio_lpchc.c,v 1.7 2021/08/07 16:18:44 thorpej Exp $"); 11 12 #include <sys/param.h> 13 #include <sys/callout.h> 14 #include <sys/cdefs.h> 15 #include <sys/device.h> 16 #include <sys/kernel.h> 17 #include <sys/systm.h> 18 19 #include <sys/bus.h> 20 21 #include <arm/gemini/gemini_obiovar.h> 22 #include <arm/gemini/gemini_lpcvar.h> 23 #include <arm/gemini/gemini_lpchcvar.h> 24 #include <arm/gemini/gemini_reg.h> 25 26 static int gemini_lpchc_match(device_t, cfdata_t, void *); 27 static void gemini_lpchc_attach(device_t, device_t, void *); 28 static int gemini_lpchc_print(void *, const char *); 29 30 CFATTACH_DECL_NEW(obio_lpchc, sizeof(struct gemini_lpchc_softc), 31 gemini_lpchc_match, gemini_lpchc_attach, NULL, NULL); 32 33 34 static int 35 gemini_lpchc_match(device_t parent, cfdata_t cf, void *aux) 36 { 37 struct obio_attach_args *obio = aux; 38 39 if (obio->obio_addr == OBIOCF_ADDR_DEFAULT) 40 panic("geminilpchc must have addr specified in config."); 41 42 if (obio->obio_addr == GEMINI_LPCHC_BASE) 43 return 1; 44 45 return 0; 46 } 47 48 static void 49 gemini_lpchc_attach(device_t parent, device_t self, void *aux) 50 { 51 gemini_lpchc_softc_t *sc = device_private(self); 52 struct obio_attach_args *obio = aux; 53 struct gemini_lpchc_attach_args lpchc; 54 uint32_t r; 55 void *ih=NULL; 56 57 sc->sc_dev = self; 58 sc->sc_addr = obio->obio_addr; 59 sc->sc_size = (obio->obio_size == OBIOCF_SIZE_DEFAULT) 60 ? GEMINI_LPCHC_SIZE : obio->obio_size; 61 62 sc->sc_iot = obio->obio_iot; 63 64 if (bus_space_map(sc->sc_iot, sc->sc_addr, sc->sc_size, 0, &sc->sc_ioh)) 65 panic("%s: Cannot map registers", device_xname(self)); 66 67 r = bus_space_read_4(sc->sc_iot, sc->sc_ioh, GEMINI_LPCHC_ID); 68 aprint_normal("\n%s: device %d, rev %#x ", 69 device_xname(self), _LPCHC_ID_DEVICE(r), _LPCHC_ID_REV(r)); 70 71 72 sc->sc_intr = obio->obio_intr; 73 if (obio->obio_intr != OBIOCF_INTR_DEFAULT) { 74 ih = intr_establish(obio->obio_intr, IPL_SERIAL, 75 IST_LEVEL_HIGH, gemini_lpchc_intr, sc); 76 if (ih == NULL) 77 panic("%s: cannot register intr %d", 78 device_xname(self), obio->obio_intr); 79 } 80 sc->sc_ih = ih; 81 82 gemini_lpchc_init(sc); 83 84 aprint_normal("\n"); 85 aprint_naive("\n"); 86 87 lpchc.lpchc_iot = obio->obio_iot; 88 lpchc.lpchc_addr = GEMINI_LPCIO_BASE; /* XXX sc_addr+offset */ 89 lpchc.lpchc_size = LPCCF_SIZE_DEFAULT; /* XXX placeholder */ 90 lpchc.lpchc_tag = sc; 91 92 config_found(sc->sc_dev, &lpchc, gemini_lpchc_print, 93 CFARGS(.iattr = "lpcbus")); 94 } 95 96 int 97 gemini_lpchc_print(void *aux, const char *name) 98 { 99 struct gemini_lpchc_attach_args *lpchc = aux; 100 101 if (lpchc->lpchc_addr != LPCCF_ADDR_DEFAULT) 102 aprint_normal(" addr %#lx", lpchc->lpchc_addr); 103 104 return UNCONF; 105 } 106