1/* 2 * Device driver for the PMU on 68K-based Apple PowerBooks 3 * 4 * The VIA (versatile interface adapter) interfaces to the PMU, 5 * a 6805 microprocessor core whose primary function is to control 6 * battery charging and system power on the PowerBooks. 7 * The PMU also controls the ADB (Apple Desktop Bus) which connects 8 * to the keyboard and mouse, as well as the non-volatile RAM 9 * and the RTC (real time clock) chip. 10 * 11 * Adapted for 68K PMU by Joshua M. Thompson 12 * 13 * Based largely on the PowerMac PMU code by Paul Mackerras and 14 * Fabio Riccardi. 15 * 16 * Also based on the PMU driver from MkLinux by Apple Computer, Inc. 17 * and the Open Software Foundation, Inc. 18 */ 19 20#include <stdarg.h> 21#include <linux/types.h> 22#include <linux/errno.h> 23#include <linux/kernel.h> 24#include <linux/delay.h> 25#include <linux/miscdevice.h> 26#include <linux/blkdev.h> 27#include <linux/pci.h> 28#include <linux/init.h> 29#include <linux/interrupt.h> 30 31#include <linux/adb.h> 32#include <linux/pmu.h> 33#include <linux/cuda.h> 34 35#include <asm/macintosh.h> 36#include <asm/macints.h> 37#include <asm/mac_via.h> 38 39#include <asm/pgtable.h> 40#include <asm/irq.h> 41#include <asm/uaccess.h> 42 43/* Misc minor number allocated for /dev/pmu */ 44#define PMU_MINOR 154 45 46/* VIA registers - spaced 0x200 bytes apart */ 47#define RS 0x200 /* skip between registers */ 48#define B 0 /* B-side data */ 49#define A RS /* A-side data */ 50#define DIRB (2*RS) /* B-side direction (1=output) */ 51#define DIRA (3*RS) /* A-side direction (1=output) */ 52#define T1CL (4*RS) /* Timer 1 ctr/latch (low 8 bits) */ 53#define T1CH (5*RS) /* Timer 1 counter (high 8 bits) */ 54#define T1LL (6*RS) /* Timer 1 latch (low 8 bits) */ 55#define T1LH (7*RS) /* Timer 1 latch (high 8 bits) */ 56#define T2CL (8*RS) /* Timer 2 ctr/latch (low 8 bits) */ 57#define T2CH (9*RS) /* Timer 2 counter (high 8 bits) */ 58#define SR (10*RS) /* Shift register */ 59#define ACR (11*RS) /* Auxiliary control register */ 60#define PCR (12*RS) /* Peripheral control register */ 61#define IFR (13*RS) /* Interrupt flag register */ 62#define IER (14*RS) /* Interrupt enable register */ 63#define ANH (15*RS) /* A-side data, no handshake */ 64 65/* Bits in B data register: both active low */ 66#define TACK 0x02 /* Transfer acknowledge (input) */ 67#define TREQ 0x04 /* Transfer request (output) */ 68 69/* Bits in ACR */ 70#define SR_CTRL 0x1c /* Shift register control bits */ 71#define SR_EXT 0x0c /* Shift on external clock */ 72#define SR_OUT 0x10 /* Shift out if 1 */ 73 74/* Bits in IFR and IER */ 75#define SR_INT 0x04 /* Shift register full/empty */ 76#define CB1_INT 0x10 /* transition on CB1 input */ 77 78static enum pmu_state { 79 idle, 80 sending, 81 intack, 82 reading, 83 reading_intr, 84} pmu_state; 85 86static struct adb_request *current_req; 87static struct adb_request *last_req; 88static struct adb_request *req_awaiting_reply; 89static unsigned char interrupt_data[32]; 90static unsigned char *reply_ptr; 91static int data_index; 92static int data_len; 93static int adb_int_pending; 94static int pmu_adb_flags; 95static int adb_dev_map; 96static struct adb_request bright_req_1, bright_req_2, bright_req_3; 97static int pmu_kind = PMU_UNKNOWN; 98static int pmu_fully_inited; 99 100int asleep; 101 102static int pmu_probe(void); 103static int pmu_init(void); 104static void pmu_start(void); 105static irqreturn_t pmu_interrupt(int irq, void *arg); 106static int pmu_send_request(struct adb_request *req, int sync); 107static int pmu_autopoll(int devs); 108void pmu_poll(void); 109static int pmu_reset_bus(void); 110 111static void pmu_start(void); 112static void send_byte(int x); 113static void recv_byte(void); 114static void pmu_done(struct adb_request *req); 115static void pmu_handle_data(unsigned char *data, int len); 116static void set_volume(int level); 117static void pmu_enable_backlight(int on); 118static void pmu_set_brightness(int level); 119 120struct adb_driver via_pmu_driver = { 121 "68K PMU", 122 pmu_probe, 123 pmu_init, 124 pmu_send_request, 125 pmu_autopoll, 126 pmu_poll, 127 pmu_reset_bus 128}; 129 130/* 131 * This table indicates for each PMU opcode: 132 * - the number of data bytes to be sent with the command, or -1 133 * if a length byte should be sent, 134 * - the number of response bytes which the PMU will return, or 135 * -1 if it will send a length byte. 136 */ 137static s8 pmu_data_len[256][2] = { 138/* 0 1 2 3 4 5 6 7 */ 139/*00*/ {-1, 0},{-1, 0},{-1, 0},{-1, 0},{-1, 0},{-1, 0},{-1, 0},{-1, 0}, 140/*08*/ {-1,-1},{-1,-1},{-1,-1},{-1,-1},{-1,-1},{-1,-1},{-1,-1},{-1,-1}, 141/*10*/ { 1, 0},{ 1, 0},{-1, 0},{-1, 0},{-1, 0},{-1, 0},{-1, 0},{-1, 0}, 142/*18*/ { 0, 1},{ 0, 1},{-1,-1},{-1,-1},{-1,-1},{-1,-1},{-1,-1},{ 0, 0}, 143/*20*/ {-1, 0},{ 0, 0},{ 2, 0},{ 1, 0},{ 1, 0},{-1, 0},{-1, 0},{-1, 0}, 144/*28*/ { 0,-1},{ 0,-1},{-1,-1},{-1,-1},{-1,-1},{-1,-1},{-1,-1},{ 0,-1}, 145/*30*/ { 4, 0},{20, 0},{-1, 0},{ 3, 0},{-1, 0},{-1, 0},{-1, 0},{-1, 0}, 146/*38*/ { 0, 4},{ 0,20},{ 2,-1},{ 2, 1},{ 3,-1},{-1,-1},{-1,-1},{ 4, 0}, 147/*40*/ { 1, 0},{ 1, 0},{-1, 0},{-1, 0},{-1, 0},{-1, 0},{-1, 0},{-1, 0}, 148/*48*/ { 0, 1},{ 0, 1},{-1,-1},{ 1, 0},{ 1, 0},{-1,-1},{-1,-1},{-1,-1}, 149/*50*/ { 1, 0},{ 0, 0},{ 2, 0},{ 2, 0},{-1, 0},{ 1, 0},{ 3, 0},{ 1, 0}, 150/*58*/ { 0, 1},{ 1, 0},{ 0, 2},{ 0, 2},{ 0,-1},{-1,-1},{-1,-1},{-1,-1}, 151/*60*/ { 2, 0},{-1, 0},{-1, 0},{-1, 0},{-1, 0},{-1, 0},{-1, 0},{-1, 0}, 152/*68*/ { 0, 3},{ 0, 3},{ 0, 2},{ 0, 8},{ 0,-1},{ 0,-1},{-1,-1},{-1,-1}, 153/*70*/ { 1, 0},{ 1, 0},{ 1, 0},{-1, 0},{-1, 0},{-1, 0},{-1, 0},{-1, 0}, 154/*78*/ { 0,-1},{ 0,-1},{-1,-1},{-1,-1},{-1,-1},{ 5, 1},{ 4, 1},{ 4, 1}, 155/*80*/ { 4, 0},{-1, 0},{ 0, 0},{-1, 0},{-1, 0},{-1, 0},{-1, 0},{-1, 0}, 156/*88*/ { 0, 5},{-1,-1},{-1,-1},{-1,-1},{-1,-1},{-1,-1},{-1,-1},{-1,-1}, 157/*90*/ { 1, 0},{ 2, 0},{-1, 0},{-1, 0},{-1, 0},{-1, 0},{-1, 0},{-1, 0}, 158/*98*/ { 0, 1},{ 0, 1},{-1,-1},{-1,-1},{-1,-1},{-1,-1},{-1,-1},{-1,-1}, 159/*a0*/ { 2, 0},{ 2, 0},{ 2, 0},{ 4, 0},{-1, 0},{ 0, 0},{-1, 0},{-1, 0}, 160/*a8*/ { 1, 1},{ 1, 0},{ 3, 0},{ 2, 0},{-1,-1},{-1,-1},{-1,-1},{-1,-1}, 161/*b0*/ {-1, 0},{-1, 0},{-1, 0},{-1, 0},{-1, 0},{-1, 0},{-1, 0},{-1, 0}, 162/*b8*/ {-1,-1},{-1,-1},{-1,-1},{-1,-1},{-1,-1},{-1,-1},{-1,-1},{-1,-1}, 163/*c0*/ {-1, 0},{-1, 0},{-1, 0},{-1, 0},{-1, 0},{-1, 0},{-1, 0},{-1, 0}, 164/*c8*/ {-1,-1},{-1,-1},{-1,-1},{-1,-1},{-1,-1},{-1,-1},{-1,-1},{-1,-1}, 165/*d0*/ { 0, 0},{-1, 0},{-1, 0},{-1, 0},{-1, 0},{-1, 0},{-1, 0},{-1, 0}, 166/*d8*/ { 1, 1},{ 1, 1},{-1,-1},{-1,-1},{ 0, 1},{ 0,-1},{-1,-1},{-1,-1}, 167/*e0*/ {-1, 0},{ 4, 0},{ 0, 1},{-1, 0},{-1, 0},{ 4, 0},{-1, 0},{-1, 0}, 168/*e8*/ { 3,-1},{-1,-1},{ 0, 1},{-1,-1},{ 0,-1},{-1,-1},{-1,-1},{ 0, 0}, 169/*f0*/ {-1, 0},{-1, 0},{-1, 0},{-1, 0},{-1, 0},{-1, 0},{-1, 0},{-1, 0}, 170/*f8*/ {-1,-1},{-1,-1},{-1,-1},{-1,-1},{-1,-1},{-1,-1},{-1,-1},{-1,-1}, 171}; 172 173int pmu_probe(void) 174{ 175 if (macintosh_config->adb_type == MAC_ADB_PB1) { 176 pmu_kind = PMU_68K_V1; 177 } else if (macintosh_config->adb_type == MAC_ADB_PB2) { 178 pmu_kind = PMU_68K_V2; 179 } else { 180 return -ENODEV; 181 } 182 183 pmu_state = idle; 184 185 return 0; 186} 187 188static int 189pmu_init(void) 190{ 191 int timeout; 192 volatile struct adb_request req; 193 194 via2[B] |= TREQ; /* negate TREQ */ 195 via2[DIRB] = (via2[DIRB] | TREQ) & ~TACK; /* TACK in, TREQ out */ 196 197 pmu_request((struct adb_request *) &req, NULL, 2, PMU_SET_INTR_MASK, PMU_INT_ADB); 198 timeout = 100000; 199 while (!req.complete) { 200 if (--timeout < 0) { 201 printk(KERN_ERR "pmu_init: no response from PMU\n"); 202 return -EAGAIN; 203 } 204 udelay(10); 205 pmu_poll(); 206 } 207 208 /* ack all pending interrupts */ 209 timeout = 100000; 210 interrupt_data[0] = 1; 211 while (interrupt_data[0] || pmu_state != idle) { 212 if (--timeout < 0) { 213 printk(KERN_ERR "pmu_init: timed out acking intrs\n"); 214 return -EAGAIN; 215 } 216 if (pmu_state == idle) { 217 adb_int_pending = 1; 218 pmu_interrupt(0, NULL); 219 } 220 pmu_poll(); 221 udelay(10); 222 } 223 224 pmu_request((struct adb_request *) &req, NULL, 2, PMU_SET_INTR_MASK, 225 PMU_INT_ADB_AUTO|PMU_INT_SNDBRT|PMU_INT_ADB); 226 timeout = 100000; 227 while (!req.complete) { 228 if (--timeout < 0) { 229 printk(KERN_ERR "pmu_init: no response from PMU\n"); 230 return -EAGAIN; 231 } 232 udelay(10); 233 pmu_poll(); 234 } 235 236 bright_req_1.complete = 1; 237 bright_req_2.complete = 1; 238 bright_req_3.complete = 1; 239 240 if (request_irq(IRQ_MAC_ADB_SR, pmu_interrupt, 0, "pmu-shift", 241 pmu_interrupt)) { 242 printk(KERN_ERR "pmu_init: can't get irq %d\n", 243 IRQ_MAC_ADB_SR); 244 return -EAGAIN; 245 } 246 if (request_irq(IRQ_MAC_ADB_CL, pmu_interrupt, 0, "pmu-clock", 247 pmu_interrupt)) { 248 printk(KERN_ERR "pmu_init: can't get irq %d\n", 249 IRQ_MAC_ADB_CL); 250 free_irq(IRQ_MAC_ADB_SR, pmu_interrupt); 251 return -EAGAIN; 252 } 253 254 pmu_fully_inited = 1; 255 256 /* Enable backlight */ 257 pmu_enable_backlight(1); 258 259 printk("adb: PMU 68K driver v0.5 for Unified ADB.\n"); 260 261 return 0; 262} 263 264int 265pmu_get_model(void) 266{ 267 return pmu_kind; 268} 269 270/* Send an ADB command */ 271static int 272pmu_send_request(struct adb_request *req, int sync) 273{ 274 int i, ret; 275 276 if (!pmu_fully_inited) 277 { 278 req->complete = 1; 279 return -ENXIO; 280 } 281 282 ret = -EINVAL; 283 284 switch (req->data[0]) { 285 case PMU_PACKET: 286 for (i = 0; i < req->nbytes - 1; ++i) 287 req->data[i] = req->data[i+1]; 288 --req->nbytes; 289 if (pmu_data_len[req->data[0]][1] != 0) { 290 req->reply[0] = ADB_RET_OK; 291 req->reply_len = 1; 292 } else 293 req->reply_len = 0; 294 ret = pmu_queue_request(req); 295 break; 296 case CUDA_PACKET: 297 switch (req->data[1]) { 298 case CUDA_GET_TIME: 299 if (req->nbytes != 2) 300 break; 301 req->data[0] = PMU_READ_RTC; 302 req->nbytes = 1; 303 req->reply_len = 3; 304 req->reply[0] = CUDA_PACKET; 305 req->reply[1] = 0; 306 req->reply[2] = CUDA_GET_TIME; 307 ret = pmu_queue_request(req); 308 break; 309 case CUDA_SET_TIME: 310 if (req->nbytes != 6) 311 break; 312 req->data[0] = PMU_SET_RTC; 313 req->nbytes = 5; 314 for (i = 1; i <= 4; ++i) 315 req->data[i] = req->data[i+1]; 316 req->reply_len = 3; 317 req->reply[0] = CUDA_PACKET; 318 req->reply[1] = 0; 319 req->reply[2] = CUDA_SET_TIME; 320 ret = pmu_queue_request(req); 321 break; 322 case CUDA_GET_PRAM: 323 if (req->nbytes != 4) 324 break; 325 req->data[0] = PMU_READ_NVRAM; 326 req->data[1] = req->data[2]; 327 req->data[2] = req->data[3]; 328 req->nbytes = 3; 329 req->reply_len = 3; 330 req->reply[0] = CUDA_PACKET; 331 req->reply[1] = 0; 332 req->reply[2] = CUDA_GET_PRAM; 333 ret = pmu_queue_request(req); 334 break; 335 case CUDA_SET_PRAM: 336 if (req->nbytes != 5) 337 break; 338 req->data[0] = PMU_WRITE_NVRAM; 339 req->data[1] = req->data[2]; 340 req->data[2] = req->data[3]; 341 req->data[3] = req->data[4]; 342 req->nbytes = 4; 343 req->reply_len = 3; 344 req->reply[0] = CUDA_PACKET; 345 req->reply[1] = 0; 346 req->reply[2] = CUDA_SET_PRAM; 347 ret = pmu_queue_request(req); 348 break; 349 } 350 break; 351 case ADB_PACKET: 352 for (i = req->nbytes - 1; i > 1; --i) 353 req->data[i+2] = req->data[i]; 354 req->data[3] = req->nbytes - 2; 355 req->data[2] = pmu_adb_flags; 356 /*req->data[1] = req->data[1];*/ 357 req->data[0] = PMU_ADB_CMD; 358 req->nbytes += 2; 359 req->reply_expected = 1; 360 req->reply_len = 0; 361 ret = pmu_queue_request(req); 362 break; 363 } 364 if (ret) 365 { 366 req->complete = 1; 367 return ret; 368 } 369 370 if (sync) { 371 while (!req->complete) 372 pmu_poll(); 373 } 374 375 return 0; 376} 377 378/* Enable/disable autopolling */ 379static int 380pmu_autopoll(int devs) 381{ 382 struct adb_request req; 383 384 if (!pmu_fully_inited) return -ENXIO; 385 386 if (devs) { 387 adb_dev_map = devs; 388 pmu_request(&req, NULL, 5, PMU_ADB_CMD, 0, 0x86, 389 adb_dev_map >> 8, adb_dev_map); 390 pmu_adb_flags = 2; 391 } else { 392 pmu_request(&req, NULL, 1, PMU_ADB_POLL_OFF); 393 pmu_adb_flags = 0; 394 } 395 while (!req.complete) 396 pmu_poll(); 397 return 0; 398} 399 400/* Reset the ADB bus */ 401static int 402pmu_reset_bus(void) 403{ 404 struct adb_request req; 405 long timeout; 406 int save_autopoll = adb_dev_map; 407 408 if (!pmu_fully_inited) return -ENXIO; 409 410 /* anyone got a better idea?? */ 411 pmu_autopoll(0); 412 413 req.nbytes = 5; 414 req.done = NULL; 415 req.data[0] = PMU_ADB_CMD; 416 req.data[1] = 0; 417 req.data[2] = 3; /* ADB_BUSRESET ??? */ 418 req.data[3] = 0; 419 req.data[4] = 0; 420 req.reply_len = 0; 421 req.reply_expected = 1; 422 if (pmu_queue_request(&req) != 0) 423 { 424 printk(KERN_ERR "pmu_adb_reset_bus: pmu_queue_request failed\n"); 425 return -EIO; 426 } 427 while (!req.complete) 428 pmu_poll(); 429 timeout = 100000; 430 while (!req.complete) { 431 if (--timeout < 0) { 432 printk(KERN_ERR "pmu_adb_reset_bus (reset): no response from PMU\n"); 433 return -EIO; 434 } 435 udelay(10); 436 pmu_poll(); 437 } 438 439 if (save_autopoll != 0) 440 pmu_autopoll(save_autopoll); 441 442 return 0; 443} 444 445/* Construct and send a pmu request */ 446int 447pmu_request(struct adb_request *req, void (*done)(struct adb_request *), 448 int nbytes, ...) 449{ 450 va_list list; 451 int i; 452 453 if (nbytes < 0 || nbytes > 32) { 454 printk(KERN_ERR "pmu_request: bad nbytes (%d)\n", nbytes); 455 req->complete = 1; 456 return -EINVAL; 457 } 458 req->nbytes = nbytes; 459 req->done = done; 460 va_start(list, nbytes); 461 for (i = 0; i < nbytes; ++i) 462 req->data[i] = va_arg(list, int); 463 va_end(list); 464 if (pmu_data_len[req->data[0]][1] != 0) { 465 req->reply[0] = ADB_RET_OK; 466 req->reply_len = 1; 467 } else 468 req->reply_len = 0; 469 req->reply_expected = 0; 470 return pmu_queue_request(req); 471} 472 473int 474pmu_queue_request(struct adb_request *req) 475{ 476 unsigned long flags; 477 int nsend; 478 479 if (req->nbytes <= 0) { 480 req->complete = 1; 481 return 0; 482 } 483 nsend = pmu_data_len[req->data[0]][0]; 484 if (nsend >= 0 && req->nbytes != nsend + 1) { 485 req->complete = 1; 486 return -EINVAL; 487 } 488 489 req->next = NULL; 490 req->sent = 0; 491 req->complete = 0; 492 local_irq_save(flags); 493 494 if (current_req != 0) { 495 last_req->next = req; 496 last_req = req; 497 } else { 498 current_req = req; 499 last_req = req; 500 if (pmu_state == idle) 501 pmu_start(); 502 } 503 504 local_irq_restore(flags); 505 return 0; 506} 507 508static void 509send_byte(int x) 510{ 511 via1[ACR] |= SR_CTRL; 512 via1[SR] = x; 513 via2[B] &= ~TREQ; /* assert TREQ */ 514} 515 516static void 517recv_byte(void) 518{ 519 char c; 520 521 via1[ACR] = (via1[ACR] | SR_EXT) & ~SR_OUT; 522 c = via1[SR]; /* resets SR */ 523 via2[B] &= ~TREQ; 524} 525 526static void 527pmu_start(void) 528{ 529 unsigned long flags; 530 struct adb_request *req; 531 532 /* assert pmu_state == idle */ 533 /* get the packet to send */ 534 local_irq_save(flags); 535 req = current_req; 536 if (req == 0 || pmu_state != idle 537 || (req->reply_expected && req_awaiting_reply)) 538 goto out; 539 540 pmu_state = sending; 541 data_index = 1; 542 data_len = pmu_data_len[req->data[0]][0]; 543 544 /* set the shift register to shift out and send a byte */ 545 send_byte(req->data[0]); 546 547out: 548 local_irq_restore(flags); 549} 550 551void 552pmu_poll(void) 553{ 554 unsigned long flags; 555 556 local_irq_save(flags); 557 if (via1[IFR] & SR_INT) { 558 via1[IFR] = SR_INT; 559 pmu_interrupt(IRQ_MAC_ADB_SR, NULL); 560 } 561 if (via1[IFR] & CB1_INT) { 562 via1[IFR] = CB1_INT; 563 pmu_interrupt(IRQ_MAC_ADB_CL, NULL); 564 } 565 local_irq_restore(flags); 566} 567 568static irqreturn_t 569pmu_interrupt(int irq, void *dev_id) 570{ 571 struct adb_request *req; 572 int timeout, bite = 0; /* to prevent compiler warning */ 573 574#if 0 575 printk("pmu_interrupt: irq %d state %d acr %02X, b %02X data_index %d/%d adb_int_pending %d\n", 576 irq, pmu_state, (uint) via1[ACR], (uint) via2[B], data_index, data_len, adb_int_pending); 577#endif 578 579 if (irq == IRQ_MAC_ADB_CL) { /* CB1 interrupt */ 580 adb_int_pending = 1; 581 } else if (irq == IRQ_MAC_ADB_SR) { /* SR interrupt */ 582 if (via2[B] & TACK) { 583 printk(KERN_DEBUG "PMU: SR_INT but ack still high! (%x)\n", via2[B]); 584 } 585 586 /* if reading grab the byte */ 587 if ((via1[ACR] & SR_OUT) == 0) bite = via1[SR]; 588 589 /* reset TREQ and wait for TACK to go high */ 590 via2[B] |= TREQ; 591 timeout = 3200; 592 while (!(via2[B] & TACK)) { 593 if (--timeout < 0) { 594 printk(KERN_ERR "PMU not responding (!ack)\n"); 595 goto finish; 596 } 597 udelay(10); 598 } 599 600 switch (pmu_state) { 601 case sending: 602 req = current_req; 603 if (data_len < 0) { 604 data_len = req->nbytes - 1; 605 send_byte(data_len); 606 break; 607 } 608 if (data_index <= data_len) { 609 send_byte(req->data[data_index++]); 610 break; 611 } 612 req->sent = 1; 613 data_len = pmu_data_len[req->data[0]][1]; 614 if (data_len == 0) { 615 pmu_state = idle; 616 current_req = req->next; 617 if (req->reply_expected) 618 req_awaiting_reply = req; 619 else 620 pmu_done(req); 621 } else { 622 pmu_state = reading; 623 data_index = 0; 624 reply_ptr = req->reply + req->reply_len; 625 recv_byte(); 626 } 627 break; 628 629 case intack: 630 data_index = 0; 631 data_len = -1; 632 pmu_state = reading_intr; 633 reply_ptr = interrupt_data; 634 recv_byte(); 635 break; 636 637 case reading: 638 case reading_intr: 639 if (data_len == -1) { 640 data_len = bite; 641 if (bite > 32) 642 printk(KERN_ERR "PMU: bad reply len %d\n", 643 bite); 644 } else { 645 reply_ptr[data_index++] = bite; 646 } 647 if (data_index < data_len) { 648 recv_byte(); 649 break; 650 } 651 652 if (pmu_state == reading_intr) { 653 pmu_handle_data(interrupt_data, data_index); 654 } else { 655 req = current_req; 656 current_req = req->next; 657 req->reply_len += data_index; 658 pmu_done(req); 659 } 660 pmu_state = idle; 661 662 break; 663 664 default: 665 printk(KERN_ERR "pmu_interrupt: unknown state %d?\n", 666 pmu_state); 667 } 668 } 669finish: 670 if (pmu_state == idle) { 671 if (adb_int_pending) { 672 pmu_state = intack; 673 send_byte(PMU_INT_ACK); 674 adb_int_pending = 0; 675 } else if (current_req) { 676 pmu_start(); 677 } 678 } 679 680#if 0 681 printk("pmu_interrupt: exit state %d acr %02X, b %02X data_index %d/%d adb_int_pending %d\n", 682 pmu_state, (uint) via1[ACR], (uint) via2[B], data_index, data_len, adb_int_pending); 683#endif 684 return IRQ_HANDLED; 685} 686 687static void 688pmu_done(struct adb_request *req) 689{ 690 req->complete = 1; 691 if (req->done) 692 (*req->done)(req); 693} 694 695/* Interrupt data could be the result data from an ADB cmd */ 696static void 697pmu_handle_data(unsigned char *data, int len) 698{ 699 static int show_pmu_ints = 1; 700 701 asleep = 0; 702 if (len < 1) { 703 adb_int_pending = 0; 704 return; 705 } 706 if (data[0] & PMU_INT_ADB) { 707 if ((data[0] & PMU_INT_ADB_AUTO) == 0) { 708 struct adb_request *req = req_awaiting_reply; 709 if (req == 0) { 710 printk(KERN_ERR "PMU: extra ADB reply\n"); 711 return; 712 } 713 req_awaiting_reply = NULL; 714 if (len <= 2) 715 req->reply_len = 0; 716 else { 717 memcpy(req->reply, data + 1, len - 1); 718 req->reply_len = len - 1; 719 } 720 pmu_done(req); 721 } else { 722 adb_input(data+1, len-1, 1); 723 } 724 } else { 725 if (data[0] == 0x08 && len == 3) { 726 /* sound/brightness buttons pressed */ 727 pmu_set_brightness(data[1] >> 3); 728 set_volume(data[2]); 729 } else if (show_pmu_ints 730 && !(data[0] == PMU_INT_TICK && len == 1)) { 731 int i; 732 printk(KERN_DEBUG "pmu intr"); 733 for (i = 0; i < len; ++i) 734 printk(" %.2x", data[i]); 735 printk("\n"); 736 } 737 } 738} 739 740static int backlight_level = -1; 741static int backlight_enabled = 0; 742 743#define LEVEL_TO_BRIGHT(lev) ((lev) < 1? 0x7f: 0x4a - ((lev) << 1)) 744 745static void 746pmu_enable_backlight(int on) 747{ 748 struct adb_request req; 749 750 if (on) { 751 /* first call: get current backlight value */ 752 if (backlight_level < 0) { 753 switch(pmu_kind) { 754 case PMU_68K_V1: 755 case PMU_68K_V2: 756 pmu_request(&req, NULL, 3, PMU_READ_NVRAM, 0x14, 0xe); 757 while (!req.complete) 758 pmu_poll(); 759 printk(KERN_DEBUG "pmu: nvram returned bright: %d\n", (int)req.reply[1]); 760 backlight_level = req.reply[1]; 761 break; 762 default: 763 backlight_enabled = 0; 764 return; 765 } 766 } 767 pmu_request(&req, NULL, 2, PMU_BACKLIGHT_BRIGHT, 768 LEVEL_TO_BRIGHT(backlight_level)); 769 while (!req.complete) 770 pmu_poll(); 771 } 772 pmu_request(&req, NULL, 2, PMU_POWER_CTRL, 773 PMU_POW_BACKLIGHT | (on ? PMU_POW_ON : PMU_POW_OFF)); 774 while (!req.complete) 775 pmu_poll(); 776 backlight_enabled = on; 777} 778 779static void 780pmu_set_brightness(int level) 781{ 782 int bright; 783 784 backlight_level = level; 785 bright = LEVEL_TO_BRIGHT(level); 786 if (!backlight_enabled) 787 return; 788 if (bright_req_1.complete) 789 pmu_request(&bright_req_1, NULL, 2, PMU_BACKLIGHT_BRIGHT, 790 bright); 791 if (bright_req_2.complete) 792 pmu_request(&bright_req_2, NULL, 2, PMU_POWER_CTRL, 793 PMU_POW_BACKLIGHT | (bright < 0x7f ? PMU_POW_ON : PMU_POW_OFF)); 794} 795 796void 797pmu_enable_irled(int on) 798{ 799 struct adb_request req; 800 801 pmu_request(&req, NULL, 2, PMU_POWER_CTRL, PMU_POW_IRLED | 802 (on ? PMU_POW_ON : PMU_POW_OFF)); 803 while (!req.complete) 804 pmu_poll(); 805} 806 807static void 808set_volume(int level) 809{ 810} 811 812int 813pmu_present(void) 814{ 815 return (pmu_kind != PMU_UNKNOWN); 816} 817