linux/drivers/macintosh/via-pmu68k.c
<<
>>
Prefs
   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}
 818