1/*-
2 * Copyright (c) 2012 Robert N. M. Watson
3 * All rights reserved.
4 *
5 * This software was developed by SRI International and the University of
6 * Cambridge Computer Laboratory under DARPA/AFRL contract (FA8750-10-C-0237)
7 * ("CTSRD"), as part of the DARPA CRASH research programme.
8 *
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
11 * are met:
12 * 1. Redistributions of source code must retain the above copyright
13 *    notice, this list of conditions and the following disclaimer.
14 * 2. Redistributions in binary form must reproduce the above copyright
15 *    notice, this list of conditions and the following disclaimer in the
16 *    documentation and/or other materials provided with the distribution.
17 *
18 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
19 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
22 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
24 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
26 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
27 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28 * SUCH DAMAGE.
29 */
30
31#include <sys/cdefs.h>
32__FBSDID("$FreeBSD: releng/10.2/sys/dev/terasic/de4led/terasic_de4led.c 245380 2013-01-13 16:57:11Z rwatson $");
33
34#include <sys/param.h>
35#include <sys/bus.h>
36#include <sys/lock.h>
37#include <sys/mutex.h>
38#include <sys/rman.h>
39
40#include <machine/bus.h>
41#include <machine/resource.h>
42
43#include <dev/led/led.h>
44#include <dev/terasic/de4led/terasic_de4led.h>
45
46devclass_t	terasic_de4led_devclass;
47
48static void
49terasic_de4led_update(struct terasic_de4led_softc *sc)
50{
51
52	TERASIC_DE4LED_LOCK_ASSERT(sc);
53
54	bus_write_1(sc->tdl_res, TERASIC_DE4LED_OFF_LED, sc->tdl_bits);
55}
56
57static void
58led_update(struct terasic_de4led_softc *sc, int bit, int onoff)
59{
60
61	TERASIC_DE4LED_LOCK(sc);
62	TERASIC_DE4LED_SETLED(sc, bit, onoff);
63	terasic_de4led_update(sc);
64	TERASIC_DE4LED_UNLOCK(sc);
65}
66
67static void
68led_0(void *arg, int onoff)
69{
70
71	led_update(arg, 0, onoff);
72}
73
74static void
75led_1(void *arg, int onoff)
76{
77
78	led_update(arg, 1, onoff);
79}
80
81static void
82led_2(void *arg, int onoff)
83{
84
85	led_update(arg, 2, onoff);
86}
87
88static void
89led_3(void *arg, int onoff)
90{
91
92	led_update(arg, 3, onoff);
93}
94
95static void
96led_4(void *arg, int onoff)
97{
98
99	led_update(arg, 4, onoff);
100}
101
102static void
103led_5(void *arg, int onoff)
104{
105
106	led_update(arg, 5, onoff);
107}
108
109static void
110led_6(void *arg, int onoff)
111{
112
113	led_update(arg, 6, onoff);
114}
115
116static void
117led_7(void *arg, int onoff)
118{
119
120	led_update(arg, 7, onoff);
121}
122
123void
124terasic_de4led_attach(struct terasic_de4led_softc *sc)
125{
126	const char *cmd;
127
128	TERASIC_DE4LED_LOCK_INIT(sc);
129
130	/*
131	 * Clear the LED array before we start.
132	 */
133	TERASIC_DE4LED_LOCK(sc);
134	TERASIC_DE4LED_CLEARBAR(sc);
135	terasic_de4led_update(sc);
136	TERASIC_DE4LED_UNLOCK(sc);
137
138	/*
139	 * Register the LED array with led(4).
140	 */
141	sc->tdl_leds[0] = led_create(led_0, sc, "de4led_0");
142	sc->tdl_leds[1] = led_create(led_1, sc, "de4led_1");
143	sc->tdl_leds[2] = led_create(led_2, sc, "de4led_2");
144	sc->tdl_leds[3] = led_create(led_3, sc, "de4led_3");
145	sc->tdl_leds[4] = led_create(led_4, sc, "de4led_4");
146	sc->tdl_leds[5] = led_create(led_5, sc, "de4led_5");
147	sc->tdl_leds[6] = led_create(led_6, sc, "de4led_6");
148	sc->tdl_leds[7] = led_create(led_7, sc, "de4led_7");
149
150	if (resource_string_value(device_get_name(sc->tdl_dev),
151	    sc->tdl_unit, "de4led_0_cmd", &cmd) == 0)
152		led_set("de4led_0", cmd);
153	if (resource_string_value(device_get_name(sc->tdl_dev),
154	    sc->tdl_unit, "de4led_1_cmd", &cmd) == 0)
155		led_set("de4led_1", cmd);
156	if (resource_string_value(device_get_name(sc->tdl_dev),
157	    sc->tdl_unit, "de4led_2_cmd", &cmd) == 0)
158		led_set("de4led_2", cmd);
159	if (resource_string_value(device_get_name(sc->tdl_dev),
160	    sc->tdl_unit, "de4led_3_cmd", &cmd) == 0)
161		led_set("de4led_3", cmd);
162	if (resource_string_value(device_get_name(sc->tdl_dev),
163	    sc->tdl_unit, "de4led_4_cmd", &cmd) == 0)
164		led_set("de4led_4", cmd);
165	if (resource_string_value(device_get_name(sc->tdl_dev),
166	    sc->tdl_unit, "de4led_5_cmd", &cmd) == 0)
167		led_set("de4led_5", cmd);
168	if (resource_string_value(device_get_name(sc->tdl_dev),
169	    sc->tdl_unit, "de4led_6_cmd", &cmd) == 0)
170		led_set("de4led_6", cmd);
171	if (resource_string_value(device_get_name(sc->tdl_dev),
172	    sc->tdl_unit, "de4led_7_cmd", &cmd) == 0)
173		led_set("de4led_7", cmd);
174}
175
176void
177terasic_de4led_detach(struct terasic_de4led_softc *sc)
178{
179	int i;
180
181	for (i = 0; i < 8; i++) {
182		led_destroy(sc->tdl_leds[i]);
183		sc->tdl_leds[i] = NULL;
184	}
185	TERASIC_DE4LED_LOCK(sc);
186	TERASIC_DE4LED_CLEARBAR(sc);
187	terasic_de4led_update(sc);
188	TERASIC_DE4LED_UNLOCK(sc);
189	TERASIC_DE4LED_LOCK_DESTROY(sc);
190}
191