pswitch.c revision 174898
112048Speter/*-
212048Speter * Copyright (C) 2002 Benno Rice.
312048Speter * All rights reserved.
412048Speter *
512048Speter * Redistribution and use in source and binary forms, with or without
612048Speter * modification, are permitted provided that the following conditions
712048Speter * are met:
812048Speter * 1. Redistributions of source code must retain the above copyright
912048Speter *    notice, this list of conditions and the following disclaimer.
1012048Speter * 2. Redistributions in binary form must reproduce the above copyright
1112048Speter *    notice, this list of conditions and the following disclaimer in the
1212048Speter *    documentation and/or other materials provided with the distribution.
1312048Speter *
1412048Speter * THIS SOFTWARE IS PROVIDED BY Benno Rice ``AS IS'' AND ANY EXPRESS OR
1512048Speter * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
1612048Speter * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
1712048Speter * IN NO EVENT SHALL TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
1812048Speter * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
1912048Speter * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
2012048Speter * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
2112048Speter * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
2212048Speter * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
2312048Speter * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
2412048Speter *
2512048Speter * $FreeBSD: head/sys/powerpc/powermac/pswitch.c 174898 2007-12-25 17:52:02Z rwatson $
2612048Speter */
2712048Speter
2812048Speter#include "opt_ddb.h"
2912048Speter
3012048Speter#include <sys/param.h>
3112048Speter#include <sys/systm.h>
3237001Scharnier#include <sys/kdb.h>
3350476Speter#include <sys/kernel.h>
3412048Speter#include <sys/module.h>
3512048Speter#include <sys/malloc.h>
3612048Speter#include <sys/bus.h>
3712048Speter#include <machine/bus.h>
3812048Speter#include <sys/rman.h>
3937001Scharnier
4012048Speter#include <machine/resource.h>
4112048Speter
4212048Speter#include <dev/ofw/openfirm.h>
4312048Speter
44122621Sjohan#include <powerpc/powermac/maciovar.h>
4512048Speter
4612048Speterstruct pswitch_softc {
4712048Speter	int	sc_irqrid;
4812048Speter	struct	resource *sc_irq;
4912048Speter	void	*sc_ih;
5012048Speter};
5112048Speter
5212048Speterstatic int	pswitch_probe(device_t);
5392881Simpstatic int	pswitch_attach(device_t);
5492881Simp
5512048Speterstatic int	pswitch_intr(void *);
5626557Scharnier
5792881Simpstatic device_method_t pswitch_methods[] = {
5812048Speter	/* Device interface */
5926557Scharnier	DEVMETHOD(device_probe,		pswitch_probe),
6026557Scharnier	DEVMETHOD(device_attach,	pswitch_attach),
6112048Speter
6212048Speter	{ 0, 0 }
6389826Sjoerg};
6489826Sjoerg
6512048Speterstatic driver_t pswitch_driver = {
6612048Speter	"pswitch",
6712048Speter	pswitch_methods,
6812048Speter	sizeof(struct pswitch_softc)
69102231Strhodes};
70102231Strhodes
7112048Speterstatic devclass_t pswitch_devclass;
7246080Simp
7392881SimpDRIVER_MODULE(pswitch, macio, pswitch_driver, pswitch_devclass, 0, 0);
7412048Speter
7512048Speterstatic int
7612048Speterpswitch_probe(device_t dev)
7712048Speter{
7826557Scharnier	char	*type = macio_get_devtype(dev);
7912048Speter
8012048Speter	if (strcmp(type, "gpio") != 0)
8126557Scharnier		return (ENXIO);
8226557Scharnier
8326557Scharnier	device_set_desc(dev, "GPIO Programmer's Switch");
8412048Speter	return (0);
8512048Speter}
8612048Speter
8712048Speterstatic int
8824956Sjoergpswitch_attach(device_t dev)
8924956Sjoerg{
9024956Sjoerg	struct		pswitch_softc *sc;
9112048Speter	phandle_t	node, child;
9212048Speter	char		type[32];
9312048Speter	u_int		irq[2];
9412048Speter
9518585Sguido	sc = device_get_softc(dev);
9618585Sguido	node = macio_get_node(dev);
9726557Scharnier
9826557Scharnier	for (child = OF_child(node); child != 0; child = OF_peer(child)) {
9926557Scharnier		if (OF_getprop(child, "device_type", type, 32) == -1)
10026557Scharnier			continue;
10118585Sguido
10275884Siedowse		if (strcmp(type, "programmer-switch") == 0)
10312048Speter			break;
104102231Strhodes	}
105102231Strhodes
10624956Sjoerg	if (child == 0) {
10712048Speter		device_printf(dev, "could not find correct node\n");
10824956Sjoerg		return (ENXIO);
10924956Sjoerg	}
11024956Sjoerg
11124956Sjoerg	if (OF_getprop(child, "interrupts", irq, sizeof(irq)) == -1) {
11224956Sjoerg		device_printf(dev, "could not get interrupt\n");
11324956Sjoerg		return (ENXIO);
11424956Sjoerg	}
11524956Sjoerg
11612048Speter	sc->sc_irqrid = 0;
11712048Speter	sc->sc_irq = bus_alloc_resource(dev, SYS_RES_IRQ, &sc->sc_irqrid,
11812048Speter	    irq[0], irq[0], 1, RF_ACTIVE);
11992881Simp	if (sc->sc_irq == NULL) {
12092881Simp		device_printf(dev, "could not allocate interrupt\n");
12112048Speter		return (ENXIO);
12212048Speter	}
12312048Speter
12412048Speter	if (bus_setup_intr(dev, sc->sc_irq, INTR_TYPE_MISC,
12589827Sjoerg	    pswitch_intr, NULL, dev, &sc->sc_ih) != 0) {
12612048Speter		device_printf(dev, "could not setup interrupt\n");
12712048Speter		bus_release_resource(dev, SYS_RES_IRQ, sc->sc_irqrid,
12812048Speter		    sc->sc_irq);
12912048Speter		return (ENXIO);
13012048Speter	}
13112048Speter
13212048Speter	return (0);
13312048Speter}
13412048Speter
13512048Speterstatic int
13612048Speterpswitch_intr(void *arg)
13718498Sguido{
13812048Speter	device_t	dev;
13912048Speter
14012048Speter	dev = (device_t)arg;
14112048Speter
14212048Speter	kdb_enter(KDB_WHY_POWERPC, device_get_nameunit(dev));
14312048Speter	return (FILTER_HANDLED);
14412048Speter}
14512048Speter