diff options
-rw-r--r-- | sys/arch/loongson/conf/GENERIC | 33 | ||||
-rw-r--r-- | sys/arch/loongson/conf/RAMDISK | 25 | ||||
-rw-r--r-- | sys/arch/loongson/conf/files.loongson | 17 | ||||
-rw-r--r-- | sys/arch/loongson/dev/gdiumiic.c | 355 | ||||
-rw-r--r-- | sys/arch/loongson/dev/glxpcib.c | 3 | ||||
-rw-r--r-- | sys/arch/loongson/dev/smfb.c | 126 | ||||
-rw-r--r-- | sys/arch/loongson/dev/smfbreg.h | 12 | ||||
-rw-r--r-- | sys/arch/loongson/dev/voyager.c | 260 | ||||
-rw-r--r-- | sys/arch/loongson/dev/voyagerreg.h | 38 | ||||
-rw-r--r-- | sys/arch/loongson/dev/voyagervar.h | 27 |
10 files changed, 810 insertions, 86 deletions
diff --git a/sys/arch/loongson/conf/GENERIC b/sys/arch/loongson/conf/GENERIC index 27ba3c0085e..546609457ad 100644 --- a/sys/arch/loongson/conf/GENERIC +++ b/sys/arch/loongson/conf/GENERIC @@ -1,4 +1,4 @@ -# $OpenBSD: GENERIC,v 1.8 2010/02/12 08:14:00 miod Exp $ +# $OpenBSD: GENERIC,v 1.9 2010/02/18 22:45:26 miod Exp $ # # For further information on compiling OpenBSD kernels, see the config(8) # man page. @@ -34,20 +34,33 @@ clock0 at mainbus0 # Main local buses bonito* at mainbus0 pci* at bonito? -glxpcib* at pci? +# Lemote Fuloong 2F and Lemote Yeeloong devices +glxpcib* at pci? isa0 at glxpcib? mcclock0 at isa? port 0x70 -pckbc0 at isa? -pckbd* at pckbc? -wskbd* at pckbd? mux 1 -pmsi* at pckbc? -wsmouse* at pmsi? mux 0 -com0 at isa? port 0x2f8 irq 3 - +pckbc0 at isa? # Yeeloong only +pckbd* at pckbc? # Yeeloong only +wskbd* at pckbd? mux 1 # Yeeloong only +pmsi* at pckbc? # Yeeloong only +wsmouse* at pmsi? mux 0 # Yeeloong only +com0 at isa? port 0x2f8 irq 3 # Fuloong 2F only pciide* at pci? wd* at pciide? flags 0x0000 -smfb* at pci? +smfb* at pci? # Yeeloong only + +# Gdium Liberty specific devices +voyager* at pci? +gpio0 at voyager? +gdiumiic0 at gpio0 offset 6 mask 0x81 # pins 6 and 13 +gdiumiic0 at gpio0 offset 46 mask 0x03 # pins 46 and 47 +iic0 at gdiumiic0 +lmtemp0 at iic0 # National Semiconductor LM75 +#gdiumiic1 at gpio0 offset 41 mask 0x03 # pins 41 and 42 +#iic* at voyager? +#ohci* at voyager? +smfb* at voyager? + wsdisplay* at smfb? # USB Controllers diff --git a/sys/arch/loongson/conf/RAMDISK b/sys/arch/loongson/conf/RAMDISK index dd840abb2fd..c914357733f 100644 --- a/sys/arch/loongson/conf/RAMDISK +++ b/sys/arch/loongson/conf/RAMDISK @@ -1,4 +1,4 @@ -# $OpenBSD: RAMDISK,v 1.6 2010/02/12 19:57:52 otto Exp $ +# $OpenBSD: RAMDISK,v 1.7 2010/02/18 22:45:26 miod Exp $ # # For further information on compiling OpenBSD kernels, see the config(8) # man page. @@ -46,20 +46,25 @@ clock0 at mainbus0 # Main local buses bonito* at mainbus0 pci* at bonito? -glxpcib* at pci? +# Lemote Fuloong 2F and Lemote Yeeloong devices +glxpcib* at pci? isa0 at glxpcib? mcclock0 at isa? port 0x70 -pckbc0 at isa? -pckbd* at pckbc? -wskbd* at pckbd? mux 1 -pmsi* at pckbc? -wsmouse* at pmsi? mux 0 -com0 at isa? port 0x2f8 irq 3 - +pckbc0 at isa? # Yeeloong only +pckbd* at pckbc? # Yeeloong only +wskbd* at pckbd? mux 1 # Yeeloong only +pmsi* at pckbc? # Yeeloong only +wsmouse* at pmsi? mux 0 # Yeeloong only +com0 at isa? port 0x2f8 irq 3 # Fuloong 2F only pciide* at pci? wd* at pciide? flags 0x0000 -smfb* at pci? +smfb* at pci? # Yeeloong only + +# Gdium Liberty specific devices +voyager* at pci? +smfb* at voyager? + wsdisplay* at smfb? # USB Controllers diff --git a/sys/arch/loongson/conf/files.loongson b/sys/arch/loongson/conf/files.loongson index f7d56de48bc..23eb91de37d 100644 --- a/sys/arch/loongson/conf/files.loongson +++ b/sys/arch/loongson/conf/files.loongson @@ -1,4 +1,4 @@ -# $OpenBSD: files.loongson,v 1.2 2010/02/05 20:51:20 miod Exp $ +# $OpenBSD: files.loongson,v 1.3 2010/02/18 22:45:26 miod Exp $ # Standard stanzas config(8) can't run without maxpartitions 16 @@ -73,7 +73,18 @@ attach mcclock at isa with mcclock_isa file arch/loongson/dev/mcclock.c mcclock file arch/loongson/dev/mcclock_isa.c mcclock_isa -# Silicon Motion SM712 frame buffer +# Silicon Motion SM502 master device +device voyager {}: gpiobus +attach voyager at pci +file arch/loongson/dev/voyager.c voyager + +# SM502 specific I2C bus bit-banging +device gdiumiic: i2cbus, i2c_bitbang +attach gdiumiic at gpio +file arch/loongson/dev/gdiumiic.c gdiumiic + +# Silicon Motion SM502/SM712 frame buffer device smfb: wsemuldisplaydev, rasops16 -attach smfb at pci +attach smfb at pci with smfb_pci +attach smfb at voyager with smfb_voyager file arch/loongson/dev/smfb.c smfb needs-flag diff --git a/sys/arch/loongson/dev/gdiumiic.c b/sys/arch/loongson/dev/gdiumiic.c new file mode 100644 index 00000000000..4120b19ff97 --- /dev/null +++ b/sys/arch/loongson/dev/gdiumiic.c @@ -0,0 +1,355 @@ +/* $OpenBSD: gdiumiic.c,v 1.1 2010/02/18 22:45:28 miod Exp $ */ + +/* + * Copyright (c) 2010 Miodrag Vallat. + * Copyright (c) 2006 Alexander Yurchenko <grange@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. + */ + +/* + * I2C bus bit-banging through GPIO pins. + * + * Derived from /sys/dev/gpio/gpioiic.c, with SDA and SCL pin order + * exchanged, and knowledge of bus contents added. + */ + +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/device.h> +#include <sys/gpio.h> +#include <sys/rwlock.h> + +#include <dev/gpio/gpiovar.h> + +#include <dev/i2c/i2cvar.h> +#include <dev/i2c/i2c_bitbang.h> + +#define GPIOIIC_PIN_SDA 1 +#define GPIOIIC_PIN_SCL 0 +#define GPIOIIC_NPINS 2 + +#define GPIOIIC_SDA 0x02 +#define GPIOIIC_SCL 0x01 + +struct gdiumiic_softc { + struct device sc_dev; + + void * sc_gpio; + struct gpio_pinmap sc_map; + int __map[GPIOIIC_NPINS]; + + struct i2c_controller sc_i2c_tag; + struct rwlock sc_i2c_lock; + + int sc_sda; + int sc_scl; +}; + +int gdiumiic_match(struct device *, void *, void *); +void gdiumiic_attach(struct device *, struct device *, void *); +int gdiumiic_detach(struct device *, int); + +int gdiumiic_i2c_acquire_bus(void *, int); +void gdiumiic_i2c_release_bus(void *, int); +int gdiumiic_i2c_send_start(void *, int); +int gdiumiic_i2c_send_stop(void *, int); +int gdiumiic_i2c_initiate_xfer(void *, i2c_addr_t, int); +int gdiumiic_i2c_read_byte(void *, u_int8_t *, int); +int gdiumiic_i2c_write_byte(void *, u_int8_t, int); + +void gdiumiic_bb_set_bits(void *, u_int32_t); +void gdiumiic_bb_set_dir(void *, u_int32_t); +u_int32_t gdiumiic_bb_read_bits(void *); + +int gdiumiic_bustype(struct gpio_attach_args *); +void gdiumiic_sensors_scan(struct device *, + struct i2cbus_attach_args *, void *); + +struct cfattach gdiumiic_ca = { + sizeof(struct gdiumiic_softc), + gdiumiic_match, + gdiumiic_attach, + gdiumiic_detach +}; + +struct cfdriver gdiumiic_cd = { + NULL, "gdiumiic", DV_DULL +}; + +static const struct i2c_bitbang_ops gdiumiic_bbops = { + gdiumiic_bb_set_bits, + gdiumiic_bb_set_dir, + gdiumiic_bb_read_bits, + { GPIOIIC_SDA, GPIOIIC_SCL, GPIOIIC_SDA, 0 } +}; + +#define GDIUMIIC_BUSTYPE_SENSORS 0 +#define GDIUMIIC_BUSTYPE_VIDCTRL 1 + +int +gdiumiic_bustype(struct gpio_attach_args *ga) +{ + extern int gdium_revision; + + /* + * Hardware pin connections depend upon the motherboard revision. + * XXX magic numbers (should match kernel configuration) + */ + switch (gdium_revision) { + case 0: + if (ga->ga_offset == 46 && ga->ga_mask == 0x03) + return GDIUMIIC_BUSTYPE_SENSORS; + break; + default: + if (ga->ga_offset == 6 && ga->ga_mask == 0x81) + return GDIUMIIC_BUSTYPE_SENSORS; + break; + } + + if (ga->ga_offset == 41 && ga->ga_mask == 0x03) + return GDIUMIIC_BUSTYPE_VIDCTRL; + + return -1; + +} + +int +gdiumiic_match(struct device *parent, void *match, void *aux) +{ + struct cfdata *cf = match; + struct gpio_attach_args *ga = aux; + + if (ga->ga_offset == -1 || gdiumiic_bustype(ga) < 0) + return 0; + + return (strcmp(cf->cf_driver->cd_name, "gdiumiic") == 0); +} + +void +gdiumiic_attach(struct device *parent, struct device *self, void *aux) +{ + struct gdiumiic_softc *sc = (struct gdiumiic_softc *)self; + struct gpio_attach_args *ga = aux; + struct i2cbus_attach_args iba; + int caps; + + /* Check that we have enough pins */ + if (gpio_npins(ga->ga_mask) != GPIOIIC_NPINS) { + printf(": invalid pin mask\n"); + return; + } + + /* Map pins */ + sc->sc_gpio = ga->ga_gpio; + sc->sc_map.pm_map = sc->__map; + if (gpio_pin_map(sc->sc_gpio, ga->ga_offset, ga->ga_mask, + &sc->sc_map)) { + printf(": can't map pins\n"); + return; + } + + /* Configure SDA pin */ + caps = gpio_pin_caps(sc->sc_gpio, &sc->sc_map, GPIOIIC_PIN_SDA); + if (!(caps & GPIO_PIN_OUTPUT)) { + printf(": SDA pin is unable to drive output\n"); + goto fail; + } + if (!(caps & GPIO_PIN_INPUT)) { + printf(": SDA pin is unable to read input\n"); + goto fail; + } + printf(": SDA[%d]", sc->sc_map.pm_map[GPIOIIC_PIN_SDA]); + sc->sc_sda = GPIO_PIN_OUTPUT; +#if 0 + if (caps & GPIO_PIN_OPENDRAIN) { + printf(" open-drain"); + sc->sc_sda |= GPIO_PIN_OPENDRAIN; + } else if ((caps & GPIO_PIN_PUSHPULL) && (caps & GPIO_PIN_TRISTATE)) { + printf(" push-pull tri-state"); + sc->sc_sda |= GPIO_PIN_PUSHPULL; + } + if (caps & GPIO_PIN_PULLUP) { + printf(" pull-up"); + sc->sc_sda |= GPIO_PIN_PULLUP; + } +#endif + gpio_pin_ctl(sc->sc_gpio, &sc->sc_map, GPIOIIC_PIN_SDA, sc->sc_sda); + + /* Configure SCL pin */ + caps = gpio_pin_caps(sc->sc_gpio, &sc->sc_map, GPIOIIC_PIN_SCL); + if (!(caps & GPIO_PIN_OUTPUT)) { + printf(": SCL pin is unable to drive output\n"); + goto fail; + } + printf(", SCL[%d]", sc->sc_map.pm_map[GPIOIIC_PIN_SCL]); + sc->sc_scl = GPIO_PIN_OUTPUT; +#if 0 + if (caps & GPIO_PIN_OPENDRAIN) { + printf(" open-drain"); + sc->sc_scl |= GPIO_PIN_OPENDRAIN; + if (caps & GPIO_PIN_PULLUP) { + printf(" pull-up"); + sc->sc_scl |= GPIO_PIN_PULLUP; + } + } else if (caps & GPIO_PIN_PUSHPULL) { + printf(" push-pull"); + sc->sc_scl |= GPIO_PIN_PUSHPULL; + } +#endif + gpio_pin_ctl(sc->sc_gpio, &sc->sc_map, GPIOIIC_PIN_SCL, sc->sc_scl); + + printf("\n"); + + /* Attach I2C bus */ + rw_init(&sc->sc_i2c_lock, "iiclk"); + sc->sc_i2c_tag.ic_cookie = sc; + sc->sc_i2c_tag.ic_acquire_bus = gdiumiic_i2c_acquire_bus; + sc->sc_i2c_tag.ic_release_bus = gdiumiic_i2c_release_bus; + sc->sc_i2c_tag.ic_send_start = gdiumiic_i2c_send_start; + sc->sc_i2c_tag.ic_send_stop = gdiumiic_i2c_send_stop; + sc->sc_i2c_tag.ic_initiate_xfer = gdiumiic_i2c_initiate_xfer; + sc->sc_i2c_tag.ic_read_byte = gdiumiic_i2c_read_byte; + sc->sc_i2c_tag.ic_write_byte = gdiumiic_i2c_write_byte; + + bzero(&iba, sizeof(iba)); + iba.iba_name = "iic"; + iba.iba_tag = &sc->sc_i2c_tag; + if (gdiumiic_bustype(ga) == GDIUMIIC_BUSTYPE_SENSORS) + iba.iba_bus_scan = gdiumiic_sensors_scan; + config_found(self, &iba, iicbus_print); + + return; + +fail: + gpio_pin_unmap(sc->sc_gpio, &sc->sc_map); +} + +int +gdiumiic_detach(struct device *self, int flags) +{ + return (0); +} + +int +gdiumiic_i2c_acquire_bus(void *cookie, int flags) +{ + struct gdiumiic_softc *sc = cookie; + + if (cold || (flags & I2C_F_POLL)) + return (0); + + return (rw_enter(&sc->sc_i2c_lock, RW_WRITE | RW_INTR)); +} + +void +gdiumiic_i2c_release_bus(void *cookie, int flags) +{ + struct gdiumiic_softc *sc = cookie; + + if (cold || (flags & I2C_F_POLL)) + return; + + rw_exit(&sc->sc_i2c_lock); +} + +int +gdiumiic_i2c_send_start(void *cookie, int flags) +{ + return (i2c_bitbang_send_start(cookie, flags, &gdiumiic_bbops)); +} + +int +gdiumiic_i2c_send_stop(void *cookie, int flags) +{ + return (i2c_bitbang_send_stop(cookie, flags, &gdiumiic_bbops)); +} + +int +gdiumiic_i2c_initiate_xfer(void *cookie, i2c_addr_t addr, int flags) +{ + return (i2c_bitbang_initiate_xfer(cookie, addr, flags, &gdiumiic_bbops)); +} + +int +gdiumiic_i2c_read_byte(void *cookie, u_int8_t *bytep, int flags) +{ + return (i2c_bitbang_read_byte(cookie, bytep, flags, &gdiumiic_bbops)); +} + +int +gdiumiic_i2c_write_byte(void *cookie, u_int8_t byte, int flags) +{ + return (i2c_bitbang_write_byte(cookie, byte, flags, &gdiumiic_bbops)); +} + +void +gdiumiic_bb_set_bits(void *cookie, u_int32_t bits) +{ + struct gdiumiic_softc *sc = cookie; + + gpio_pin_write(sc->sc_gpio, &sc->sc_map, GPIOIIC_PIN_SDA, + bits & GPIOIIC_SDA ? GPIO_PIN_HIGH : GPIO_PIN_LOW); + gpio_pin_write(sc->sc_gpio, &sc->sc_map, GPIOIIC_PIN_SCL, + bits & GPIOIIC_SCL ? GPIO_PIN_HIGH : GPIO_PIN_LOW); +} + +void +gdiumiic_bb_set_dir(void *cookie, u_int32_t bits) +{ + struct gdiumiic_softc *sc = cookie; + int sda = sc->sc_sda; + + sda &= ~(GPIO_PIN_INPUT | GPIO_PIN_OUTPUT | GPIO_PIN_TRISTATE); + sda |= (bits & GPIOIIC_SDA ? GPIO_PIN_OUTPUT : GPIO_PIN_INPUT); +#if 0 + if ((sda & GPIO_PIN_PUSHPULL) && !(bits & GPIOIIC_SDA)) + sda |= GPIO_PIN_TRISTATE; +#endif + if (sc->sc_sda != sda) { + sc->sc_sda = sda; + gpio_pin_ctl(sc->sc_gpio, &sc->sc_map, GPIOIIC_PIN_SDA, + sc->sc_sda); + } +} + +u_int32_t +gdiumiic_bb_read_bits(void *cookie) +{ + struct gdiumiic_softc *sc = cookie; + + return (gpio_pin_read(sc->sc_gpio, &sc->sc_map, + GPIOIIC_PIN_SDA) == GPIO_PIN_HIGH ? GPIOIIC_SDA : 0); +} + +/* + * Attach devices to the first (sensors + RTC) i2c bus. + * + * Note that the i2c scan performed by the MI i2c code will fail to + * identify our lm75 chip correctly. + */ +void +gdiumiic_sensors_scan(struct device *iicdev, struct i2cbus_attach_args *iba, + void *arg) +{ + struct i2c_attach_args ia; + /* not worth #define'ing _I2C_PRIVATE for */ + extern int iic_print(void *, const char *); + + bzero(&ia, sizeof ia); + ia.ia_tag = iba->iba_tag; + ia.ia_addr = 0x48; + ia.ia_size = 1; + ia.ia_name = "lm75"; + config_found(iicdev, &ia, iic_print); +} diff --git a/sys/arch/loongson/dev/glxpcib.c b/sys/arch/loongson/dev/glxpcib.c index f3049b9f2b9..1d77c31cd74 100644 --- a/sys/arch/loongson/dev/glxpcib.c +++ b/sys/arch/loongson/dev/glxpcib.c @@ -1,4 +1,4 @@ -/* $OpenBSD: glxpcib.c,v 1.3 2010/02/05 22:19:24 miod Exp $ */ +/* $OpenBSD: glxpcib.c,v 1.4 2010/02/18 22:45:28 miod Exp $ */ /* * Copyright (c) 2007 Marc Balmer <mbalmer@openbsd.org> @@ -183,6 +183,7 @@ glxpcib_attach(struct device *parent, struct device *self, void *aux) struct glxpcib_softc *sc = (struct glxpcib_softc *)self; struct timecounter *tc = &sc->sc_timecounter; #if NGPIO > 0 + struct pci_attach_args *pa = (struct pci_attach_args *)aux; u_int64_t wa, ga; struct gpiobus_attach_args gba; int i, gpio = 0; diff --git a/sys/arch/loongson/dev/smfb.c b/sys/arch/loongson/dev/smfb.c index 281e7ccf93e..7bb9ace4430 100644 --- a/sys/arch/loongson/dev/smfb.c +++ b/sys/arch/loongson/dev/smfb.c @@ -1,4 +1,4 @@ -/* $OpenBSD: smfb.c,v 1.4 2010/02/05 20:56:49 miod Exp $ */ +/* $OpenBSD: smfb.c,v 1.5 2010/02/18 22:45:28 miod Exp $ */ /* * Copyright (c) 2009, 2010 Miodrag Vallat. @@ -17,8 +17,7 @@ */ /* - * Routines for early console with video memory at fixed address. - * And eventually the whole driver as well. + * Minimal SiliconMotion SM502 and SM712 frame buffer driver. */ #include <sys/param.h> @@ -38,6 +37,8 @@ #include <dev/wscons/wsdisplayvar.h> #include <dev/rasops/rasops.h> +#include <loongson/dev/voyagerreg.h> +#include <loongson/dev/voyagervar.h> #include <loongson/dev/smfbreg.h> #define DPR_READ(fb, reg) (fb)->dpr[(reg) / 4] @@ -76,11 +77,17 @@ struct smfb_softc { int sc_nscr; }; -int smfb_match(struct device *, void *, void *); -void smfb_attach(struct device *, struct device *, void *); +int smfb_pci_match(struct device *, void *, void *); +void smfb_pci_attach(struct device *, struct device *, void *); +int smfb_voyager_match(struct device *, void *, void *); +void smfb_voyager_attach(struct device *, struct device *, void *); -const struct cfattach smfb_ca = { - sizeof(struct smfb_softc), smfb_match, smfb_attach +const struct cfattach smfb_pci_ca = { + sizeof(struct smfb_softc), smfb_pci_match, smfb_pci_attach +}; + +const struct cfattach smfb_voyager_ca = { + sizeof(struct smfb_softc), smfb_voyager_match, smfb_voyager_attach }; struct cfdriver smfb_cd = { @@ -117,41 +124,37 @@ int smfb_do_cursor(struct rasops_info *); int smfb_erasecols(void *, int, int, int, long); int smfb_eraserows(void *, int, int, long); int smfb_wait(struct smfb *); -int smfb_is5xx(pcireg_t); + +void smfb_attach_common(struct smfb_softc *, int); static struct smfb smfbcn; +const struct pci_matchid smfb_devices[] = { + { PCI_VENDOR_SMI, PCI_PRODUCT_SMI_SM712 } +}; + int -smfb_is5xx(pcireg_t id) +smfb_pci_match(struct device *parent, void *vcf, void *aux) { - switch(id) { - default: - return -1; - case PCI_ID_CODE(PCI_VENDOR_SMI, PCI_PRODUCT_SMI_SM712): - return 0; - case PCI_ID_CODE(PCI_VENDOR_SMI, PCI_PRODUCT_SMI_SM501): - return 1; - } + struct pci_attach_args *pa = (struct pci_attach_args *)aux; + + return pci_matchbyid(pa, smfb_devices, nitems(smfb_devices)); } int -smfb_match(struct device *parent, void *vcf, void *aux) +smfb_voyager_match(struct device *parent, void *vcf, void *aux) { - struct pci_attach_args *pa = (struct pci_attach_args *)aux; - int is5xx = smfb_is5xx(pa->pa_id); + struct voyager_attach_args *vaa = (struct voyager_attach_args *)aux; + struct cfdata *cf = (struct cfdata *)vcf; - return is5xx < 0 ? 0 : 1; + return strcmp(vaa->vaa_name, cf->cf_driver->cd_name) == 0; } void -smfb_attach(struct device *parent, struct device *self, void *aux) +smfb_pci_attach(struct device *parent, struct device *self, void *aux) { struct smfb_softc *sc = (struct smfb_softc *)self; struct pci_attach_args *pa = (struct pci_attach_args *)aux; - struct wsemuldisplaydev_attach_args waa; - vaddr_t fbbase, regbase; - int console; - int is5xx = smfb_is5xx(pa->pa_id); if (pci_mapreg_map(pa, PCI_MAPREG_START, PCI_MAPREG_TYPE_MEM, BUS_SPACE_MAP_LINEAR, &sc->sc_memt, &sc->sc_memh, @@ -160,14 +163,29 @@ smfb_attach(struct device *parent, struct device *self, void *aux) return; } - if (is5xx) { - if (pci_mapreg_map(pa, PCI_MAPREG_START + 0x04, - PCI_MAPREG_TYPE_MEM, - BUS_SPACE_MAP_LINEAR, &sc->sc_regt, &sc->sc_regh, - NULL, NULL, 0) != 0) { - printf(": can't map registers\n%s", self->dv_xname); - } - } + smfb_attach_common(sc, 0); +} + +void +smfb_voyager_attach(struct device *parent, struct device *self, void *aux) +{ + struct smfb_softc *sc = (struct smfb_softc *)self; + struct voyager_attach_args *vaa = (struct voyager_attach_args *)aux; + + sc->sc_memt = vaa->vaa_fbt; + sc->sc_memh = vaa->vaa_fbh; + sc->sc_regt = vaa->vaa_mmiot; + sc->sc_regh = vaa->vaa_mmioh; + + smfb_attach_common(sc, 1); +} + +void +smfb_attach_common(struct smfb_softc *sc, int is5xx) +{ + struct wsemuldisplaydev_attach_args waa; + vaddr_t fbbase, regbase; + int console; console = smfbcn.ri.ri_hw != NULL; @@ -178,7 +196,7 @@ smfb_attach(struct device *parent, struct device *self, void *aux) sc->sc_fb = &sc->sc_fb_store; sc->sc_fb->is5xx = is5xx; fbbase = (vaddr_t)bus_space_vaddr(sc->sc_memt, sc->sc_memh); - if (sc->sc_regh != 0) { + if (is5xx) { regbase = (vaddr_t)bus_space_vaddr(sc->sc_regt, sc->sc_regh); } else { @@ -190,6 +208,7 @@ smfb_attach(struct device *parent, struct device *self, void *aux) } } + /* XXX print resolution */ printf("\n"); sc->sc_scrlist[0] = &sc->sc_fb->wsd; @@ -327,14 +346,10 @@ smfb_setup(struct smfb *fb, vaddr_t fbbase, vaddr_t regbase) fb->wsd.capabilities = ri->ri_caps; if (fb->is5xx) { - if (regbase != 0) { - fb->dpr = (volatile uint32_t *) - (regbase + SM5XX_DPR_BASE); - fb->mmio = NULL; - fb->regs = (volatile uint32_t *) - (regbase + SM5XX_REG_BASE); - accel = 1; - } + fb->dpr = (volatile uint32_t *)(regbase + SM5XX_DPR_BASE); + fb->mmio = NULL; + fb->regs = (volatile uint32_t *)(regbase + SM5XX_MMIO_BASE); + accel = 1; } else { fb->dpr = (volatile uint32_t *)(fbbase + SM7XX_DPR_BASE); fb->mmio = (volatile uint8_t *)(fbbase + SM7XX_MMIO_BASE); @@ -507,9 +522,9 @@ smfb_wait(struct smfb *fb) i = 10000; while (i-- != 0) { if (fb->is5xx) { - reg = REG_READ(fb, REG_SYSTEM_CONTROL); - if ((reg & (RSC_FIFO_EMPTY | RSC_STATUS_BUSY)) == - RSC_FIFO_EMPTY) + reg = REG_READ(fb, VOYAGER_SYSTEM_CONTROL); + if ((reg & (VSC_FIFO_EMPTY | VSC_STATUS_BUSY)) == + VSC_FIFO_EMPTY) return 0; } else { fb->mmio[0x3c4] = 0x16; @@ -540,9 +555,16 @@ smfb_cnattach(bus_space_tag_t memt, pcitag_t tag, pcireg_t id) int rc, is5xx; /* filter out unrecognized devices */ - is5xx = smfb_is5xx(id); - if (is5xx < 0) + switch(id) { + default: return ENODEV; + case PCI_ID_CODE(PCI_VENDOR_SMI, PCI_PRODUCT_SMI_SM712): + is5xx = 0; + break; + case PCI_ID_CODE(PCI_VENDOR_SMI, PCI_PRODUCT_SMI_SM501): + is5xx = 1; + break; + } smfbcn.is5xx = is5xx; @@ -551,11 +573,13 @@ smfb_cnattach(bus_space_tag_t memt, pcitag_t tag, pcireg_t id) return EINVAL; fbbase = memt->bus_base + PCI_MAPREG_MEM_ADDR(bar); - regbase = 0; if (smfbcn.is5xx) { bar = pci_conf_read_early(tag, PCI_MAPREG_START + 0x04); - if (PCI_MAPREG_TYPE(bar) == PCI_MAPREG_TYPE_MEM) - regbase = memt->bus_base + PCI_MAPREG_MEM_ADDR(bar); + if (PCI_MAPREG_TYPE(bar) != PCI_MAPREG_TYPE_MEM) + return EINVAL; + regbase = memt->bus_base + PCI_MAPREG_MEM_ADDR(bar); + } else { + regbase = 0; } rc = smfb_setup(&smfbcn, fbbase, regbase); diff --git a/sys/arch/loongson/dev/smfbreg.h b/sys/arch/loongson/dev/smfbreg.h index 3b05235d6a6..92cbd81b120 100644 --- a/sys/arch/loongson/dev/smfbreg.h +++ b/sys/arch/loongson/dev/smfbreg.h @@ -1,4 +1,4 @@ -/* $OpenBSD: smfbreg.h,v 1.3 2010/02/09 05:39:39 miod Exp $ */ +/* $OpenBSD: smfbreg.h,v 1.4 2010/02/18 22:45:28 miod Exp $ */ /* * Copyright (c) 2009, 2010 Miodrag Vallat. @@ -70,13 +70,3 @@ */ #define SM7XX_MMIO_BASE 0x00700000 - -/* - * Generic registers (SM5xx only) - */ - -#define SM5XX_REG_BASE 0x00000000 - -#define REG_SYSTEM_CONTROL 0x00 -#define RSC_FIFO_EMPTY 0x00100000 -#define RSC_STATUS_BUSY 0x00080000 diff --git a/sys/arch/loongson/dev/voyager.c b/sys/arch/loongson/dev/voyager.c new file mode 100644 index 00000000000..a72681e81ec --- /dev/null +++ b/sys/arch/loongson/dev/voyager.c @@ -0,0 +1,260 @@ +/* $OpenBSD: voyager.c,v 1.1 2010/02/18 22:45:28 miod Exp $ */ + +/* + * Copyright (c) 2010 Miodrag Vallat. + * + * 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. + */ + +/* + * Silicon Motion SM501/SM502 (VoyagerGX) master driver. + */ + +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/device.h> +#include <sys/gpio.h> + +#include <machine/bus.h> +#include <machine/cpu.h> + +#include <dev/gpio/gpiovar.h> + +#include <dev/pci/pcireg.h> +#include <dev/pci/pcivar.h> +#include <dev/pci/pcidevs.h> + +#include <loongson/dev/voyagerreg.h> +#include <loongson/dev/voyagervar.h> + +struct voyager_softc { + struct device sc_dev; + + bus_space_tag_t sc_fbt; + bus_space_handle_t sc_fbh; + bus_size_t sc_fbsize; + + bus_space_tag_t sc_mmiot; + bus_space_handle_t sc_mmioh; + bus_size_t sc_mmiosize; + + struct gpio_chipset_tag sc_gpio_tag; + gpio_pin_t sc_gpio_pins[VOYAGER_NGPIO]; +}; + +int voyager_match(struct device *, void *, void *); +void voyager_attach(struct device *, struct device *, void *); + +const struct cfattach voyager_ca = { + sizeof(struct voyager_softc), voyager_match, voyager_attach +}; + +struct cfdriver voyager_cd = { + NULL, "voyager", DV_DULL +}; + +void voyager_attach_gpio(struct voyager_softc *); +int voyager_print(void *, const char *); +int voyager_search(struct device *, void *, void *); + +const struct pci_matchid voyager_devices[] = { + /* + * 502 shares the same device ID as 501, but uses a different + * revision number. + */ + { PCI_VENDOR_SMI, PCI_PRODUCT_SMI_SM501 } +}; + +int +voyager_match(struct device *parent, void *vcf, void *aux) +{ + struct pci_attach_args *pa = (struct pci_attach_args *)aux; + + return pci_matchbyid(pa, voyager_devices, nitems(voyager_devices)); +} + +void +voyager_attach(struct device *parent, struct device *self, void *aux) +{ + struct voyager_softc *sc = (struct voyager_softc *)self; + struct pci_attach_args *pa = (struct pci_attach_args *)aux; + + if (pci_mapreg_map(pa, PCI_MAPREG_START, PCI_MAPREG_TYPE_MEM, + BUS_SPACE_MAP_LINEAR, &sc->sc_fbt, &sc->sc_fbh, + NULL, &sc->sc_fbsize, 0) != 0) { + printf(": can't map frame buffer\n"); + return; + } + + if (pci_mapreg_map(pa, PCI_MAPREG_START + 0x04, PCI_MAPREG_TYPE_MEM, + BUS_SPACE_MAP_LINEAR, &sc->sc_mmiot, &sc->sc_mmioh, + NULL, &sc->sc_mmiosize, 0) != 0) { + printf(": can't map mmio\n"); + bus_space_unmap(sc->sc_fbt, sc->sc_fbh, sc->sc_fbsize); + return; + } + + printf("\n"); + + /* + * Attach GPIO devices. + */ + voyager_attach_gpio(sc); + + /* + * Attach child devices. + */ + config_search(voyager_search, self, pa); +} + +int +voyager_print(void *args, const char *parentname) +{ + struct voyager_attach_args *vaa = (struct voyager_attach_args *)args; + + if (parentname != NULL) + printf("%s at %s", vaa->vaa_name, parentname); + + return UNCONF; +} + +int +voyager_search(struct device *parent, void *vcf, void *args) +{ + struct voyager_softc *sc = (struct voyager_softc *)parent; + struct cfdata *cf = (struct cfdata *)vcf; + struct pci_attach_args *pa = (struct pci_attach_args *)args; + struct voyager_attach_args vaa; + + /* + * Caller should have attached gpio already. If it didn't, bail + * out here. + */ + if (strcmp(cf->cf_driver->cd_name, "gpio") == 0) + return 0; + + vaa.vaa_name = cf->cf_driver->cd_name; + vaa.vaa_pa = pa; + vaa.vaa_fbt = sc->sc_fbt; + vaa.vaa_fbh = sc->sc_fbh; + vaa.vaa_mmiot = sc->sc_mmiot; + vaa.vaa_mmioh = sc->sc_mmioh; + + if (cf->cf_attach->ca_match(parent, cf, &vaa) == 0) + return 0; + + config_attach(parent, cf, &vaa, voyager_print); + return 1; +} + +/* + * GPIO support code + */ + +int voyager_gpio_pin_read(void *, int); +void voyager_gpio_pin_write(void *, int, int); +void voyager_gpio_pin_ctl(void *, int, int); + +static const struct gpio_chipset_tag voyager_gpio_tag = { + .gp_pin_read = voyager_gpio_pin_read, + .gp_pin_write = voyager_gpio_pin_write, + .gp_pin_ctl = voyager_gpio_pin_ctl +}; + +int +voyager_gpio_pin_read(void *cookie, int pin) +{ + struct voyager_softc *sc = (struct voyager_softc *)cookie; + bus_addr_t reg; + int32_t data, mask; + + if (pin >= 32) { + pin -= 32; + reg = VOYAGER_GPIO_DATA_HIGH; + } else { + reg = VOYAGER_GPIO_DATA_LOW; + } + mask = 1 << pin; + + data = bus_space_read_4(sc->sc_mmiot, sc->sc_mmioh, reg); + return data & mask ? GPIO_PIN_HIGH : GPIO_PIN_LOW; +} + +void +voyager_gpio_pin_write(void *cookie, int pin, int val) +{ + struct voyager_softc *sc = (struct voyager_softc *)cookie; + bus_addr_t reg; + int32_t data, mask; + + if (pin >= 32) { + pin -= 32; + reg = VOYAGER_GPIO_DATA_HIGH; + } else { + reg = VOYAGER_GPIO_DATA_LOW; + } + mask = 1 << pin; + data = bus_space_read_4(sc->sc_mmiot, sc->sc_mmioh, reg); + if (val) + data |= mask; + else + data &= ~mask; + bus_space_write_4(sc->sc_mmiot, sc->sc_mmioh, reg, data); +} + +void +voyager_gpio_pin_ctl(void *cookie, int pin, int flags) +{ + struct voyager_softc *sc = (struct voyager_softc *)cookie; + bus_addr_t reg; + int32_t data, mask; + + if (pin >= 32) { + pin -= 32; + reg = VOYAGER_GPIO_DIR_HIGH; + } else { + reg = VOYAGER_GPIO_DIR_LOW; + } + mask = 1 << pin; + data = bus_space_read_4(sc->sc_mmiot, sc->sc_mmioh, reg); + if (ISSET(flags, GPIO_PIN_OUTPUT)) + data |= mask; + else + data &= ~mask; + bus_space_write_4(sc->sc_mmiot, sc->sc_mmioh, reg, data); +} + +void +voyager_attach_gpio(struct voyager_softc *sc) +{ + struct gpiobus_attach_args gba; + int pin; + + bcopy(&voyager_gpio_tag, &sc->sc_gpio_tag, sizeof voyager_gpio_tag); + sc->sc_gpio_tag.gp_cookie = sc; + + for (pin = 0; pin < VOYAGER_NGPIO; pin++) { + sc->sc_gpio_pins[pin].pin_num = pin; + sc->sc_gpio_pins[pin].pin_caps = + GPIO_PIN_INPUT | GPIO_PIN_OUTPUT; + sc->sc_gpio_pins[pin].pin_state = + voyager_gpio_pin_read(sc, pin); + } + + gba.gba_name = "gpio"; + gba.gba_gc = &sc->sc_gpio_tag; + gba.gba_pins = sc->sc_gpio_pins; + gba.gba_npins = VOYAGER_NGPIO; + + config_found(&sc->sc_dev, &gba, voyager_print); +} diff --git a/sys/arch/loongson/dev/voyagerreg.h b/sys/arch/loongson/dev/voyagerreg.h new file mode 100644 index 00000000000..4a56a51d88c --- /dev/null +++ b/sys/arch/loongson/dev/voyagerreg.h @@ -0,0 +1,38 @@ +/* $OpenBSD: voyagerreg.h,v 1.1 2010/02/18 22:45:28 miod Exp $ */ + +/* + * Copyright (c) 2010 Miodrag Vallat. + * + * 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. + */ + +/* + * Silicon Motion SM501/SM502 registers + */ + +#define SM5XX_MMIO_BASE 0x00000000 + +#define VOYAGER_SYSTEM_CONTROL 0x00 +#define VSC_FIFO_EMPTY 0x00100000 +#define VSC_STATUS_BUSY 0x00080000 + +/* + * GPIO + */ + +#define VOYAGER_NGPIO (32 + 32) + +#define VOYAGER_GPIO_DATA_LOW 0x00010000 +#define VOYAGER_GPIO_DATA_HIGH 0x00010004 +#define VOYAGER_GPIO_DIR_LOW 0x00010008 +#define VOYAGER_GPIO_DIR_HIGH 0x0001000c diff --git a/sys/arch/loongson/dev/voyagervar.h b/sys/arch/loongson/dev/voyagervar.h new file mode 100644 index 00000000000..6e4e38f43ec --- /dev/null +++ b/sys/arch/loongson/dev/voyagervar.h @@ -0,0 +1,27 @@ +/* $OpenBSD: voyagervar.h,v 1.1 2010/02/18 22:45:28 miod Exp $ */ + +/* + * Copyright (c) 2010 Miodrag Vallat. + * + * 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. + */ + +struct voyager_attach_args { + const char *vaa_name; + + struct pci_attach_args *vaa_pa; + bus_space_tag_t vaa_fbt; + bus_space_handle_t vaa_fbh; + bus_space_tag_t vaa_mmiot; + bus_space_handle_t vaa_mmioh; +}; |