xref: /dflybsd-src/sys/dev/powermng/lm/lm78_isa.c (revision 5d302545124b16bb6e9f48d720cba81afba1adb3)
11d03db02SHasso Tepper /*
21d03db02SHasso Tepper  * Copyright (c) 2005, 2006 Mark Kettenis
31d03db02SHasso Tepper  * Copyright (c) 2007 Constantine A. Murenin, Google Summer of Code
41d03db02SHasso Tepper  *
51d03db02SHasso Tepper  * Permission to use, copy, modify, and distribute this software for any
61d03db02SHasso Tepper  * purpose with or without fee is hereby granted, provided that the above
71d03db02SHasso Tepper  * copyright notice and this permission notice appear in all copies.
81d03db02SHasso Tepper  *
91d03db02SHasso Tepper  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
101d03db02SHasso Tepper  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
111d03db02SHasso Tepper  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
121d03db02SHasso Tepper  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
131d03db02SHasso Tepper  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
141d03db02SHasso Tepper  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
151d03db02SHasso Tepper  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
161d03db02SHasso Tepper  *
171d03db02SHasso Tepper  * $OpenBSD: lm78_isa.c,v 1.2 2007/07/01 21:48:57 cnst Exp $
181d03db02SHasso Tepper  */
191d03db02SHasso Tepper 
201d03db02SHasso Tepper #include <sys/param.h>
211d03db02SHasso Tepper #include <sys/kernel.h>
221d03db02SHasso Tepper #include <sys/bus.h>
231d03db02SHasso Tepper #include <sys/module.h>
241d03db02SHasso Tepper #include <sys/rman.h>
251d03db02SHasso Tepper 
261d03db02SHasso Tepper #include <bus/isa/isavar.h>
271d03db02SHasso Tepper 
281d03db02SHasso Tepper #include <sys/systm.h>
291d03db02SHasso Tepper 
301d03db02SHasso Tepper #include <sys/sensors.h>
311d03db02SHasso Tepper 
321d03db02SHasso Tepper #include "lm78var.h"
331d3c4164SMatthew Dillon #include "../wbsio/wbsioreg.h"
341d3c4164SMatthew Dillon #include "../wbsio/wbsiovar.h"
351d03db02SHasso Tepper 
361d03db02SHasso Tepper /* ISA registers */
371d03db02SHasso Tepper #define LMC_ADDR	0x05
381d03db02SHasso Tepper #define LMC_DATA	0x06
391d03db02SHasso Tepper 
401d03db02SHasso Tepper #if defined(LMDEBUG)
416ab5c081SSascha Wildner #define DPRINTF(x)		do { kprintf x; } while (0)
421d03db02SHasso Tepper #else
431d03db02SHasso Tepper #define DPRINTF(x)
441d03db02SHasso Tepper #endif
451d03db02SHasso Tepper 
461d03db02SHasso Tepper struct lm_isa_softc {
471d03db02SHasso Tepper 	struct lm_softc sc_lmsc;
481d03db02SHasso Tepper 
491d03db02SHasso Tepper 	struct resource *sc_iores;
501d03db02SHasso Tepper 	int sc_iorid;
511d03db02SHasso Tepper 	bus_space_tag_t sc_iot;
521d03db02SHasso Tepper 	bus_space_handle_t sc_ioh;
531d03db02SHasso Tepper };
541d03db02SHasso Tepper 
55*5d302545SFrançois Tigeot static int lm_isa_probe(device_t);
56*5d302545SFrançois Tigeot static int lm_isa_attach(device_t);
57*5d302545SFrançois Tigeot static int lm_isa_detach(device_t);
581d03db02SHasso Tepper u_int8_t lm_isa_readreg(struct lm_softc *, int);
591d03db02SHasso Tepper void lm_isa_writereg(struct lm_softc *, int, int);
601d03db02SHasso Tepper 
611d03db02SHasso Tepper static device_method_t lm_isa_methods[] = {
621d03db02SHasso Tepper 	/* Methods from the device interface */
631d03db02SHasso Tepper 	DEVMETHOD(device_probe,         lm_isa_probe),
641d03db02SHasso Tepper 	DEVMETHOD(device_attach,        lm_isa_attach),
651d03db02SHasso Tepper 	DEVMETHOD(device_detach,        lm_isa_detach),
661d03db02SHasso Tepper 
671d03db02SHasso Tepper 	/* Terminate method list */
68d3c9c58eSSascha Wildner 	DEVMETHOD_END
691d03db02SHasso Tepper };
701d03db02SHasso Tepper 
711d03db02SHasso Tepper static driver_t lm_isa_driver = {
721d03db02SHasso Tepper 	"lm",
731d03db02SHasso Tepper 	lm_isa_methods,
741d03db02SHasso Tepper 	sizeof (struct lm_isa_softc)
751d03db02SHasso Tepper };
761d03db02SHasso Tepper 
771d03db02SHasso Tepper static devclass_t lm_devclass;
781d03db02SHasso Tepper 
791d03db02SHasso Tepper DRIVER_MODULE(lm, isa, lm_isa_driver, lm_devclass, NULL, NULL);
801d3c4164SMatthew Dillon DRIVER_MODULE(lm, wbsio, lm_isa_driver, lm_devclass, NULL, NULL);
811d03db02SHasso Tepper 
820d4e06bcSSascha Wildner static int
lm_isa_probe(device_t dev)83*5d302545SFrançois Tigeot lm_isa_probe(device_t dev)
841d03db02SHasso Tepper {
851d03db02SHasso Tepper 	struct lm_isa_softc *sc = device_get_softc(dev);
861d3c4164SMatthew Dillon 	struct wbsio_softc *wbsc = NULL;
871d03db02SHasso Tepper 	struct resource *iores;
881d3c4164SMatthew Dillon 	struct devclass *parent_devclass;
891d3c4164SMatthew Dillon 	const char *parent_name;
901d03db02SHasso Tepper 	int iorid = 0;
911d03db02SHasso Tepper 	bus_space_tag_t iot;
921d03db02SHasso Tepper 	bus_space_handle_t ioh;
931d03db02SHasso Tepper 	int banksel, vendid, chipid, addr;
941d03db02SHasso Tepper 
951d3c4164SMatthew Dillon 	parent_devclass = device_get_devclass(device_get_parent(dev));
961d3c4164SMatthew Dillon 	parent_name = devclass_get_name(parent_devclass);
971d3c4164SMatthew Dillon 	if (strcmp("wbsio", parent_name) == 0) {
981d3c4164SMatthew Dillon 		wbsc = device_get_softc(device_get_parent(dev));
991d3c4164SMatthew Dillon 		sc->sc_lmsc.sioid = wbsc->sc_devid;
1001d3c4164SMatthew Dillon 	} else {
1011d3c4164SMatthew Dillon 		sc->sc_lmsc.sioid = 0;
1021d3c4164SMatthew Dillon 	}
1031d3c4164SMatthew Dillon 
1041d03db02SHasso Tepper 	iores = bus_alloc_resource(dev, SYS_RES_IOPORT, &iorid,
1051d03db02SHasso Tepper 	    0ul, ~0ul, 8, RF_ACTIVE);
1061d03db02SHasso Tepper 	if (iores == NULL) {
1071d03db02SHasso Tepper 		DPRINTF(("%s: can't map i/o space\n", __func__));
1081d03db02SHasso Tepper 		return (1);
1091d03db02SHasso Tepper 	}
1101d03db02SHasso Tepper 	iot = rman_get_bustag(iores);
1111d03db02SHasso Tepper 	ioh = rman_get_bushandle(iores);
1121d03db02SHasso Tepper 
1131d03db02SHasso Tepper 	/* Probe for Winbond chips. */
1141d03db02SHasso Tepper 	bus_space_write_1(iot, ioh, LMC_ADDR, WB_BANKSEL);
1151d03db02SHasso Tepper 	banksel = bus_space_read_1(iot, ioh, LMC_DATA);
1161d3c4164SMatthew Dillon 	bus_space_write_1(iot, ioh, LMC_ADDR, WB_BANKSEL);
1171d3c4164SMatthew Dillon 	bus_space_write_1(iot, ioh, LMC_DATA, WB_BANKSEL_HBAC);
1181d03db02SHasso Tepper 	bus_space_write_1(iot, ioh, LMC_ADDR, WB_VENDID);
1191d3c4164SMatthew Dillon 	vendid = bus_space_read_1(iot, ioh, LMC_DATA) << 8;
1201d3c4164SMatthew Dillon 	bus_space_write_1(iot, ioh, LMC_ADDR, WB_BANKSEL);
1211d3c4164SMatthew Dillon 	bus_space_write_1(iot, ioh, LMC_DATA, 0);
1221d3c4164SMatthew Dillon 	bus_space_write_1(iot, ioh, LMC_ADDR, WB_VENDID);
1231d3c4164SMatthew Dillon 	vendid |= bus_space_read_1(iot, ioh, LMC_DATA);
1241d3c4164SMatthew Dillon 	bus_space_write_1(iot, ioh, LMC_ADDR, WB_BANKSEL);
1251d3c4164SMatthew Dillon 	bus_space_write_1(iot, ioh, LMC_DATA, banksel);
1261d3c4164SMatthew Dillon 	if (vendid == WB_VENDID_WINBOND)
1271d03db02SHasso Tepper 		goto found;
1281d03db02SHasso Tepper 
1291d03db02SHasso Tepper 	/* Probe for ITE chips (and don't attach if we find one). */
1301d03db02SHasso Tepper 	bus_space_write_1(iot, ioh, LMC_ADDR, 0x58 /*ITD_CHIPID*/);
1311d03db02SHasso Tepper 	vendid = bus_space_read_1(iot, ioh, LMC_DATA);
1321d03db02SHasso Tepper 	if (vendid == 0x90 /*IT_ID_IT87*/)
1331d03db02SHasso Tepper 		goto notfound;
1341d03db02SHasso Tepper 
1351d03db02SHasso Tepper 	/*
1361d03db02SHasso Tepper 	 * Probe for National Semiconductor LM78/79/81.
1371d03db02SHasso Tepper 	 *
1381d03db02SHasso Tepper 	 * XXX This assumes the address has not been changed from the
1391d03db02SHasso Tepper 	 * power up default.  This is probably a reasonable
1401d03db02SHasso Tepper 	 * assumption, and if it isn't true, we should be able to
1411d03db02SHasso Tepper 	 * access the chip using the serial bus.
1421d03db02SHasso Tepper 	 */
1431d03db02SHasso Tepper 	bus_space_write_1(iot, ioh, LMC_ADDR, LM_SBUSADDR);
1441d03db02SHasso Tepper 	addr = bus_space_read_1(iot, ioh, LMC_DATA);
1451d03db02SHasso Tepper 	if ((addr & 0xfc) == 0x2c) {
1461d03db02SHasso Tepper 		bus_space_write_1(iot, ioh, LMC_ADDR, LM_CHIPID);
1471d03db02SHasso Tepper 		chipid = bus_space_read_1(iot, ioh, LMC_DATA);
1481d03db02SHasso Tepper 
1491d03db02SHasso Tepper 		switch (chipid & LM_CHIPID_MASK) {
1501d03db02SHasso Tepper 		case LM_CHIPID_LM78:
1511d03db02SHasso Tepper 		case LM_CHIPID_LM78J:
1521d03db02SHasso Tepper 		case LM_CHIPID_LM79:
1531d03db02SHasso Tepper 		case LM_CHIPID_LM81:
1541d03db02SHasso Tepper 			goto found;
1551d03db02SHasso Tepper 		}
1561d03db02SHasso Tepper 	}
1571d03db02SHasso Tepper 
1581d03db02SHasso Tepper  notfound:
1591d03db02SHasso Tepper 	bus_release_resource(dev, SYS_RES_IOPORT, iorid, iores);
1601d03db02SHasso Tepper 
1611d03db02SHasso Tepper 	return (1);
1621d03db02SHasso Tepper 
1631d03db02SHasso Tepper  found:
1641d03db02SHasso Tepper 	/* Bus-independent probe */
1651d03db02SHasso Tepper 	sc->sc_lmsc.sc_dev = dev;
1661d03db02SHasso Tepper 	sc->sc_iot = iot;
1671d03db02SHasso Tepper 	sc->sc_ioh = ioh;
1681d03db02SHasso Tepper 	sc->sc_lmsc.lm_writereg = lm_isa_writereg;
1691d03db02SHasso Tepper 	sc->sc_lmsc.lm_readreg = lm_isa_readreg;
1701d03db02SHasso Tepper 	lm_probe(&sc->sc_lmsc);
1711d03db02SHasso Tepper 
1721d03db02SHasso Tepper 	bus_release_resource(dev, SYS_RES_IOPORT, iorid, iores);
1731d03db02SHasso Tepper 	sc->sc_iot = 0;
1741d03db02SHasso Tepper 	sc->sc_ioh = 0;
1751d03db02SHasso Tepper 
1761d03db02SHasso Tepper 	return (0);
1771d03db02SHasso Tepper }
1781d03db02SHasso Tepper 
1790d4e06bcSSascha Wildner static int
lm_isa_attach(device_t dev)180*5d302545SFrançois Tigeot lm_isa_attach(device_t dev)
1811d03db02SHasso Tepper {
1821d03db02SHasso Tepper 	struct lm_isa_softc *sc = device_get_softc(dev);
1831d03db02SHasso Tepper #ifdef notyet
1841d03db02SHasso Tepper 	struct lm_softc *lmsc;
1851d03db02SHasso Tepper 	int i;
1861d03db02SHasso Tepper 	u_int8_t sbusaddr;
1871d03db02SHasso Tepper #endif
1881d03db02SHasso Tepper 
1891d03db02SHasso Tepper 	sc->sc_iores = bus_alloc_resource(dev, SYS_RES_IOPORT, &sc->sc_iorid,
1901d03db02SHasso Tepper 	    0ul, ~0ul, 8, RF_ACTIVE);
1911d03db02SHasso Tepper 	if (sc->sc_iores == NULL) {
1921d03db02SHasso Tepper 		device_printf(dev, "can't map i/o space\n");
1931d03db02SHasso Tepper 		return (1);
1941d03db02SHasso Tepper 	}
1951d03db02SHasso Tepper 	sc->sc_iot = rman_get_bustag(sc->sc_iores);
1961d03db02SHasso Tepper 	sc->sc_ioh = rman_get_bushandle(sc->sc_iores);
1971d03db02SHasso Tepper 
1981d03db02SHasso Tepper 	/* Bus-independent attachment */
1991d03db02SHasso Tepper 	lm_attach(&sc->sc_lmsc);
2001d03db02SHasso Tepper 
2011d03db02SHasso Tepper #ifdef notyet
2021d03db02SHasso Tepper 	/*
2031d03db02SHasso Tepper 	 * Most devices supported by this driver can attach to iic(4)
2041d03db02SHasso Tepper 	 * as well.  However, we prefer to attach them to isa(4) since
2051d03db02SHasso Tepper 	 * that causes less overhead and is more reliable.  We look
2061d03db02SHasso Tepper 	 * through all previously attached devices, and if we find an
2071d03db02SHasso Tepper 	 * identical chip at the same serial bus address, we stop
2081d03db02SHasso Tepper 	 * updating its sensors and mark them as invalid.
2091d03db02SHasso Tepper 	 */
2101d03db02SHasso Tepper 
2111d03db02SHasso Tepper 	sbusaddr = lm_isa_readreg(&sc->sc_lmsc, LM_SBUSADDR);
2121d03db02SHasso Tepper 	if (sbusaddr == 0)
2131d03db02SHasso Tepper 		return (0);
2141d03db02SHasso Tepper 
2151d03db02SHasso Tepper 	for (i = 0; i < lm_cd.cd_ndevs; i++) {
2161d03db02SHasso Tepper 		lmsc = lm_cd.cd_devs[i];
2171d03db02SHasso Tepper 		if (lmsc == &sc->sc_lmsc)
2181d03db02SHasso Tepper 			continue;
2191d03db02SHasso Tepper 		if (lmsc && lmsc->sbusaddr == sbusaddr &&
2201d03db02SHasso Tepper 		    lmsc->chipid == sc->sc_lmsc.chipid)
2211d03db02SHasso Tepper 			config_detach(&lmsc->sc_dev, 0);
2221d03db02SHasso Tepper 	}
2231d03db02SHasso Tepper #endif
2241d03db02SHasso Tepper 	return (0);
2251d03db02SHasso Tepper }
2261d03db02SHasso Tepper 
2270d4e06bcSSascha Wildner static int
lm_isa_detach(device_t dev)228*5d302545SFrançois Tigeot lm_isa_detach(device_t dev)
2291d03db02SHasso Tepper {
2301d03db02SHasso Tepper 	struct lm_isa_softc *sc = device_get_softc(dev);
2311d03db02SHasso Tepper 	int error;
2321d03db02SHasso Tepper 
2331d03db02SHasso Tepper 	/* Bus-independent detachment */
2341d03db02SHasso Tepper 	error = lm_detach(&sc->sc_lmsc);
2351d03db02SHasso Tepper 	if (error)
2361d03db02SHasso Tepper 		return (error);
2371d03db02SHasso Tepper 
2381d03db02SHasso Tepper 	error = bus_release_resource(dev, SYS_RES_IOPORT, sc->sc_iorid,
2391d03db02SHasso Tepper 	    sc->sc_iores);
2401d03db02SHasso Tepper 	if (error)
2411d03db02SHasso Tepper 		return (error);
2421d03db02SHasso Tepper 
2431d03db02SHasso Tepper 	return (0);
2441d03db02SHasso Tepper }
2451d03db02SHasso Tepper 
2461d03db02SHasso Tepper u_int8_t
lm_isa_readreg(struct lm_softc * lmsc,int reg)2471d03db02SHasso Tepper lm_isa_readreg(struct lm_softc *lmsc, int reg)
2481d03db02SHasso Tepper {
2491d03db02SHasso Tepper 	struct lm_isa_softc *sc = (struct lm_isa_softc *)lmsc;
2501d03db02SHasso Tepper 
2511d03db02SHasso Tepper 	bus_space_write_1(sc->sc_iot, sc->sc_ioh, LMC_ADDR, reg);
2521d03db02SHasso Tepper 	return (bus_space_read_1(sc->sc_iot, sc->sc_ioh, LMC_DATA));
2531d03db02SHasso Tepper }
2541d03db02SHasso Tepper 
2551d03db02SHasso Tepper void
lm_isa_writereg(struct lm_softc * lmsc,int reg,int val)2561d03db02SHasso Tepper lm_isa_writereg(struct lm_softc *lmsc, int reg, int val)
2571d03db02SHasso Tepper {
2581d03db02SHasso Tepper 	struct lm_isa_softc *sc = (struct lm_isa_softc *)lmsc;
2591d03db02SHasso Tepper 
2601d03db02SHasso Tepper 	bus_space_write_1(sc->sc_iot, sc->sc_ioh, LMC_ADDR, reg);
2611d03db02SHasso Tepper 	bus_space_write_1(sc->sc_iot, sc->sc_ioh, LMC_DATA, val);
2621d03db02SHasso Tepper }
263