1 1.33 andvar /* $NetBSD: pfckbd.c,v 1.33 2023/06/01 20:15:16 andvar Exp $ */ 2 1.1 uch 3 1.1 uch /*- 4 1.4 uch * Copyright (c) 2001, 2002 The NetBSD Foundation, Inc. 5 1.1 uch * All rights reserved. 6 1.1 uch * 7 1.1 uch * This code is derived from software contributed to The NetBSD Foundation 8 1.1 uch * by UCHIYAMA Yasushi. 9 1.1 uch * 10 1.1 uch * Redistribution and use in source and binary forms, with or without 11 1.1 uch * modification, are permitted provided that the following conditions 12 1.1 uch * are met: 13 1.1 uch * 1. Redistributions of source code must retain the above copyright 14 1.1 uch * notice, this list of conditions and the following disclaimer. 15 1.1 uch * 2. Redistributions in binary form must reproduce the above copyright 16 1.1 uch * notice, this list of conditions and the following disclaimer in the 17 1.1 uch * documentation and/or other materials provided with the distribution. 18 1.1 uch * 19 1.1 uch * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 20 1.1 uch * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 21 1.1 uch * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 22 1.1 uch * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 23 1.1 uch * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24 1.1 uch * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25 1.1 uch * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26 1.1 uch * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27 1.1 uch * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28 1.1 uch * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29 1.1 uch * POSSIBILITY OF SUCH DAMAGE. 30 1.1 uch */ 31 1.11 lukem 32 1.19 uwe /* 33 1.19 uwe * Matrix scan keyboard connected to SH7709, SH7709A PFC module. 34 1.19 uwe * currently, HP Jornada 680/690, HITACHI PERSONA HPW-50PAD only. 35 1.19 uwe */ 36 1.11 lukem #include <sys/cdefs.h> 37 1.33 andvar __KERNEL_RCSID(0, "$NetBSD: pfckbd.c,v 1.33 2023/06/01 20:15:16 andvar Exp $"); 38 1.4 uch 39 1.4 uch #include "debug_hpcsh.h" 40 1.1 uch 41 1.1 uch #include <sys/param.h> 42 1.1 uch #include <sys/systm.h> 43 1.1 uch #include <sys/device.h> 44 1.1 uch #include <sys/callout.h> 45 1.28 dyoung #include <sys/bus.h> 46 1.1 uch 47 1.3 uch #include <machine/platid.h> 48 1.3 uch #include <machine/platid_mask.h> 49 1.3 uch 50 1.1 uch #include <dev/hpc/hpckbdvar.h> 51 1.1 uch 52 1.1 uch #include <sh3/pfcreg.h> 53 1.1 uch 54 1.1 uch #include <hpcsh/dev/pfckbdvar.h> 55 1.1 uch 56 1.4 uch #ifdef PFCKBD_DEBUG 57 1.4 uch #define DPRINTF_ENABLE 58 1.4 uch #define DPRINTF_DEBUG pfckbd_debug 59 1.1 uch #endif 60 1.5 uch #include <machine/debug.h> 61 1.1 uch 62 1.19 uwe static struct pfckbd_core { 63 1.1 uch int pc_attached; 64 1.1 uch int pc_enabled; 65 1.1 uch struct callout pc_soft_ch; 66 1.1 uch struct hpckbd_ic_if pc_if; 67 1.1 uch struct hpckbd_if *pc_hpckbd; 68 1.14 uwe uint16_t pc_column[8]; 69 1.30 uwe void (*pc_callout)(struct pfckbd_core *); 70 1.1 uch } pfckbd_core; 71 1.1 uch 72 1.24 uwe static int pfckbd_match(device_t, cfdata_t, void *); 73 1.24 uwe static void pfckbd_attach(device_t, device_t, void *); 74 1.20 uwe 75 1.24 uwe CFATTACH_DECL_NEW(pfckbd, 0, 76 1.20 uwe pfckbd_match, pfckbd_attach, NULL, NULL); 77 1.20 uwe 78 1.20 uwe static void pfckbd_ifsetup(struct pfckbd_core *); 79 1.20 uwe 80 1.20 uwe /* callbacks for hpckbd */ 81 1.20 uwe static int pfckbd_input_establish(void *, struct hpckbd_if *); 82 1.20 uwe static int pfckbd_poll(void *); 83 1.20 uwe 84 1.20 uwe static void pfckbd_input(struct pfckbd_core *, int, uint16_t); 85 1.20 uwe 86 1.30 uwe static void (*pfckbd_callout_lookup(void))(struct pfckbd_core *); 87 1.30 uwe static void pfckbd_callout(void *); 88 1.30 uwe static void pfckbd_callout_hp(struct pfckbd_core *); 89 1.30 uwe static void pfckbd_callout_hitachi(struct pfckbd_core *); 90 1.22 kiyohara void pfckbd_poll_hitachi_power(void); 91 1.22 kiyohara 92 1.20 uwe 93 1.33 andvar /* callout function table. this function is platform specific. */ 94 1.19 uwe static const struct { 95 1.3 uch platid_mask_t *platform; 96 1.30 uwe void (*func)(struct pfckbd_core *); 97 1.3 uch } pfckbd_calloutfunc_table[] = { 98 1.3 uch { &platid_mask_MACH_HP , pfckbd_callout_hp }, 99 1.3 uch { &platid_mask_MACH_HITACHI , pfckbd_callout_hitachi } 100 1.1 uch }; 101 1.1 uch 102 1.1 uch 103 1.1 uch void 104 1.26 cegger pfckbd_cnattach(void) 105 1.1 uch { 106 1.1 uch struct pfckbd_core *pc = &pfckbd_core; 107 1.20 uwe 108 1.20 uwe if ((cpu_product != CPU_PRODUCT_7709) 109 1.20 uwe && (cpu_product != CPU_PRODUCT_7709A)) 110 1.7 uch return; 111 1.7 uch 112 1.1 uch /* initialize interface */ 113 1.1 uch pfckbd_ifsetup(pc); 114 1.3 uch 115 1.20 uwe /* attach descendants */ 116 1.1 uch hpckbd_cnattach(&pc->pc_if); 117 1.1 uch } 118 1.1 uch 119 1.19 uwe static int 120 1.24 uwe pfckbd_match(device_t parent, cfdata_t cf, void *aux) 121 1.1 uch { 122 1.1 uch 123 1.20 uwe if ((cpu_product != CPU_PRODUCT_7709) 124 1.20 uwe && (cpu_product != CPU_PRODUCT_7709A)) 125 1.20 uwe return 0; 126 1.7 uch 127 1.20 uwe return !pfckbd_core.pc_attached; /* attach only once */ 128 1.1 uch } 129 1.1 uch 130 1.19 uwe static void 131 1.24 uwe pfckbd_attach(device_t parent, device_t self, void *aux) 132 1.1 uch { 133 1.1 uch struct hpckbd_attach_args haa; 134 1.20 uwe 135 1.24 uwe aprint_naive("\n"); 136 1.24 uwe aprint_normal("\n"); 137 1.1 uch 138 1.1 uch pfckbd_core.pc_attached = 1; 139 1.20 uwe 140 1.1 uch pfckbd_ifsetup(&pfckbd_core); 141 1.1 uch 142 1.1 uch /* attach hpckbd */ 143 1.20 uwe haa.haa_ic = &pfckbd_core.pc_if; /* tell hpckbd our interface */ 144 1.32 thorpej config_found(self, &haa, hpckbd_print, CFARGS_NONE); 145 1.1 uch 146 1.1 uch /* install callout handler */ 147 1.30 uwe if (pfckbd_core.pc_callout != NULL) { 148 1.30 uwe callout_init(&pfckbd_core.pc_soft_ch, 0); 149 1.30 uwe callout_reset(&pfckbd_core.pc_soft_ch, 1, 150 1.30 uwe pfckbd_callout, &pfckbd_core); 151 1.30 uwe } 152 1.30 uwe else 153 1.30 uwe aprint_error_dev(self, "unsupported platform\n"); 154 1.27 uwe 155 1.27 uwe if (!pmf_device_register(self, NULL, NULL)) 156 1.27 uwe aprint_error_dev(self, "unable to establish power handler\n"); 157 1.1 uch } 158 1.1 uch 159 1.20 uwe static void 160 1.20 uwe pfckbd_ifsetup(struct pfckbd_core *pc) 161 1.20 uwe { 162 1.20 uwe int i; 163 1.20 uwe 164 1.20 uwe pc->pc_if.hii_ctx = pc; 165 1.20 uwe pc->pc_if.hii_establish = pfckbd_input_establish; 166 1.20 uwe pc->pc_if.hii_poll = pfckbd_poll; 167 1.20 uwe 168 1.20 uwe for (i = 0; i < 8; i++) 169 1.20 uwe pc->pc_column[i] = 0xdfff; 170 1.20 uwe 171 1.20 uwe /* select PFC access method */ 172 1.20 uwe pc->pc_callout = pfckbd_callout_lookup(); 173 1.20 uwe } 174 1.20 uwe 175 1.20 uwe 176 1.20 uwe /* 177 1.20 uwe * Callback for hpckbd_initif 178 1.20 uwe */ 179 1.19 uwe static int 180 1.1 uch pfckbd_input_establish(void *ic, struct hpckbd_if *kbdif) 181 1.1 uch { 182 1.1 uch struct pfckbd_core *pc = ic; 183 1.1 uch 184 1.20 uwe pc->pc_hpckbd = kbdif; /* save hpckbd interface */ 185 1.20 uwe pc->pc_enabled = 1; /* ok to talk to hpckbd */ 186 1.1 uch 187 1.1 uch return 0; 188 1.1 uch } 189 1.1 uch 190 1.20 uwe /* 191 1.20 uwe * Callback for hpckbd_cngetc 192 1.20 uwe */ 193 1.19 uwe static int 194 1.20 uwe pfckbd_poll(void *ic) 195 1.1 uch { 196 1.20 uwe struct pfckbd_core *pc = ic; 197 1.1 uch 198 1.30 uwe if (pc->pc_enabled && pc->pc_callout != NULL) 199 1.20 uwe (*pc->pc_callout)(pc); 200 1.1 uch 201 1.1 uch return 0; 202 1.1 uch } 203 1.1 uch 204 1.30 uwe static void 205 1.30 uwe pfckbd_callout(void *arg) 206 1.30 uwe { 207 1.30 uwe struct pfckbd_core *pc = arg; 208 1.30 uwe 209 1.30 uwe (*pc->pc_callout)(pc); 210 1.30 uwe callout_schedule(&pc->pc_soft_ch, 1); 211 1.30 uwe } 212 1.30 uwe 213 1.30 uwe 214 1.20 uwe /* 215 1.20 uwe * Called by platform specific scan routines to report key events to hpckbd 216 1.20 uwe */ 217 1.19 uwe static void 218 1.20 uwe pfckbd_input(struct pfckbd_core *pc, int column, uint16_t data) 219 1.3 uch { 220 1.3 uch int row, type, val; 221 1.18 uwe unsigned int edge, mask; 222 1.3 uch 223 1.20 uwe edge = data ^ pc->pc_column[column]; 224 1.20 uwe if (edge == 0) 225 1.20 uwe return; /* no changes in this column */ 226 1.20 uwe 227 1.20 uwe pc->pc_column[column] = data; 228 1.20 uwe 229 1.20 uwe for (row = 0, mask = 1; row < 16; ++row, mask <<= 1) { 230 1.20 uwe if (mask & edge) { 231 1.20 uwe type = mask & data ? /* up */ 0 : /* down */ 1; 232 1.20 uwe DPRINTF("(%2d, %2d) %d \n", row, column, type); 233 1.20 uwe 234 1.20 uwe val = row * 8 + column; 235 1.20 uwe hpckbd_input(pc->pc_hpckbd, type, val); 236 1.3 uch } 237 1.3 uch } 238 1.1 uch } 239 1.1 uch 240 1.20 uwe 241 1.3 uch /* 242 1.20 uwe * Platform dependent scan routines. 243 1.3 uch */ 244 1.3 uch 245 1.3 uch /* Look up appropriate callback handler */ 246 1.19 uwe static void 247 1.30 uwe (*pfckbd_callout_lookup(void))(struct pfckbd_core *) 248 1.3 uch { 249 1.20 uwe int i, n; 250 1.20 uwe 251 1.20 uwe n = sizeof(pfckbd_calloutfunc_table) 252 1.20 uwe / sizeof(pfckbd_calloutfunc_table[0]); 253 1.20 uwe 254 1.3 uch for (i = 0; i < n; i++) 255 1.3 uch if (platid_match(&platid, 256 1.20 uwe pfckbd_calloutfunc_table[i].platform)) 257 1.20 uwe return pfckbd_calloutfunc_table[i].func; 258 1.3 uch 259 1.30 uwe return NULL; 260 1.3 uch } 261 1.3 uch 262 1.20 uwe /* 263 1.20 uwe * HP Jornada680/690, HP620LX 264 1.20 uwe */ 265 1.19 uwe static void 266 1.30 uwe pfckbd_callout_hp(struct pfckbd_core *pc) 267 1.1 uch { 268 1.10 uwe #define PFCKBD_HP_PDCR_MASK 0xcc0c 269 1.10 uwe #define PFCKBD_HP_PECR_MASK 0xf0cf 270 1.10 uwe 271 1.10 uwe /* 272 1.10 uwe * Disable output on all lines but the n'th line in D. 273 1.10 uwe * Pull the n'th scan line in D low. 274 1.10 uwe */ 275 1.10 uwe #define PD(n) \ 276 1.14 uwe { (uint16_t)(PFCKBD_HP_PDCR_MASK & (~(1 << (2*(n)+1)))), \ 277 1.14 uwe (uint16_t)(PFCKBD_HP_PECR_MASK & 0xffff), \ 278 1.14 uwe (uint8_t)~(1 << (n)), \ 279 1.10 uwe 0xff } 280 1.10 uwe 281 1.10 uwe /* Ditto for E */ 282 1.10 uwe #define PE(n) \ 283 1.14 uwe { (uint16_t)(PFCKBD_HP_PDCR_MASK & 0xffff), \ 284 1.14 uwe (uint16_t)(PFCKBD_HP_PECR_MASK & (~(1 << (2*(n)+1)))), \ 285 1.10 uwe 0xff, \ 286 1.14 uwe (uint8_t)~(1 << (n)) } 287 1.10 uwe 288 1.1 uch static const struct { 289 1.14 uwe uint16_t dc, ec; uint8_t d, e; 290 1.1 uch } scan[] = { 291 1.10 uwe PD(1), PD(5), PE(1), PE(6), PE(7), PE(3), PE(0), PD(7) 292 1.1 uch }; 293 1.10 uwe 294 1.10 uwe #undef PD 295 1.10 uwe #undef PE 296 1.10 uwe 297 1.14 uwe uint16_t dc, ec; 298 1.3 uch int column; 299 1.14 uwe uint16_t data; 300 1.1 uch 301 1.1 uch if (!pc->pc_enabled) 302 1.30 uwe return; 303 1.1 uch 304 1.10 uwe /* bits in D/E control regs we do not touch (XXX: can they change?) */ 305 1.10 uwe dc = _reg_read_2(SH7709_PDCR) & ~PFCKBD_HP_PDCR_MASK; 306 1.10 uwe ec = _reg_read_2(SH7709_PECR) & ~PFCKBD_HP_PECR_MASK; 307 1.10 uwe 308 1.1 uch for (column = 0; column < 8; column++) { 309 1.10 uwe /* disable output to all lines except the one we scan */ 310 1.10 uwe _reg_write_2(SH7709_PDCR, dc | scan[column].dc); 311 1.10 uwe _reg_write_2(SH7709_PECR, ec | scan[column].ec); 312 1.10 uwe delay(5); 313 1.10 uwe 314 1.10 uwe /* pull the scan line low */ 315 1.7 uch _reg_write_1(SH7709_PDDR, scan[column].d); 316 1.7 uch _reg_write_1(SH7709_PEDR, scan[column].e); 317 1.1 uch delay(50); 318 1.10 uwe 319 1.10 uwe /* read sense */ 320 1.20 uwe data = _reg_read_1(SH7709_PFDR) 321 1.20 uwe | (_reg_read_1(SH7709_PCDR) << 8); 322 1.2 uch 323 1.20 uwe pfckbd_input(pc, column, data); 324 1.3 uch } 325 1.3 uch 326 1.10 uwe /* scan no lines */ 327 1.7 uch _reg_write_1(SH7709_PDDR, 0xff); 328 1.7 uch _reg_write_1(SH7709_PEDR, 0xff); 329 1.10 uwe 330 1.10 uwe /* enable all scan lines */ 331 1.10 uwe _reg_write_2(SH7709_PDCR, dc | (0x5555 & PFCKBD_HP_PDCR_MASK)); 332 1.10 uwe _reg_write_2(SH7709_PECR, ec | (0x5555 & PFCKBD_HP_PECR_MASK)); 333 1.10 uwe 334 1.12 uwe #if 0 335 1.10 uwe /* (ignore) extra keys/events (recorder buttons, lid, cable &c) */ 336 1.7 uch data = _reg_read_1(SH7709_PGDR) | (_reg_read_1(SH7709_PHDR) << 8); 337 1.12 uwe #endif 338 1.3 uch } 339 1.3 uch 340 1.20 uwe /* 341 1.20 uwe * HITACH PERSONA (HPW-50PAD) 342 1.20 uwe */ 343 1.19 uwe static void 344 1.30 uwe pfckbd_callout_hitachi(struct pfckbd_core *pc) 345 1.3 uch { 346 1.15 kiyohara #define PFCKBD_HITACHI_PCCR_MASK 0xfff3 347 1.13 uwe #define PFCKBD_HITACHI_PDCR_MASK 0x000c 348 1.13 uwe #define PFCKBD_HITACHI_PECR_MASK 0x30cf 349 1.13 uwe 350 1.15 kiyohara #define PFCKBD_HITACHI_PCDR_SCN_MASK 0xfd 351 1.22 kiyohara #define PFCKBD_HITACHI_PDDR_SCN_MASK 0x02 352 1.22 kiyohara #define PFCKBD_HITACHI_PEDR_SCN_MASK 0x4b 353 1.13 uwe 354 1.13 uwe #define PFCKBD_HITACHI_PCDR_SNS_MASK 0x01 355 1.13 uwe #define PFCKBD_HITACHI_PFDR_SNS_MASK 0xfe 356 1.13 uwe 357 1.13 uwe /* 358 1.13 uwe * Disable output on all lines but the n'th line in C. 359 1.13 uwe * Pull the n'th scan line in C low. 360 1.13 uwe */ 361 1.13 uwe #define PC(n) \ 362 1.14 uwe { (uint16_t)(PFCKBD_HITACHI_PCCR_MASK & (~(1 << (2*(n)+1)))), \ 363 1.14 uwe (uint16_t)(PFCKBD_HITACHI_PDCR_MASK & 0xffff), \ 364 1.14 uwe (uint16_t)(PFCKBD_HITACHI_PECR_MASK & 0xffff), \ 365 1.14 uwe (uint8_t)(PFCKBD_HITACHI_PCDR_SCN_MASK & ~(1 << (n))), \ 366 1.13 uwe PFCKBD_HITACHI_PDDR_SCN_MASK, \ 367 1.13 uwe PFCKBD_HITACHI_PEDR_SCN_MASK } 368 1.13 uwe 369 1.13 uwe /* Ditto for D */ 370 1.13 uwe #define PD(n) \ 371 1.14 uwe { (uint16_t)(PFCKBD_HITACHI_PCCR_MASK & 0xffff), \ 372 1.14 uwe (uint16_t)(PFCKBD_HITACHI_PDCR_MASK & (~(1 << (2*(n)+1)))), \ 373 1.14 uwe (uint16_t)(PFCKBD_HITACHI_PECR_MASK & 0xffff), \ 374 1.13 uwe PFCKBD_HITACHI_PCDR_SCN_MASK, \ 375 1.14 uwe (uint8_t)(PFCKBD_HITACHI_PDDR_SCN_MASK & ~(1 << (n))), \ 376 1.13 uwe PFCKBD_HITACHI_PEDR_SCN_MASK } 377 1.13 uwe 378 1.13 uwe /* Ditto for E */ 379 1.13 uwe #define PE(n) \ 380 1.14 uwe { (uint16_t)(PFCKBD_HITACHI_PCCR_MASK & 0xffff), \ 381 1.14 uwe (uint16_t)(PFCKBD_HITACHI_PDCR_MASK & 0xffff), \ 382 1.14 uwe (uint16_t)(PFCKBD_HITACHI_PECR_MASK & (~(1 << (2*(n)+1)))), \ 383 1.13 uwe PFCKBD_HITACHI_PCDR_SCN_MASK, \ 384 1.13 uwe PFCKBD_HITACHI_PDDR_SCN_MASK, \ 385 1.14 uwe (uint8_t)(PFCKBD_HITACHI_PEDR_SCN_MASK & ~(1 << (n))) } 386 1.13 uwe 387 1.3 uch static const struct { 388 1.14 uwe uint16_t cc, dc, ec; uint8_t c, d, e; 389 1.3 uch } scan[] = { 390 1.13 uwe PE(6), PE(3), PE(1), PE(0), PC(7), PC(6), PC(5), PC(4), 391 1.15 kiyohara PC(3), PC(2), PD(1), PC(0) 392 1.3 uch }; 393 1.13 uwe 394 1.14 uwe uint16_t cc, dc, ec; 395 1.15 kiyohara uint8_t data[2], cd, dd, ed; 396 1.13 uwe int i; 397 1.3 uch 398 1.3 uch if (!pc->pc_enabled) 399 1.30 uwe return; 400 1.3 uch 401 1.13 uwe /* bits in C/D/E control regs we do not touch (XXX: can they change?) */ 402 1.13 uwe cc = _reg_read_2(SH7709_PCCR) & ~PFCKBD_HITACHI_PCCR_MASK; 403 1.13 uwe dc = _reg_read_2(SH7709_PDCR) & ~PFCKBD_HITACHI_PDCR_MASK; 404 1.13 uwe ec = _reg_read_2(SH7709_PECR) & ~PFCKBD_HITACHI_PECR_MASK; 405 1.13 uwe 406 1.13 uwe for (i = 0; i < 12; i++) { 407 1.13 uwe /* disable output to all lines except the one we scan */ 408 1.15 kiyohara _reg_write_2(SH7709_PCCR, cc | scan[i].cc); 409 1.13 uwe _reg_write_2(SH7709_PDCR, dc | scan[i].dc); 410 1.13 uwe _reg_write_2(SH7709_PECR, ec | scan[i].ec); 411 1.13 uwe delay(5); 412 1.13 uwe 413 1.22 kiyohara cd = _reg_read_1(SH7709_PCDR) & ~PFCKBD_HITACHI_PCDR_SCN_MASK; 414 1.22 kiyohara dd = _reg_read_1(SH7709_PDDR) & ~PFCKBD_HITACHI_PDDR_SCN_MASK; 415 1.22 kiyohara ed = _reg_read_1(SH7709_PEDR) & ~PFCKBD_HITACHI_PEDR_SCN_MASK; 416 1.22 kiyohara 417 1.13 uwe /* pull the scan line low */ 418 1.22 kiyohara _reg_write_1(SH7709_PCDR, cd | scan[i].c); 419 1.22 kiyohara _reg_write_1(SH7709_PDDR, dd | scan[i].d); 420 1.22 kiyohara _reg_write_1(SH7709_PEDR, ed | scan[i].e); 421 1.3 uch delay(50); 422 1.1 uch 423 1.13 uwe /* read sense */ 424 1.13 uwe data[i & 0x1] = 425 1.20 uwe (_reg_read_1(SH7709_PCDR) & PFCKBD_HITACHI_PCDR_SNS_MASK) 426 1.20 uwe | (_reg_read_1(SH7709_PFDR) & PFCKBD_HITACHI_PFDR_SNS_MASK); 427 1.13 uwe 428 1.13 uwe if (i & 0x1) 429 1.20 uwe pfckbd_input(pc, (i >> 1), (data[0] | (data[1] << 8))); 430 1.1 uch } 431 1.1 uch 432 1.13 uwe /* enable all scan lines */ 433 1.13 uwe _reg_write_2(SH7709_PCCR, cc | (0x5555 & PFCKBD_HITACHI_PCCR_MASK)); 434 1.13 uwe _reg_write_2(SH7709_PDCR, dc | (0x5555 & PFCKBD_HITACHI_PDCR_MASK)); 435 1.13 uwe _reg_write_2(SH7709_PECR, ec | (0x5555 & PFCKBD_HITACHI_PECR_MASK)); 436 1.1 uch } 437 1.22 kiyohara 438 1.22 kiyohara void 439 1.26 cegger pfckbd_poll_hitachi_power(void) 440 1.22 kiyohara { 441 1.22 kiyohara static const struct { 442 1.22 kiyohara uint16_t cc, dc, ec; uint8_t c, d, e; 443 1.22 kiyohara } poll = PD(1); 444 1.22 kiyohara 445 1.22 kiyohara #undef PC 446 1.22 kiyohara #undef PD 447 1.22 kiyohara #undef PE 448 1.22 kiyohara 449 1.22 kiyohara uint16_t cc, dc, ec; 450 1.22 kiyohara uint8_t cd, dd, ed; 451 1.22 kiyohara 452 1.22 kiyohara /* bits in C/D/E control regs we do not touch (XXX: can they change?) */ 453 1.22 kiyohara cc = _reg_read_2(SH7709_PCCR) & ~PFCKBD_HITACHI_PCCR_MASK; 454 1.22 kiyohara dc = _reg_read_2(SH7709_PDCR) & ~PFCKBD_HITACHI_PDCR_MASK; 455 1.22 kiyohara ec = _reg_read_2(SH7709_PECR) & ~PFCKBD_HITACHI_PECR_MASK; 456 1.22 kiyohara 457 1.22 kiyohara /* disable output to all lines except the one we scan */ 458 1.22 kiyohara _reg_write_2(SH7709_PCCR, cc | poll.cc); 459 1.22 kiyohara _reg_write_2(SH7709_PDCR, dc | poll.dc); 460 1.22 kiyohara _reg_write_2(SH7709_PECR, ec | poll.ec); 461 1.22 kiyohara delay(5); 462 1.22 kiyohara 463 1.22 kiyohara cd = _reg_read_1(SH7709_PCDR) & ~PFCKBD_HITACHI_PCDR_SCN_MASK; 464 1.22 kiyohara dd = _reg_read_1(SH7709_PDDR) & ~PFCKBD_HITACHI_PDDR_SCN_MASK; 465 1.22 kiyohara ed = _reg_read_1(SH7709_PEDR) & ~PFCKBD_HITACHI_PEDR_SCN_MASK; 466 1.22 kiyohara 467 1.22 kiyohara /* pull the scan line low */ 468 1.22 kiyohara _reg_write_1(SH7709_PCDR, cd | poll.c); 469 1.22 kiyohara _reg_write_1(SH7709_PDDR, dd | poll.d); 470 1.22 kiyohara _reg_write_1(SH7709_PEDR, ed | poll.e); 471 1.22 kiyohara delay(50); 472 1.22 kiyohara 473 1.22 kiyohara /* poll POWER On */ 474 1.22 kiyohara while (_reg_read_1(SH7709_PCDR) & PFCKBD_HITACHI_PCDR_SNS_MASK & 0x01); 475 1.22 kiyohara 476 1.22 kiyohara /* enable all scan lines */ 477 1.22 kiyohara _reg_write_2(SH7709_PCCR, cc | (0x5555 & PFCKBD_HITACHI_PCCR_MASK)); 478 1.22 kiyohara _reg_write_2(SH7709_PDCR, dc | (0x5555 & PFCKBD_HITACHI_PDCR_MASK)); 479 1.22 kiyohara _reg_write_2(SH7709_PECR, ec | (0x5555 & PFCKBD_HITACHI_PECR_MASK)); 480 1.22 kiyohara } 481