OpenCores
URL https://opencores.org/ocsvn/test_project/test_project/trunk

Subversion Repositories test_project

[/] [test_project/] [trunk/] [linux_sd_driver/] [drivers/] [macintosh/] [via-pmu68k.c] - Blame information for rev 62

Details | Compare with Previous | View Log

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

powered by: WebSVN 2.1.0

© copyright 1999-2025 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.