1 /* $NetBSD: obio_lpchc.c,v 1.2 2008/11/20 20:23:05 cliff 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.2 2008/11/20 20:23:05 cliff 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 <machine/param.h> 20 #include <machine/bus.h> 21 22 #include <arm/gemini/gemini_obiovar.h> 23 #include <arm/gemini/gemini_lpcvar.h> 24 #include <arm/gemini/gemini_lpchcvar.h> 25 #include <arm/gemini/gemini_reg.h> 26 27 static int gemini_lpchc_match(struct device *, struct cfdata *, void *); 28 static void gemini_lpchc_attach(struct device *, struct device *, void *); 29 static int gemini_lpchc_print(void *, const char *); 30 31 CFATTACH_DECL_NEW(obio_lpchc, sizeof(struct gemini_lpchc_softc), 32 gemini_lpchc_match, gemini_lpchc_attach, NULL, NULL); 33 34 35 static int 36 gemini_lpchc_match(struct device *parent, struct cfdata *cf, void *aux) 37 { 38 struct obio_attach_args *obio = aux; 39 40 if (obio->obio_addr == OBIOCF_ADDR_DEFAULT) 41 panic("geminilpchc must have addr specified in config."); 42 43 if (obio->obio_addr == GEMINI_LPCHC_BASE) 44 return 1; 45 46 return 0; 47 } 48 49 static void 50 gemini_lpchc_attach(struct device *parent, struct device *self, void *aux) 51 { 52 gemini_lpchc_softc_t *sc = device_private(self); 53 struct obio_attach_args *obio = aux; 54 struct gemini_lpchc_attach_args lpchc; 55 uint32_t r; 56 void *ih=NULL; 57 58 sc->sc_dev = self; 59 sc->sc_addr = obio->obio_addr; 60 sc->sc_size = (obio->obio_size == OBIOCF_SIZE_DEFAULT) 61 ? GEMINI_LPCHC_SIZE : obio->obio_size; 62 63 sc->sc_iot = obio->obio_iot; 64 65 if (bus_space_map(sc->sc_iot, sc->sc_addr, sc->sc_size, 0, &sc->sc_ioh)) 66 panic("%s: Cannot map registers", device_xname(self)); 67 68 r = bus_space_read_4(sc->sc_iot, sc->sc_ioh, GEMINI_LPCHC_ID); 69 aprint_normal("\n%s: device %d, rev %#x ", 70 device_xname(self), _LPCHC_ID_DEVICE(r), _LPCHC_ID_REV(r)); 71 72 73 sc->sc_intr = obio->obio_intr; 74 if (obio->obio_intr != OBIOCF_INTR_DEFAULT) { 75 ih = intr_establish(obio->obio_intr, IPL_SERIAL, 76 IST_LEVEL_HIGH, gemini_lpchc_intr, sc); 77 if (ih == NULL) 78 panic("%s: cannot register intr %d", 79 device_xname(self), obio->obio_intr); 80 } 81 sc->sc_ih = ih; 82 83 gemini_lpchc_init(sc); 84 85 aprint_normal("\n"); 86 aprint_naive("\n"); 87 88 lpchc.lpchc_iot = obio->obio_iot; 89 lpchc.lpchc_addr = GEMINI_LPCIO_BASE; /* XXX sc_addr+offset */ 90 lpchc.lpchc_size = LPCCF_SIZE_DEFAULT; /* XXX placeholder */ 91 lpchc.lpchc_tag = sc; 92 93 (void)config_found_ia(sc->sc_dev, "lpcbus", &lpchc, gemini_lpchc_print); 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