xref: /freebsd/sys/powerpc/mikrotik/rb_led.c (revision fdafd315ad0d0f28a11b9fb4476a9ab059c62b92)
1d9720179SJustin Hibbits /*-
2d9720179SJustin Hibbits  * Copyright (c) 2017 Justin Hibbits
3d9720179SJustin Hibbits  * All rights reserved.
4d9720179SJustin Hibbits  *
5d9720179SJustin Hibbits  * Redistribution and use in source and binary forms, with or without
6d9720179SJustin Hibbits  * modification, are permitted provided that the following conditions
7d9720179SJustin Hibbits  * are met:
8d9720179SJustin Hibbits  * 1. Redistributions of source code must retain the above copyright
9d9720179SJustin Hibbits  *    notice, this list of conditions and the following disclaimer.
10d9720179SJustin Hibbits  * 2. Redistributions in binary form must reproduce the above copyright
11d9720179SJustin Hibbits  *    notice, this list of conditions and the following disclaimer in the
12d9720179SJustin Hibbits  *    documentation and/or other materials provided with the distribution.
13d9720179SJustin Hibbits  *
14d9720179SJustin Hibbits  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
15d9720179SJustin Hibbits  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
16d9720179SJustin Hibbits  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
17d9720179SJustin Hibbits  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
18d9720179SJustin Hibbits  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
19d9720179SJustin Hibbits  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
20d9720179SJustin Hibbits  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
21d9720179SJustin Hibbits  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
22d9720179SJustin Hibbits  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23d9720179SJustin Hibbits  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24d9720179SJustin Hibbits  * SUCH DAMAGE.
25d9720179SJustin Hibbits  *
26d9720179SJustin Hibbits  */
27d9720179SJustin Hibbits 
28d9720179SJustin Hibbits #include <sys/param.h>
29d9720179SJustin Hibbits #include <sys/systm.h>
30d9720179SJustin Hibbits #include <sys/module.h>
31d9720179SJustin Hibbits #include <sys/bus.h>
32d9720179SJustin Hibbits #include <sys/conf.h>
33d9720179SJustin Hibbits #include <sys/kernel.h>
34d9720179SJustin Hibbits 
35d9720179SJustin Hibbits #include <dev/ofw/ofw_bus.h>
36d9720179SJustin Hibbits #include <dev/ofw/openfirm.h>
37d9720179SJustin Hibbits #include <dev/led/led.h>
38d9720179SJustin Hibbits 
39d9720179SJustin Hibbits #include "gpio_if.h"
40d9720179SJustin Hibbits 
41d9720179SJustin Hibbits struct rbled_softc {
42d9720179SJustin Hibbits 	struct cdev	*sc_led;
43d9720179SJustin Hibbits 	device_t	 sc_gpio;
44d9720179SJustin Hibbits 	uint32_t	 sc_ledpin;
45d9720179SJustin Hibbits };
46d9720179SJustin Hibbits 
47d9720179SJustin Hibbits static int	rbled_probe(device_t);
48d9720179SJustin Hibbits static int	rbled_attach(device_t);
49d9720179SJustin Hibbits static int	rbled_detach(device_t);
50d9720179SJustin Hibbits static void	rbled_toggle(void *, int);
51d9720179SJustin Hibbits 
52d9720179SJustin Hibbits static device_method_t  rbled_methods[] = {
53d9720179SJustin Hibbits 	/* Device interface */
54d9720179SJustin Hibbits 	DEVMETHOD(device_probe,		rbled_probe),
55d9720179SJustin Hibbits 	DEVMETHOD(device_attach,	rbled_attach),
56d9720179SJustin Hibbits         DEVMETHOD(device_detach,        rbled_detach),
57d9720179SJustin Hibbits 
58d9720179SJustin Hibbits 	DEVMETHOD_END
59d9720179SJustin Hibbits };
60d9720179SJustin Hibbits 
61d9720179SJustin Hibbits static driver_t rbled_driver = {
62d9720179SJustin Hibbits 	"rbled",
63d9720179SJustin Hibbits 	rbled_methods,
64d9720179SJustin Hibbits 	sizeof(struct rbled_softc),
65d9720179SJustin Hibbits };
66d9720179SJustin Hibbits 
67*54b3d1efSJohn Baldwin DRIVER_MODULE(rbled, simplebus, rbled_driver, 0, 0);
68d9720179SJustin Hibbits 
69d9720179SJustin Hibbits static int
rbled_probe(device_t dev)70d9720179SJustin Hibbits rbled_probe(device_t dev)
71d9720179SJustin Hibbits {
72d9720179SJustin Hibbits 	phandle_t node;
73d9720179SJustin Hibbits 	const char *name;
74d9720179SJustin Hibbits 	cell_t gp[2];
75d9720179SJustin Hibbits 	char model[6];
76d9720179SJustin Hibbits 
77d9720179SJustin Hibbits 	node = ofw_bus_get_node(dev);
78d9720179SJustin Hibbits 
79d9720179SJustin Hibbits 	name = ofw_bus_get_name(dev);
80d9720179SJustin Hibbits 	if (name == NULL)
81d9720179SJustin Hibbits 		return (ENXIO);
82d9720179SJustin Hibbits 	if (strcmp(name, "led") != 0)
83d9720179SJustin Hibbits 		return (ENXIO);
84d9720179SJustin Hibbits 
85d9720179SJustin Hibbits 	if (OF_getprop(node, "user_led", gp, sizeof(gp)) <= 0)
86d9720179SJustin Hibbits 		return (ENXIO);
87d9720179SJustin Hibbits 
88d9720179SJustin Hibbits 	/* Check root model. */
89d9720179SJustin Hibbits 	node = OF_peer(0);
90d9720179SJustin Hibbits 	if (OF_getprop(node, "model", model, sizeof(model)) <= 0)
91d9720179SJustin Hibbits 		return (ENXIO);
92d9720179SJustin Hibbits 	if (strcmp(model, "RB800") != 0)
93d9720179SJustin Hibbits 		return (ENXIO);
94d9720179SJustin Hibbits 
95d9720179SJustin Hibbits 	device_set_desc(dev, "RouterBoard LED");
96d9720179SJustin Hibbits 	return (0);
97d9720179SJustin Hibbits }
98d9720179SJustin Hibbits 
99d9720179SJustin Hibbits static int
rbled_attach(device_t dev)100d9720179SJustin Hibbits rbled_attach(device_t dev)
101d9720179SJustin Hibbits {
102d9720179SJustin Hibbits 	struct rbled_softc *sc;
103d9720179SJustin Hibbits 	phandle_t node;
104d9720179SJustin Hibbits 	cell_t gp[2];
105d9720179SJustin Hibbits 
106d9720179SJustin Hibbits 	sc = device_get_softc(dev);
107d9720179SJustin Hibbits 	node = ofw_bus_get_node(dev);
108d9720179SJustin Hibbits 
109d9720179SJustin Hibbits 	if (OF_getprop(node, "user_led", gp, sizeof(gp)) <= 0)
110d9720179SJustin Hibbits 		return (ENXIO);
111d9720179SJustin Hibbits 
112d9720179SJustin Hibbits 	sc->sc_gpio = OF_device_from_xref(gp[0]);
113d9720179SJustin Hibbits 	if (sc->sc_gpio == NULL) {
114d9720179SJustin Hibbits 		device_printf(dev, "No GPIO resource found!\n");
115d9720179SJustin Hibbits 		return (ENXIO);
116d9720179SJustin Hibbits 	}
117d9720179SJustin Hibbits 	sc->sc_ledpin = gp[1];
118d9720179SJustin Hibbits 
119d9720179SJustin Hibbits 	sc->sc_led = led_create(rbled_toggle, sc, "user_led");
120d9720179SJustin Hibbits 
121d9720179SJustin Hibbits 	if (sc->sc_led == NULL)
122d9720179SJustin Hibbits 		return (ENXIO);
123d9720179SJustin Hibbits 
124d9720179SJustin Hibbits 	return (0);
125d9720179SJustin Hibbits }
126d9720179SJustin Hibbits 
127d9720179SJustin Hibbits static int
rbled_detach(device_t dev)128d9720179SJustin Hibbits rbled_detach(device_t dev)
129d9720179SJustin Hibbits {
130d9720179SJustin Hibbits 	struct rbled_softc *sc;
131d9720179SJustin Hibbits 
132d9720179SJustin Hibbits 	sc = device_get_softc(dev);
133d9720179SJustin Hibbits 	led_destroy(sc->sc_led);
134d9720179SJustin Hibbits 
135d9720179SJustin Hibbits 	return (0);
136d9720179SJustin Hibbits }
137d9720179SJustin Hibbits 
138d9720179SJustin Hibbits static void
rbled_toggle(void * priv,int onoff)139d9720179SJustin Hibbits rbled_toggle(void *priv, int onoff)
140d9720179SJustin Hibbits {
141d9720179SJustin Hibbits 	struct rbled_softc *sc = priv;
142d9720179SJustin Hibbits 
143d9720179SJustin Hibbits 	GPIO_PIN_SET(sc->sc_gpio, sc->sc_ledpin, onoff);
144d9720179SJustin Hibbits }
145