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: releng/10.3/sys/dev/uart/uart_bus_scc.c 176772 2008-03-03 18:20:17Z raj $");
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