Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

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