1*1da177e4SLinus Torvalds /* 2*1da177e4SLinus Torvalds * Device driver for the via-cuda on Apple Powermacs. 3*1da177e4SLinus Torvalds * 4*1da177e4SLinus Torvalds * The VIA (versatile interface adapter) interfaces to the CUDA, 5*1da177e4SLinus Torvalds * a 6805 microprocessor core which controls the ADB (Apple Desktop 6*1da177e4SLinus Torvalds * Bus) which connects to the keyboard and mouse. The CUDA also 7*1da177e4SLinus Torvalds * controls system power and the RTC (real time clock) chip. 8*1da177e4SLinus Torvalds * 9*1da177e4SLinus Torvalds * Copyright (C) 1996 Paul Mackerras. 10*1da177e4SLinus Torvalds */ 11*1da177e4SLinus Torvalds #include <stdarg.h> 12*1da177e4SLinus Torvalds #include <linux/config.h> 13*1da177e4SLinus Torvalds #include <linux/types.h> 14*1da177e4SLinus Torvalds #include <linux/errno.h> 15*1da177e4SLinus Torvalds #include <linux/kernel.h> 16*1da177e4SLinus Torvalds #include <linux/delay.h> 17*1da177e4SLinus Torvalds #include <linux/sched.h> 18*1da177e4SLinus Torvalds #include <linux/adb.h> 19*1da177e4SLinus Torvalds #include <linux/cuda.h> 20*1da177e4SLinus Torvalds #include <linux/spinlock.h> 21*1da177e4SLinus Torvalds #include <linux/interrupt.h> 22*1da177e4SLinus Torvalds #ifdef CONFIG_PPC 23*1da177e4SLinus Torvalds #include <asm/prom.h> 24*1da177e4SLinus Torvalds #include <asm/machdep.h> 25*1da177e4SLinus Torvalds #else 26*1da177e4SLinus Torvalds #include <asm/macintosh.h> 27*1da177e4SLinus Torvalds #include <asm/macints.h> 28*1da177e4SLinus Torvalds #include <asm/machw.h> 29*1da177e4SLinus Torvalds #include <asm/mac_via.h> 30*1da177e4SLinus Torvalds #endif 31*1da177e4SLinus Torvalds #include <asm/io.h> 32*1da177e4SLinus Torvalds #include <asm/system.h> 33*1da177e4SLinus Torvalds #include <linux/init.h> 34*1da177e4SLinus Torvalds 35*1da177e4SLinus Torvalds static volatile unsigned char __iomem *via; 36*1da177e4SLinus Torvalds static DEFINE_SPINLOCK(cuda_lock); 37*1da177e4SLinus Torvalds 38*1da177e4SLinus Torvalds #ifdef CONFIG_MAC 39*1da177e4SLinus Torvalds #define CUDA_IRQ IRQ_MAC_ADB 40*1da177e4SLinus Torvalds #define __openfirmware 41*1da177e4SLinus Torvalds #define eieio() 42*1da177e4SLinus Torvalds #else 43*1da177e4SLinus Torvalds #define CUDA_IRQ vias->intrs[0].line 44*1da177e4SLinus Torvalds #endif 45*1da177e4SLinus Torvalds 46*1da177e4SLinus Torvalds /* VIA registers - spaced 0x200 bytes apart */ 47*1da177e4SLinus Torvalds #define RS 0x200 /* skip between registers */ 48*1da177e4SLinus Torvalds #define B 0 /* B-side data */ 49*1da177e4SLinus Torvalds #define A RS /* A-side data */ 50*1da177e4SLinus Torvalds #define DIRB (2*RS) /* B-side direction (1=output) */ 51*1da177e4SLinus Torvalds #define DIRA (3*RS) /* A-side direction (1=output) */ 52*1da177e4SLinus Torvalds #define T1CL (4*RS) /* Timer 1 ctr/latch (low 8 bits) */ 53*1da177e4SLinus Torvalds #define T1CH (5*RS) /* Timer 1 counter (high 8 bits) */ 54*1da177e4SLinus Torvalds #define T1LL (6*RS) /* Timer 1 latch (low 8 bits) */ 55*1da177e4SLinus Torvalds #define T1LH (7*RS) /* Timer 1 latch (high 8 bits) */ 56*1da177e4SLinus Torvalds #define T2CL (8*RS) /* Timer 2 ctr/latch (low 8 bits) */ 57*1da177e4SLinus Torvalds #define T2CH (9*RS) /* Timer 2 counter (high 8 bits) */ 58*1da177e4SLinus Torvalds #define SR (10*RS) /* Shift register */ 59*1da177e4SLinus Torvalds #define ACR (11*RS) /* Auxiliary control register */ 60*1da177e4SLinus Torvalds #define PCR (12*RS) /* Peripheral control register */ 61*1da177e4SLinus Torvalds #define IFR (13*RS) /* Interrupt flag register */ 62*1da177e4SLinus Torvalds #define IER (14*RS) /* Interrupt enable register */ 63*1da177e4SLinus Torvalds #define ANH (15*RS) /* A-side data, no handshake */ 64*1da177e4SLinus Torvalds 65*1da177e4SLinus Torvalds /* Bits in B data register: all active low */ 66*1da177e4SLinus Torvalds #define TREQ 0x08 /* Transfer request (input) */ 67*1da177e4SLinus Torvalds #define TACK 0x10 /* Transfer acknowledge (output) */ 68*1da177e4SLinus Torvalds #define TIP 0x20 /* Transfer in progress (output) */ 69*1da177e4SLinus Torvalds 70*1da177e4SLinus Torvalds /* Bits in ACR */ 71*1da177e4SLinus Torvalds #define SR_CTRL 0x1c /* Shift register control bits */ 72*1da177e4SLinus Torvalds #define SR_EXT 0x0c /* Shift on external clock */ 73*1da177e4SLinus Torvalds #define SR_OUT 0x10 /* Shift out if 1 */ 74*1da177e4SLinus Torvalds 75*1da177e4SLinus Torvalds /* Bits in IFR and IER */ 76*1da177e4SLinus Torvalds #define IER_SET 0x80 /* set bits in IER */ 77*1da177e4SLinus Torvalds #define IER_CLR 0 /* clear bits in IER */ 78*1da177e4SLinus Torvalds #define SR_INT 0x04 /* Shift register full/empty */ 79*1da177e4SLinus Torvalds 80*1da177e4SLinus Torvalds static enum cuda_state { 81*1da177e4SLinus Torvalds idle, 82*1da177e4SLinus Torvalds sent_first_byte, 83*1da177e4SLinus Torvalds sending, 84*1da177e4SLinus Torvalds reading, 85*1da177e4SLinus Torvalds read_done, 86*1da177e4SLinus Torvalds awaiting_reply 87*1da177e4SLinus Torvalds } cuda_state; 88*1da177e4SLinus Torvalds 89*1da177e4SLinus Torvalds static struct adb_request *current_req; 90*1da177e4SLinus Torvalds static struct adb_request *last_req; 91*1da177e4SLinus Torvalds static unsigned char cuda_rbuf[16]; 92*1da177e4SLinus Torvalds static unsigned char *reply_ptr; 93*1da177e4SLinus Torvalds static int reading_reply; 94*1da177e4SLinus Torvalds static int data_index; 95*1da177e4SLinus Torvalds #ifdef CONFIG_PPC 96*1da177e4SLinus Torvalds static struct device_node *vias; 97*1da177e4SLinus Torvalds #endif 98*1da177e4SLinus Torvalds static int cuda_fully_inited = 0; 99*1da177e4SLinus Torvalds 100*1da177e4SLinus Torvalds #ifdef CONFIG_ADB 101*1da177e4SLinus Torvalds static int cuda_probe(void); 102*1da177e4SLinus Torvalds static int cuda_init(void); 103*1da177e4SLinus Torvalds static int cuda_send_request(struct adb_request *req, int sync); 104*1da177e4SLinus Torvalds static int cuda_adb_autopoll(int devs); 105*1da177e4SLinus Torvalds static int cuda_reset_adb_bus(void); 106*1da177e4SLinus Torvalds #endif /* CONFIG_ADB */ 107*1da177e4SLinus Torvalds 108*1da177e4SLinus Torvalds static int cuda_init_via(void); 109*1da177e4SLinus Torvalds static void cuda_start(void); 110*1da177e4SLinus Torvalds static irqreturn_t cuda_interrupt(int irq, void *arg, struct pt_regs *regs); 111*1da177e4SLinus Torvalds static void cuda_input(unsigned char *buf, int nb, struct pt_regs *regs); 112*1da177e4SLinus Torvalds void cuda_poll(void); 113*1da177e4SLinus Torvalds static int cuda_write(struct adb_request *req); 114*1da177e4SLinus Torvalds 115*1da177e4SLinus Torvalds int cuda_request(struct adb_request *req, 116*1da177e4SLinus Torvalds void (*done)(struct adb_request *), int nbytes, ...); 117*1da177e4SLinus Torvalds 118*1da177e4SLinus Torvalds #ifdef CONFIG_ADB 119*1da177e4SLinus Torvalds struct adb_driver via_cuda_driver = { 120*1da177e4SLinus Torvalds "CUDA", 121*1da177e4SLinus Torvalds cuda_probe, 122*1da177e4SLinus Torvalds cuda_init, 123*1da177e4SLinus Torvalds cuda_send_request, 124*1da177e4SLinus Torvalds cuda_adb_autopoll, 125*1da177e4SLinus Torvalds cuda_poll, 126*1da177e4SLinus Torvalds cuda_reset_adb_bus 127*1da177e4SLinus Torvalds }; 128*1da177e4SLinus Torvalds #endif /* CONFIG_ADB */ 129*1da177e4SLinus Torvalds 130*1da177e4SLinus Torvalds #ifdef CONFIG_PPC 131*1da177e4SLinus Torvalds int __init 132*1da177e4SLinus Torvalds find_via_cuda(void) 133*1da177e4SLinus Torvalds { 134*1da177e4SLinus Torvalds int err; 135*1da177e4SLinus Torvalds struct adb_request req; 136*1da177e4SLinus Torvalds 137*1da177e4SLinus Torvalds if (vias != 0) 138*1da177e4SLinus Torvalds return 1; 139*1da177e4SLinus Torvalds vias = find_devices("via-cuda"); 140*1da177e4SLinus Torvalds if (vias == 0) 141*1da177e4SLinus Torvalds return 0; 142*1da177e4SLinus Torvalds if (vias->next != 0) 143*1da177e4SLinus Torvalds printk(KERN_WARNING "Warning: only using 1st via-cuda\n"); 144*1da177e4SLinus Torvalds 145*1da177e4SLinus Torvalds #if 0 146*1da177e4SLinus Torvalds { int i; 147*1da177e4SLinus Torvalds 148*1da177e4SLinus Torvalds printk("find_via_cuda: node = %p, addrs =", vias->node); 149*1da177e4SLinus Torvalds for (i = 0; i < vias->n_addrs; ++i) 150*1da177e4SLinus Torvalds printk(" %x(%x)", vias->addrs[i].address, vias->addrs[i].size); 151*1da177e4SLinus Torvalds printk(", intrs ="); 152*1da177e4SLinus Torvalds for (i = 0; i < vias->n_intrs; ++i) 153*1da177e4SLinus Torvalds printk(" %x", vias->intrs[i].line); 154*1da177e4SLinus Torvalds printk("\n"); } 155*1da177e4SLinus Torvalds #endif 156*1da177e4SLinus Torvalds 157*1da177e4SLinus Torvalds if (vias->n_addrs != 1 || vias->n_intrs != 1) { 158*1da177e4SLinus Torvalds printk(KERN_ERR "via-cuda: expecting 1 address (%d) and 1 interrupt (%d)\n", 159*1da177e4SLinus Torvalds vias->n_addrs, vias->n_intrs); 160*1da177e4SLinus Torvalds if (vias->n_addrs < 1 || vias->n_intrs < 1) 161*1da177e4SLinus Torvalds return 0; 162*1da177e4SLinus Torvalds } 163*1da177e4SLinus Torvalds via = ioremap(vias->addrs->address, 0x2000); 164*1da177e4SLinus Torvalds 165*1da177e4SLinus Torvalds cuda_state = idle; 166*1da177e4SLinus Torvalds sys_ctrler = SYS_CTRLER_CUDA; 167*1da177e4SLinus Torvalds 168*1da177e4SLinus Torvalds err = cuda_init_via(); 169*1da177e4SLinus Torvalds if (err) { 170*1da177e4SLinus Torvalds printk(KERN_ERR "cuda_init_via() failed\n"); 171*1da177e4SLinus Torvalds via = NULL; 172*1da177e4SLinus Torvalds return 0; 173*1da177e4SLinus Torvalds } 174*1da177e4SLinus Torvalds 175*1da177e4SLinus Torvalds /* Clear and enable interrupts, but only on PPC. On 68K it's done */ 176*1da177e4SLinus Torvalds /* for us by the main VIA driver in arch/m68k/mac/via.c */ 177*1da177e4SLinus Torvalds 178*1da177e4SLinus Torvalds #ifndef CONFIG_MAC 179*1da177e4SLinus Torvalds out_8(&via[IFR], 0x7f); /* clear interrupts by writing 1s */ 180*1da177e4SLinus Torvalds out_8(&via[IER], IER_SET|SR_INT); /* enable interrupt from SR */ 181*1da177e4SLinus Torvalds #endif 182*1da177e4SLinus Torvalds 183*1da177e4SLinus Torvalds /* enable autopoll */ 184*1da177e4SLinus Torvalds cuda_request(&req, NULL, 3, CUDA_PACKET, CUDA_AUTOPOLL, 1); 185*1da177e4SLinus Torvalds while (!req.complete) 186*1da177e4SLinus Torvalds cuda_poll(); 187*1da177e4SLinus Torvalds 188*1da177e4SLinus Torvalds return 1; 189*1da177e4SLinus Torvalds } 190*1da177e4SLinus Torvalds #endif /* CONFIG_PPC */ 191*1da177e4SLinus Torvalds 192*1da177e4SLinus Torvalds static int __init via_cuda_start(void) 193*1da177e4SLinus Torvalds { 194*1da177e4SLinus Torvalds if (via == NULL) 195*1da177e4SLinus Torvalds return -ENODEV; 196*1da177e4SLinus Torvalds 197*1da177e4SLinus Torvalds #ifdef CONFIG_PPC 198*1da177e4SLinus Torvalds request_OF_resource(vias, 0, NULL); 199*1da177e4SLinus Torvalds #endif 200*1da177e4SLinus Torvalds 201*1da177e4SLinus Torvalds if (request_irq(CUDA_IRQ, cuda_interrupt, 0, "ADB", cuda_interrupt)) { 202*1da177e4SLinus Torvalds printk(KERN_ERR "cuda_init: can't get irq %d\n", CUDA_IRQ); 203*1da177e4SLinus Torvalds return -EAGAIN; 204*1da177e4SLinus Torvalds } 205*1da177e4SLinus Torvalds 206*1da177e4SLinus Torvalds printk("Macintosh CUDA driver v0.5 for Unified ADB.\n"); 207*1da177e4SLinus Torvalds 208*1da177e4SLinus Torvalds cuda_fully_inited = 1; 209*1da177e4SLinus Torvalds return 0; 210*1da177e4SLinus Torvalds } 211*1da177e4SLinus Torvalds 212*1da177e4SLinus Torvalds device_initcall(via_cuda_start); 213*1da177e4SLinus Torvalds 214*1da177e4SLinus Torvalds #ifdef CONFIG_ADB 215*1da177e4SLinus Torvalds static int 216*1da177e4SLinus Torvalds cuda_probe(void) 217*1da177e4SLinus Torvalds { 218*1da177e4SLinus Torvalds #ifdef CONFIG_PPC 219*1da177e4SLinus Torvalds if (sys_ctrler != SYS_CTRLER_CUDA) 220*1da177e4SLinus Torvalds return -ENODEV; 221*1da177e4SLinus Torvalds #else 222*1da177e4SLinus Torvalds if (macintosh_config->adb_type != MAC_ADB_CUDA) 223*1da177e4SLinus Torvalds return -ENODEV; 224*1da177e4SLinus Torvalds via = via1; 225*1da177e4SLinus Torvalds #endif 226*1da177e4SLinus Torvalds return 0; 227*1da177e4SLinus Torvalds } 228*1da177e4SLinus Torvalds 229*1da177e4SLinus Torvalds static int __init 230*1da177e4SLinus Torvalds cuda_init(void) 231*1da177e4SLinus Torvalds { 232*1da177e4SLinus Torvalds #ifdef CONFIG_PPC 233*1da177e4SLinus Torvalds if (via == NULL) 234*1da177e4SLinus Torvalds return -ENODEV; 235*1da177e4SLinus Torvalds return 0; 236*1da177e4SLinus Torvalds #else 237*1da177e4SLinus Torvalds int err = cuda_init_via(); 238*1da177e4SLinus Torvalds if (err) { 239*1da177e4SLinus Torvalds printk(KERN_ERR "cuda_init_via() failed\n"); 240*1da177e4SLinus Torvalds return -ENODEV; 241*1da177e4SLinus Torvalds } 242*1da177e4SLinus Torvalds 243*1da177e4SLinus Torvalds return via_cuda_start(); 244*1da177e4SLinus Torvalds #endif 245*1da177e4SLinus Torvalds } 246*1da177e4SLinus Torvalds #endif /* CONFIG_ADB */ 247*1da177e4SLinus Torvalds 248*1da177e4SLinus Torvalds #define WAIT_FOR(cond, what) \ 249*1da177e4SLinus Torvalds do { \ 250*1da177e4SLinus Torvalds int x; \ 251*1da177e4SLinus Torvalds for (x = 1000; !(cond); --x) { \ 252*1da177e4SLinus Torvalds if (x == 0) { \ 253*1da177e4SLinus Torvalds printk("Timeout waiting for " what "\n"); \ 254*1da177e4SLinus Torvalds return -ENXIO; \ 255*1da177e4SLinus Torvalds } \ 256*1da177e4SLinus Torvalds udelay(100); \ 257*1da177e4SLinus Torvalds } \ 258*1da177e4SLinus Torvalds } while (0) 259*1da177e4SLinus Torvalds 260*1da177e4SLinus Torvalds static int 261*1da177e4SLinus Torvalds cuda_init_via(void) 262*1da177e4SLinus Torvalds { 263*1da177e4SLinus Torvalds out_8(&via[DIRB], (in_8(&via[DIRB]) | TACK | TIP) & ~TREQ); /* TACK & TIP out */ 264*1da177e4SLinus Torvalds out_8(&via[B], in_8(&via[B]) | TACK | TIP); /* negate them */ 265*1da177e4SLinus Torvalds out_8(&via[ACR] ,(in_8(&via[ACR]) & ~SR_CTRL) | SR_EXT); /* SR data in */ 266*1da177e4SLinus Torvalds (void)in_8(&via[SR]); /* clear any left-over data */ 267*1da177e4SLinus Torvalds #ifndef CONFIG_MAC 268*1da177e4SLinus Torvalds out_8(&via[IER], 0x7f); /* disable interrupts from VIA */ 269*1da177e4SLinus Torvalds (void)in_8(&via[IER]); 270*1da177e4SLinus Torvalds #endif 271*1da177e4SLinus Torvalds 272*1da177e4SLinus Torvalds /* delay 4ms and then clear any pending interrupt */ 273*1da177e4SLinus Torvalds mdelay(4); 274*1da177e4SLinus Torvalds (void)in_8(&via[SR]); 275*1da177e4SLinus Torvalds out_8(&via[IFR], in_8(&via[IFR]) & 0x7f); 276*1da177e4SLinus Torvalds 277*1da177e4SLinus Torvalds /* sync with the CUDA - assert TACK without TIP */ 278*1da177e4SLinus Torvalds out_8(&via[B], in_8(&via[B]) & ~TACK); 279*1da177e4SLinus Torvalds 280*1da177e4SLinus Torvalds /* wait for the CUDA to assert TREQ in response */ 281*1da177e4SLinus Torvalds WAIT_FOR((in_8(&via[B]) & TREQ) == 0, "CUDA response to sync"); 282*1da177e4SLinus Torvalds 283*1da177e4SLinus Torvalds /* wait for the interrupt and then clear it */ 284*1da177e4SLinus Torvalds WAIT_FOR(in_8(&via[IFR]) & SR_INT, "CUDA response to sync (2)"); 285*1da177e4SLinus Torvalds (void)in_8(&via[SR]); 286*1da177e4SLinus Torvalds out_8(&via[IFR], in_8(&via[IFR]) & 0x7f); 287*1da177e4SLinus Torvalds 288*1da177e4SLinus Torvalds /* finish the sync by negating TACK */ 289*1da177e4SLinus Torvalds out_8(&via[B], in_8(&via[B]) | TACK); 290*1da177e4SLinus Torvalds 291*1da177e4SLinus Torvalds /* wait for the CUDA to negate TREQ and the corresponding interrupt */ 292*1da177e4SLinus Torvalds WAIT_FOR(in_8(&via[B]) & TREQ, "CUDA response to sync (3)"); 293*1da177e4SLinus Torvalds WAIT_FOR(in_8(&via[IFR]) & SR_INT, "CUDA response to sync (4)"); 294*1da177e4SLinus Torvalds (void)in_8(&via[SR]); 295*1da177e4SLinus Torvalds out_8(&via[IFR], in_8(&via[IFR]) & 0x7f); 296*1da177e4SLinus Torvalds out_8(&via[B], in_8(&via[B]) | TIP); /* should be unnecessary */ 297*1da177e4SLinus Torvalds 298*1da177e4SLinus Torvalds return 0; 299*1da177e4SLinus Torvalds } 300*1da177e4SLinus Torvalds 301*1da177e4SLinus Torvalds #ifdef CONFIG_ADB 302*1da177e4SLinus Torvalds /* Send an ADB command */ 303*1da177e4SLinus Torvalds static int 304*1da177e4SLinus Torvalds cuda_send_request(struct adb_request *req, int sync) 305*1da177e4SLinus Torvalds { 306*1da177e4SLinus Torvalds int i; 307*1da177e4SLinus Torvalds 308*1da177e4SLinus Torvalds if ((via == NULL) || !cuda_fully_inited) { 309*1da177e4SLinus Torvalds req->complete = 1; 310*1da177e4SLinus Torvalds return -ENXIO; 311*1da177e4SLinus Torvalds } 312*1da177e4SLinus Torvalds 313*1da177e4SLinus Torvalds req->reply_expected = 1; 314*1da177e4SLinus Torvalds 315*1da177e4SLinus Torvalds i = cuda_write(req); 316*1da177e4SLinus Torvalds if (i) 317*1da177e4SLinus Torvalds return i; 318*1da177e4SLinus Torvalds 319*1da177e4SLinus Torvalds if (sync) { 320*1da177e4SLinus Torvalds while (!req->complete) 321*1da177e4SLinus Torvalds cuda_poll(); 322*1da177e4SLinus Torvalds } 323*1da177e4SLinus Torvalds return 0; 324*1da177e4SLinus Torvalds } 325*1da177e4SLinus Torvalds 326*1da177e4SLinus Torvalds 327*1da177e4SLinus Torvalds /* Enable/disable autopolling */ 328*1da177e4SLinus Torvalds static int 329*1da177e4SLinus Torvalds cuda_adb_autopoll(int devs) 330*1da177e4SLinus Torvalds { 331*1da177e4SLinus Torvalds struct adb_request req; 332*1da177e4SLinus Torvalds 333*1da177e4SLinus Torvalds if ((via == NULL) || !cuda_fully_inited) 334*1da177e4SLinus Torvalds return -ENXIO; 335*1da177e4SLinus Torvalds 336*1da177e4SLinus Torvalds cuda_request(&req, NULL, 3, CUDA_PACKET, CUDA_AUTOPOLL, (devs? 1: 0)); 337*1da177e4SLinus Torvalds while (!req.complete) 338*1da177e4SLinus Torvalds cuda_poll(); 339*1da177e4SLinus Torvalds return 0; 340*1da177e4SLinus Torvalds } 341*1da177e4SLinus Torvalds 342*1da177e4SLinus Torvalds /* Reset adb bus - how do we do this?? */ 343*1da177e4SLinus Torvalds static int 344*1da177e4SLinus Torvalds cuda_reset_adb_bus(void) 345*1da177e4SLinus Torvalds { 346*1da177e4SLinus Torvalds struct adb_request req; 347*1da177e4SLinus Torvalds 348*1da177e4SLinus Torvalds if ((via == NULL) || !cuda_fully_inited) 349*1da177e4SLinus Torvalds return -ENXIO; 350*1da177e4SLinus Torvalds 351*1da177e4SLinus Torvalds cuda_request(&req, NULL, 2, ADB_PACKET, 0); /* maybe? */ 352*1da177e4SLinus Torvalds while (!req.complete) 353*1da177e4SLinus Torvalds cuda_poll(); 354*1da177e4SLinus Torvalds return 0; 355*1da177e4SLinus Torvalds } 356*1da177e4SLinus Torvalds #endif /* CONFIG_ADB */ 357*1da177e4SLinus Torvalds /* Construct and send a cuda request */ 358*1da177e4SLinus Torvalds int 359*1da177e4SLinus Torvalds cuda_request(struct adb_request *req, void (*done)(struct adb_request *), 360*1da177e4SLinus Torvalds int nbytes, ...) 361*1da177e4SLinus Torvalds { 362*1da177e4SLinus Torvalds va_list list; 363*1da177e4SLinus Torvalds int i; 364*1da177e4SLinus Torvalds 365*1da177e4SLinus Torvalds if (via == NULL) { 366*1da177e4SLinus Torvalds req->complete = 1; 367*1da177e4SLinus Torvalds return -ENXIO; 368*1da177e4SLinus Torvalds } 369*1da177e4SLinus Torvalds 370*1da177e4SLinus Torvalds req->nbytes = nbytes; 371*1da177e4SLinus Torvalds req->done = done; 372*1da177e4SLinus Torvalds va_start(list, nbytes); 373*1da177e4SLinus Torvalds for (i = 0; i < nbytes; ++i) 374*1da177e4SLinus Torvalds req->data[i] = va_arg(list, int); 375*1da177e4SLinus Torvalds va_end(list); 376*1da177e4SLinus Torvalds req->reply_expected = 1; 377*1da177e4SLinus Torvalds return cuda_write(req); 378*1da177e4SLinus Torvalds } 379*1da177e4SLinus Torvalds 380*1da177e4SLinus Torvalds static int 381*1da177e4SLinus Torvalds cuda_write(struct adb_request *req) 382*1da177e4SLinus Torvalds { 383*1da177e4SLinus Torvalds unsigned long flags; 384*1da177e4SLinus Torvalds 385*1da177e4SLinus Torvalds if (req->nbytes < 2 || req->data[0] > CUDA_PACKET) { 386*1da177e4SLinus Torvalds req->complete = 1; 387*1da177e4SLinus Torvalds return -EINVAL; 388*1da177e4SLinus Torvalds } 389*1da177e4SLinus Torvalds req->next = NULL; 390*1da177e4SLinus Torvalds req->sent = 0; 391*1da177e4SLinus Torvalds req->complete = 0; 392*1da177e4SLinus Torvalds req->reply_len = 0; 393*1da177e4SLinus Torvalds 394*1da177e4SLinus Torvalds spin_lock_irqsave(&cuda_lock, flags); 395*1da177e4SLinus Torvalds if (current_req != 0) { 396*1da177e4SLinus Torvalds last_req->next = req; 397*1da177e4SLinus Torvalds last_req = req; 398*1da177e4SLinus Torvalds } else { 399*1da177e4SLinus Torvalds current_req = req; 400*1da177e4SLinus Torvalds last_req = req; 401*1da177e4SLinus Torvalds if (cuda_state == idle) 402*1da177e4SLinus Torvalds cuda_start(); 403*1da177e4SLinus Torvalds } 404*1da177e4SLinus Torvalds spin_unlock_irqrestore(&cuda_lock, flags); 405*1da177e4SLinus Torvalds 406*1da177e4SLinus Torvalds return 0; 407*1da177e4SLinus Torvalds } 408*1da177e4SLinus Torvalds 409*1da177e4SLinus Torvalds static void 410*1da177e4SLinus Torvalds cuda_start(void) 411*1da177e4SLinus Torvalds { 412*1da177e4SLinus Torvalds struct adb_request *req; 413*1da177e4SLinus Torvalds 414*1da177e4SLinus Torvalds /* assert cuda_state == idle */ 415*1da177e4SLinus Torvalds /* get the packet to send */ 416*1da177e4SLinus Torvalds req = current_req; 417*1da177e4SLinus Torvalds if (req == 0) 418*1da177e4SLinus Torvalds return; 419*1da177e4SLinus Torvalds if ((in_8(&via[B]) & TREQ) == 0) 420*1da177e4SLinus Torvalds return; /* a byte is coming in from the CUDA */ 421*1da177e4SLinus Torvalds 422*1da177e4SLinus Torvalds /* set the shift register to shift out and send a byte */ 423*1da177e4SLinus Torvalds out_8(&via[ACR], in_8(&via[ACR]) | SR_OUT); 424*1da177e4SLinus Torvalds out_8(&via[SR], req->data[0]); 425*1da177e4SLinus Torvalds out_8(&via[B], in_8(&via[B]) & ~TIP); 426*1da177e4SLinus Torvalds cuda_state = sent_first_byte; 427*1da177e4SLinus Torvalds } 428*1da177e4SLinus Torvalds 429*1da177e4SLinus Torvalds void 430*1da177e4SLinus Torvalds cuda_poll(void) 431*1da177e4SLinus Torvalds { 432*1da177e4SLinus Torvalds unsigned long flags; 433*1da177e4SLinus Torvalds 434*1da177e4SLinus Torvalds /* cuda_interrupt only takes a normal lock, we disable 435*1da177e4SLinus Torvalds * interrupts here to avoid re-entering and thus deadlocking. 436*1da177e4SLinus Torvalds * An option would be to disable only the IRQ source with 437*1da177e4SLinus Torvalds * disable_irq(), would that work on m68k ? --BenH 438*1da177e4SLinus Torvalds */ 439*1da177e4SLinus Torvalds local_irq_save(flags); 440*1da177e4SLinus Torvalds cuda_interrupt(0, NULL, NULL); 441*1da177e4SLinus Torvalds local_irq_restore(flags); 442*1da177e4SLinus Torvalds } 443*1da177e4SLinus Torvalds 444*1da177e4SLinus Torvalds static irqreturn_t 445*1da177e4SLinus Torvalds cuda_interrupt(int irq, void *arg, struct pt_regs *regs) 446*1da177e4SLinus Torvalds { 447*1da177e4SLinus Torvalds int status; 448*1da177e4SLinus Torvalds struct adb_request *req = NULL; 449*1da177e4SLinus Torvalds unsigned char ibuf[16]; 450*1da177e4SLinus Torvalds int ibuf_len = 0; 451*1da177e4SLinus Torvalds int complete = 0; 452*1da177e4SLinus Torvalds unsigned char virq; 453*1da177e4SLinus Torvalds 454*1da177e4SLinus Torvalds spin_lock(&cuda_lock); 455*1da177e4SLinus Torvalds 456*1da177e4SLinus Torvalds virq = in_8(&via[IFR]) & 0x7f; 457*1da177e4SLinus Torvalds out_8(&via[IFR], virq); 458*1da177e4SLinus Torvalds if ((virq & SR_INT) == 0) { 459*1da177e4SLinus Torvalds spin_unlock(&cuda_lock); 460*1da177e4SLinus Torvalds return IRQ_NONE; 461*1da177e4SLinus Torvalds } 462*1da177e4SLinus Torvalds 463*1da177e4SLinus Torvalds status = (~in_8(&via[B]) & (TIP|TREQ)) | (in_8(&via[ACR]) & SR_OUT); 464*1da177e4SLinus Torvalds /* printk("cuda_interrupt: state=%d status=%x\n", cuda_state, status); */ 465*1da177e4SLinus Torvalds switch (cuda_state) { 466*1da177e4SLinus Torvalds case idle: 467*1da177e4SLinus Torvalds /* CUDA has sent us the first byte of data - unsolicited */ 468*1da177e4SLinus Torvalds if (status != TREQ) 469*1da177e4SLinus Torvalds printk("cuda: state=idle, status=%x\n", status); 470*1da177e4SLinus Torvalds (void)in_8(&via[SR]); 471*1da177e4SLinus Torvalds out_8(&via[B], in_8(&via[B]) & ~TIP); 472*1da177e4SLinus Torvalds cuda_state = reading; 473*1da177e4SLinus Torvalds reply_ptr = cuda_rbuf; 474*1da177e4SLinus Torvalds reading_reply = 0; 475*1da177e4SLinus Torvalds break; 476*1da177e4SLinus Torvalds 477*1da177e4SLinus Torvalds case awaiting_reply: 478*1da177e4SLinus Torvalds /* CUDA has sent us the first byte of data of a reply */ 479*1da177e4SLinus Torvalds if (status != TREQ) 480*1da177e4SLinus Torvalds printk("cuda: state=awaiting_reply, status=%x\n", status); 481*1da177e4SLinus Torvalds (void)in_8(&via[SR]); 482*1da177e4SLinus Torvalds out_8(&via[B], in_8(&via[B]) & ~TIP); 483*1da177e4SLinus Torvalds cuda_state = reading; 484*1da177e4SLinus Torvalds reply_ptr = current_req->reply; 485*1da177e4SLinus Torvalds reading_reply = 1; 486*1da177e4SLinus Torvalds break; 487*1da177e4SLinus Torvalds 488*1da177e4SLinus Torvalds case sent_first_byte: 489*1da177e4SLinus Torvalds if (status == TREQ + TIP + SR_OUT) { 490*1da177e4SLinus Torvalds /* collision */ 491*1da177e4SLinus Torvalds out_8(&via[ACR], in_8(&via[ACR]) & ~SR_OUT); 492*1da177e4SLinus Torvalds (void)in_8(&via[SR]); 493*1da177e4SLinus Torvalds out_8(&via[B], in_8(&via[B]) | TIP | TACK); 494*1da177e4SLinus Torvalds cuda_state = idle; 495*1da177e4SLinus Torvalds } else { 496*1da177e4SLinus Torvalds /* assert status == TIP + SR_OUT */ 497*1da177e4SLinus Torvalds if (status != TIP + SR_OUT) 498*1da177e4SLinus Torvalds printk("cuda: state=sent_first_byte status=%x\n", status); 499*1da177e4SLinus Torvalds out_8(&via[SR], current_req->data[1]); 500*1da177e4SLinus Torvalds out_8(&via[B], in_8(&via[B]) ^ TACK); 501*1da177e4SLinus Torvalds data_index = 2; 502*1da177e4SLinus Torvalds cuda_state = sending; 503*1da177e4SLinus Torvalds } 504*1da177e4SLinus Torvalds break; 505*1da177e4SLinus Torvalds 506*1da177e4SLinus Torvalds case sending: 507*1da177e4SLinus Torvalds req = current_req; 508*1da177e4SLinus Torvalds if (data_index >= req->nbytes) { 509*1da177e4SLinus Torvalds out_8(&via[ACR], in_8(&via[ACR]) & ~SR_OUT); 510*1da177e4SLinus Torvalds (void)in_8(&via[SR]); 511*1da177e4SLinus Torvalds out_8(&via[B], in_8(&via[B]) | TACK | TIP); 512*1da177e4SLinus Torvalds req->sent = 1; 513*1da177e4SLinus Torvalds if (req->reply_expected) { 514*1da177e4SLinus Torvalds cuda_state = awaiting_reply; 515*1da177e4SLinus Torvalds } else { 516*1da177e4SLinus Torvalds current_req = req->next; 517*1da177e4SLinus Torvalds complete = 1; 518*1da177e4SLinus Torvalds /* not sure about this */ 519*1da177e4SLinus Torvalds cuda_state = idle; 520*1da177e4SLinus Torvalds cuda_start(); 521*1da177e4SLinus Torvalds } 522*1da177e4SLinus Torvalds } else { 523*1da177e4SLinus Torvalds out_8(&via[SR], req->data[data_index++]); 524*1da177e4SLinus Torvalds out_8(&via[B], in_8(&via[B]) ^ TACK); 525*1da177e4SLinus Torvalds } 526*1da177e4SLinus Torvalds break; 527*1da177e4SLinus Torvalds 528*1da177e4SLinus Torvalds case reading: 529*1da177e4SLinus Torvalds *reply_ptr++ = in_8(&via[SR]); 530*1da177e4SLinus Torvalds if (status == TIP) { 531*1da177e4SLinus Torvalds /* that's all folks */ 532*1da177e4SLinus Torvalds out_8(&via[B], in_8(&via[B]) | TACK | TIP); 533*1da177e4SLinus Torvalds cuda_state = read_done; 534*1da177e4SLinus Torvalds } else { 535*1da177e4SLinus Torvalds /* assert status == TIP | TREQ */ 536*1da177e4SLinus Torvalds if (status != TIP + TREQ) 537*1da177e4SLinus Torvalds printk("cuda: state=reading status=%x\n", status); 538*1da177e4SLinus Torvalds out_8(&via[B], in_8(&via[B]) ^ TACK); 539*1da177e4SLinus Torvalds } 540*1da177e4SLinus Torvalds break; 541*1da177e4SLinus Torvalds 542*1da177e4SLinus Torvalds case read_done: 543*1da177e4SLinus Torvalds (void)in_8(&via[SR]); 544*1da177e4SLinus Torvalds if (reading_reply) { 545*1da177e4SLinus Torvalds req = current_req; 546*1da177e4SLinus Torvalds req->reply_len = reply_ptr - req->reply; 547*1da177e4SLinus Torvalds if (req->data[0] == ADB_PACKET) { 548*1da177e4SLinus Torvalds /* Have to adjust the reply from ADB commands */ 549*1da177e4SLinus Torvalds if (req->reply_len <= 2 || (req->reply[1] & 2) != 0) { 550*1da177e4SLinus Torvalds /* the 0x2 bit indicates no response */ 551*1da177e4SLinus Torvalds req->reply_len = 0; 552*1da177e4SLinus Torvalds } else { 553*1da177e4SLinus Torvalds /* leave just the command and result bytes in the reply */ 554*1da177e4SLinus Torvalds req->reply_len -= 2; 555*1da177e4SLinus Torvalds memmove(req->reply, req->reply + 2, req->reply_len); 556*1da177e4SLinus Torvalds } 557*1da177e4SLinus Torvalds } 558*1da177e4SLinus Torvalds current_req = req->next; 559*1da177e4SLinus Torvalds complete = 1; 560*1da177e4SLinus Torvalds } else { 561*1da177e4SLinus Torvalds /* This is tricky. We must break the spinlock to call 562*1da177e4SLinus Torvalds * cuda_input. However, doing so means we might get 563*1da177e4SLinus Torvalds * re-entered from another CPU getting an interrupt 564*1da177e4SLinus Torvalds * or calling cuda_poll(). I ended up using the stack 565*1da177e4SLinus Torvalds * (it's only for 16 bytes) and moving the actual 566*1da177e4SLinus Torvalds * call to cuda_input to outside of the lock. 567*1da177e4SLinus Torvalds */ 568*1da177e4SLinus Torvalds ibuf_len = reply_ptr - cuda_rbuf; 569*1da177e4SLinus Torvalds memcpy(ibuf, cuda_rbuf, ibuf_len); 570*1da177e4SLinus Torvalds } 571*1da177e4SLinus Torvalds if (status == TREQ) { 572*1da177e4SLinus Torvalds out_8(&via[B], in_8(&via[B]) & ~TIP); 573*1da177e4SLinus Torvalds cuda_state = reading; 574*1da177e4SLinus Torvalds reply_ptr = cuda_rbuf; 575*1da177e4SLinus Torvalds reading_reply = 0; 576*1da177e4SLinus Torvalds } else { 577*1da177e4SLinus Torvalds cuda_state = idle; 578*1da177e4SLinus Torvalds cuda_start(); 579*1da177e4SLinus Torvalds } 580*1da177e4SLinus Torvalds break; 581*1da177e4SLinus Torvalds 582*1da177e4SLinus Torvalds default: 583*1da177e4SLinus Torvalds printk("cuda_interrupt: unknown cuda_state %d?\n", cuda_state); 584*1da177e4SLinus Torvalds } 585*1da177e4SLinus Torvalds spin_unlock(&cuda_lock); 586*1da177e4SLinus Torvalds if (complete && req) { 587*1da177e4SLinus Torvalds void (*done)(struct adb_request *) = req->done; 588*1da177e4SLinus Torvalds mb(); 589*1da177e4SLinus Torvalds req->complete = 1; 590*1da177e4SLinus Torvalds /* Here, we assume that if the request has a done member, the 591*1da177e4SLinus Torvalds * struct request will survive to setting req->complete to 1 592*1da177e4SLinus Torvalds */ 593*1da177e4SLinus Torvalds if (done) 594*1da177e4SLinus Torvalds (*done)(req); 595*1da177e4SLinus Torvalds } 596*1da177e4SLinus Torvalds if (ibuf_len) 597*1da177e4SLinus Torvalds cuda_input(ibuf, ibuf_len, regs); 598*1da177e4SLinus Torvalds return IRQ_HANDLED; 599*1da177e4SLinus Torvalds } 600*1da177e4SLinus Torvalds 601*1da177e4SLinus Torvalds static void 602*1da177e4SLinus Torvalds cuda_input(unsigned char *buf, int nb, struct pt_regs *regs) 603*1da177e4SLinus Torvalds { 604*1da177e4SLinus Torvalds int i; 605*1da177e4SLinus Torvalds 606*1da177e4SLinus Torvalds switch (buf[0]) { 607*1da177e4SLinus Torvalds case ADB_PACKET: 608*1da177e4SLinus Torvalds #ifdef CONFIG_XMON 609*1da177e4SLinus Torvalds if (nb == 5 && buf[2] == 0x2c) { 610*1da177e4SLinus Torvalds extern int xmon_wants_key, xmon_adb_keycode; 611*1da177e4SLinus Torvalds if (xmon_wants_key) { 612*1da177e4SLinus Torvalds xmon_adb_keycode = buf[3]; 613*1da177e4SLinus Torvalds return; 614*1da177e4SLinus Torvalds } 615*1da177e4SLinus Torvalds } 616*1da177e4SLinus Torvalds #endif /* CONFIG_XMON */ 617*1da177e4SLinus Torvalds #ifdef CONFIG_ADB 618*1da177e4SLinus Torvalds adb_input(buf+2, nb-2, regs, buf[1] & 0x40); 619*1da177e4SLinus Torvalds #endif /* CONFIG_ADB */ 620*1da177e4SLinus Torvalds break; 621*1da177e4SLinus Torvalds 622*1da177e4SLinus Torvalds default: 623*1da177e4SLinus Torvalds printk("data from cuda (%d bytes):", nb); 624*1da177e4SLinus Torvalds for (i = 0; i < nb; ++i) 625*1da177e4SLinus Torvalds printk(" %.2x", buf[i]); 626*1da177e4SLinus Torvalds printk("\n"); 627*1da177e4SLinus Torvalds } 628*1da177e4SLinus Torvalds } 629