Changeset View
Changeset View
Standalone View
Standalone View
sys/mips/broadcom/uart_bus_chipc.c
| Show All 39 Lines | |||||
| #include <machine/bus.h> | #include <machine/bus.h> | ||||
| #include <machine/resource.h> | #include <machine/resource.h> | ||||
| #include <dev/uart/uart.h> | #include <dev/uart/uart.h> | ||||
| #include <dev/uart/uart_bus.h> | #include <dev/uart/uart_bus.h> | ||||
| #include <dev/uart/uart_cpu.h> | #include <dev/uart/uart_cpu.h> | ||||
| #include <dev/bhnd/cores/chipc/chipcvar.h> | |||||
| #include "uart_if.h" | #include "uart_if.h" | ||||
| #include "bhnd_chipc_if.h" | #include "bhnd_chipc_if.h" | ||||
| #include "bcm_socinfo.h" | |||||
| static int uart_chipc_probe(device_t dev); | |||||
| extern SLIST_HEAD(uart_devinfo_list, uart_devinfo) uart_sysdevs; | |||||
| static void | |||||
| uart_chipc_identify(driver_t *driver, device_t parent) | |||||
| { | |||||
| struct chipc_caps *caps; | |||||
| if (device_find_child(parent, "uart", -1) != NULL) | |||||
| return; | |||||
| caps = BHND_CHIPC_GET_CAPS(parent); | |||||
| if (caps == NULL) { | |||||
| device_printf(parent, "error: can't retrieve ChipCommon " | |||||
| "capabilities\n"); | |||||
| return; | |||||
| } | |||||
| if (caps->num_uarts == 0) | |||||
| return; | |||||
| /* | |||||
| * TODO: add more than one UART | |||||
| */ | |||||
| BUS_ADD_CHILD(parent, 0, "uart", -1); | |||||
| } | |||||
| static int | static int | ||||
| uart_chipc_probe(device_t dev) | uart_chipc_probe(device_t dev) | ||||
| { | { | ||||
| struct uart_softc *sc; | struct uart_softc *sc; | ||||
| struct resource *res; | struct bcm_socinfo *socinfo; | ||||
| int rid; | |||||
| int err; | |||||
| rid = 0; | |||||
| res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid, RF_ACTIVE); | |||||
| if (res == NULL) { | |||||
| device_printf(dev, "can't allocate main resource\n"); | |||||
| return (ENXIO); | |||||
| } | |||||
| sc = device_get_softc(dev); | sc = device_get_softc(dev); | ||||
| sc->sc_class = &uart_ns8250_class; | sc->sc_class = &uart_ns8250_class; | ||||
| sc->sc_sysdev = SLIST_FIRST(&uart_sysdevs); | |||||
| if (sc->sc_sysdev == NULL) { | |||||
| device_printf(dev, "missing sysdev\n"); | |||||
| return (EINVAL); | |||||
| } | |||||
| bcopy(&sc->sc_sysdev->bas, &sc->sc_bas, sizeof(sc->sc_bas)); | /* TODO: UART rate should be calculated from CPU clock speed | ||||
| * as fetched from bhnd bus */ | |||||
| sc->sc_sysdev->bas.bst = rman_get_bustag(res); | socinfo = bcm_get_socinfo(); | ||||
| sc->sc_sysdev->bas.bsh = rman_get_bushandle(res); | return (uart_bus_probe(dev, 0, socinfo->uartrate, 0, 0)); | ||||
| sc->sc_bas.bst = sc->sc_sysdev->bas.bst; | |||||
| sc->sc_bas.bsh = sc->sc_sysdev->bas.bsh; | |||||
| err = bus_release_resource(dev, SYS_RES_MEMORY, rid, res); | |||||
| if (err) { | |||||
| device_printf(dev, "can't release resource [%d]\n", rid); | |||||
| return (ENXIO); | |||||
| } | } | ||||
| /* We use internal SoC clock generator with non-standart freq MHz */ | |||||
| return (uart_bus_probe(dev, 0, sc->sc_sysdev->bas.rclk, 0, 0)); | |||||
| } | |||||
| static device_method_t uart_chipc_methods[] = { | static device_method_t uart_chipc_methods[] = { | ||||
| /* Device interface */ | /* Device interface */ | ||||
| DEVMETHOD(device_identify, uart_chipc_identify), | |||||
| DEVMETHOD(device_probe, uart_chipc_probe), | DEVMETHOD(device_probe, uart_chipc_probe), | ||||
| DEVMETHOD(device_attach, uart_bus_attach), | DEVMETHOD(device_attach, uart_bus_attach), | ||||
| DEVMETHOD(device_detach, uart_bus_detach), | DEVMETHOD(device_detach, uart_bus_detach), | ||||
| { 0, 0 } | { 0, 0 } | ||||
| }; | }; | ||||
| static driver_t uart_chipc_driver = { | static driver_t uart_chipc_driver = { | ||||
| uart_driver_name, | uart_driver_name, | ||||
| uart_chipc_methods, | uart_chipc_methods, | ||||
| sizeof(struct uart_softc), | sizeof(struct uart_softc), | ||||
| }; | }; | ||||
| DRIVER_MODULE(uart, bhnd_chipc, uart_chipc_driver, uart_devclass, 0, 0); | DRIVER_MODULE(uart, bhnd_chipc, uart_chipc_driver, uart_devclass, 0, 0); | ||||