| @@ -1,14 +1,14 @@ | | | @@ -1,14 +1,14 @@ |
1 | /* $NetBSD: pfckbd.c,v 1.29 2012/02/12 16:34:08 matt Exp $ */ | | 1 | /* $NetBSD: pfckbd.c,v 1.29.22.1 2017/08/09 06:56:02 snj Exp $ */ |
2 | | | 2 | |
3 | /*- | | 3 | /*- |
4 | * Copyright (c) 2001, 2002 The NetBSD Foundation, Inc. | | 4 | * Copyright (c) 2001, 2002 The NetBSD Foundation, Inc. |
5 | * All rights reserved. | | 5 | * All rights reserved. |
6 | * | | 6 | * |
7 | * This code is derived from software contributed to The NetBSD Foundation | | 7 | * This code is derived from software contributed to The NetBSD Foundation |
8 | * by UCHIYAMA Yasushi. | | 8 | * by UCHIYAMA Yasushi. |
9 | * | | 9 | * |
10 | * Redistribution and use in source and binary forms, with or without | | 10 | * Redistribution and use in source and binary forms, with or without |
11 | * modification, are permitted provided that the following conditions | | 11 | * modification, are permitted provided that the following conditions |
12 | * are met: | | 12 | * are met: |
13 | * 1. Redistributions of source code must retain the above copyright | | 13 | * 1. Redistributions of source code must retain the above copyright |
14 | * notice, this list of conditions and the following disclaimer. | | 14 | * notice, this list of conditions and the following disclaimer. |
| @@ -24,27 +24,27 @@ | | | @@ -24,27 +24,27 @@ |
24 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | | 24 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
25 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | | 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 | | 26 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
27 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | | 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 | | 28 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
29 | * POSSIBILITY OF SUCH DAMAGE. | | 29 | * POSSIBILITY OF SUCH DAMAGE. |
30 | */ | | 30 | */ |
31 | | | 31 | |
32 | /* | | 32 | /* |
33 | * Matrix scan keyboard connected to SH7709, SH7709A PFC module. | | 33 | * Matrix scan keyboard connected to SH7709, SH7709A PFC module. |
34 | * currently, HP Jornada 680/690, HITACHI PERSONA HPW-50PAD only. | | 34 | * currently, HP Jornada 680/690, HITACHI PERSONA HPW-50PAD only. |
35 | */ | | 35 | */ |
36 | #include <sys/cdefs.h> | | 36 | #include <sys/cdefs.h> |
37 | __KERNEL_RCSID(0, "$NetBSD: pfckbd.c,v 1.29 2012/02/12 16:34:08 matt Exp $"); | | 37 | __KERNEL_RCSID(0, "$NetBSD: pfckbd.c,v 1.29.22.1 2017/08/09 06:56:02 snj Exp $"); |
38 | | | 38 | |
39 | #include "debug_hpcsh.h" | | 39 | #include "debug_hpcsh.h" |
40 | | | 40 | |
41 | #include <sys/param.h> | | 41 | #include <sys/param.h> |
42 | #include <sys/systm.h> | | 42 | #include <sys/systm.h> |
43 | #include <sys/device.h> | | 43 | #include <sys/device.h> |
44 | #include <sys/callout.h> | | 44 | #include <sys/callout.h> |
45 | #include <sys/bus.h> | | 45 | #include <sys/bus.h> |
46 | | | 46 | |
47 | #include <machine/platid.h> | | 47 | #include <machine/platid.h> |
48 | #include <machine/platid_mask.h> | | 48 | #include <machine/platid_mask.h> |
49 | | | 49 | |
50 | #include <dev/hpc/hpckbdvar.h> | | 50 | #include <dev/hpc/hpckbdvar.h> |
| @@ -56,54 +56,54 @@ __KERNEL_RCSID(0, "$NetBSD: pfckbd.c,v 1 | | | @@ -56,54 +56,54 @@ __KERNEL_RCSID(0, "$NetBSD: pfckbd.c,v 1 |
56 | #ifdef PFCKBD_DEBUG | | 56 | #ifdef PFCKBD_DEBUG |
57 | #define DPRINTF_ENABLE | | 57 | #define DPRINTF_ENABLE |
58 | #define DPRINTF_DEBUG pfckbd_debug | | 58 | #define DPRINTF_DEBUG pfckbd_debug |
59 | #endif | | 59 | #endif |
60 | #include <machine/debug.h> | | 60 | #include <machine/debug.h> |
61 | | | 61 | |
62 | static struct pfckbd_core { | | 62 | static struct pfckbd_core { |
63 | int pc_attached; | | 63 | int pc_attached; |
64 | int pc_enabled; | | 64 | int pc_enabled; |
65 | struct callout pc_soft_ch; | | 65 | struct callout pc_soft_ch; |
66 | struct hpckbd_ic_if pc_if; | | 66 | struct hpckbd_ic_if pc_if; |
67 | struct hpckbd_if *pc_hpckbd; | | 67 | struct hpckbd_if *pc_hpckbd; |
68 | uint16_t pc_column[8]; | | 68 | uint16_t pc_column[8]; |
69 | void (*pc_callout)(void *); | | 69 | void (*pc_callout)(struct pfckbd_core *); |
70 | } pfckbd_core; | | 70 | } pfckbd_core; |
71 | | | 71 | |
72 | static int pfckbd_match(device_t, cfdata_t, void *); | | 72 | static int pfckbd_match(device_t, cfdata_t, void *); |
73 | static void pfckbd_attach(device_t, device_t, void *); | | 73 | static void pfckbd_attach(device_t, device_t, void *); |
74 | | | 74 | |
75 | CFATTACH_DECL_NEW(pfckbd, 0, | | 75 | CFATTACH_DECL_NEW(pfckbd, 0, |
76 | pfckbd_match, pfckbd_attach, NULL, NULL); | | 76 | pfckbd_match, pfckbd_attach, NULL, NULL); |
77 | | | 77 | |
78 | static void pfckbd_ifsetup(struct pfckbd_core *); | | 78 | static void pfckbd_ifsetup(struct pfckbd_core *); |
79 | | | 79 | |
80 | /* callbacks for hpckbd */ | | 80 | /* callbacks for hpckbd */ |
81 | static int pfckbd_input_establish(void *, struct hpckbd_if *); | | 81 | static int pfckbd_input_establish(void *, struct hpckbd_if *); |
82 | static int pfckbd_poll(void *); | | 82 | static int pfckbd_poll(void *); |
83 | | | 83 | |
84 | static void pfckbd_input(struct pfckbd_core *, int, uint16_t); | | 84 | static void pfckbd_input(struct pfckbd_core *, int, uint16_t); |
85 | | | 85 | |
86 | static void (*pfckbd_callout_lookup(void))(void *); | | 86 | static void (*pfckbd_callout_lookup(void))(struct pfckbd_core *); |
87 | static void pfckbd_callout_unknown(void *); | | 87 | static void pfckbd_callout(void *); |
88 | static void pfckbd_callout_hp(void *); | | 88 | static void pfckbd_callout_hp(struct pfckbd_core *); |
89 | static void pfckbd_callout_hitachi(void *); | | 89 | static void pfckbd_callout_hitachi(struct pfckbd_core *); |
90 | void pfckbd_poll_hitachi_power(void); | | 90 | void pfckbd_poll_hitachi_power(void); |
91 | | | 91 | |
92 | | | 92 | |
93 | /* callout function table. this function is platfrom specific. */ | | 93 | /* callout function table. this function is platfrom specific. */ |
94 | static const struct { | | 94 | static const struct { |
95 | platid_mask_t *platform; | | 95 | platid_mask_t *platform; |
96 | void (*func)(void *); | | 96 | void (*func)(struct pfckbd_core *); |
97 | } pfckbd_calloutfunc_table[] = { | | 97 | } pfckbd_calloutfunc_table[] = { |
98 | { &platid_mask_MACH_HP , pfckbd_callout_hp }, | | 98 | { &platid_mask_MACH_HP , pfckbd_callout_hp }, |
99 | { &platid_mask_MACH_HITACHI , pfckbd_callout_hitachi } | | 99 | { &platid_mask_MACH_HITACHI , pfckbd_callout_hitachi } |
100 | }; | | 100 | }; |
101 | | | 101 | |
102 | | | 102 | |
103 | void | | 103 | void |
104 | pfckbd_cnattach(void) | | 104 | pfckbd_cnattach(void) |
105 | { | | 105 | { |
106 | struct pfckbd_core *pc = &pfckbd_core; | | 106 | struct pfckbd_core *pc = &pfckbd_core; |
107 | | | 107 | |
108 | if ((cpu_product != CPU_PRODUCT_7709) | | 108 | if ((cpu_product != CPU_PRODUCT_7709) |
109 | && (cpu_product != CPU_PRODUCT_7709A)) | | 109 | && (cpu_product != CPU_PRODUCT_7709A)) |
| @@ -134,29 +134,33 @@ pfckbd_attach(device_t parent, device_t | | | @@ -134,29 +134,33 @@ pfckbd_attach(device_t parent, device_t |
134 | | | 134 | |
135 | aprint_naive("\n"); | | 135 | aprint_naive("\n"); |
136 | aprint_normal("\n"); | | 136 | aprint_normal("\n"); |
137 | | | 137 | |
138 | pfckbd_core.pc_attached = 1; | | 138 | pfckbd_core.pc_attached = 1; |
139 | | | 139 | |
140 | pfckbd_ifsetup(&pfckbd_core); | | 140 | pfckbd_ifsetup(&pfckbd_core); |
141 | | | 141 | |
142 | /* attach hpckbd */ | | 142 | /* attach hpckbd */ |
143 | haa.haa_ic = &pfckbd_core.pc_if; /* tell hpckbd our interface */ | | 143 | haa.haa_ic = &pfckbd_core.pc_if; /* tell hpckbd our interface */ |
144 | config_found(self, &haa, hpckbd_print); | | 144 | config_found(self, &haa, hpckbd_print); |
145 | | | 145 | |
146 | /* install callout handler */ | | 146 | /* install callout handler */ |
147 | callout_init(&pfckbd_core.pc_soft_ch, 0); | | 147 | if (pfckbd_core.pc_callout != NULL) { |
148 | callout_reset(&pfckbd_core.pc_soft_ch, 1, | | 148 | callout_init(&pfckbd_core.pc_soft_ch, 0); |
149 | pfckbd_core.pc_callout, &pfckbd_core); | | 149 | callout_reset(&pfckbd_core.pc_soft_ch, 1, |
| | | 150 | pfckbd_callout, &pfckbd_core); |
| | | 151 | } |
| | | 152 | else |
| | | 153 | aprint_error_dev(self, "unsupported platform\n"); |
150 | | | 154 | |
151 | if (!pmf_device_register(self, NULL, NULL)) | | 155 | if (!pmf_device_register(self, NULL, NULL)) |
152 | aprint_error_dev(self, "unable to establish power handler\n"); | | 156 | aprint_error_dev(self, "unable to establish power handler\n"); |
153 | } | | 157 | } |
154 | | | 158 | |
155 | static void | | 159 | static void |
156 | pfckbd_ifsetup(struct pfckbd_core *pc) | | 160 | pfckbd_ifsetup(struct pfckbd_core *pc) |
157 | { | | 161 | { |
158 | int i; | | 162 | int i; |
159 | | | 163 | |
160 | pc->pc_if.hii_ctx = pc; | | 164 | pc->pc_if.hii_ctx = pc; |
161 | pc->pc_if.hii_establish = pfckbd_input_establish; | | 165 | pc->pc_if.hii_establish = pfckbd_input_establish; |
162 | pc->pc_if.hii_poll = pfckbd_poll; | | 166 | pc->pc_if.hii_poll = pfckbd_poll; |
| @@ -181,32 +185,42 @@ pfckbd_input_establish(void *ic, struct | | | @@ -181,32 +185,42 @@ pfckbd_input_establish(void *ic, struct |
181 | pc->pc_enabled = 1; /* ok to talk to hpckbd */ | | 185 | pc->pc_enabled = 1; /* ok to talk to hpckbd */ |
182 | | | 186 | |
183 | return 0; | | 187 | return 0; |
184 | } | | 188 | } |
185 | | | 189 | |
186 | /* | | 190 | /* |
187 | * Callback for hpckbd_cngetc | | 191 | * Callback for hpckbd_cngetc |
188 | */ | | 192 | */ |
189 | static int | | 193 | static int |
190 | pfckbd_poll(void *ic) | | 194 | pfckbd_poll(void *ic) |
191 | { | | 195 | { |
192 | struct pfckbd_core *pc = ic; | | 196 | struct pfckbd_core *pc = ic; |
193 | | | 197 | |
194 | if (pc->pc_enabled) | | 198 | if (pc->pc_enabled && pc->pc_callout != NULL) |
195 | (*pc->pc_callout)(pc); | | 199 | (*pc->pc_callout)(pc); |
196 | | | 200 | |
197 | return 0; | | 201 | return 0; |
198 | } | | 202 | } |
199 | | | 203 | |
| | | 204 | static void |
| | | 205 | pfckbd_callout(void *arg) |
| | | 206 | { |
| | | 207 | struct pfckbd_core *pc = arg; |
| | | 208 | |
| | | 209 | (*pc->pc_callout)(pc); |
| | | 210 | callout_schedule(&pc->pc_soft_ch, 1); |
| | | 211 | } |
| | | 212 | |
| | | 213 | |
200 | /* | | 214 | /* |
201 | * Called by platform specific scan routines to report key events to hpckbd | | 215 | * Called by platform specific scan routines to report key events to hpckbd |
202 | */ | | 216 | */ |
203 | static void | | 217 | static void |
204 | pfckbd_input(struct pfckbd_core *pc, int column, uint16_t data) | | 218 | pfckbd_input(struct pfckbd_core *pc, int column, uint16_t data) |
205 | { | | 219 | { |
206 | int row, type, val; | | 220 | int row, type, val; |
207 | unsigned int edge, mask; | | 221 | unsigned int edge, mask; |
208 | | | 222 | |
209 | edge = data ^ pc->pc_column[column]; | | 223 | edge = data ^ pc->pc_column[column]; |
210 | if (edge == 0) | | 224 | if (edge == 0) |
211 | return; /* no changes in this column */ | | 225 | return; /* no changes in this column */ |
212 | | | 226 | |
| @@ -220,54 +234,46 @@ pfckbd_input(struct pfckbd_core *pc, int | | | @@ -220,54 +234,46 @@ pfckbd_input(struct pfckbd_core *pc, int |
220 | val = row * 8 + column; | | 234 | val = row * 8 + column; |
221 | hpckbd_input(pc->pc_hpckbd, type, val); | | 235 | hpckbd_input(pc->pc_hpckbd, type, val); |
222 | } | | 236 | } |
223 | } | | 237 | } |
224 | } | | 238 | } |
225 | | | 239 | |
226 | | | 240 | |
227 | /* | | 241 | /* |
228 | * Platform dependent scan routines. | | 242 | * Platform dependent scan routines. |
229 | */ | | 243 | */ |
230 | | | 244 | |
231 | /* Look up appropriate callback handler */ | | 245 | /* Look up appropriate callback handler */ |
232 | static void | | 246 | static void |
233 | (*pfckbd_callout_lookup(void))(void *) | | 247 | (*pfckbd_callout_lookup(void))(struct pfckbd_core *) |
234 | { | | 248 | { |
235 | int i, n; | | 249 | int i, n; |
236 | | | 250 | |
237 | n = sizeof(pfckbd_calloutfunc_table) | | 251 | n = sizeof(pfckbd_calloutfunc_table) |
238 | / sizeof(pfckbd_calloutfunc_table[0]); | | 252 | / sizeof(pfckbd_calloutfunc_table[0]); |
239 | | | 253 | |
240 | for (i = 0; i < n; i++) | | 254 | for (i = 0; i < n; i++) |
241 | if (platid_match(&platid, | | 255 | if (platid_match(&platid, |
242 | pfckbd_calloutfunc_table[i].platform)) | | 256 | pfckbd_calloutfunc_table[i].platform)) |
243 | return pfckbd_calloutfunc_table[i].func; | | 257 | return pfckbd_calloutfunc_table[i].func; |
244 | | | 258 | |
245 | return pfckbd_callout_unknown; | | 259 | return NULL; |
246 | } | | | |
247 | | | | |
248 | /* Placeholder for unknown platform */ | | | |
249 | static void | | | |
250 | pfckbd_callout_unknown(void *arg) | | | |
251 | { | | | |
252 | | | | |
253 | printf("%s: unknown keyboard switch\n", __func__); | | | |
254 | } | | 260 | } |
255 | | | 261 | |
256 | /* | | 262 | /* |
257 | * HP Jornada680/690, HP620LX | | 263 | * HP Jornada680/690, HP620LX |
258 | */ | | 264 | */ |
259 | static void | | 265 | static void |
260 | pfckbd_callout_hp(void *arg) | | 266 | pfckbd_callout_hp(struct pfckbd_core *pc) |
261 | { | | 267 | { |
262 | #define PFCKBD_HP_PDCR_MASK 0xcc0c | | 268 | #define PFCKBD_HP_PDCR_MASK 0xcc0c |
263 | #define PFCKBD_HP_PECR_MASK 0xf0cf | | 269 | #define PFCKBD_HP_PECR_MASK 0xf0cf |
264 | | | 270 | |
265 | /* | | 271 | /* |
266 | * Disable output on all lines but the n'th line in D. | | 272 | * Disable output on all lines but the n'th line in D. |
267 | * Pull the n'th scan line in D low. | | 273 | * Pull the n'th scan line in D low. |
268 | */ | | 274 | */ |
269 | #define PD(n) \ | | 275 | #define PD(n) \ |
270 | { (uint16_t)(PFCKBD_HP_PDCR_MASK & (~(1 << (2*(n)+1)))), \ | | 276 | { (uint16_t)(PFCKBD_HP_PDCR_MASK & (~(1 << (2*(n)+1)))), \ |
271 | (uint16_t)(PFCKBD_HP_PECR_MASK & 0xffff), \ | | 277 | (uint16_t)(PFCKBD_HP_PECR_MASK & 0xffff), \ |
272 | (uint8_t)~(1 << (n)), \ | | 278 | (uint8_t)~(1 << (n)), \ |
273 | 0xff } | | 279 | 0xff } |
| @@ -278,33 +284,32 @@ pfckbd_callout_hp(void *arg) | | | @@ -278,33 +284,32 @@ pfckbd_callout_hp(void *arg) |
278 | (uint16_t)(PFCKBD_HP_PECR_MASK & (~(1 << (2*(n)+1)))), \ | | 284 | (uint16_t)(PFCKBD_HP_PECR_MASK & (~(1 << (2*(n)+1)))), \ |
279 | 0xff, \ | | 285 | 0xff, \ |
280 | (uint8_t)~(1 << (n)) } | | 286 | (uint8_t)~(1 << (n)) } |
281 | | | 287 | |
282 | static const struct { | | 288 | static const struct { |
283 | uint16_t dc, ec; uint8_t d, e; | | 289 | uint16_t dc, ec; uint8_t d, e; |
284 | } scan[] = { | | 290 | } scan[] = { |
285 | PD(1), PD(5), PE(1), PE(6), PE(7), PE(3), PE(0), PD(7) | | 291 | PD(1), PD(5), PE(1), PE(6), PE(7), PE(3), PE(0), PD(7) |
286 | }; | | 292 | }; |
287 | | | 293 | |
288 | #undef PD | | 294 | #undef PD |
289 | #undef PE | | 295 | #undef PE |
290 | | | 296 | |
291 | struct pfckbd_core *pc = arg; | | | |
292 | uint16_t dc, ec; | | 297 | uint16_t dc, ec; |
293 | int column; | | 298 | int column; |
294 | uint16_t data; | | 299 | uint16_t data; |
295 | | | 300 | |
296 | if (!pc->pc_enabled) | | 301 | if (!pc->pc_enabled) |
297 | goto reinstall; | | 302 | return; |
298 | | | 303 | |
299 | /* bits in D/E control regs we do not touch (XXX: can they change?) */ | | 304 | /* bits in D/E control regs we do not touch (XXX: can they change?) */ |
300 | dc = _reg_read_2(SH7709_PDCR) & ~PFCKBD_HP_PDCR_MASK; | | 305 | dc = _reg_read_2(SH7709_PDCR) & ~PFCKBD_HP_PDCR_MASK; |
301 | ec = _reg_read_2(SH7709_PECR) & ~PFCKBD_HP_PECR_MASK; | | 306 | ec = _reg_read_2(SH7709_PECR) & ~PFCKBD_HP_PECR_MASK; |
302 | | | 307 | |
303 | for (column = 0; column < 8; column++) { | | 308 | for (column = 0; column < 8; column++) { |
304 | /* disable output to all lines except the one we scan */ | | 309 | /* disable output to all lines except the one we scan */ |
305 | _reg_write_2(SH7709_PDCR, dc | scan[column].dc); | | 310 | _reg_write_2(SH7709_PDCR, dc | scan[column].dc); |
306 | _reg_write_2(SH7709_PECR, ec | scan[column].ec); | | 311 | _reg_write_2(SH7709_PECR, ec | scan[column].ec); |
307 | delay(5); | | 312 | delay(5); |
308 | | | 313 | |
309 | /* pull the scan line low */ | | 314 | /* pull the scan line low */ |
310 | _reg_write_1(SH7709_PDDR, scan[column].d); | | 315 | _reg_write_1(SH7709_PDDR, scan[column].d); |
| @@ -320,36 +325,33 @@ pfckbd_callout_hp(void *arg) | | | @@ -320,36 +325,33 @@ pfckbd_callout_hp(void *arg) |
320 | | | 325 | |
321 | /* scan no lines */ | | 326 | /* scan no lines */ |
322 | _reg_write_1(SH7709_PDDR, 0xff); | | 327 | _reg_write_1(SH7709_PDDR, 0xff); |
323 | _reg_write_1(SH7709_PEDR, 0xff); | | 328 | _reg_write_1(SH7709_PEDR, 0xff); |
324 | | | 329 | |
325 | /* enable all scan lines */ | | 330 | /* enable all scan lines */ |
326 | _reg_write_2(SH7709_PDCR, dc | (0x5555 & PFCKBD_HP_PDCR_MASK)); | | 331 | _reg_write_2(SH7709_PDCR, dc | (0x5555 & PFCKBD_HP_PDCR_MASK)); |
327 | _reg_write_2(SH7709_PECR, ec | (0x5555 & PFCKBD_HP_PECR_MASK)); | | 332 | _reg_write_2(SH7709_PECR, ec | (0x5555 & PFCKBD_HP_PECR_MASK)); |
328 | | | 333 | |
329 | #if 0 | | 334 | #if 0 |
330 | /* (ignore) extra keys/events (recorder buttons, lid, cable &c) */ | | 335 | /* (ignore) extra keys/events (recorder buttons, lid, cable &c) */ |
331 | data = _reg_read_1(SH7709_PGDR) | (_reg_read_1(SH7709_PHDR) << 8); | | 336 | data = _reg_read_1(SH7709_PGDR) | (_reg_read_1(SH7709_PHDR) << 8); |
332 | #endif | | 337 | #endif |
333 | | | | |
334 | reinstall: | | | |
335 | callout_schedule(&pc->pc_soft_ch, 1); | | | |
336 | } | | 338 | } |
337 | | | 339 | |
338 | /* | | 340 | /* |
339 | * HITACH PERSONA (HPW-50PAD) | | 341 | * HITACH PERSONA (HPW-50PAD) |
340 | */ | | 342 | */ |
341 | static void | | 343 | static void |
342 | pfckbd_callout_hitachi(void *arg) | | 344 | pfckbd_callout_hitachi(struct pfckbd_core *pc) |
343 | { | | 345 | { |
344 | #define PFCKBD_HITACHI_PCCR_MASK 0xfff3 | | 346 | #define PFCKBD_HITACHI_PCCR_MASK 0xfff3 |
345 | #define PFCKBD_HITACHI_PDCR_MASK 0x000c | | 347 | #define PFCKBD_HITACHI_PDCR_MASK 0x000c |
346 | #define PFCKBD_HITACHI_PECR_MASK 0x30cf | | 348 | #define PFCKBD_HITACHI_PECR_MASK 0x30cf |
347 | | | 349 | |
348 | #define PFCKBD_HITACHI_PCDR_SCN_MASK 0xfd | | 350 | #define PFCKBD_HITACHI_PCDR_SCN_MASK 0xfd |
349 | #define PFCKBD_HITACHI_PDDR_SCN_MASK 0x02 | | 351 | #define PFCKBD_HITACHI_PDDR_SCN_MASK 0x02 |
350 | #define PFCKBD_HITACHI_PEDR_SCN_MASK 0x4b | | 352 | #define PFCKBD_HITACHI_PEDR_SCN_MASK 0x4b |
351 | | | 353 | |
352 | #define PFCKBD_HITACHI_PCDR_SNS_MASK 0x01 | | 354 | #define PFCKBD_HITACHI_PCDR_SNS_MASK 0x01 |
353 | #define PFCKBD_HITACHI_PFDR_SNS_MASK 0xfe | | 355 | #define PFCKBD_HITACHI_PFDR_SNS_MASK 0xfe |
354 | | | 356 | |
355 | /* | | 357 | /* |
| @@ -379,33 +381,32 @@ pfckbd_callout_hitachi(void *arg) | | | @@ -379,33 +381,32 @@ pfckbd_callout_hitachi(void *arg) |
379 | (uint16_t)(PFCKBD_HITACHI_PDCR_MASK & 0xffff), \ | | 381 | (uint16_t)(PFCKBD_HITACHI_PDCR_MASK & 0xffff), \ |
380 | (uint16_t)(PFCKBD_HITACHI_PECR_MASK & (~(1 << (2*(n)+1)))), \ | | 382 | (uint16_t)(PFCKBD_HITACHI_PECR_MASK & (~(1 << (2*(n)+1)))), \ |
381 | PFCKBD_HITACHI_PCDR_SCN_MASK, \ | | 383 | PFCKBD_HITACHI_PCDR_SCN_MASK, \ |
382 | PFCKBD_HITACHI_PDDR_SCN_MASK, \ | | 384 | PFCKBD_HITACHI_PDDR_SCN_MASK, \ |
383 | (uint8_t)(PFCKBD_HITACHI_PEDR_SCN_MASK & ~(1 << (n))) } | | 385 | (uint8_t)(PFCKBD_HITACHI_PEDR_SCN_MASK & ~(1 << (n))) } |
384 | | | 386 | |
385 | static const struct { | | 387 | static const struct { |
386 | uint16_t cc, dc, ec; uint8_t c, d, e; | | 388 | uint16_t cc, dc, ec; uint8_t c, d, e; |
387 | } scan[] = { | | 389 | } scan[] = { |
388 | PE(6), PE(3), PE(1), PE(0), PC(7), PC(6), PC(5), PC(4), | | 390 | PE(6), PE(3), PE(1), PE(0), PC(7), PC(6), PC(5), PC(4), |
389 | PC(3), PC(2), PD(1), PC(0) | | 391 | PC(3), PC(2), PD(1), PC(0) |
390 | }; | | 392 | }; |
391 | | | 393 | |
392 | struct pfckbd_core *pc = arg; | | | |
393 | uint16_t cc, dc, ec; | | 394 | uint16_t cc, dc, ec; |
394 | uint8_t data[2], cd, dd, ed; | | 395 | uint8_t data[2], cd, dd, ed; |
395 | int i; | | 396 | int i; |
396 | | | 397 | |
397 | if (!pc->pc_enabled) | | 398 | if (!pc->pc_enabled) |
398 | goto reinstall; | | 399 | return; |
399 | | | 400 | |
400 | /* bits in C/D/E control regs we do not touch (XXX: can they change?) */ | | 401 | /* bits in C/D/E control regs we do not touch (XXX: can they change?) */ |
401 | cc = _reg_read_2(SH7709_PCCR) & ~PFCKBD_HITACHI_PCCR_MASK; | | 402 | cc = _reg_read_2(SH7709_PCCR) & ~PFCKBD_HITACHI_PCCR_MASK; |
402 | dc = _reg_read_2(SH7709_PDCR) & ~PFCKBD_HITACHI_PDCR_MASK; | | 403 | dc = _reg_read_2(SH7709_PDCR) & ~PFCKBD_HITACHI_PDCR_MASK; |
403 | ec = _reg_read_2(SH7709_PECR) & ~PFCKBD_HITACHI_PECR_MASK; | | 404 | ec = _reg_read_2(SH7709_PECR) & ~PFCKBD_HITACHI_PECR_MASK; |
404 | | | 405 | |
405 | for (i = 0; i < 12; i++) { | | 406 | for (i = 0; i < 12; i++) { |
406 | /* disable output to all lines except the one we scan */ | | 407 | /* disable output to all lines except the one we scan */ |
407 | _reg_write_2(SH7709_PCCR, cc | scan[i].cc); | | 408 | _reg_write_2(SH7709_PCCR, cc | scan[i].cc); |
408 | _reg_write_2(SH7709_PDCR, dc | scan[i].dc); | | 409 | _reg_write_2(SH7709_PDCR, dc | scan[i].dc); |
409 | _reg_write_2(SH7709_PECR, ec | scan[i].ec); | | 410 | _reg_write_2(SH7709_PECR, ec | scan[i].ec); |
410 | delay(5); | | 411 | delay(5); |
411 | | | 412 | |
| @@ -422,29 +423,26 @@ pfckbd_callout_hitachi(void *arg) | | | @@ -422,29 +423,26 @@ pfckbd_callout_hitachi(void *arg) |
422 | /* read sense */ | | 423 | /* read sense */ |
423 | data[i & 0x1] = | | 424 | data[i & 0x1] = |
424 | (_reg_read_1(SH7709_PCDR) & PFCKBD_HITACHI_PCDR_SNS_MASK) | | 425 | (_reg_read_1(SH7709_PCDR) & PFCKBD_HITACHI_PCDR_SNS_MASK) |
425 | | (_reg_read_1(SH7709_PFDR) & PFCKBD_HITACHI_PFDR_SNS_MASK); | | 426 | | (_reg_read_1(SH7709_PFDR) & PFCKBD_HITACHI_PFDR_SNS_MASK); |
426 | | | 427 | |
427 | if (i & 0x1) | | 428 | if (i & 0x1) |
428 | pfckbd_input(pc, (i >> 1), (data[0] | (data[1] << 8))); | | 429 | pfckbd_input(pc, (i >> 1), (data[0] | (data[1] << 8))); |
429 | } | | 430 | } |
430 | | | 431 | |
431 | /* enable all scan lines */ | | 432 | /* enable all scan lines */ |
432 | _reg_write_2(SH7709_PCCR, cc | (0x5555 & PFCKBD_HITACHI_PCCR_MASK)); | | 433 | _reg_write_2(SH7709_PCCR, cc | (0x5555 & PFCKBD_HITACHI_PCCR_MASK)); |
433 | _reg_write_2(SH7709_PDCR, dc | (0x5555 & PFCKBD_HITACHI_PDCR_MASK)); | | 434 | _reg_write_2(SH7709_PDCR, dc | (0x5555 & PFCKBD_HITACHI_PDCR_MASK)); |
434 | _reg_write_2(SH7709_PECR, ec | (0x5555 & PFCKBD_HITACHI_PECR_MASK)); | | 435 | _reg_write_2(SH7709_PECR, ec | (0x5555 & PFCKBD_HITACHI_PECR_MASK)); |
435 | | | | |
436 | reinstall: | | | |
437 | callout_schedule(&pc->pc_soft_ch, 1); | | | |
438 | } | | 436 | } |
439 | | | 437 | |
440 | void | | 438 | void |
441 | pfckbd_poll_hitachi_power(void) | | 439 | pfckbd_poll_hitachi_power(void) |
442 | { | | 440 | { |
443 | static const struct { | | 441 | static const struct { |
444 | uint16_t cc, dc, ec; uint8_t c, d, e; | | 442 | uint16_t cc, dc, ec; uint8_t c, d, e; |
445 | } poll = PD(1); | | 443 | } poll = PD(1); |
446 | | | 444 | |
447 | #undef PC | | 445 | #undef PC |
448 | #undef PD | | 446 | #undef PD |
449 | #undef PE | | 447 | #undef PE |
450 | | | 448 | |