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