psh3pwr.c revision 1.1 1 1.1 kiyohara /* $NetBSD: psh3pwr.c,v 1.1 2007/09/24 16:16:42 kiyohara Exp $ */
2 1.1 kiyohara /*
3 1.1 kiyohara * Copyright (c) 2005, 2007 KIYOHARA Takashi
4 1.1 kiyohara * All rights reserved.
5 1.1 kiyohara *
6 1.1 kiyohara * Redistribution and use in source and binary forms, with or without
7 1.1 kiyohara * modification, are permitted provided that the following conditions
8 1.1 kiyohara * are met:
9 1.1 kiyohara * 1. Redistributions of source code must retain the above copyright
10 1.1 kiyohara * notice, this list of conditions and the following disclaimer.
11 1.1 kiyohara * 2. Redistributions in binary form must reproduce the above copyright
12 1.1 kiyohara * notice, this list of conditions and the following disclaimer in the
13 1.1 kiyohara * documentation and/or other materials provided with the distribution.
14 1.1 kiyohara *
15 1.1 kiyohara * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
16 1.1 kiyohara * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
17 1.1 kiyohara * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
18 1.1 kiyohara * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
19 1.1 kiyohara * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
20 1.1 kiyohara * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
21 1.1 kiyohara * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22 1.1 kiyohara * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
23 1.1 kiyohara * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
24 1.1 kiyohara * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
25 1.1 kiyohara * POSSIBILITY OF SUCH DAMAGE.
26 1.1 kiyohara *
27 1.1 kiyohara */
28 1.1 kiyohara
29 1.1 kiyohara #include <sys/cdefs.h>
30 1.1 kiyohara __KERNEL_RCSID(0, "$NetBSD: psh3pwr.c,v 1.1 2007/09/24 16:16:42 kiyohara Exp $");
31 1.1 kiyohara
32 1.1 kiyohara #include <sys/param.h>
33 1.1 kiyohara #include <sys/kernel.h>
34 1.1 kiyohara #include <sys/device.h>
35 1.1 kiyohara #include <sys/systm.h>
36 1.1 kiyohara #include <sys/callout.h>
37 1.1 kiyohara
38 1.1 kiyohara #include <machine/platid.h>
39 1.1 kiyohara #include <machine/platid_mask.h>
40 1.1 kiyohara
41 1.1 kiyohara #include <dev/sysmon/sysmonvar.h>
42 1.1 kiyohara
43 1.1 kiyohara #include <sh3/exception.h>
44 1.1 kiyohara #include <sh3/intcreg.h>
45 1.1 kiyohara #include <sh3/pfcreg.h>
46 1.1 kiyohara
47 1.1 kiyohara #include <sh3/dev/adcvar.h>
48 1.1 kiyohara
49 1.1 kiyohara
50 1.1 kiyohara #ifdef PSH3PWR_DEBUG
51 1.1 kiyohara #define DPRINTF(arg) printf arg
52 1.1 kiyohara #else
53 1.1 kiyohara #define DPRINTF(arg) ((void)0)
54 1.1 kiyohara #endif
55 1.1 kiyohara
56 1.1 kiyohara
57 1.1 kiyohara /* A/D covnerter channels to get power stats from */
58 1.1 kiyohara #define ADC_CHANNEL_BATTERY 3
59 1.1 kiyohara
60 1.1 kiyohara /* On/Off bit for Green LED. pin 7 in SH7709 GPIO port H. */
61 1.1 kiyohara #define PSH3_GREEN_LED_ON 0x80
62 1.1 kiyohara
63 1.1 kiyohara /*
64 1.1 kiyohara * XXXX:
65 1.1 kiyohara * WindowsCE seem to be using this as a flag.
66 1.1 kiyohara * pin 6 in SH7709 GPIO port SCPDR.
67 1.1 kiyohara */
68 1.1 kiyohara #define PSH3PWR_PLUG_OUT 0x40
69 1.1 kiyohara
70 1.1 kiyohara /* warn that main battery is low after drops below this value */
71 1.1 kiyohara #define PSH3PWR_BATTERY_WARNING_THRESHOLD 200
72 1.1 kiyohara
73 1.1 kiyohara
74 1.1 kiyohara struct psh3pwr_softc {
75 1.1 kiyohara struct device sc_dev;
76 1.1 kiyohara
77 1.1 kiyohara struct callout sc_poll_ch;
78 1.1 kiyohara void *sc_ih_pin;
79 1.1 kiyohara void *sc_ih_pout;
80 1.1 kiyohara
81 1.1 kiyohara int sc_plug; /* In/Out flug */
82 1.1 kiyohara int sc_capacity;
83 1.1 kiyohara
84 1.1 kiyohara struct sysmon_envsys sc_sysmon;
85 1.1 kiyohara struct envsys_data sc_data;
86 1.1 kiyohara };
87 1.1 kiyohara
88 1.1 kiyohara static int psh3pwr_match(struct device *, struct cfdata *, void *);
89 1.1 kiyohara static void psh3pwr_attach(struct device *, struct device *, void *);
90 1.1 kiyohara
91 1.1 kiyohara CFATTACH_DECL(psh3pwr, sizeof(struct psh3pwr_softc),
92 1.1 kiyohara psh3pwr_match, psh3pwr_attach, NULL, NULL);
93 1.1 kiyohara
94 1.1 kiyohara static int psh3pwr_intr_plug_out(void *);
95 1.1 kiyohara static int psh3pwr_intr_plug_in(void *);
96 1.1 kiyohara static void psh3pwr_poll_callout(void *);
97 1.1 kiyohara static void psh3pwr_sleep(void *);
98 1.1 kiyohara static int psh3pwr_gtredata(struct sysmon_envsys *, envsys_data_t *);
99 1.1 kiyohara
100 1.1 kiyohara
101 1.1 kiyohara static int
102 1.1 kiyohara psh3pwr_match(struct device *parent, struct cfdata *cfp, void *aux)
103 1.1 kiyohara {
104 1.1 kiyohara
105 1.1 kiyohara if (!platid_match(&platid, &platid_mask_MACH_HITACHI_PERSONA))
106 1.1 kiyohara return 0;
107 1.1 kiyohara
108 1.1 kiyohara if (strcmp(cfp->cf_name, "psh3pwr") != 0)
109 1.1 kiyohara return 0;
110 1.1 kiyohara
111 1.1 kiyohara return 1;
112 1.1 kiyohara }
113 1.1 kiyohara
114 1.1 kiyohara
115 1.1 kiyohara static void
116 1.1 kiyohara psh3pwr_attach(struct device *parent, struct device *self, void *aux)
117 1.1 kiyohara {
118 1.1 kiyohara extern void (*__sleep_func)(void *);
119 1.1 kiyohara extern void *__sleep_ctx;
120 1.1 kiyohara struct psh3pwr_softc *sc = (struct psh3pwr_softc *)self;
121 1.1 kiyohara uint8_t phdr, scpdr;
122 1.1 kiyohara
123 1.1 kiyohara /* regisiter sleep function to APM */
124 1.1 kiyohara __sleep_func = psh3pwr_sleep;
125 1.1 kiyohara __sleep_ctx = self;
126 1.1 kiyohara
127 1.1 kiyohara callout_init(&sc->sc_poll_ch, 0);
128 1.1 kiyohara callout_setfunc(&sc->sc_poll_ch, psh3pwr_poll_callout, sc);
129 1.1 kiyohara
130 1.1 kiyohara phdr = _reg_read_1(SH7709_PHDR);
131 1.1 kiyohara _reg_write_1(SH7709_PHDR, phdr | PSH3_GREEN_LED_ON);
132 1.1 kiyohara
133 1.1 kiyohara printf("\n");
134 1.1 kiyohara
135 1.1 kiyohara sc->sc_ih_pout = intc_intr_establish(SH7709_INTEVT2_IRQ0,
136 1.1 kiyohara IST_EDGE, IPL_TTY, psh3pwr_intr_plug_out, sc);
137 1.1 kiyohara sc->sc_ih_pin = intc_intr_establish(SH7709_INTEVT2_IRQ1,
138 1.1 kiyohara IST_EDGE, IPL_TTY, psh3pwr_intr_plug_in, sc);
139 1.1 kiyohara
140 1.1 kiyohara /* XXXX: WindowsCE sets this bit. */
141 1.1 kiyohara scpdr = _reg_read_1(SH7709_SCPDR);
142 1.1 kiyohara if (scpdr & PSH3PWR_PLUG_OUT) {
143 1.1 kiyohara sc->sc_plug = 0;
144 1.1 kiyohara printf("%s: plug status: out\n", device_xname(&sc->sc_dev));
145 1.1 kiyohara } else {
146 1.1 kiyohara sc->sc_plug = 1;
147 1.1 kiyohara printf("%s: plug status: in\n", device_xname(&sc->sc_dev));
148 1.1 kiyohara }
149 1.1 kiyohara psh3pwr_poll_callout(sc);
150 1.1 kiyohara
151 1.1 kiyohara sc->sc_data.sensor = 0;
152 1.1 kiyohara sc->sc_data.units = ENVSYS_INDICATOR;
153 1.1 kiyohara sc->sc_data.state = ENVSYS_SVALID;
154 1.1 kiyohara sc->sc_data.value_cur = sc->sc_plug;
155 1.1 kiyohara snprintf(sc->sc_data.desc, sizeof(sc->sc_data.desc),
156 1.1 kiyohara "%s %s", device_xname(&sc->sc_dev), "plug");
157 1.1 kiyohara
158 1.1 kiyohara sc->sc_sysmon.sme_sensor_data = &sc->sc_data;
159 1.1 kiyohara sc->sc_sysmon.sme_name = device_xname(&sc->sc_dev);
160 1.1 kiyohara sc->sc_sysmon.sme_cookie = sc;
161 1.1 kiyohara sc->sc_sysmon.sme_gtredata = psh3pwr_gtredata;
162 1.1 kiyohara sc->sc_sysmon.sme_nsensors =
163 1.1 kiyohara sizeof(sc->sc_data) / sizeof(struct envsys_data);
164 1.1 kiyohara
165 1.1 kiyohara if (sysmon_envsys_register(&sc->sc_sysmon))
166 1.1 kiyohara aprint_error("%s: unable to register with sysmon\n",
167 1.1 kiyohara device_xname(&sc->sc_dev));
168 1.1 kiyohara }
169 1.1 kiyohara
170 1.1 kiyohara
171 1.1 kiyohara static int
172 1.1 kiyohara psh3pwr_intr_plug_out(void *self)
173 1.1 kiyohara {
174 1.1 kiyohara struct psh3pwr_softc *sc = (struct psh3pwr_softc *)self;
175 1.1 kiyohara uint8_t irr0, scpdr;
176 1.1 kiyohara
177 1.1 kiyohara irr0 = _reg_read_1(SH7709_IRR0);
178 1.1 kiyohara if (!(irr0 & IRR0_IRQ0)) {
179 1.1 kiyohara return 0;
180 1.1 kiyohara }
181 1.1 kiyohara _reg_write_1(SH7709_IRR0, irr0 & ~IRR0_IRQ0);
182 1.1 kiyohara
183 1.1 kiyohara /* XXXX: WindowsCE sets this bit. */
184 1.1 kiyohara scpdr = _reg_read_1(SH7709_SCPDR);
185 1.1 kiyohara _reg_write_1(SH7709_SCPDR, scpdr | PSH3PWR_PLUG_OUT);
186 1.1 kiyohara
187 1.1 kiyohara sc->sc_plug = 0;
188 1.1 kiyohara DPRINTF(("%s: plug out\n", device_xname(&sc->sc_dev)));
189 1.1 kiyohara
190 1.1 kiyohara return 1;
191 1.1 kiyohara }
192 1.1 kiyohara
193 1.1 kiyohara static int
194 1.1 kiyohara psh3pwr_intr_plug_in(void *self)
195 1.1 kiyohara {
196 1.1 kiyohara struct psh3pwr_softc *sc = (struct psh3pwr_softc *)self;
197 1.1 kiyohara uint8_t irr0, scpdr;
198 1.1 kiyohara
199 1.1 kiyohara irr0 = _reg_read_1(SH7709_IRR0);
200 1.1 kiyohara if (!(irr0 & IRR0_IRQ1))
201 1.1 kiyohara return 0;
202 1.1 kiyohara _reg_write_1(SH7709_IRR0, irr0 & ~IRR0_IRQ1);
203 1.1 kiyohara
204 1.1 kiyohara /* XXXX: WindowsCE sets this bit. */
205 1.1 kiyohara scpdr = _reg_read_1(SH7709_SCPDR);
206 1.1 kiyohara _reg_write_1(SH7709_SCPDR, scpdr & ~PSH3PWR_PLUG_OUT);
207 1.1 kiyohara
208 1.1 kiyohara sc->sc_plug = 1;
209 1.1 kiyohara DPRINTF(("%s: plug in\n", device_xname(&sc->sc_dev)));
210 1.1 kiyohara
211 1.1 kiyohara return 1;
212 1.1 kiyohara }
213 1.1 kiyohara
214 1.1 kiyohara void
215 1.1 kiyohara psh3pwr_sleep(void *self)
216 1.1 kiyohara {
217 1.1 kiyohara /* splhigh on entry */
218 1.1 kiyohara extern void pfckbd_poll_hitachi_power(void);
219 1.1 kiyohara
220 1.1 kiyohara uint8_t phdr;
221 1.1 kiyohara
222 1.1 kiyohara phdr = _reg_read_1(SH7709_PHDR);
223 1.1 kiyohara _reg_write_1(SH7709_PHDR, phdr & ~PSH3_GREEN_LED_ON);
224 1.1 kiyohara
225 1.1 kiyohara pfckbd_poll_hitachi_power();
226 1.1 kiyohara
227 1.1 kiyohara phdr = _reg_read_1(SH7709_PHDR);
228 1.1 kiyohara _reg_write_1(SH7709_PHDR, phdr | PSH3_GREEN_LED_ON);
229 1.1 kiyohara }
230 1.1 kiyohara
231 1.1 kiyohara volatile int psh3pwr_poll_verbose = 0; /* XXX: tweak from ddb */
232 1.1 kiyohara
233 1.1 kiyohara static void
234 1.1 kiyohara psh3pwr_poll_callout(void *self)
235 1.1 kiyohara {
236 1.1 kiyohara struct psh3pwr_softc *sc = (struct psh3pwr_softc *)self;
237 1.1 kiyohara int s;
238 1.1 kiyohara
239 1.1 kiyohara s = spltty();
240 1.1 kiyohara sc->sc_capacity = adc_sample_channel(ADC_CHANNEL_BATTERY);
241 1.1 kiyohara splx(s);
242 1.1 kiyohara
243 1.1 kiyohara if (psh3pwr_poll_verbose != 0)
244 1.1 kiyohara printf_nolog("%s: main=%-4d\n",
245 1.1 kiyohara device_xname(&sc->sc_dev), sc->sc_capacity);
246 1.1 kiyohara
247 1.1 kiyohara if (!sc->sc_plug && sc->sc_capacity < PSH3PWR_BATTERY_WARNING_THRESHOLD)
248 1.1 kiyohara printf("%s: WARNING: main battery %d is low!\n",
249 1.1 kiyohara device_xname(&sc->sc_dev), sc->sc_capacity);
250 1.1 kiyohara
251 1.1 kiyohara callout_schedule(&sc->sc_poll_ch, 5 * hz);
252 1.1 kiyohara }
253 1.1 kiyohara
254 1.1 kiyohara static int
255 1.1 kiyohara psh3pwr_gtredata(struct sysmon_envsys *sme, envsys_data_t *edata)
256 1.1 kiyohara {
257 1.1 kiyohara struct psh3pwr_softc *sc = sme->sme_cookie;
258 1.1 kiyohara
259 1.1 kiyohara edata->value_cur = sc->sc_plug;
260 1.1 kiyohara
261 1.1 kiyohara return 0;
262 1.1 kiyohara }
263