No empty .Rs/.Re
[netbsd-mini2440.git] / sys / arch / evbarm / tsarm / toastersensors.c
blob8be37f3d7a88e234f216ab25e6033aafa29e1fc4
1 /* $NetBSD: toastersensors.c,v 1.7 2008/04/28 20:23:17 martin Exp $ */
3 /*-
4 * Copyright (c) 2005 The NetBSD Foundation, Inc.
5 * All rights reserved.
7 * This code is from software contributed to The NetBSD Foundation
8 * by Jesse Off.
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
12 * are met:
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
19 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 * POSSIBILITY OF SUCH DAMAGE.
31 #include <sys/cdefs.h>
32 __KERNEL_RCSID(0, "$NetBSD: toastersensors.c,v 1.7 2008/04/28 20:23:17 martin Exp $");
34 #include <sys/param.h>
35 #include <sys/sysctl.h>
36 #include <sys/systm.h>
37 #include <sys/proc.h>
38 #include <sys/poll.h>
39 #include <sys/conf.h>
40 #include <sys/uio.h>
41 #include <sys/types.h>
42 #include <sys/kernel.h>
43 #include <sys/device.h>
44 #include <sys/callout.h>
45 #include <sys/select.h>
47 #include <machine/bus.h>
48 #include <machine/autoconf.h>
50 #include <dev/wscons/wsconsio.h>
51 #include <dev/wscons/wskbdvar.h>
52 #include <dev/wscons/wsksymdef.h>
53 #include <dev/wscons/wsksymvar.h>
55 #include <arm/ep93xx/ep93xxreg.h>
56 #include <arm/ep93xx/epgpioreg.h>
57 #include <dev/ic/matrixkpvar.h>
58 #include <evbarm/tsarm/tspldvar.h>
59 #include <evbarm/tsarm/tsarmreg.h>
61 struct toastersensors_softc {
62 struct device sc_dev;
63 struct matrixkp_softc sc_mxkp;
64 bus_space_tag_t sc_iot;
65 bus_space_handle_t sc_gpioh;
66 bus_space_handle_t sc_adch;
67 u_int32_t toast_down;
68 u_int32_t burnlevel_knob;
69 u_int32_t cancel_key;
70 u_int32_t toast_key;
71 u_int32_t frozen_key;
72 u_int32_t warm_key;
73 u_int32_t bagel_key;
74 u_int32_t toast_down_ticks;
75 u_int32_t cancel_key_ticks;
76 u_int32_t toast_key_ticks;
77 u_int32_t frozen_key_ticks;
78 u_int32_t warm_key_ticks;
79 u_int32_t bagel_key_ticks;
80 struct callout poll;
83 #define KC(n) KS_KEYCODE(n)
84 static const keysym_t mxkp_keydesc_default[] = {
85 /* pos normal shifted */
86 KC(0), KS_f,
87 KC(1), KS_b,
88 KC(2), KS_w,
89 KC(3), KS_t,
90 KC(4), KS_c,
92 #undef KC
93 #define KBD_MAP(name, base, map) \
94 { name, base, sizeof(map)/sizeof(keysym_t), map }
95 const struct wscons_keydesc mxkp_keydesctab[] = {
96 KBD_MAP(KB_US, 0, mxkp_keydesc_default),
97 {0, 0, 0, 0}
99 #undef KBD_MAP
101 struct wskbd_mapdata mxkp_keymapdata = {
102 mxkp_keydesctab,
103 KB_US,
106 static int toastersensors_match(struct device *, struct cfdata *, void *);
107 static void toastersensors_attach(struct device *, struct device *, void *);
108 static void toastersensors_scankeys(struct matrixkp_softc *, u_int32_t *);
109 static void toastersensors_poll(void *);
111 CFATTACH_DECL(toastersensors, sizeof(struct toastersensors_softc),
112 toastersensors_match, toastersensors_attach, NULL, NULL);
114 static int
115 toastersensors_match(struct device *parent, struct cfdata *match, void *aux)
117 return 1;
120 #define GPIO_GET(x) bus_space_read_1(sc->sc_iot, sc->sc_gpioh, \
121 (EP93XX_GPIO_ ## x))
123 #define GPIO_SET(x, y) bus_space_write_1(sc->sc_iot, sc->sc_gpioh, \
124 (EP93XX_GPIO_ ## x), (y))
126 #define GPIO_SETBITS(x, y) bus_space_write_1(sc->sc_iot, sc->sc_gpioh, \
127 (EP93XX_GPIO_ ## x), GPIO_GET(x) | (y))
129 #define GPIO_CLEARBITS(x, y) bus_space_write_1(sc->sc_iot, sc->sc_gpioh, \
130 (EP93XX_GPIO_ ## x), GPIO_GET(x) & (~(y)))
132 static void
133 toastersensors_poll(void *arg)
135 struct toastersensors_softc *sc = arg;
137 if (sc->cancel_key) sc->cancel_key_ticks++;
138 if (sc->toast_key) sc->toast_key_ticks++;
139 if (sc->warm_key) sc->warm_key_ticks++;
140 if (sc->frozen_key) sc->frozen_key_ticks++;
141 if (sc->bagel_key) sc->bagel_key_ticks++;
142 if (sc->toast_down) sc->toast_down_ticks++;
144 sc->burnlevel_knob = bus_space_read_1(sc->sc_iot, sc->sc_adch, 0) |
145 (bus_space_read_1(sc->sc_iot, sc->sc_adch, 1) << 8);
146 /* Initiate another conversion */
147 bus_space_write_1(sc->sc_iot, sc->sc_adch, 0, 0x40);
148 callout_schedule(&sc->poll, 1);
151 static void
152 toastersensors_attach(struct device *parent, struct device *self, void *aux)
154 struct toastersensors_softc *sc = (void *)self;
155 struct tspld_attach_args *taa = aux;
156 struct wskbddev_attach_args wa;
157 const struct sysctlnode *node, *datnode;
158 u_int32_t i;
160 sc->sc_iot = taa->ta_iot;
161 if (bus_space_map(sc->sc_iot, EP93XX_APB_HWBASE + EP93XX_APB_GPIO,
162 EP93XX_APB_GPIO_SIZE, 0, &sc->sc_gpioh))
163 panic("toastersensors_attach: couldn't map GPIO registers");
165 if (bus_space_map(sc->sc_iot, TS7XXX_IO8_HWBASE + TS7XXX_MAX197ADC,
166 2, 0, &sc->sc_adch))
167 panic("toastersensors_attach: couldn't map MAX197-ADC registers");
169 sc->sc_mxkp.mxkp_scankeys = toastersensors_scankeys;
170 sc->sc_mxkp.mxkp_event = mxkp_wskbd_event;
171 sc->sc_mxkp.mxkp_nkeys = 5;
172 sc->sc_mxkp.debounce_stable_ms = 3;
173 sc->sc_mxkp.sc_dev = self;
174 sc->sc_mxkp.poll_freq = hz;
176 GPIO_CLEARBITS(PBDDR, 0x3f); /* tristate all lines */
178 aprint_normal(": internal toaster sensor inputs\n");
179 aprint_normal("%s: using signal DIO_0 for toast down sensor\n", sc->sc_dev.dv_xname);
180 aprint_normal("%s: using signals DIO_1-DIO_5 for panel buttons\n", sc->sc_dev.dv_xname);
181 aprint_normal("%s: using 12-bit MAX197-ADC channel 0 for burnlevel knob\n", sc->sc_dev.dv_xname);
183 if (sysctl_createv(NULL, 0, NULL, NULL,
184 CTLFLAG_PERMANENT, CTLTYPE_NODE, "hw",
185 NULL, NULL, 0, NULL, 0,
186 CTL_HW, CTL_EOL) != 0) {
187 printf("%s: could not create sysctl\n",
188 sc->sc_dev.dv_xname);
189 return;
191 if (sysctl_createv(NULL, 0, NULL, &node,
192 0, CTLTYPE_NODE, sc->sc_dev.dv_xname,
193 NULL,
194 NULL, 0, NULL, 0,
195 CTL_HW, CTL_CREATE, CTL_EOL) != 0) {
196 printf("%s: could not create sysctl\n",
197 sc->sc_dev.dv_xname);
198 return;
202 if ((i = sysctl_createv(NULL, 0, NULL, &datnode,
203 0, CTLTYPE_INT,
204 "burnlevel_knob",
205 SYSCTL_DESCR(
206 "12-bit analog reading of front-panel potentiometer"),
207 NULL, 0, &sc->burnlevel_knob, 0,
208 CTL_HW, node->sysctl_num,
209 CTL_CREATE, CTL_EOL))
210 != 0) {
211 printf("%s: could not create sysctl\n",
212 sc->sc_dev.dv_xname);
213 return;
216 #define KEYSYSCTL_SETUP(x) if ((i = sysctl_createv(NULL, 0, NULL, &datnode, \
217 0, CTLTYPE_INT, \
218 #x, \
219 SYSCTL_DESCR( \
220 "toaster user input sensor"), \
221 NULL, 0, &sc->x, 0, \
222 CTL_HW, node->sysctl_num, \
223 CTL_CREATE, CTL_EOL)) \
224 != 0) { \
225 printf("%s: could not create sysctl\n", \
226 sc->sc_dev.dv_xname); \
227 return; \
230 if ((i = sysctl_createv(NULL, 0, NULL, &datnode, \
231 CTLFLAG_READWRITE, CTLTYPE_INT, \
232 #x "_ticks", \
233 SYSCTL_DESCR( \
234 "running total of on-time in ticks"), \
235 NULL, 0, &sc->x ## _ticks, 0, \
236 CTL_HW, node->sysctl_num, \
237 CTL_CREATE, CTL_EOL)) \
238 != 0) { \
239 printf("%s: could not create sysctl\n", \
240 sc->sc_dev.dv_xname); \
241 return; \
244 KEYSYSCTL_SETUP(cancel_key);
245 KEYSYSCTL_SETUP(toast_key);
246 KEYSYSCTL_SETUP(bagel_key);
247 KEYSYSCTL_SETUP(warm_key);
248 KEYSYSCTL_SETUP(frozen_key);
249 KEYSYSCTL_SETUP(toast_down);
251 sc->cancel_key_ticks = 0;
252 sc->toast_key_ticks = 0;
253 sc->frozen_key_ticks = 0;
254 sc->warm_key_ticks = 0;
255 sc->bagel_key_ticks = 0;
256 sc->toast_down_ticks = 0;
258 mxkp_attach(&sc->sc_mxkp);
259 wa.console = 0;
260 wa.keymap = &mxkp_keymapdata;
261 wa.accessops = &mxkp_accessops;
262 wa.accesscookie = &sc->sc_mxkp;
263 sc->sc_mxkp.sc_wskbddev = config_found(self, &wa, wskbddevprint);
265 callout_init(&sc->poll, 0);
266 callout_setfunc(&sc->poll, toastersensors_poll, sc);
267 callout_schedule(&sc->poll, 1);
270 static void
271 toastersensors_scankeys(struct matrixkp_softc *mxkp_sc, u_int32_t *keys)
273 struct toastersensors_softc *sc = (void *)mxkp_sc->sc_dev;
274 u_int32_t val = GPIO_GET(PBDR) & 0x3f;
277 * toast_down isn't a key, but we update its state here since its
278 * read in the same reg.
280 sc->toast_down = (val & 0x1) ? 0 : 1;
282 *keys = ~(val >> 1);
284 sc->cancel_key = (*keys & 0x10) ? 1 : 0;
285 sc->toast_key = (*keys & 0x8) ? 1 : 0;
286 sc->warm_key = (*keys & 0x4) ? 1 : 0;
287 sc->bagel_key = (*keys & 0x2) ? 1 : 0;
288 sc->frozen_key = (*keys & 0x1) ? 1 : 0;