Date: Tue, 12 Jun 2012 03:22:19 +0000 (UTC) From: Marcel Moolenaar <marcel@FreeBSD.org> To: src-committers@freebsd.org, svn-src-projects@freebsd.org Subject: svn commit: r236940 - in projects/altix2/sys/dev: ata ioc4 uart Message-ID: <201206120322.q5C3MJF8026808@svn.freebsd.org>
next in thread | raw e-mail | index | archive | help
Author: marcel Date: Tue Jun 12 03:22:18 2012 New Revision: 236940 URL: http://svn.freebsd.org/changeset/base/236940 Log: Flesh-out ioc4 a bit more. In particular, add: o uart(4) bus attachment o ata(4) bus attachment This has been fleshed out enough to indicate that we still have a platform problem -- interrupts I suspect. Fixing that should allow me to make forward progress on the busdma code again. Added: projects/altix2/sys/dev/ata/ata-ioc4.c (contents, props changed) projects/altix2/sys/dev/ioc4/ioc4_reg.h (contents, props changed) projects/altix2/sys/dev/uart/uart_bus_ioc4.c (contents, props changed) Modified: projects/altix2/sys/dev/ioc4/ioc4.c projects/altix2/sys/dev/ioc4/ioc4_bus.h Added: projects/altix2/sys/dev/ata/ata-ioc4.c ============================================================================== --- /dev/null 00:00:00 1970 (empty, because file is newly added) +++ projects/altix2/sys/dev/ata/ata-ioc4.c Tue Jun 12 03:22:18 2012 (r236940) @@ -0,0 +1,138 @@ +/*- + * Copyright (c) 2012 Marcel Moolenaar + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include <sys/cdefs.h> +__FBSDID("$FreeBSD$"); + +#include "opt_ata.h" + +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/ata.h> +#include <sys/kernel.h> +#include <sys/module.h> +#include <sys/bus.h> +#include <sys/malloc.h> +#include <sys/sema.h> +#include <sys/taskqueue.h> +#include <vm/uma.h> +#include <machine/stdarg.h> +#include <machine/resource.h> +#include <machine/bus.h> +#include <sys/rman.h> + +#include <dev/ata/ata-all.h> + +#include <dev/ioc4/ioc4_bus.h> + +#include "ata_if.h" + +static int ata_ioc4_probe(device_t); +static int ata_ioc4_attach(device_t); +static int ata_ioc4_detach(device_t); + +static device_method_t ata_ioc4_methods[] = { + /* device interface */ + DEVMETHOD(device_probe, ata_ioc4_probe), + DEVMETHOD(device_attach, ata_ioc4_attach), + DEVMETHOD(device_detach, ata_ioc4_detach), + + DEVMETHOD(bus_alloc_resource, bus_generic_alloc_resource), + DEVMETHOD(bus_release_resource, bus_generic_release_resource), + DEVMETHOD(bus_setup_intr, bus_generic_setup_intr), + DEVMETHOD(bus_teardown_intr, bus_generic_teardown_intr), + DEVMETHOD_END +}; + +static driver_t ata_ioc4_driver = { + "ata", + ata_ioc4_methods, + sizeof(struct ata_channel), +}; + +DRIVER_MODULE(ata, ioc4, ata_ioc4_driver, ata_devclass, NULL, NULL); +MODULE_DEPEND(ata, ata, 1, 1, 1); + +static int +ata_ioc4_probe(device_t dev) +{ + device_t parent; + uintptr_t type; + + parent = device_get_parent(dev); + if (BUS_READ_IVAR(parent, dev, IOC4_IVAR_TYPE, &type)) + return (ENXIO); + if (type != IOC4_TYPE_ATA) + return (ENXIO); + + device_set_desc(dev, "SGI IOC4 ATA channel"); + return (ata_probe(dev)); +} + +static int +ata_ioc4_attach(device_t dev) +{ + struct ata_channel *ch = device_get_softc(dev); + struct resource *mres; + int i, rid; + + if (ch->attached) + return (0); + ch->attached = 1; + + rid = 0; + mres = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid, RF_ACTIVE); + if (mres == NULL) + return (ENXIO); + + for (i = ATA_DATA; i <= ATA_COMMAND; i++) { + ch->r_io[i].res = mres; + ch->r_io[i].offset = i << 2; + } + ch->r_io[ATA_CONTROL].res = mres; + ch->r_io[ATA_CONTROL].offset = 32; + ata_default_registers(dev); + + ch->unit = 0; + ata_generic_hw(dev); + return (ata_attach(dev)); +} + +int +ata_ioc4_detach(device_t dev) +{ + struct ata_channel *ch = device_get_softc(dev); + int error; + + if (!ch->attached) + return (0); + ch->attached = 0; + + error = ata_detach(dev); + + bus_release_resource(dev, SYS_RES_MEMORY, 0, ch->r_io[ATA_CONTROL].res); + return (error); +} Modified: projects/altix2/sys/dev/ioc4/ioc4.c ============================================================================== --- projects/altix2/sys/dev/ioc4/ioc4.c Tue Jun 12 01:13:59 2012 (r236939) +++ projects/altix2/sys/dev/ioc4/ioc4.c Tue Jun 12 03:22:18 2012 (r236940) @@ -32,6 +32,7 @@ __FBSDID("$FreeBSD$"); #include <sys/bus.h> #include <sys/conf.h> #include <sys/kernel.h> +#include <sys/malloc.h> #include <sys/module.h> #include <machine/bus.h> #include <sys/rman.h> @@ -40,6 +41,20 @@ __FBSDID("$FreeBSD$"); #include <dev/pci/pcireg.h> #include <dev/pci/pcivar.h> +#include <dev/ioc4/ioc4_bus.h> +#include <dev/ioc4/ioc4_reg.h> + +struct ioc4_softc; + +struct ioc4_child { + struct ioc4_softc *ch_softc; + device_t ch_dev; + struct resource *ch_ires; + struct resource *ch_mres; + u_int ch_type; + u_int ch_unit; +}; + struct ioc4_softc { device_t sc_dev; @@ -50,6 +65,8 @@ struct ioc4_softc { struct resource *sc_ires; void *sc_icookie; + struct rman sc_rm; + u_int sc_fastintr:1; }; @@ -57,7 +74,15 @@ static int ioc4_probe(device_t dev); static int ioc4_attach(device_t dev); static int ioc4_detach(device_t dev); -static char ioc4_name[] = "ioc"; +static int ioc4_bus_read_ivar(device_t, device_t, int, uintptr_t *); +static struct resource *ioc4_bus_alloc_resource(device_t, device_t, int, int *, + u_long, u_long, u_long, u_int); +static int ioc4_bus_release_resource(device_t, device_t, int, int, + struct resource *); +static int ioc4_bus_get_resource(device_t, device_t, int, int, u_long *, + u_long *); + +static char ioc4_name[] = "ioc4"; static devclass_t ioc4_devclass; static device_method_t ioc4_methods[] = { @@ -65,7 +90,15 @@ static device_method_t ioc4_methods[] = DEVMETHOD(device_probe, ioc4_probe), DEVMETHOD(device_attach, ioc4_attach), DEVMETHOD(device_detach, ioc4_detach), - { 0, 0 } + + DEVMETHOD(bus_alloc_resource, ioc4_bus_alloc_resource), + DEVMETHOD(bus_get_resource, ioc4_bus_get_resource), + DEVMETHOD(bus_read_ivar, ioc4_bus_read_ivar), + DEVMETHOD(bus_release_resource, ioc4_bus_release_resource), + DEVMETHOD(bus_setup_intr, bus_generic_setup_intr), + DEVMETHOD(bus_teardown_intr, bus_generic_teardown_intr), + + DEVMETHOD_END }; static driver_t ioc4_driver = { @@ -74,6 +107,7 @@ static driver_t ioc4_driver = { sizeof(struct ioc4_softc), }; +#if 0 static int ioc4_intr(void *arg) { @@ -82,6 +116,80 @@ ioc4_intr(void *arg) device_printf(sc->sc_dev, "%s\n", __func__); return (FILTER_HANDLED); } +#endif + +static int +ioc4_child_add(struct ioc4_softc *sc, u_int type, u_int unit) +{ + struct ioc4_child *ch; + bus_space_handle_t bsh; + bus_space_tag_t bst; + u_long base, ofs, len; + int error; + + ch = malloc(sizeof(*ch), M_DEVBUF, M_WAITOK | M_ZERO); + ch->ch_softc = sc; + ch->ch_type = type; + ch->ch_unit = unit; + + error = ENXIO; + + ch->ch_dev = device_add_child(sc->sc_dev, NULL, -1); + if (ch->ch_dev == NULL) + goto fail_free; + + error = ENOMEM; + + base = rman_get_start(sc->sc_mres); + + switch (type) { + case IOC4_TYPE_UART: + ofs = IOC4_UART_REG(unit); + len = IOC4_UART_REG_SIZE; + break; + case IOC4_TYPE_ATA: + ofs = IOC4_ATA_BASE; + len = IOC4_ATA_SIZE; + break; + default: + ofs = len = 0; + break; + } + if (len == 0 || ofs == 0) + goto fail_free; + + ch->ch_mres = rman_reserve_resource(&sc->sc_rm, base + ofs, + base + ofs + len - 1, len, 0, NULL); + if (ch->ch_mres == NULL) + goto fail_delete; + + ch->ch_ires = sc->sc_ires; + + bsh = rman_get_bushandle(sc->sc_mres); + bst = rman_get_bustag(sc->sc_mres); + bus_space_subregion(bst, bsh, ofs, len, &bsh); + rman_set_bushandle(ch->ch_mres, bsh); + rman_set_bustag(ch->ch_mres, bst); + + device_set_ivars(ch->ch_dev, (void *)ch); + + error = device_probe_and_attach(ch->ch_dev); + if (error) + goto fail_release; + + return (0); + + fail_release: + rman_release_resource(ch->ch_mres); + + fail_delete: + device_delete_child(sc->sc_dev, ch->ch_dev); + + fail_free: + free(ch, M_DEVBUF); + device_printf(sc->sc_dev, "%s: error=%d\n", __func__, error); + return (error); +} static int ioc4_probe(device_t dev) @@ -99,27 +207,28 @@ ioc4_probe(device_t dev) static int ioc4_attach(device_t dev) { + char descr[RM_TEXTLEN]; struct ioc4_softc *sc; int error; sc = device_get_softc(dev); sc->sc_dev = dev; + error = ENXIO; + sc->sc_mrid = PCIR_BAR(0); sc->sc_mres = bus_alloc_resource_any(sc->sc_dev, SYS_RES_MEMORY, &sc->sc_mrid, RF_ACTIVE); if (sc->sc_mres == NULL) - return (ENXIO); + goto fail_return; sc->sc_irid = 0; sc->sc_ires = bus_alloc_resource_any(sc->sc_dev, SYS_RES_IRQ, &sc->sc_irid, RF_ACTIVE|RF_SHAREABLE); - if (sc->sc_ires == NULL) { - bus_release_resource(sc->sc_dev, SYS_RES_MEMORY, sc->sc_mrid, - sc->sc_mres); - return (ENXIO); - } + if (sc->sc_ires == NULL) + goto fail_rel_mres; +#if 0 error = bus_setup_intr(dev, sc->sc_ires, INTR_TYPE_TTY, ioc4_intr, NULL, sc, &sc->sc_icookie); if (error) @@ -129,19 +238,59 @@ ioc4_attach(device_t dev) else sc->sc_fastintr = 1; - if (error) { - bus_release_resource(sc->sc_dev, SYS_RES_IRQ, sc->sc_irid, - sc->sc_ires); - bus_release_resource(sc->sc_dev, SYS_RES_MEMORY, sc->sc_mrid, - sc->sc_mres); - return (error); - } + if (error) + goto fail_rel_ires; +#endif + + sc->sc_rm.rm_type = RMAN_ARRAY; + error = rman_init(&sc->sc_rm); + if (error) + goto fail_teardown; + error = rman_manage_region(&sc->sc_rm, rman_get_start(sc->sc_mres), + rman_get_end(sc->sc_mres)); + if (error) + goto fail_teardown; + + snprintf(descr, sizeof(descr), "%s I/O memory", + device_get_nameunit(sc->sc_dev)); + sc->sc_rm.rm_descr = strdup(descr, M_DEVBUF); + + pci_enable_busmaster(sc->sc_dev); + + bus_write_4(sc->sc_mres, IOC4_CTL_CR, 0xf); + bus_write_4(sc->sc_mres, IOC4_CTL_GPIO_SET, 0xf0); + + bus_write_4(sc->sc_mres, IOC4_CTL_UART_INT_CLR, ~0U); + bus_write_4(sc->sc_mres, IOC4_CTL_UART_INT, ~0U); + + bus_write_4(sc->sc_mres, IOC4_CTL_MISC_INT_CLR, ~0U); + bus_write_4(sc->sc_mres, IOC4_CTL_MISC_INT, ~0U); /* * Create, probe and attach children */ +#if 0 + for (n = 0; n < 4; n++) + ioc4_child_add(sc, IOC4_TYPE_UART, n); +#endif + ioc4_child_add(sc, IOC4_TYPE_ATA, 0); return (0); + + fail_teardown: + bus_teardown_intr(sc->sc_dev, sc->sc_ires, sc->sc_icookie); + +#if 0 + fail_rel_ires: +#endif + bus_release_resource(sc->sc_dev, SYS_RES_IRQ, sc->sc_irid, sc->sc_ires); + + fail_rel_mres: + bus_release_resource(sc->sc_dev, SYS_RES_MEMORY, sc->sc_mrid, + sc->sc_mres); + + fail_return: + return (error); } static int @@ -155,6 +304,9 @@ ioc4_detach(device_t dev) * Detach children and destroy children */ + free(__DECONST(void *, sc->sc_rm.rm_descr), M_DEVBUF); + rman_fini(&sc->sc_rm); + bus_teardown_intr(sc->sc_dev, sc->sc_ires, sc->sc_icookie); bus_release_resource(sc->sc_dev, SYS_RES_IRQ, sc->sc_irid, sc->sc_ires); @@ -163,4 +315,155 @@ ioc4_detach(device_t dev) return (0); } +static struct ioc4_child * +_ioc4_get_child(device_t dev, device_t child) +{ + struct ioc4_child *ch; + + /* Get our immediate child. */ + while (child != NULL && device_get_parent(child) != dev) + child = device_get_parent(child); + if (child == NULL) + return (NULL); + + ch = device_get_ivars(child); + KASSERT(ch != NULL, ("%s %d", __func__, __LINE__)); + return (ch); +} + +static int +ioc4_bus_read_ivar(device_t dev, device_t child, int index, uintptr_t *result) +{ + struct ioc4_child *ch; + struct ioc4_softc *sc; + uint32_t pci; + + if (result == NULL) + return (EINVAL); + + ch = _ioc4_get_child(dev, child); + if (ch == NULL) + return (EINVAL); + + sc = ch->ch_softc; + + switch(index) { + case IOC4_IVAR_CLOCK: + pci = bus_read_4(sc->sc_mres, IOC4_CTL_PCI); + *result = (pci & 1) ? 66666667 : 33333333; + break; + case IOC4_IVAR_TYPE: + *result = ch->ch_type; + break; + default: + return (ENOENT); + } + return (0); +} + +static struct resource * +ioc4_bus_alloc_resource(device_t dev, device_t child, int type, int *rid, + u_long start, u_long end, u_long count, u_int flags) +{ + struct ioc4_child *ch; + struct resource *res; + device_t assigned; + int error; + + if (rid == NULL || *rid != 0) + return (NULL); + + /* We only support default allocations. */ + if (start != 0UL || end != ~0UL) + return (NULL); + + ch = _ioc4_get_child(dev, child); + if (ch == NULL) + return (NULL); + + if (type == SYS_RES_IRQ) + return (ch->ch_ires); + if (type != SYS_RES_MEMORY) + return (NULL); + + res = ch->ch_mres; + + assigned = rman_get_device(res); + if (assigned == NULL) /* Not allocated */ + rman_set_device(res, child); + else if (assigned != child) + return (NULL); + + if (flags & RF_ACTIVE) { + error = rman_activate_resource(res); + if (error) { + if (assigned == NULL) + rman_set_device(res, NULL); + res = NULL; + } + } + + return (res); +} + +static int +ioc4_bus_release_resource(device_t dev, device_t child, int type, int rid, + struct resource *res) +{ + struct ioc4_child *ch; + + if (rid != 0 || res == NULL) + return (EINVAL); + + ch = _ioc4_get_child(dev, child); + if (ch == NULL) + return (EINVAL); + + if (type == SYS_RES_MEMORY) { + if (res != ch->ch_mres) + return (EINVAL); + } else if (type == SYS_RES_IRQ) { + if (res != ch->ch_ires) + return (EINVAL); + } else + return (EINVAL); + + if (rman_get_device(res) != child) + return (ENXIO); + if (rman_get_flags(res) & RF_ACTIVE) + rman_deactivate_resource(res); + rman_set_device(res, NULL); + return (0); +} + +static int +ioc4_bus_get_resource(device_t dev, device_t child, int type, int rid, + u_long *startp, u_long *countp) +{ + struct ioc4_child *ch; + struct resource *res; + u_long start; + + ch = _ioc4_get_child(dev, child); + if (ch == NULL) + return (EINVAL); + + if (type == SYS_RES_MEMORY) + res = ch->ch_mres; + else if (type == SYS_RES_IRQ) + res = ch->ch_ires; + else + return (ENXIO); + + if (rid != 0 || res == NULL) + return (ENXIO); + + start = rman_get_start(res); + if (startp != NULL) + *startp = start; + if (countp != NULL) + *countp = rman_get_end(res) - start + 1; + return (0); +} + DRIVER_MODULE(ioc4, pci, ioc4_driver, ioc4_devclass, 0, 0); Modified: projects/altix2/sys/dev/ioc4/ioc4_bus.h ============================================================================== --- projects/altix2/sys/dev/ioc4/ioc4_bus.h Tue Jun 12 01:13:59 2012 (r236939) +++ projects/altix2/sys/dev/ioc4/ioc4_bus.h Tue Jun 12 03:22:18 2012 (r236940) @@ -30,8 +30,10 @@ #define _DEV_IOC4_BUS_H_ #define IOC4_IVAR_TYPE 1 +#define IOC4_IVAR_CLOCK 2 #define IOC4_TYPE_NONE 0 #define IOC4_TYPE_UART 1 +#define IOC4_TYPE_ATA 2 #endif /* _DEV_IOC4_BUS_H_ */ Added: projects/altix2/sys/dev/ioc4/ioc4_reg.h ============================================================================== --- /dev/null 00:00:00 1970 (empty, because file is newly added) +++ projects/altix2/sys/dev/ioc4/ioc4_reg.h Tue Jun 12 03:22:18 2012 (r236940) @@ -0,0 +1,71 @@ +/*- + * Copyright (c) 2012 Marcel Moolenaar + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * $FreeBSD$ + */ + +#ifndef _DEV_IOC4_REG_H_ +#define _DEV_IOC4_REG_H_ + +#define IOC4_CTL_ERR_LO 0x0000 +#define IOC4_CTL_ERR_HI 0x0004 +#define IOC4_CTL_UART_INT 0x0008 +#define IOC4_CTL_MISC_INT 0x000c +#define IOC4_CTL_UART_INT_SET 0x0010 +#define IOC4_CTL_MISC_INT_SET 0x0014 +#define IOC4_CTL_UART_INT_CLR 0x0018 +#define IOC4_CTL_MISC_INT_CLR 0x001c +#define IOC4_CTL_CR 0x0020 +#define IOC4_CTL_PCI 0x0024 +#define IOC4_CTL_EXTINT 0x0028 + +#define IOC4_CTL_GPIO_SET 0x0030 +#define IOC4_CTL_GPIO_CLR 0x0034 +#define IOC4_CTL_GPIO_DATA 0x0038 + +#define IOC4_GPIO_0 0x0040 +#define IOC4_GPIO_1 0x0044 +#define IOC4_GPIO_2 0x0048 +#define IOC4_GPIO_3 0x004C +#define IOC4_GPIO_4 0x0050 +#define IOC4_GPIO_5 0x0054 +#define IOC4_GPIO_6 0x0058 +#define IOC4_GPIO_7 0x005C + +#define IOC4_ATA_BASE 0x0100 +#define IOC4_ATA_SIZE 0x0100 + +#define IOC4_KBD_BASE 0x0200 +#define IOC4_KBD_SIZE 0x0020 + +#define IOC4_UART_BASE 0x0300 +#define IOC4_UART_SIZE 0x0100 + +#define IOC4_UART_DMA_SIZE (7 * 4) +#define IOC4_UART_DMA(x) (0x0310 + (x) * IOC4_UART_DMA_SIZE) +#define IOC4_UART_REG_SIZE 8 +#define IOC4_UART_REG(x) (0x0380 + (x) * IOC4_UART_REG_SIZE) + +#endif /* _DEV_IOC4_REG_H_ */ Added: projects/altix2/sys/dev/uart/uart_bus_ioc4.c ============================================================================== --- /dev/null 00:00:00 1970 (empty, because file is newly added) +++ projects/altix2/sys/dev/uart/uart_bus_ioc4.c Tue Jun 12 03:22:18 2012 (r236940) @@ -0,0 +1,90 @@ +/*- + * Copyright (c) 2012 Marcel Moolenaar + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include <sys/cdefs.h> +__FBSDID("$FreeBSD$"); + +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/bus.h> +#include <sys/conf.h> +#include <sys/kernel.h> +#include <sys/module.h> + +#include <machine/bus.h> +#include <sys/rman.h> +#include <machine/resource.h> + +#include <sys/serial.h> +#include <serdev_if.h> + +#include <dev/ioc4/ioc4_bus.h> + +#include <dev/uart/uart.h> +#include <dev/uart/uart_bus.h> + +static int uart_ioc4_probe(device_t dev); + +static device_method_t uart_ioc4_methods[] = { + /* Device interface */ + DEVMETHOD(device_probe, uart_ioc4_probe), + DEVMETHOD(device_attach, uart_bus_attach), + DEVMETHOD(device_detach, uart_bus_detach), + /* Serdev interface */ + DEVMETHOD(serdev_ihand, uart_bus_ihand), + DEVMETHOD(serdev_ipend, uart_bus_ipend), + { 0, 0 } +}; + +static driver_t uart_ioc4_driver = { + uart_driver_name, + uart_ioc4_methods, + sizeof(struct uart_softc), +}; + +static int +uart_ioc4_probe(device_t dev) +{ + device_t parent; + struct uart_softc *sc; + uintptr_t rclk, type; + + parent = device_get_parent(dev); + + if (BUS_READ_IVAR(parent, dev, IOC4_IVAR_TYPE, &type)) + return (ENXIO); + if (type != IOC4_TYPE_UART) + return (ENXIO); + + sc = device_get_softc(dev); + sc->sc_class = &uart_ns8250_class; + + if (BUS_READ_IVAR(parent, dev, IOC4_IVAR_CLOCK, &rclk)) + rclk = 0; + return (uart_bus_probe(dev, 0, rclk, 0, 0)); +} + +DRIVER_MODULE(uart, ioc4, uart_ioc4_driver, uart_devclass, 0, 0);
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201206120322.q5C3MJF8026808>