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