diff options
author | Mark Kettenis <kettenis@cvs.openbsd.org> | 2008-02-17 15:04:09 +0000 |
---|---|---|
committer | Mark Kettenis <kettenis@cvs.openbsd.org> | 2008-02-17 15:04:09 +0000 |
commit | 97352354de18b262caf002a548867077cbf1c881 (patch) | |
tree | 2847742ff5794821850b8a73d35322c8b89ccd23 /sys/dev | |
parent | 57083155d9b00469a9c8d5bf4426b6c3fa020391 (diff) |
Enter wbsio(4), a driver for the Winbond LPC Super I/O chips.
ok henning@
Diffstat (limited to 'sys/dev')
-rw-r--r-- | sys/dev/isa/files.isa | 10 | ||||
-rw-r--r-- | sys/dev/isa/lm78_isa.c | 8 | ||||
-rw-r--r-- | sys/dev/isa/wbsio.c | 225 |
3 files changed, 240 insertions, 3 deletions
diff --git a/sys/dev/isa/files.isa b/sys/dev/isa/files.isa index f43d2761b4e..c9c510baaca 100644 --- a/sys/dev/isa/files.isa +++ b/sys/dev/isa/files.isa @@ -1,4 +1,4 @@ -# $OpenBSD: files.isa,v 1.100 2007/12/18 21:17:54 form Exp $ +# $OpenBSD: files.isa,v 1.101 2008/02/17 15:04:08 kettenis Exp $ # $NetBSD: files.isa,v 1.21 1996/05/16 03:45:55 mycroft Exp $ # # Config file and device description for machine-independent ISA code. @@ -336,9 +336,15 @@ file dev/isa/midi_pcppi.c midi_pcppi attach lpt at isa with lpt_isa file dev/isa/lpt_isa.c lpt_isa needs-flag +# Winbond LPC Super I/O +device wbsio {} +attach wbsio at isa +file dev/isa/wbsio.c wbsio + # National Semiconductor LM78/79/81 and compatible hardware monitors attach lm at isa with lm_isa -file dev/isa/lm78_isa.c lm_isa +attach lm at wbsio with lm_wbsio +file dev/isa/lm78_isa.c lm_isa | lm_wbsio # NSC PC87366 Super IO / monitor chip device nsclpcsio: gpiobus diff --git a/sys/dev/isa/lm78_isa.c b/sys/dev/isa/lm78_isa.c index be84ec3ea4f..648890d28f3 100644 --- a/sys/dev/isa/lm78_isa.c +++ b/sys/dev/isa/lm78_isa.c @@ -1,4 +1,4 @@ -/* $OpenBSD: lm78_isa.c,v 1.3 2007/12/18 21:17:54 form Exp $ */ +/* $OpenBSD: lm78_isa.c,v 1.4 2008/02/17 15:04:08 kettenis Exp $ */ /* * Copyright (c) 2005, 2006 Mark Kettenis @@ -57,6 +57,12 @@ struct cfattach lm_isa_ca = { lm_isa_attach }; +struct cfattach lm_wbsio_ca = { + sizeof(struct lm_isa_softc), + lm_isa_match, + lm_isa_attach +}; + int lm_isa_match(struct device *parent, void *match, void *aux) { diff --git a/sys/dev/isa/wbsio.c b/sys/dev/isa/wbsio.c new file mode 100644 index 00000000000..1690ba8e63b --- /dev/null +++ b/sys/dev/isa/wbsio.c @@ -0,0 +1,225 @@ +/* $OpenBSD: wbsio.c,v 1.1 2008/02/17 15:04:08 kettenis Exp $ */ +/* + * Copyright (c) 2008 Mark Kettenis <kettenis@openbsd.org> + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * Winbond LPC Super I/O driver. + */ + +#include <sys/param.h> +#include <sys/device.h> +#include <sys/kernel.h> +#include <sys/systm.h> + +#include <machine/bus.h> + +#include <dev/isa/isareg.h> +#include <dev/isa/isavar.h> + +/* ISA bus registers */ +#define WBSIO_INDEX 0x00 /* Configuration Index Register */ +#define WBSIO_DATA 0x01 /* Configuration Data Register */ + +#define WBSIO_IOSIZE 0x02 /* ISA I/O space size */ + +#define WBSIO_CONF_EN_MAGIC 0x87 /* enable configuration mode */ +#define WBSIO_CONF_DS_MAGIC 0xaa /* disable configuration mode */ + +/* Configuration Space Registers */ +#define WBSIO_LDN 0x07 /* Logical Device Number */ +#define WBSIO_ID 0x20 /* Device ID */ +#define WBSIO_REV 0x21 /* Device Revision */ + +#define WBSIO_ID_W83627HF 0x52 +#define WBSIO_ID_W83627THF 0x82 +#define WBSIO_ID_W83627EHF 0x88 +#define WBSIO_ID_W83627DHG 0xa0 +#define WBSIO_ID_W83627SF 0x59 +#define WBSIO_ID_W83637HF 0x70 +#define WBSIO_ID_W83697HF 0x60 + +/* Logical Device Number (LDN) Assignments */ +#define WBSIO_LDN_HM 0x0b + +/* Hardware Monitor Control Registers (LDN B) */ +#define WBSIO_HM_ADDR_MSB 0x60 /* Address [15:8] */ +#define WBSIO_HM_ADDR_LSB 0x61 /* Address [7:0] */ + +#ifdef WBSIO_DEBUG +#define DPRINTF(x) printf x +#else +#define DPRINTF(x) +#endif + +struct wbsio_softc { + struct device sc_dev; + + bus_space_tag_t sc_iot; + bus_space_handle_t sc_ioh; +}; + +int wbsio_probe(struct device *, void *, void *); +void wbsio_attach(struct device *, struct device *, void *); +int wbsio_print(void *, const char *); + +struct cfattach wbsio_ca = { + sizeof(struct wbsio_softc), + wbsio_probe, + wbsio_attach +}; + +struct cfdriver wbsio_cd = { + NULL, "wbsio", DV_DULL +}; + +static __inline void +wbsio_conf_enable(bus_space_tag_t iot, bus_space_handle_t ioh) +{ + bus_space_write_1(iot, ioh, WBSIO_INDEX, WBSIO_CONF_EN_MAGIC); + bus_space_write_1(iot, ioh, WBSIO_INDEX, WBSIO_CONF_EN_MAGIC); +} + +static __inline void +wbsio_conf_disable(bus_space_tag_t iot, bus_space_handle_t ioh) +{ + bus_space_write_1(iot, ioh, WBSIO_INDEX, WBSIO_CONF_DS_MAGIC); +} + +static __inline u_int8_t +wbsio_conf_read(bus_space_tag_t iot, bus_space_handle_t ioh, u_int8_t index) +{ + bus_space_write_1(iot, ioh, WBSIO_INDEX, index); + return (bus_space_read_1(iot, ioh, WBSIO_DATA)); +} + +static __inline void +wbsio_conf_write(bus_space_tag_t iot, bus_space_handle_t ioh, u_int8_t index, + u_int8_t data) +{ + bus_space_write_1(iot, ioh, WBSIO_INDEX, index); + bus_space_write_1(iot, ioh, WBSIO_DATA, data); +} + +int +wbsio_probe(struct device *parent, void *match, void *aux) +{ + struct isa_attach_args *ia = aux; + bus_space_tag_t iot; + bus_space_handle_t ioh; + u_int8_t reg; + + /* Match by device ID */ + iot = ia->ia_iot; + if (bus_space_map(iot, ia->ipa_io[0].base, WBSIO_IOSIZE, 0, &ioh)) + return (0); + wbsio_conf_enable(iot, ioh); + reg = wbsio_conf_read(iot, ioh, WBSIO_ID); + DPRINTF(("wbsio_probe: id 0x%02x\n", reg)); + wbsio_conf_disable(iot, ioh); + bus_space_unmap(iot, ioh, WBSIO_IOSIZE); + switch (reg) { + case WBSIO_ID_W83627HF: + case WBSIO_ID_W83627THF: + case WBSIO_ID_W83627EHF: + case WBSIO_ID_W83627DHG: + case WBSIO_ID_W83637HF: + case WBSIO_ID_W83697HF: + ia->ipa_nio = 1; + ia->ipa_io[0].length = WBSIO_IOSIZE; + ia->ipa_nmem = 0; + ia->ipa_nirq = 0; + ia->ipa_ndrq = 0; + return (1); + } + + return (0); +} + +void +wbsio_attach(struct device *parent, struct device *self, void *aux) +{ + struct wbsio_softc *sc = (void *)self; + struct isa_attach_args *ia = aux; + struct isa_attach_args nia; + u_int8_t reg, reg0, reg1; + u_int16_t iobase; + + /* Map ISA I/O space */ + sc->sc_iot = ia->ia_iot; + if (bus_space_map(sc->sc_iot, ia->ipa_io[0].base, + WBSIO_IOSIZE, 0, &sc->sc_ioh)) { + printf(": can't map I/O space\n"); + return; + } + + /* Enter configuration mode */ + wbsio_conf_enable(sc->sc_iot, sc->sc_ioh); + + /* Read device ID */ + reg = wbsio_conf_read(sc->sc_iot, sc->sc_ioh, WBSIO_ID); + switch (reg) { + case WBSIO_ID_W83627HF: + printf(": W83627HF"); + break; + case WBSIO_ID_W83627THF: + printf(": W83627THF"); + break; + case WBSIO_ID_W83627EHF: + printf(": W83627EHF"); + break; + case WBSIO_ID_W83627DHG: + printf(": W83627DHG"); + break; + case WBSIO_ID_W83637HF: + printf(": W83637HF"); + break; + case WBSIO_ID_W83697HF: + printf(": W83697HF"); + break; + } + + /* Read device revision */ + reg = wbsio_conf_read(sc->sc_iot, sc->sc_ioh, WBSIO_REV); + printf(" rev 0x%02x", reg); + + /* Select HM logical device */ + wbsio_conf_write(sc->sc_iot, sc->sc_ioh, WBSIO_LDN, WBSIO_LDN_HM); + + reg0 = wbsio_conf_read(sc->sc_iot, sc->sc_ioh, WBSIO_HM_ADDR_LSB); + reg1 = wbsio_conf_read(sc->sc_iot, sc->sc_ioh, WBSIO_HM_ADDR_MSB); + iobase = (reg1 << 8) | reg0; + + printf("\n"); + + /* Escape from configuration mode */ + wbsio_conf_disable(sc->sc_iot, sc->sc_ioh); + + nia = *ia; + nia.ia_iobase = iobase; + config_found(self, &nia, wbsio_print); +} + +int +wbsio_print(void *aux, const char *isa) +{ + struct isa_attach_args *ia = aux; + + if (ia->ia_iosize) + printf(" port 0x%x", ia->ia_iobase); + if (ia->ia_iosize > 1) + printf("/%d", ia->ia_iosize); + return (UNCONF); +} |