Home | History | Annotate | Line # | Download | only in gemini
gemini_lpc.c revision 1.4.52.3
      1  1.4.52.3  thorpej /*	$NetBSD: gemini_lpc.c,v 1.4.52.3 2021/04/03 01:57:09 thorpej Exp $	*/
      2       1.1    cliff 
      3       1.1    cliff #include "opt_gemini.h"
      4       1.1    cliff #include "locators.h"
      5       1.1    cliff 
      6       1.1    cliff #include <sys/cdefs.h>
      7  1.4.52.3  thorpej __KERNEL_RCSID(0, "$NetBSD: gemini_lpc.c,v 1.4.52.3 2021/04/03 01:57:09 thorpej Exp $");
      8       1.1    cliff 
      9       1.1    cliff #include <sys/param.h>
     10       1.1    cliff #include <sys/systm.h>
     11       1.1    cliff #include <sys/device.h>
     12       1.1    cliff #include <arch/arm/gemini/gemini_lpcvar.h>
     13       1.1    cliff #include <arch/arm/gemini/gemini_lpchcvar.h>
     14       1.1    cliff #include <arch/arm/gemini/gemini_reg.h>
     15       1.1    cliff 
     16       1.1    cliff 
     17       1.1    cliff /* XXX these should be in lpcreg.h or it8721reg.h */
     18       1.1    cliff #define IT8712_CFGCTL		0x02
     19       1.1    cliff # define CFGCTL_WAITKEY		__BIT(1)
     20       1.1    cliff #define IT8712_LDN		0x07
     21       1.1    cliff #define IT8712_CHIPID1		0x20
     22       1.1    cliff #define IT8712_CHIPID2		0x21
     23       1.1    cliff #define IT8712_CSCV		0x22
     24       1.1    cliff # define CSCV_VERSION		__BITS(3,0);
     25       1.1    cliff #define IT8712_CLKSEL		0x23
     26       1.1    cliff #define IT8712_SWSUSPEND	0x24
     27       1.1    cliff #define IT8712_ADDR		0x2e
     28       1.1    cliff #define IT8712_DATA		0x2f
     29       1.1    cliff 
     30       1.4      chs static int  gemini_lpc_match(device_t, cfdata_t, void *);
     31       1.4      chs static void gemini_lpc_attach(device_t, device_t, void *);
     32       1.1    cliff static int  gemini_lpc_search(device_t, cfdata_t, const int *, void *);
     33       1.1    cliff static int  gemini_lpc_busprint(void *, const char *);
     34       1.1    cliff 
     35       1.1    cliff static uint8_t it8712_pnp_read(lpctag_t, int, uint);
     36       1.1    cliff static void    it8712_pnp_write(lpctag_t, int, uint, uint8_t);
     37       1.1    cliff static void    it8712_pnp_enter(lpctag_t);
     38       1.1    cliff static void    it8712_pnp_exit(lpctag_t);
     39       1.3    cliff static void   *it8712_intr_establish(lpctag_t, uint, int, int, int (*)(void *), void *);
     40       1.3    cliff static void    it8712_intr_disestablish(lpctag_t, void *);
     41       1.1    cliff 
     42       1.1    cliff CFATTACH_DECL_NEW(lpc, sizeof(struct gemini_lpc_softc),
     43       1.1    cliff     gemini_lpc_match, gemini_lpc_attach, NULL, NULL);
     44       1.1    cliff 
     45       1.2    cliff gemini_lpc_bus_ops_t gemini_lpc_bus_ops = {
     46       1.1    cliff 	it8712_pnp_read,
     47       1.1    cliff 	it8712_pnp_write,
     48       1.1    cliff 	it8712_pnp_enter,
     49       1.1    cliff 	it8712_pnp_exit,
     50       1.3    cliff 	it8712_intr_establish,
     51       1.3    cliff 	it8712_intr_disestablish,
     52       1.1    cliff };
     53       1.1    cliff 
     54       1.1    cliff 
     55       1.1    cliff static int
     56       1.4      chs gemini_lpc_match(device_t parent, cfdata_t cf, void *aux)
     57       1.1    cliff {
     58       1.1    cliff 	struct gemini_lpc_attach_args *lpc = aux;
     59       1.1    cliff 
     60       1.1    cliff 	if (lpc->lpc_addr == LPCCF_ADDR_DEFAULT)
     61       1.1    cliff 		panic("lpc must have addr specified in config.");
     62       1.1    cliff 
     63       1.1    cliff 	return 1;
     64       1.1    cliff }
     65       1.1    cliff 
     66       1.1    cliff static void
     67       1.4      chs gemini_lpc_attach(device_t parent, device_t self, void *aux)
     68       1.1    cliff {
     69       1.1    cliff 	gemini_lpc_softc_t *sc = device_private(self);
     70       1.1    cliff 	struct gemini_lpchc_attach_args *lpchc = aux;
     71       1.1    cliff 	bus_space_tag_t iot;
     72       1.1    cliff 	bus_space_handle_t ioh;
     73       1.1    cliff 	uint8_t id1, id2, vers, clk, susp;
     74       1.1    cliff 
     75       1.1    cliff 	sc->sc_addr = lpchc->lpchc_addr;
     76       1.1    cliff #if 0
     77       1.1    cliff 	sc->sc_size = lpchc->lpchc_size;
     78       1.1    cliff #else
     79       1.1    cliff 	/*
     80       1.1    cliff 	 * we just map the configuration registers
     81       1.1    cliff 	 * child devices can map their own I/O
     82       1.1    cliff 	 */
     83       1.1    cliff 	sc->sc_size = 4096;
     84       1.1    cliff #endif
     85       1.1    cliff 
     86       1.1    cliff 	iot = lpchc->lpchc_iot;
     87       1.1    cliff 	if (bus_space_map(iot, sc->sc_addr, sc->sc_size, 0, &ioh))
     88       1.1    cliff 		panic("%s: Cannot map registers", device_xname(self));
     89       1.1    cliff 	sc->sc_iot = iot;
     90       1.1    cliff 	sc->sc_ioh = ioh;
     91       1.1    cliff 
     92       1.1    cliff 	it8712_pnp_enter(sc);
     93       1.1    cliff 	id1  = it8712_pnp_read(sc, GEMINI_LPC_LDN_ALL, IT8712_CHIPID1);
     94       1.1    cliff 	id2  = it8712_pnp_read(sc, GEMINI_LPC_LDN_ALL, IT8712_CHIPID2);
     95       1.1    cliff 	vers = it8712_pnp_read(sc, GEMINI_LPC_LDN_ALL, IT8712_CSCV);
     96       1.1    cliff 	vers &= CSCV_VERSION;
     97       1.1    cliff 	clk  = it8712_pnp_read(sc, GEMINI_LPC_LDN_ALL, IT8712_CLKSEL);
     98       1.1    cliff 	susp = it8712_pnp_read(sc, GEMINI_LPC_LDN_ALL, IT8712_SWSUSPEND);
     99       1.1    cliff 	it8712_pnp_exit(sc);
    100       1.1    cliff 
    101       1.1    cliff 	aprint_normal("\n%s: chip ID %x%x, version %d",
    102       1.1    cliff 		device_xname(self), id1, id2, vers);
    103       1.1    cliff 	aprint_normal("\n%s: clksel %#x, susp %#x ",
    104       1.1    cliff 		device_xname(self), clk, susp);
    105       1.1    cliff 
    106       1.1    cliff 	sc->sc_lpchctag = lpchc->lpchc_tag;
    107       1.3    cliff 	sc->sc_bus_ops  = &gemini_lpc_bus_ops;
    108       1.1    cliff 
    109       1.1    cliff 	aprint_normal("\n");
    110       1.1    cliff 	aprint_naive("\n");
    111       1.1    cliff 
    112       1.1    cliff 	/*
    113       1.1    cliff 	 * attach the rest of our devices
    114       1.1    cliff 	 */
    115  1.4.52.1  thorpej 	config_search(self, NULL,
    116  1.4.52.1  thorpej 	    CFARG_SUBMATCH, gemini_lpc_search,
    117  1.4.52.1  thorpej 	    CFARG_EOL);
    118       1.1    cliff }
    119       1.1    cliff 
    120       1.1    cliff static int
    121       1.1    cliff gemini_lpc_search(device_t parent, cfdata_t cf, const int *ldesc, void *aux)
    122       1.1    cliff {
    123       1.1    cliff 	gemini_lpc_softc_t *sc = device_private(parent);
    124       1.1    cliff 	gemini_lpc_attach_args_t lpc;
    125       1.1    cliff 
    126       1.1    cliff 	lpc.lpc_ldn      = cf->cf_loc[LPCCF_LDN];
    127       1.1    cliff 	lpc.lpc_addr     = cf->cf_loc[LPCCF_ADDR];
    128       1.1    cliff 	lpc.lpc_size     = cf->cf_loc[LPCCF_SIZE];
    129       1.1    cliff 	lpc.lpc_intr     = cf->cf_loc[LPCCF_INTR];
    130       1.1    cliff 	lpc.lpc_iot      = sc->sc_iot;
    131       1.1    cliff 	lpc.lpc_tag      = sc;
    132       1.1    cliff 	lpc.lpc_base     = sc->sc_addr;
    133       1.1    cliff 
    134       1.1    cliff 	if (config_match(parent, cf, &lpc)) {
    135  1.4.52.3  thorpej 		config_attach(parent, cf, &lpc, gemini_lpc_busprint, CFARG_EOL);
    136       1.1    cliff 		return 0;			/* love it */
    137       1.1    cliff 	}
    138       1.1    cliff 
    139       1.1    cliff 	return UNCONF;				/* hate it */
    140       1.1    cliff }
    141       1.1    cliff 
    142       1.1    cliff static int
    143       1.1    cliff gemini_lpc_busprint(void *aux, const char *name)
    144       1.1    cliff {
    145       1.1    cliff         struct gemini_lpc_attach_args *lpc = aux;
    146       1.1    cliff 
    147       1.1    cliff 	if (lpc->lpc_ldn != LPCCF_LDN_DEFAULT)
    148       1.1    cliff 		aprint_normal(" ldn %d", lpc->lpc_ldn);
    149       1.1    cliff 	if (lpc->lpc_addr != LPCCF_ADDR_DEFAULT)
    150       1.1    cliff 		aprint_normal(" addr %#lx", lpc->lpc_addr);
    151       1.1    cliff 	if (lpc->lpc_size != LPCCF_SIZE_DEFAULT)
    152       1.1    cliff 		aprint_normal(" size %#lx", lpc->lpc_size);
    153       1.1    cliff 	if (lpc->lpc_intr != LPCCF_INTR_DEFAULT)
    154       1.1    cliff 		aprint_normal(" intr %d", lpc->lpc_intr);
    155       1.1    cliff 
    156       1.1    cliff 	return UNCONF;
    157       1.1    cliff }
    158       1.1    cliff 
    159       1.1    cliff /*
    160       1.1    cliff  * LPC bus ops
    161       1.1    cliff  */
    162       1.1    cliff 
    163       1.1    cliff static uint8_t
    164       1.1    cliff it8712_pnp_read(lpctag_t tag, int ldn, uint index)
    165       1.1    cliff {
    166       1.1    cliff 	gemini_lpc_softc_t *sc = tag;
    167       1.1    cliff 	bus_space_tag_t iot = sc->sc_iot;
    168       1.1    cliff 	bus_space_handle_t ioh = sc->sc_ioh;
    169       1.1    cliff 
    170       1.1    cliff 	if (ldn != GEMINI_LPC_LDN_ALL) {
    171       1.1    cliff 		bus_space_write_1(iot, ioh, IT8712_ADDR, IT8712_LDN);
    172       1.1    cliff 		bus_space_write_1(iot, ioh, IT8712_DATA, ldn);
    173       1.1    cliff 	}
    174       1.1    cliff 	bus_space_write_1(iot, ioh, IT8712_ADDR, index);
    175       1.1    cliff 	return bus_space_read_1(iot, ioh, IT8712_DATA);
    176       1.1    cliff }
    177       1.1    cliff 
    178       1.1    cliff static void
    179       1.1    cliff it8712_pnp_write(lpctag_t tag, int ldn, uint index, uint8_t val)
    180       1.1    cliff {
    181       1.1    cliff 	gemini_lpc_softc_t *sc = tag;
    182       1.1    cliff 	bus_space_tag_t iot = sc->sc_iot;
    183       1.1    cliff 	bus_space_handle_t ioh = sc->sc_ioh;
    184       1.1    cliff 
    185       1.1    cliff 	if (ldn != GEMINI_LPC_LDN_ALL) {
    186       1.1    cliff 		bus_space_write_1(iot, ioh, IT8712_ADDR, IT8712_LDN);
    187       1.1    cliff 		bus_space_write_1(iot, ioh, IT8712_DATA, ldn);
    188       1.1    cliff 	}
    189       1.1    cliff 	bus_space_write_1(iot, ioh, IT8712_ADDR, index);
    190       1.1    cliff 	bus_space_write_1(iot, ioh, IT8712_DATA, val);
    191       1.1    cliff }
    192       1.1    cliff 
    193       1.1    cliff static void
    194       1.1    cliff it8712_pnp_enter(lpctag_t tag)
    195       1.1    cliff {
    196       1.1    cliff 	gemini_lpc_softc_t *sc = tag;
    197       1.1    cliff 	bus_space_tag_t iot = sc->sc_iot;
    198       1.1    cliff 	bus_space_handle_t ioh = sc->sc_ioh;
    199       1.1    cliff 
    200       1.1    cliff 	bus_space_write_1(iot, ioh, IT8712_ADDR, 0x87);
    201       1.1    cliff 	bus_space_write_1(iot, ioh, IT8712_ADDR, 0x01);
    202       1.1    cliff 	bus_space_write_1(iot, ioh, IT8712_ADDR, 0x55);
    203       1.1    cliff 	bus_space_write_1(iot, ioh, IT8712_ADDR, 0x55);
    204       1.1    cliff }
    205       1.1    cliff 
    206       1.1    cliff static void
    207       1.1    cliff it8712_pnp_exit(lpctag_t tag)
    208       1.1    cliff {
    209       1.1    cliff 	gemini_lpc_softc_t *sc = tag;
    210       1.1    cliff 	bus_space_tag_t iot = sc->sc_iot;
    211       1.1    cliff 	bus_space_handle_t ioh = sc->sc_ioh;
    212       1.1    cliff 
    213       1.1    cliff 	bus_space_write_1(iot, ioh, IT8712_ADDR, IT8712_CFGCTL);
    214       1.1    cliff 	bus_space_write_1(iot, ioh, IT8712_DATA, CFGCTL_WAITKEY);
    215       1.1    cliff }
    216       1.3    cliff 
    217       1.3    cliff static void *
    218       1.3    cliff it8712_intr_establish(lpctag_t tag, uint intr, int ipl, int ist,
    219       1.3    cliff 	int (*func)(void *), void *arg)
    220       1.3    cliff {
    221       1.3    cliff 	gemini_lpc_softc_t *sc = tag;
    222       1.3    cliff 	void *ih;
    223       1.3    cliff 
    224       1.3    cliff 	ih = gemini_lpchc_intr_establish(sc->sc_lpchctag, intr, ipl, ist, func, arg);
    225       1.3    cliff 
    226       1.3    cliff 	return ih;
    227       1.3    cliff }
    228       1.3    cliff 
    229       1.3    cliff static void
    230       1.3    cliff it8712_intr_disestablish(lpctag_t tag, void *ih)
    231       1.3    cliff {
    232       1.3    cliff 	gemini_lpc_softc_t *sc = tag;
    233       1.3    cliff 
    234       1.3    cliff 	gemini_lpchc_intr_disestablish(sc->sc_lpchctag, ih);
    235       1.3    cliff }
    236