1157299Smarcel/*- 2157299Smarcel * Copyright (c) 2004-2006 Marcel Moolenaar 3157299Smarcel * All rights reserved. 4157299Smarcel * 5157299Smarcel * Redistribution and use in source and binary forms, with or without 6157299Smarcel * modification, are permitted provided that the following conditions 7157299Smarcel * are met: 8157299Smarcel * 9157299Smarcel * 1. Redistributions of source code must retain the above copyright 10157299Smarcel * notice, this list of conditions and the following disclaimer. 11157299Smarcel * 2. Redistributions in binary form must reproduce the above copyright 12157299Smarcel * notice, this list of conditions and the following disclaimer in the 13157299Smarcel * documentation and/or other materials provided with the distribution. 14157299Smarcel * 15157299Smarcel * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 16157299Smarcel * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 17157299Smarcel * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 18157299Smarcel * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 19157299Smarcel * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 20157299Smarcel * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 21157299Smarcel * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 22157299Smarcel * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 23157299Smarcel * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 24157299Smarcel * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25157299Smarcel */ 26157299Smarcel 27157299Smarcel#include <sys/cdefs.h> 28157299Smarcel__FBSDID("$FreeBSD$"); 29157299Smarcel 30157299Smarcel#include <sys/param.h> 31157299Smarcel#include <sys/systm.h> 32157299Smarcel#include <sys/bus.h> 33157299Smarcel#include <sys/conf.h> 34157299Smarcel#include <sys/kernel.h> 35157299Smarcel#include <sys/module.h> 36157299Smarcel 37157299Smarcel#include <machine/bus.h> 38157299Smarcel#include <sys/rman.h> 39157299Smarcel#include <machine/resource.h> 40157299Smarcel 41157299Smarcel#include <dev/scc/scc_bus.h> 42157299Smarcel 43157299Smarcel#include <dev/uart/uart.h> 44157299Smarcel#include <dev/uart/uart_bus.h> 45157299Smarcel 46157299Smarcelstatic int uart_scc_attach(device_t dev); 47157299Smarcelstatic int uart_scc_probe(device_t dev); 48157299Smarcel 49157299Smarcelstatic device_method_t uart_scc_methods[] = { 50157299Smarcel /* Device interface */ 51157299Smarcel DEVMETHOD(device_probe, uart_scc_probe), 52157299Smarcel DEVMETHOD(device_attach, uart_scc_attach), 53157299Smarcel DEVMETHOD(device_detach, uart_bus_detach), 54157299Smarcel /* Serdev interface */ 55157299Smarcel DEVMETHOD(serdev_ihand, uart_bus_ihand), 56157299Smarcel DEVMETHOD(serdev_sysdev, uart_bus_sysdev), 57157299Smarcel { 0, 0 } 58157299Smarcel}; 59157299Smarcel 60157299Smarcelstatic driver_t uart_scc_driver = { 61157299Smarcel uart_driver_name, 62157299Smarcel uart_scc_methods, 63157299Smarcel sizeof(struct uart_softc), 64157299Smarcel}; 65157299Smarcel 66157299Smarcelstatic int 67157299Smarceluart_scc_attach(device_t dev) 68157299Smarcel{ 69157299Smarcel device_t parent; 70157299Smarcel struct uart_softc *sc; 71157299Smarcel uintptr_t mtx; 72157299Smarcel 73157299Smarcel parent = device_get_parent(dev); 74157299Smarcel sc = device_get_softc(dev); 75157299Smarcel 76157299Smarcel if (BUS_READ_IVAR(parent, dev, SCC_IVAR_HWMTX, &mtx)) 77157299Smarcel return (ENXIO); 78157299Smarcel sc->sc_hwmtx = (struct mtx *)(void *)mtx; 79157299Smarcel return (uart_bus_attach(dev)); 80157299Smarcel} 81157299Smarcel 82157299Smarcelstatic int 83157299Smarceluart_scc_probe(device_t dev) 84157299Smarcel{ 85157299Smarcel device_t parent; 86157299Smarcel struct uart_softc *sc; 87157299Smarcel uintptr_t ch, cl, md, rs; 88157299Smarcel 89157299Smarcel parent = device_get_parent(dev); 90157299Smarcel sc = device_get_softc(dev); 91157299Smarcel 92157299Smarcel if (BUS_READ_IVAR(parent, dev, SCC_IVAR_MODE, &md) || 93157299Smarcel BUS_READ_IVAR(parent, dev, SCC_IVAR_CLASS, &cl)) 94157299Smarcel return (ENXIO); 95157299Smarcel if (md != SCC_MODE_ASYNC) 96157299Smarcel return (ENXIO); 97157299Smarcel switch (cl) { 98176772Sraj case SCC_CLASS_QUICC: 99176772Sraj sc->sc_class = &uart_quicc_class; 100176772Sraj break; 101157299Smarcel case SCC_CLASS_SAB82532: 102157299Smarcel sc->sc_class = &uart_sab82532_class; 103157299Smarcel break; 104157299Smarcel case SCC_CLASS_Z8530: 105157299Smarcel sc->sc_class = &uart_z8530_class; 106157299Smarcel break; 107157299Smarcel default: 108157299Smarcel return (ENXIO); 109157299Smarcel } 110157299Smarcel if (BUS_READ_IVAR(parent, dev, SCC_IVAR_CHANNEL, &ch) || 111157299Smarcel BUS_READ_IVAR(parent, dev, SCC_IVAR_CLOCK, &cl) || 112157299Smarcel BUS_READ_IVAR(parent, dev, SCC_IVAR_REGSHFT, &rs)) 113157299Smarcel return (ENXIO); 114157299Smarcel 115157299Smarcel return (uart_bus_probe(dev, rs, cl, 0, ch)); 116157299Smarcel} 117157299Smarcel 118157299SmarcelDRIVER_MODULE(uart, scc, uart_scc_driver, uart_devclass, 0, 0); 119