VisionFive2 Linux kernel

StarFive Tech Linux Kernel for VisionFive (JH7110) boards (mirror)

More than 9999 Commits   32 Branches   54 Tags
b24413180f560 (Greg Kroah-Hartman     2017-11-01 15:07:57 +0100   1) // SPDX-License-Identifier: GPL-2.0
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700   2) /*
d23eee88b5692 (Finn Thain             2016-12-31 19:56:26 -0500   3)  * Device driver for the Cuda and Egret system controllers found on PowerMacs
d23eee88b5692 (Finn Thain             2016-12-31 19:56:26 -0500   4)  * and 68k Macs.
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700   5)  *
d23eee88b5692 (Finn Thain             2016-12-31 19:56:26 -0500   6)  * The Cuda or Egret is a 6805 microcontroller interfaced to the 6522 VIA.
d23eee88b5692 (Finn Thain             2016-12-31 19:56:26 -0500   7)  * This MCU controls system power, Parameter RAM, Real Time Clock and the
d23eee88b5692 (Finn Thain             2016-12-31 19:56:26 -0500   8)  * Apple Desktop Bus (ADB) that connects to the keyboard and mouse.
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700   9)  *
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700  10)  * Copyright (C) 1996 Paul Mackerras.
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700  11)  */
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700  12) #include <stdarg.h>
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700  13) #include <linux/types.h>
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700  14) #include <linux/errno.h>
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700  15) #include <linux/kernel.h>
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700  16) #include <linux/delay.h>
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700  17) #include <linux/adb.h>
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700  18) #include <linux/cuda.h>
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700  19) #include <linux/spinlock.h>
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700  20) #include <linux/interrupt.h>
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700  21) #ifdef CONFIG_PPC
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700  22) #include <asm/prom.h>
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700  23) #include <asm/machdep.h>
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700  24) #else
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700  25) #include <asm/macintosh.h>
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700  26) #include <asm/macints.h>
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700  27) #include <asm/mac_via.h>
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700  28) #endif
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700  29) #include <asm/io.h>
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700  30) #include <linux/init.h>
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700  31) 
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700  32) static volatile unsigned char __iomem *via;
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700  33) static DEFINE_SPINLOCK(cuda_lock);
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700  34) 
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700  35) /* VIA registers - spaced 0x200 bytes apart */
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700  36) #define RS		0x200		/* skip between registers */
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700  37) #define B		0		/* B-side data */
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700  38) #define A		RS		/* A-side data */
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700  39) #define DIRB		(2*RS)		/* B-side direction (1=output) */
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700  40) #define DIRA		(3*RS)		/* A-side direction (1=output) */
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700  41) #define T1CL		(4*RS)		/* Timer 1 ctr/latch (low 8 bits) */
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700  42) #define T1CH		(5*RS)		/* Timer 1 counter (high 8 bits) */
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700  43) #define T1LL		(6*RS)		/* Timer 1 latch (low 8 bits) */
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700  44) #define T1LH		(7*RS)		/* Timer 1 latch (high 8 bits) */
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700  45) #define T2CL		(8*RS)		/* Timer 2 ctr/latch (low 8 bits) */
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700  46) #define T2CH		(9*RS)		/* Timer 2 counter (high 8 bits) */
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700  47) #define SR		(10*RS)		/* Shift register */
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700  48) #define ACR		(11*RS)		/* Auxiliary control register */
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700  49) #define PCR		(12*RS)		/* Peripheral control register */
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700  50) #define IFR		(13*RS)		/* Interrupt flag register */
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700  51) #define IER		(14*RS)		/* Interrupt enable register */
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700  52) #define ANH		(15*RS)		/* A-side data, no handshake */
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700  53) 
d23eee88b5692 (Finn Thain             2016-12-31 19:56:26 -0500  54) /*
d23eee88b5692 (Finn Thain             2016-12-31 19:56:26 -0500  55)  * When the Cuda design replaced the Egret, some signal names and
d23eee88b5692 (Finn Thain             2016-12-31 19:56:26 -0500  56)  * logic sense changed. They all serve the same purposes, however.
d23eee88b5692 (Finn Thain             2016-12-31 19:56:26 -0500  57)  *
d23eee88b5692 (Finn Thain             2016-12-31 19:56:26 -0500  58)  *   VIA pin       |  Egret pin
d23eee88b5692 (Finn Thain             2016-12-31 19:56:26 -0500  59)  * ----------------+------------------------------------------
d23eee88b5692 (Finn Thain             2016-12-31 19:56:26 -0500  60)  *   PB3 (input)   |  Transceiver session   (active low)
d23eee88b5692 (Finn Thain             2016-12-31 19:56:26 -0500  61)  *   PB4 (output)  |  VIA full              (active high)
d23eee88b5692 (Finn Thain             2016-12-31 19:56:26 -0500  62)  *   PB5 (output)  |  System session        (active high)
d23eee88b5692 (Finn Thain             2016-12-31 19:56:26 -0500  63)  *
d23eee88b5692 (Finn Thain             2016-12-31 19:56:26 -0500  64)  *   VIA pin       |  Cuda pin
d23eee88b5692 (Finn Thain             2016-12-31 19:56:26 -0500  65)  * ----------------+------------------------------------------
d23eee88b5692 (Finn Thain             2016-12-31 19:56:26 -0500  66)  *   PB3 (input)   |  Transfer request      (active low)
d23eee88b5692 (Finn Thain             2016-12-31 19:56:26 -0500  67)  *   PB4 (output)  |  Byte acknowledge      (active low)
d23eee88b5692 (Finn Thain             2016-12-31 19:56:26 -0500  68)  *   PB5 (output)  |  Transfer in progress  (active low)
d23eee88b5692 (Finn Thain             2016-12-31 19:56:26 -0500  69)  */
d23eee88b5692 (Finn Thain             2016-12-31 19:56:26 -0500  70) 
d23eee88b5692 (Finn Thain             2016-12-31 19:56:26 -0500  71) /* Bits in Port B data register */
d23eee88b5692 (Finn Thain             2016-12-31 19:56:26 -0500  72) #define TREQ		0x08		/* Transfer request */
d23eee88b5692 (Finn Thain             2016-12-31 19:56:26 -0500  73) #define TACK		0x10		/* Transfer acknowledge */
d23eee88b5692 (Finn Thain             2016-12-31 19:56:26 -0500  74) #define TIP		0x20		/* Transfer in progress */
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700  75) 
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700  76) /* Bits in ACR */
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700  77) #define SR_CTRL		0x1c		/* Shift register control bits */
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700  78) #define SR_EXT		0x0c		/* Shift on external clock */
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700  79) #define SR_OUT		0x10		/* Shift out if 1 */
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700  80) 
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700  81) /* Bits in IFR and IER */
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700  82) #define IER_SET		0x80		/* set bits in IER */
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700  83) #define IER_CLR		0		/* clear bits in IER */
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700  84) #define SR_INT		0x04		/* Shift register full/empty */
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700  85) 
d23eee88b5692 (Finn Thain             2016-12-31 19:56:26 -0500  86) /* Duration of byte acknowledgement pulse (us) */
d23eee88b5692 (Finn Thain             2016-12-31 19:56:26 -0500  87) #define EGRET_TACK_ASSERTED_DELAY	300
d23eee88b5692 (Finn Thain             2016-12-31 19:56:26 -0500  88) #define EGRET_TACK_NEGATED_DELAY	400
d23eee88b5692 (Finn Thain             2016-12-31 19:56:26 -0500  89) 
d23eee88b5692 (Finn Thain             2016-12-31 19:56:26 -0500  90) /* Interval from interrupt to start of session (us) */
d23eee88b5692 (Finn Thain             2016-12-31 19:56:26 -0500  91) #define EGRET_SESSION_DELAY		450
d23eee88b5692 (Finn Thain             2016-12-31 19:56:26 -0500  92) 
d23eee88b5692 (Finn Thain             2016-12-31 19:56:26 -0500  93) #ifdef CONFIG_PPC
d23eee88b5692 (Finn Thain             2016-12-31 19:56:26 -0500  94) #define mcu_is_egret	false
d23eee88b5692 (Finn Thain             2016-12-31 19:56:26 -0500  95) #else
d23eee88b5692 (Finn Thain             2016-12-31 19:56:26 -0500  96) static bool mcu_is_egret;
d23eee88b5692 (Finn Thain             2016-12-31 19:56:26 -0500  97) #endif
d23eee88b5692 (Finn Thain             2016-12-31 19:56:26 -0500  98) 
fd7a65a27c6cb (Finn Thain             2016-12-31 19:56:26 -0500  99) static inline bool TREQ_asserted(u8 portb)
fd7a65a27c6cb (Finn Thain             2016-12-31 19:56:26 -0500 100) {
fd7a65a27c6cb (Finn Thain             2016-12-31 19:56:26 -0500 101) 	return !(portb & TREQ);
fd7a65a27c6cb (Finn Thain             2016-12-31 19:56:26 -0500 102) }
fd7a65a27c6cb (Finn Thain             2016-12-31 19:56:26 -0500 103) 
fd7a65a27c6cb (Finn Thain             2016-12-31 19:56:26 -0500 104) static inline void assert_TIP(void)
fd7a65a27c6cb (Finn Thain             2016-12-31 19:56:26 -0500 105) {
d23eee88b5692 (Finn Thain             2016-12-31 19:56:26 -0500 106) 	if (mcu_is_egret) {
d23eee88b5692 (Finn Thain             2016-12-31 19:56:26 -0500 107) 		udelay(EGRET_SESSION_DELAY);
d23eee88b5692 (Finn Thain             2016-12-31 19:56:26 -0500 108) 		out_8(&via[B], in_8(&via[B]) | TIP);
d23eee88b5692 (Finn Thain             2016-12-31 19:56:26 -0500 109) 	} else
d23eee88b5692 (Finn Thain             2016-12-31 19:56:26 -0500 110) 		out_8(&via[B], in_8(&via[B]) & ~TIP);
d23eee88b5692 (Finn Thain             2016-12-31 19:56:26 -0500 111) }
d23eee88b5692 (Finn Thain             2016-12-31 19:56:26 -0500 112) 
d23eee88b5692 (Finn Thain             2016-12-31 19:56:26 -0500 113) static inline void assert_TIP_and_TACK(void)
d23eee88b5692 (Finn Thain             2016-12-31 19:56:26 -0500 114) {
d23eee88b5692 (Finn Thain             2016-12-31 19:56:26 -0500 115) 	if (mcu_is_egret) {
d23eee88b5692 (Finn Thain             2016-12-31 19:56:26 -0500 116) 		udelay(EGRET_SESSION_DELAY);
d23eee88b5692 (Finn Thain             2016-12-31 19:56:26 -0500 117) 		out_8(&via[B], in_8(&via[B]) | TIP | TACK);
d23eee88b5692 (Finn Thain             2016-12-31 19:56:26 -0500 118) 	} else
d23eee88b5692 (Finn Thain             2016-12-31 19:56:26 -0500 119) 		out_8(&via[B], in_8(&via[B]) & ~(TIP | TACK));
fd7a65a27c6cb (Finn Thain             2016-12-31 19:56:26 -0500 120) }
fd7a65a27c6cb (Finn Thain             2016-12-31 19:56:26 -0500 121) 
fd7a65a27c6cb (Finn Thain             2016-12-31 19:56:26 -0500 122) static inline void assert_TACK(void)
fd7a65a27c6cb (Finn Thain             2016-12-31 19:56:26 -0500 123) {
d23eee88b5692 (Finn Thain             2016-12-31 19:56:26 -0500 124) 	if (mcu_is_egret) {
d23eee88b5692 (Finn Thain             2016-12-31 19:56:26 -0500 125) 		udelay(EGRET_TACK_NEGATED_DELAY);
d23eee88b5692 (Finn Thain             2016-12-31 19:56:26 -0500 126) 		out_8(&via[B], in_8(&via[B]) | TACK);
d23eee88b5692 (Finn Thain             2016-12-31 19:56:26 -0500 127) 	} else
d23eee88b5692 (Finn Thain             2016-12-31 19:56:26 -0500 128) 		out_8(&via[B], in_8(&via[B]) & ~TACK);
fd7a65a27c6cb (Finn Thain             2016-12-31 19:56:26 -0500 129) }
fd7a65a27c6cb (Finn Thain             2016-12-31 19:56:26 -0500 130) 
fd7a65a27c6cb (Finn Thain             2016-12-31 19:56:26 -0500 131) static inline void toggle_TACK(void)
fd7a65a27c6cb (Finn Thain             2016-12-31 19:56:26 -0500 132) {
fd7a65a27c6cb (Finn Thain             2016-12-31 19:56:26 -0500 133) 	out_8(&via[B], in_8(&via[B]) ^ TACK);
fd7a65a27c6cb (Finn Thain             2016-12-31 19:56:26 -0500 134) }
fd7a65a27c6cb (Finn Thain             2016-12-31 19:56:26 -0500 135) 
fd7a65a27c6cb (Finn Thain             2016-12-31 19:56:26 -0500 136) static inline void negate_TACK(void)
fd7a65a27c6cb (Finn Thain             2016-12-31 19:56:26 -0500 137) {
d23eee88b5692 (Finn Thain             2016-12-31 19:56:26 -0500 138) 	if (mcu_is_egret) {
d23eee88b5692 (Finn Thain             2016-12-31 19:56:26 -0500 139) 		udelay(EGRET_TACK_ASSERTED_DELAY);
d23eee88b5692 (Finn Thain             2016-12-31 19:56:26 -0500 140) 		out_8(&via[B], in_8(&via[B]) & ~TACK);
d23eee88b5692 (Finn Thain             2016-12-31 19:56:26 -0500 141) 	} else
d23eee88b5692 (Finn Thain             2016-12-31 19:56:26 -0500 142) 		out_8(&via[B], in_8(&via[B]) | TACK);
fd7a65a27c6cb (Finn Thain             2016-12-31 19:56:26 -0500 143) }
fd7a65a27c6cb (Finn Thain             2016-12-31 19:56:26 -0500 144) 
fd7a65a27c6cb (Finn Thain             2016-12-31 19:56:26 -0500 145) static inline void negate_TIP_and_TACK(void)
fd7a65a27c6cb (Finn Thain             2016-12-31 19:56:26 -0500 146) {
d23eee88b5692 (Finn Thain             2016-12-31 19:56:26 -0500 147) 	if (mcu_is_egret) {
d23eee88b5692 (Finn Thain             2016-12-31 19:56:26 -0500 148) 		udelay(EGRET_TACK_ASSERTED_DELAY);
d23eee88b5692 (Finn Thain             2016-12-31 19:56:26 -0500 149) 		out_8(&via[B], in_8(&via[B]) & ~(TIP | TACK));
d23eee88b5692 (Finn Thain             2016-12-31 19:56:26 -0500 150) 	} else
d23eee88b5692 (Finn Thain             2016-12-31 19:56:26 -0500 151) 		out_8(&via[B], in_8(&via[B]) | TIP | TACK);
fd7a65a27c6cb (Finn Thain             2016-12-31 19:56:26 -0500 152) }
fd7a65a27c6cb (Finn Thain             2016-12-31 19:56:26 -0500 153) 
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 154) static enum cuda_state {
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 155)     idle,
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 156)     sent_first_byte,
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 157)     sending,
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 158)     reading,
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 159)     read_done,
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 160)     awaiting_reply
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 161) } cuda_state;
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 162) 
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 163) static struct adb_request *current_req;
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 164) static struct adb_request *last_req;
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 165) static unsigned char cuda_rbuf[16];
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 166) static unsigned char *reply_ptr;
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 167) static int reading_reply;
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 168) static int data_index;
0251c38ce503d (Finn Thain             2007-05-01 22:33:00 +0200 169) static int cuda_irq;
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 170) #ifdef CONFIG_PPC
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 171) static struct device_node *vias;
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 172) #endif
872758563d7f1 (Olaf Hering            2007-02-10 21:35:12 +0100 173) static int cuda_fully_inited;
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 174) 
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 175) #ifdef CONFIG_ADB
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 176) static int cuda_probe(void);
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 177) static int cuda_send_request(struct adb_request *req, int sync);
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 178) static int cuda_adb_autopoll(int devs);
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 179) static int cuda_reset_adb_bus(void);
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 180) #endif /* CONFIG_ADB */
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 181) 
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 182) static int cuda_init_via(void);
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 183) static void cuda_start(void);
7d12e780e003f (David Howells          2006-10-05 14:55:46 +0100 184) static irqreturn_t cuda_interrupt(int irq, void *arg);
7d12e780e003f (David Howells          2006-10-05 14:55:46 +0100 185) static void cuda_input(unsigned char *buf, int nb);
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 186) void cuda_poll(void);
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 187) static int cuda_write(struct adb_request *req);
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 188) 
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 189) int cuda_request(struct adb_request *req,
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 190) 		 void (*done)(struct adb_request *), int nbytes, ...);
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 191) 
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 192) #ifdef CONFIG_ADB
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 193) struct adb_driver via_cuda_driver = {
18814ee846357 (Finn Thain             2009-11-17 20:03:05 +1100 194) 	.name         = "CUDA",
18814ee846357 (Finn Thain             2009-11-17 20:03:05 +1100 195) 	.probe        = cuda_probe,
18814ee846357 (Finn Thain             2009-11-17 20:03:05 +1100 196) 	.send_request = cuda_send_request,
18814ee846357 (Finn Thain             2009-11-17 20:03:05 +1100 197) 	.autopoll     = cuda_adb_autopoll,
18814ee846357 (Finn Thain             2009-11-17 20:03:05 +1100 198) 	.poll         = cuda_poll,
18814ee846357 (Finn Thain             2009-11-17 20:03:05 +1100 199) 	.reset_bus    = cuda_reset_adb_bus,
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 200) };
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 201) #endif /* CONFIG_ADB */
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 202) 
18814ee846357 (Finn Thain             2009-11-17 20:03:05 +1100 203) #ifdef CONFIG_MAC
18814ee846357 (Finn Thain             2009-11-17 20:03:05 +1100 204) int __init find_via_cuda(void)
18814ee846357 (Finn Thain             2009-11-17 20:03:05 +1100 205) {
18814ee846357 (Finn Thain             2009-11-17 20:03:05 +1100 206)     struct adb_request req;
18814ee846357 (Finn Thain             2009-11-17 20:03:05 +1100 207)     int err;
18814ee846357 (Finn Thain             2009-11-17 20:03:05 +1100 208) 
f74faec6b3af9 (Finn Thain             2016-12-31 19:56:26 -0500 209)     if (macintosh_config->adb_type != MAC_ADB_CUDA &&
f74faec6b3af9 (Finn Thain             2016-12-31 19:56:26 -0500 210)         macintosh_config->adb_type != MAC_ADB_EGRET)
18814ee846357 (Finn Thain             2009-11-17 20:03:05 +1100 211) 	return 0;
18814ee846357 (Finn Thain             2009-11-17 20:03:05 +1100 212) 
18814ee846357 (Finn Thain             2009-11-17 20:03:05 +1100 213)     via = via1;
18814ee846357 (Finn Thain             2009-11-17 20:03:05 +1100 214)     cuda_state = idle;
f74faec6b3af9 (Finn Thain             2016-12-31 19:56:26 -0500 215)     mcu_is_egret = macintosh_config->adb_type == MAC_ADB_EGRET;
18814ee846357 (Finn Thain             2009-11-17 20:03:05 +1100 216) 
18814ee846357 (Finn Thain             2009-11-17 20:03:05 +1100 217)     err = cuda_init_via();
18814ee846357 (Finn Thain             2009-11-17 20:03:05 +1100 218)     if (err) {
18814ee846357 (Finn Thain             2009-11-17 20:03:05 +1100 219) 	printk(KERN_ERR "cuda_init_via() failed\n");
18814ee846357 (Finn Thain             2009-11-17 20:03:05 +1100 220) 	via = NULL;
18814ee846357 (Finn Thain             2009-11-17 20:03:05 +1100 221) 	return 0;
18814ee846357 (Finn Thain             2009-11-17 20:03:05 +1100 222)     }
18814ee846357 (Finn Thain             2009-11-17 20:03:05 +1100 223) 
18814ee846357 (Finn Thain             2009-11-17 20:03:05 +1100 224)     /* enable autopoll */
18814ee846357 (Finn Thain             2009-11-17 20:03:05 +1100 225)     cuda_request(&req, NULL, 3, CUDA_PACKET, CUDA_AUTOPOLL, 1);
18814ee846357 (Finn Thain             2009-11-17 20:03:05 +1100 226)     while (!req.complete)
18814ee846357 (Finn Thain             2009-11-17 20:03:05 +1100 227) 	cuda_poll();
18814ee846357 (Finn Thain             2009-11-17 20:03:05 +1100 228) 
18814ee846357 (Finn Thain             2009-11-17 20:03:05 +1100 229)     return 1;
18814ee846357 (Finn Thain             2009-11-17 20:03:05 +1100 230) }
18814ee846357 (Finn Thain             2009-11-17 20:03:05 +1100 231) #else
51d3082fe6e55 (Benjamin Herrenschmidt 2005-11-23 17:57:25 +1100 232) int __init find_via_cuda(void)
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 233) {
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 234)     struct adb_request req;
51d3082fe6e55 (Benjamin Herrenschmidt 2005-11-23 17:57:25 +1100 235)     phys_addr_t taddr;
018a3d1db7cdb (Jeremy Kerr            2006-07-12 15:40:29 +1000 236)     const u32 *reg;
51d3082fe6e55 (Benjamin Herrenschmidt 2005-11-23 17:57:25 +1100 237)     int err;
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 238) 
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 239)     if (vias != 0)
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 240) 	return 1;
51d3082fe6e55 (Benjamin Herrenschmidt 2005-11-23 17:57:25 +1100 241)     vias = of_find_node_by_name(NULL, "via-cuda");
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 242)     if (vias == 0)
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 243) 	return 0;
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 244) 
01b2726dd11ef (Stephen Rothwell       2007-04-27 13:41:15 +1000 245)     reg = of_get_property(vias, "reg", NULL);
51d3082fe6e55 (Benjamin Herrenschmidt 2005-11-23 17:57:25 +1100 246)     if (reg == NULL) {
51d3082fe6e55 (Benjamin Herrenschmidt 2005-11-23 17:57:25 +1100 247) 	    printk(KERN_ERR "via-cuda: No \"reg\" property !\n");
51d3082fe6e55 (Benjamin Herrenschmidt 2005-11-23 17:57:25 +1100 248) 	    goto fail;
51d3082fe6e55 (Benjamin Herrenschmidt 2005-11-23 17:57:25 +1100 249)     }
51d3082fe6e55 (Benjamin Herrenschmidt 2005-11-23 17:57:25 +1100 250)     taddr = of_translate_address(vias, reg);
51d3082fe6e55 (Benjamin Herrenschmidt 2005-11-23 17:57:25 +1100 251)     if (taddr == 0) {
51d3082fe6e55 (Benjamin Herrenschmidt 2005-11-23 17:57:25 +1100 252) 	    printk(KERN_ERR "via-cuda: Can't translate address !\n");
51d3082fe6e55 (Benjamin Herrenschmidt 2005-11-23 17:57:25 +1100 253) 	    goto fail;
51d3082fe6e55 (Benjamin Herrenschmidt 2005-11-23 17:57:25 +1100 254)     }
51d3082fe6e55 (Benjamin Herrenschmidt 2005-11-23 17:57:25 +1100 255)     via = ioremap(taddr, 0x2000);
51d3082fe6e55 (Benjamin Herrenschmidt 2005-11-23 17:57:25 +1100 256)     if (via == NULL) {
51d3082fe6e55 (Benjamin Herrenschmidt 2005-11-23 17:57:25 +1100 257) 	    printk(KERN_ERR "via-cuda: Can't map address !\n");
51d3082fe6e55 (Benjamin Herrenschmidt 2005-11-23 17:57:25 +1100 258) 	    goto fail;
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 259)     }
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 260) 
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 261)     cuda_state = idle;
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 262)     sys_ctrler = SYS_CTRLER_CUDA;
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 263) 
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 264)     err = cuda_init_via();
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 265)     if (err) {
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 266) 	printk(KERN_ERR "cuda_init_via() failed\n");
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 267) 	via = NULL;
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 268) 	return 0;
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 269)     }
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 270) 
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 271)     /* Clear and enable interrupts, but only on PPC. On 68K it's done  */
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 272)     /* for us by the main VIA driver in arch/m68k/mac/via.c        */
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 273) 
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 274)     out_8(&via[IFR], 0x7f);	/* clear interrupts by writing 1s */
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 275)     out_8(&via[IER], IER_SET|SR_INT); /* enable interrupt from SR */
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 276) 
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 277)     /* enable autopoll */
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 278)     cuda_request(&req, NULL, 3, CUDA_PACKET, CUDA_AUTOPOLL, 1);
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 279)     while (!req.complete)
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 280) 	cuda_poll();
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 281) 
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 282)     return 1;
51d3082fe6e55 (Benjamin Herrenschmidt 2005-11-23 17:57:25 +1100 283) 
51d3082fe6e55 (Benjamin Herrenschmidt 2005-11-23 17:57:25 +1100 284)  fail:
51d3082fe6e55 (Benjamin Herrenschmidt 2005-11-23 17:57:25 +1100 285)     of_node_put(vias);
51d3082fe6e55 (Benjamin Herrenschmidt 2005-11-23 17:57:25 +1100 286)     vias = NULL;
51d3082fe6e55 (Benjamin Herrenschmidt 2005-11-23 17:57:25 +1100 287)     return 0;
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 288) }
18814ee846357 (Finn Thain             2009-11-17 20:03:05 +1100 289) #endif /* !defined CONFIG_MAC */
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 290) 
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 291) static int __init via_cuda_start(void)
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 292) {
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 293)     if (via == NULL)
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 294) 	return -ENODEV;
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 295) 
0ebfff1491ef8 (Benjamin Herrenschmidt 2006-07-03 21:36:01 +1000 296) #ifdef CONFIG_MAC
0251c38ce503d (Finn Thain             2007-05-01 22:33:00 +0200 297)     cuda_irq = IRQ_MAC_ADB;
18814ee846357 (Finn Thain             2009-11-17 20:03:05 +1100 298) #else
0251c38ce503d (Finn Thain             2007-05-01 22:33:00 +0200 299)     cuda_irq = irq_of_parse_and_map(vias, 0);
ef24ba7091517 (Michael Ellerman       2016-09-06 21:53:24 +1000 300)     if (!cuda_irq) {
b6a945ae03fd3 (Rob Herring            2017-07-18 16:43:12 -0500 301) 	printk(KERN_ERR "via-cuda: can't map interrupts for %pOF\n",
b6a945ae03fd3 (Rob Herring            2017-07-18 16:43:12 -0500 302) 	       vias);
0ebfff1491ef8 (Benjamin Herrenschmidt 2006-07-03 21:36:01 +1000 303) 	return -ENODEV;
0ebfff1491ef8 (Benjamin Herrenschmidt 2006-07-03 21:36:01 +1000 304)     }
18814ee846357 (Finn Thain             2009-11-17 20:03:05 +1100 305) #endif
0ebfff1491ef8 (Benjamin Herrenschmidt 2006-07-03 21:36:01 +1000 306) 
0251c38ce503d (Finn Thain             2007-05-01 22:33:00 +0200 307)     if (request_irq(cuda_irq, cuda_interrupt, 0, "ADB", cuda_interrupt)) {
0251c38ce503d (Finn Thain             2007-05-01 22:33:00 +0200 308) 	printk(KERN_ERR "via-cuda: can't request irq %d\n", cuda_irq);
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 309) 	return -EAGAIN;
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 310)     }
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 311) 
d23eee88b5692 (Finn Thain             2016-12-31 19:56:26 -0500 312)     pr_info("Macintosh Cuda and Egret driver.\n");
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 313) 
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 314)     cuda_fully_inited = 1;
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 315)     return 0;
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 316) }
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 317) 
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 318) device_initcall(via_cuda_start);
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 319) 
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 320) #ifdef CONFIG_ADB
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 321) static int
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 322) cuda_probe(void)
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 323) {
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 324) #ifdef CONFIG_PPC
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 325)     if (sys_ctrler != SYS_CTRLER_CUDA)
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 326) 	return -ENODEV;
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 327) #else
f74faec6b3af9 (Finn Thain             2016-12-31 19:56:26 -0500 328)     if (macintosh_config->adb_type != MAC_ADB_CUDA &&
f74faec6b3af9 (Finn Thain             2016-12-31 19:56:26 -0500 329)         macintosh_config->adb_type != MAC_ADB_EGRET)
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 330) 	return -ENODEV;
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 331) #endif
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 332)     if (via == NULL)
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 333) 	return -ENODEV;
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 334)     return 0;
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 335) }
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 336) #endif /* CONFIG_ADB */
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 337) 
d23eee88b5692 (Finn Thain             2016-12-31 19:56:26 -0500 338) static int __init sync_egret(void)
d23eee88b5692 (Finn Thain             2016-12-31 19:56:26 -0500 339) {
d23eee88b5692 (Finn Thain             2016-12-31 19:56:26 -0500 340) 	if (TREQ_asserted(in_8(&via[B]))) {
d23eee88b5692 (Finn Thain             2016-12-31 19:56:26 -0500 341) 		/* Complete the inbound transfer */
d23eee88b5692 (Finn Thain             2016-12-31 19:56:26 -0500 342) 		assert_TIP_and_TACK();
d23eee88b5692 (Finn Thain             2016-12-31 19:56:26 -0500 343) 		while (1) {
d23eee88b5692 (Finn Thain             2016-12-31 19:56:26 -0500 344) 			negate_TACK();
d23eee88b5692 (Finn Thain             2016-12-31 19:56:26 -0500 345) 			mdelay(1);
d23eee88b5692 (Finn Thain             2016-12-31 19:56:26 -0500 346) 			(void)in_8(&via[SR]);
d23eee88b5692 (Finn Thain             2016-12-31 19:56:26 -0500 347) 			assert_TACK();
d23eee88b5692 (Finn Thain             2016-12-31 19:56:26 -0500 348) 			if (!TREQ_asserted(in_8(&via[B])))
d23eee88b5692 (Finn Thain             2016-12-31 19:56:26 -0500 349) 				break;
d23eee88b5692 (Finn Thain             2016-12-31 19:56:26 -0500 350) 		}
d23eee88b5692 (Finn Thain             2016-12-31 19:56:26 -0500 351) 		negate_TIP_and_TACK();
d23eee88b5692 (Finn Thain             2016-12-31 19:56:26 -0500 352) 	} else if (in_8(&via[B]) & TIP) {
d23eee88b5692 (Finn Thain             2016-12-31 19:56:26 -0500 353) 		/* Terminate the outbound transfer */
d23eee88b5692 (Finn Thain             2016-12-31 19:56:26 -0500 354) 		negate_TACK();
d23eee88b5692 (Finn Thain             2016-12-31 19:56:26 -0500 355) 		assert_TACK();
d23eee88b5692 (Finn Thain             2016-12-31 19:56:26 -0500 356) 		mdelay(1);
d23eee88b5692 (Finn Thain             2016-12-31 19:56:26 -0500 357) 		negate_TIP_and_TACK();
d23eee88b5692 (Finn Thain             2016-12-31 19:56:26 -0500 358) 	}
d23eee88b5692 (Finn Thain             2016-12-31 19:56:26 -0500 359) 	/* Clear shift register interrupt */
d23eee88b5692 (Finn Thain             2016-12-31 19:56:26 -0500 360) 	if (in_8(&via[IFR]) & SR_INT)
d23eee88b5692 (Finn Thain             2016-12-31 19:56:26 -0500 361) 		(void)in_8(&via[SR]);
d23eee88b5692 (Finn Thain             2016-12-31 19:56:26 -0500 362) 	return 0;
d23eee88b5692 (Finn Thain             2016-12-31 19:56:26 -0500 363) }
d23eee88b5692 (Finn Thain             2016-12-31 19:56:26 -0500 364) 
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 365) #define WAIT_FOR(cond, what)					\
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 366)     do {                                                        \
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 367)     	int x;							\
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 368) 	for (x = 1000; !(cond); --x) {				\
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 369) 	    if (x == 0) {					\
523717d1496c7 (Finn Thain             2016-12-31 19:56:26 -0500 370) 		pr_err("Timeout waiting for " what "\n");	\
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 371) 		return -ENXIO;					\
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 372) 	    }							\
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 373) 	    udelay(100);					\
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 374) 	}							\
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 375)     } while (0)
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 376) 
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 377) static int
330dae1999807 (Geert Uytterhoeven     2013-06-30 12:03:23 +0200 378) __init cuda_init_via(void)
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 379) {
0251c38ce503d (Finn Thain             2007-05-01 22:33:00 +0200 380) #ifdef CONFIG_PPC
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 381)     out_8(&via[IER], 0x7f);					/* disable interrupts from VIA */
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 382)     (void)in_8(&via[IER]);
0251c38ce503d (Finn Thain             2007-05-01 22:33:00 +0200 383) #else
0251c38ce503d (Finn Thain             2007-05-01 22:33:00 +0200 384)     out_8(&via[IER], SR_INT);					/* disable SR interrupt from VIA */
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 385) #endif
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 386) 
d23eee88b5692 (Finn Thain             2016-12-31 19:56:26 -0500 387)     out_8(&via[DIRB], (in_8(&via[DIRB]) | TACK | TIP) & ~TREQ);	/* TACK & TIP out */
d23eee88b5692 (Finn Thain             2016-12-31 19:56:26 -0500 388)     out_8(&via[ACR], (in_8(&via[ACR]) & ~SR_CTRL) | SR_EXT);	/* SR data in */
d23eee88b5692 (Finn Thain             2016-12-31 19:56:26 -0500 389)     (void)in_8(&via[SR]);					/* clear any left-over data */
d23eee88b5692 (Finn Thain             2016-12-31 19:56:26 -0500 390) 
d23eee88b5692 (Finn Thain             2016-12-31 19:56:26 -0500 391)     if (mcu_is_egret)
d23eee88b5692 (Finn Thain             2016-12-31 19:56:26 -0500 392) 	return sync_egret();
d23eee88b5692 (Finn Thain             2016-12-31 19:56:26 -0500 393) 
d23eee88b5692 (Finn Thain             2016-12-31 19:56:26 -0500 394)     negate_TIP_and_TACK();
d23eee88b5692 (Finn Thain             2016-12-31 19:56:26 -0500 395) 
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 396)     /* delay 4ms and then clear any pending interrupt */
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 397)     mdelay(4);
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 398)     (void)in_8(&via[SR]);
0251c38ce503d (Finn Thain             2007-05-01 22:33:00 +0200 399)     out_8(&via[IFR], SR_INT);
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 400) 
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 401)     /* sync with the CUDA - assert TACK without TIP */
fd7a65a27c6cb (Finn Thain             2016-12-31 19:56:26 -0500 402)     assert_TACK();
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 403) 
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 404)     /* wait for the CUDA to assert TREQ in response */
fd7a65a27c6cb (Finn Thain             2016-12-31 19:56:26 -0500 405)     WAIT_FOR(TREQ_asserted(in_8(&via[B])), "CUDA response to sync");
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 406) 
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 407)     /* wait for the interrupt and then clear it */
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 408)     WAIT_FOR(in_8(&via[IFR]) & SR_INT, "CUDA response to sync (2)");
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 409)     (void)in_8(&via[SR]);
0251c38ce503d (Finn Thain             2007-05-01 22:33:00 +0200 410)     out_8(&via[IFR], SR_INT);
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 411) 
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 412)     /* finish the sync by negating TACK */
fd7a65a27c6cb (Finn Thain             2016-12-31 19:56:26 -0500 413)     negate_TACK();
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 414) 
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 415)     /* wait for the CUDA to negate TREQ and the corresponding interrupt */
fd7a65a27c6cb (Finn Thain             2016-12-31 19:56:26 -0500 416)     WAIT_FOR(!TREQ_asserted(in_8(&via[B])), "CUDA response to sync (3)");
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 417)     WAIT_FOR(in_8(&via[IFR]) & SR_INT, "CUDA response to sync (4)");
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 418)     (void)in_8(&via[SR]);
0251c38ce503d (Finn Thain             2007-05-01 22:33:00 +0200 419)     out_8(&via[IFR], SR_INT);
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 420) 
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 421)     return 0;
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 422) }
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 423) 
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 424) #ifdef CONFIG_ADB
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 425) /* Send an ADB command */
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 426) static int
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 427) cuda_send_request(struct adb_request *req, int sync)
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 428) {
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 429)     int i;
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 430) 
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 431)     if ((via == NULL) || !cuda_fully_inited) {
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 432) 	req->complete = 1;
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 433) 	return -ENXIO;
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 434)     }
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 435)   
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 436)     req->reply_expected = 1;
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 437) 
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 438)     i = cuda_write(req);
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 439)     if (i)
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 440) 	return i;
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 441) 
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 442)     if (sync) {
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 443) 	while (!req->complete)
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 444) 	    cuda_poll();
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 445)     }
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 446)     return 0;
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 447) }
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 448) 
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 449) 
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 450) /* Enable/disable autopolling */
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 451) static int
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 452) cuda_adb_autopoll(int devs)
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 453) {
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 454)     struct adb_request req;
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 455) 
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 456)     if ((via == NULL) || !cuda_fully_inited)
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 457) 	return -ENXIO;
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 458) 
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 459)     cuda_request(&req, NULL, 3, CUDA_PACKET, CUDA_AUTOPOLL, (devs? 1: 0));
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 460)     while (!req.complete)
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 461) 	cuda_poll();
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 462)     return 0;
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 463) }
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 464) 
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 465) /* Reset adb bus - how do we do this?? */
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 466) static int
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 467) cuda_reset_adb_bus(void)
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 468) {
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 469)     struct adb_request req;
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 470) 
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 471)     if ((via == NULL) || !cuda_fully_inited)
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 472) 	return -ENXIO;
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 473) 
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 474)     cuda_request(&req, NULL, 2, ADB_PACKET, 0);		/* maybe? */
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 475)     while (!req.complete)
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 476) 	cuda_poll();
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 477)     return 0;
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 478) }
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 479) #endif /* CONFIG_ADB */
523717d1496c7 (Finn Thain             2016-12-31 19:56:26 -0500 480) 
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 481) /* Construct and send a cuda request */
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 482) int
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 483) cuda_request(struct adb_request *req, void (*done)(struct adb_request *),
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 484) 	     int nbytes, ...)
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 485) {
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 486)     va_list list;
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 487)     int i;
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 488) 
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 489)     if (via == NULL) {
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 490) 	req->complete = 1;
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 491) 	return -ENXIO;
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 492)     }
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 493) 
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 494)     req->nbytes = nbytes;
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 495)     req->done = done;
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 496)     va_start(list, nbytes);
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 497)     for (i = 0; i < nbytes; ++i)
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 498) 	req->data[i] = va_arg(list, int);
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 499)     va_end(list);
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 500)     req->reply_expected = 1;
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 501)     return cuda_write(req);
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 502) }
4a1b08e84454f (Anton Blanchard        2014-08-20 08:00:01 +1000 503) EXPORT_SYMBOL(cuda_request);
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 504) 
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 505) static int
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 506) cuda_write(struct adb_request *req)
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 507) {
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 508)     unsigned long flags;
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 509) 
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 510)     if (req->nbytes < 2 || req->data[0] > CUDA_PACKET) {
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 511) 	req->complete = 1;
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 512) 	return -EINVAL;
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 513)     }
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 514)     req->next = NULL;
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 515)     req->sent = 0;
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 516)     req->complete = 0;
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 517)     req->reply_len = 0;
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 518) 
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 519)     spin_lock_irqsave(&cuda_lock, flags);
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 520)     if (current_req != 0) {
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 521) 	last_req->next = req;
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 522) 	last_req = req;
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 523)     } else {
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 524) 	current_req = req;
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 525) 	last_req = req;
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 526) 	if (cuda_state == idle)
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 527) 	    cuda_start();
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 528)     }
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 529)     spin_unlock_irqrestore(&cuda_lock, flags);
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 530) 
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 531)     return 0;
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 532) }
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 533) 
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 534) static void
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 535) cuda_start(void)
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 536) {
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 537)     /* assert cuda_state == idle */
06d7e99408acd (Finn Thain             2016-12-31 19:56:26 -0500 538)     if (current_req == NULL)
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 539) 	return;
97ced1aac07e7 (Finn Thain             2016-12-31 19:56:26 -0500 540)     data_index = 0;
fd7a65a27c6cb (Finn Thain             2016-12-31 19:56:26 -0500 541)     if (TREQ_asserted(in_8(&via[B])))
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 542) 	return;			/* a byte is coming in from the CUDA */
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 543) 
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 544)     /* set the shift register to shift out and send a byte */
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 545)     out_8(&via[ACR], in_8(&via[ACR]) | SR_OUT);
97ced1aac07e7 (Finn Thain             2016-12-31 19:56:26 -0500 546)     out_8(&via[SR], current_req->data[data_index++]);
d23eee88b5692 (Finn Thain             2016-12-31 19:56:26 -0500 547)     if (mcu_is_egret)
d23eee88b5692 (Finn Thain             2016-12-31 19:56:26 -0500 548) 	assert_TIP_and_TACK();
d23eee88b5692 (Finn Thain             2016-12-31 19:56:26 -0500 549)     else
d23eee88b5692 (Finn Thain             2016-12-31 19:56:26 -0500 550) 	assert_TIP();
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 551)     cuda_state = sent_first_byte;
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 552) }
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 553) 
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 554) void
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 555) cuda_poll(void)
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 556) {
ac39452e942af (Finn Thain             2016-12-31 19:56:26 -0500 557) 	cuda_interrupt(0, NULL);
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 558) }
4a1b08e84454f (Anton Blanchard        2014-08-20 08:00:01 +1000 559) EXPORT_SYMBOL(cuda_poll);
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 560) 
fe73b582f1793 (Finn Thain             2016-12-31 19:56:26 -0500 561) #define ARRAY_FULL(a, p)	((p) - (a) == ARRAY_SIZE(a))
fe73b582f1793 (Finn Thain             2016-12-31 19:56:26 -0500 562) 
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 563) static irqreturn_t
7d12e780e003f (David Howells          2006-10-05 14:55:46 +0100 564) cuda_interrupt(int irq, void *arg)
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 565) {
ac39452e942af (Finn Thain             2016-12-31 19:56:26 -0500 566)     unsigned long flags;
fd7a65a27c6cb (Finn Thain             2016-12-31 19:56:26 -0500 567)     u8 status;
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 568)     struct adb_request *req = NULL;
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 569)     unsigned char ibuf[16];
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 570)     int ibuf_len = 0;
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 571)     int complete = 0;
458c77f3de0ed (Finn Thain             2019-01-15 15:18:56 +1100 572)     bool full;
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 573)     
ac39452e942af (Finn Thain             2016-12-31 19:56:26 -0500 574)     spin_lock_irqsave(&cuda_lock, flags);
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 575) 
18814ee846357 (Finn Thain             2009-11-17 20:03:05 +1100 576)     /* On powermacs, this handler is registered for the VIA IRQ. But they use
0251c38ce503d (Finn Thain             2007-05-01 22:33:00 +0200 577)      * just the shift register IRQ -- other VIA interrupt sources are disabled.
0251c38ce503d (Finn Thain             2007-05-01 22:33:00 +0200 578)      * On m68k macs, the VIA IRQ sources are dispatched individually. Unless
0251c38ce503d (Finn Thain             2007-05-01 22:33:00 +0200 579)      * we are polling, the shift register IRQ flag has already been cleared.
0251c38ce503d (Finn Thain             2007-05-01 22:33:00 +0200 580)      */
0251c38ce503d (Finn Thain             2007-05-01 22:33:00 +0200 581) 
0251c38ce503d (Finn Thain             2007-05-01 22:33:00 +0200 582) #ifdef CONFIG_MAC
0251c38ce503d (Finn Thain             2007-05-01 22:33:00 +0200 583)     if (!arg)
0251c38ce503d (Finn Thain             2007-05-01 22:33:00 +0200 584) #endif
0251c38ce503d (Finn Thain             2007-05-01 22:33:00 +0200 585)     {
0251c38ce503d (Finn Thain             2007-05-01 22:33:00 +0200 586)         if ((in_8(&via[IFR]) & SR_INT) == 0) {
ac39452e942af (Finn Thain             2016-12-31 19:56:26 -0500 587)             spin_unlock_irqrestore(&cuda_lock, flags);
0251c38ce503d (Finn Thain             2007-05-01 22:33:00 +0200 588)             return IRQ_NONE;
0251c38ce503d (Finn Thain             2007-05-01 22:33:00 +0200 589)         } else {
0251c38ce503d (Finn Thain             2007-05-01 22:33:00 +0200 590)             out_8(&via[IFR], SR_INT);
0251c38ce503d (Finn Thain             2007-05-01 22:33:00 +0200 591)         }
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 592)     }
fd7a65a27c6cb (Finn Thain             2016-12-31 19:56:26 -0500 593) 
fd7a65a27c6cb (Finn Thain             2016-12-31 19:56:26 -0500 594)     status = in_8(&via[B]) & (TIP | TACK | TREQ);
fd7a65a27c6cb (Finn Thain             2016-12-31 19:56:26 -0500 595) 
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 596)     switch (cuda_state) {
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 597)     case idle:
d23eee88b5692 (Finn Thain             2016-12-31 19:56:26 -0500 598) 	/* System controller has unsolicited data for us */
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 599) 	(void)in_8(&via[SR]);
d23eee88b5692 (Finn Thain             2016-12-31 19:56:26 -0500 600) idle_state:
fd7a65a27c6cb (Finn Thain             2016-12-31 19:56:26 -0500 601) 	assert_TIP();
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 602) 	cuda_state = reading;
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 603) 	reply_ptr = cuda_rbuf;
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 604) 	reading_reply = 0;
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 605) 	break;
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 606) 
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 607)     case awaiting_reply:
d23eee88b5692 (Finn Thain             2016-12-31 19:56:26 -0500 608) 	/* System controller has reply data for us */
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 609) 	(void)in_8(&via[SR]);
fd7a65a27c6cb (Finn Thain             2016-12-31 19:56:26 -0500 610) 	assert_TIP();
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 611) 	cuda_state = reading;
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 612) 	reply_ptr = current_req->reply;
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 613) 	reading_reply = 1;
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 614) 	break;
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 615) 
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 616)     case sent_first_byte:
fd7a65a27c6cb (Finn Thain             2016-12-31 19:56:26 -0500 617) 	if (TREQ_asserted(status)) {
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 618) 	    /* collision */
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 619) 	    out_8(&via[ACR], in_8(&via[ACR]) & ~SR_OUT);
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 620) 	    (void)in_8(&via[SR]);
fd7a65a27c6cb (Finn Thain             2016-12-31 19:56:26 -0500 621) 	    negate_TIP_and_TACK();
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 622) 	    cuda_state = idle;
d23eee88b5692 (Finn Thain             2016-12-31 19:56:26 -0500 623) 	    /* Egret does not raise an "aborted" interrupt */
d23eee88b5692 (Finn Thain             2016-12-31 19:56:26 -0500 624) 	    if (mcu_is_egret)
d23eee88b5692 (Finn Thain             2016-12-31 19:56:26 -0500 625) 		goto idle_state;
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 626) 	} else {
97ced1aac07e7 (Finn Thain             2016-12-31 19:56:26 -0500 627) 	    out_8(&via[SR], current_req->data[data_index++]);
fd7a65a27c6cb (Finn Thain             2016-12-31 19:56:26 -0500 628) 	    toggle_TACK();
d23eee88b5692 (Finn Thain             2016-12-31 19:56:26 -0500 629) 	    if (mcu_is_egret)
d23eee88b5692 (Finn Thain             2016-12-31 19:56:26 -0500 630) 		assert_TACK();
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 631) 	    cuda_state = sending;
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 632) 	}
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 633) 	break;
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 634) 
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 635)     case sending:
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 636) 	req = current_req;
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 637) 	if (data_index >= req->nbytes) {
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 638) 	    out_8(&via[ACR], in_8(&via[ACR]) & ~SR_OUT);
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 639) 	    (void)in_8(&via[SR]);
fd7a65a27c6cb (Finn Thain             2016-12-31 19:56:26 -0500 640) 	    negate_TIP_and_TACK();
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 641) 	    req->sent = 1;
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 642) 	    if (req->reply_expected) {
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 643) 		cuda_state = awaiting_reply;
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 644) 	    } else {
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 645) 		current_req = req->next;
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 646) 		complete = 1;
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 647) 		/* not sure about this */
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 648) 		cuda_state = idle;
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 649) 		cuda_start();
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 650) 	    }
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 651) 	} else {
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 652) 	    out_8(&via[SR], req->data[data_index++]);
fd7a65a27c6cb (Finn Thain             2016-12-31 19:56:26 -0500 653) 	    toggle_TACK();
d23eee88b5692 (Finn Thain             2016-12-31 19:56:26 -0500 654) 	    if (mcu_is_egret)
d23eee88b5692 (Finn Thain             2016-12-31 19:56:26 -0500 655) 		assert_TACK();
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 656) 	}
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 657) 	break;
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 658) 
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 659)     case reading:
458c77f3de0ed (Finn Thain             2019-01-15 15:18:56 +1100 660) 	full = reading_reply ? ARRAY_FULL(current_req->reply, reply_ptr)
458c77f3de0ed (Finn Thain             2019-01-15 15:18:56 +1100 661) 	                     : ARRAY_FULL(cuda_rbuf, reply_ptr);
458c77f3de0ed (Finn Thain             2019-01-15 15:18:56 +1100 662) 	if (full)
fe73b582f1793 (Finn Thain             2016-12-31 19:56:26 -0500 663) 	    (void)in_8(&via[SR]);
fe73b582f1793 (Finn Thain             2016-12-31 19:56:26 -0500 664) 	else
fe73b582f1793 (Finn Thain             2016-12-31 19:56:26 -0500 665) 	    *reply_ptr++ = in_8(&via[SR]);
458c77f3de0ed (Finn Thain             2019-01-15 15:18:56 +1100 666) 	if (!TREQ_asserted(status) || full) {
d23eee88b5692 (Finn Thain             2016-12-31 19:56:26 -0500 667) 	    if (mcu_is_egret)
d23eee88b5692 (Finn Thain             2016-12-31 19:56:26 -0500 668) 		assert_TACK();
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 669) 	    /* that's all folks */
fd7a65a27c6cb (Finn Thain             2016-12-31 19:56:26 -0500 670) 	    negate_TIP_and_TACK();
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 671) 	    cuda_state = read_done;
d23eee88b5692 (Finn Thain             2016-12-31 19:56:26 -0500 672) 	    /* Egret does not raise a "read done" interrupt */
d23eee88b5692 (Finn Thain             2016-12-31 19:56:26 -0500 673) 	    if (mcu_is_egret)
d23eee88b5692 (Finn Thain             2016-12-31 19:56:26 -0500 674) 		goto read_done_state;
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 675) 	} else {
fd7a65a27c6cb (Finn Thain             2016-12-31 19:56:26 -0500 676) 	    toggle_TACK();
d23eee88b5692 (Finn Thain             2016-12-31 19:56:26 -0500 677) 	    if (mcu_is_egret)
d23eee88b5692 (Finn Thain             2016-12-31 19:56:26 -0500 678) 		negate_TACK();
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 679) 	}
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 680) 	break;
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 681) 
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 682)     case read_done:
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 683) 	(void)in_8(&via[SR]);
d23eee88b5692 (Finn Thain             2016-12-31 19:56:26 -0500 684) read_done_state:
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 685) 	if (reading_reply) {
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 686) 	    req = current_req;
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 687) 	    req->reply_len = reply_ptr - req->reply;
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 688) 	    if (req->data[0] == ADB_PACKET) {
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 689) 		/* Have to adjust the reply from ADB commands */
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 690) 		if (req->reply_len <= 2 || (req->reply[1] & 2) != 0) {
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 691) 		    /* the 0x2 bit indicates no response */
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 692) 		    req->reply_len = 0;
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 693) 		} else {
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 694) 		    /* leave just the command and result bytes in the reply */
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 695) 		    req->reply_len -= 2;
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 696) 		    memmove(req->reply, req->reply + 2, req->reply_len);
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 697) 		}
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 698) 	    }
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 699) 	    current_req = req->next;
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 700) 	    complete = 1;
cfbf99801bcaf (Finn Thain             2016-12-31 19:56:26 -0500 701) 	    reading_reply = 0;
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 702) 	} else {
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 703) 	    /* This is tricky. We must break the spinlock to call
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 704) 	     * cuda_input. However, doing so means we might get
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 705) 	     * re-entered from another CPU getting an interrupt
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 706) 	     * or calling cuda_poll(). I ended up using the stack
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 707) 	     * (it's only for 16 bytes) and moving the actual
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 708) 	     * call to cuda_input to outside of the lock.
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 709) 	     */
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 710) 	    ibuf_len = reply_ptr - cuda_rbuf;
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 711) 	    memcpy(ibuf, cuda_rbuf, ibuf_len);
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 712) 	}
cfbf99801bcaf (Finn Thain             2016-12-31 19:56:26 -0500 713) 	reply_ptr = cuda_rbuf;
a64662432200f (Finn Thain             2016-12-31 19:56:26 -0500 714) 	cuda_state = idle;
a64662432200f (Finn Thain             2016-12-31 19:56:26 -0500 715) 	cuda_start();
a64662432200f (Finn Thain             2016-12-31 19:56:26 -0500 716) 	if (cuda_state == idle && TREQ_asserted(in_8(&via[B]))) {
fd7a65a27c6cb (Finn Thain             2016-12-31 19:56:26 -0500 717) 	    assert_TIP();
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 718) 	    cuda_state = reading;
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 719) 	}
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 720) 	break;
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 721) 
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 722)     default:
523717d1496c7 (Finn Thain             2016-12-31 19:56:26 -0500 723) 	pr_err("cuda_interrupt: unknown cuda_state %d?\n", cuda_state);
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 724)     }
ac39452e942af (Finn Thain             2016-12-31 19:56:26 -0500 725)     spin_unlock_irqrestore(&cuda_lock, flags);
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 726)     if (complete && req) {
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 727)     	void (*done)(struct adb_request *) = req->done;
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 728)     	mb();
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 729)     	req->complete = 1;
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 730)     	/* Here, we assume that if the request has a done member, the
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 731)     	 * struct request will survive to setting req->complete to 1
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 732)     	 */
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 733)     	if (done)
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 734) 		(*done)(req);
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 735)     }
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 736)     if (ibuf_len)
7d12e780e003f (David Howells          2006-10-05 14:55:46 +0100 737) 	cuda_input(ibuf, ibuf_len);
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 738)     return IRQ_HANDLED;
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 739) }
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 740) 
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 741) static void
7d12e780e003f (David Howells          2006-10-05 14:55:46 +0100 742) cuda_input(unsigned char *buf, int nb)
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 743) {
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 744)     switch (buf[0]) {
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 745)     case ADB_PACKET:
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 746) #ifdef CONFIG_XMON
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 747) 	if (nb == 5 && buf[2] == 0x2c) {
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 748) 	    extern int xmon_wants_key, xmon_adb_keycode;
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 749) 	    if (xmon_wants_key) {
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 750) 		xmon_adb_keycode = buf[3];
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 751) 		return;
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 752) 	    }
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 753) 	}
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 754) #endif /* CONFIG_XMON */
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 755) #ifdef CONFIG_ADB
7d12e780e003f (David Howells          2006-10-05 14:55:46 +0100 756) 	adb_input(buf+2, nb-2, buf[1] & 0x40);
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 757) #endif /* CONFIG_ADB */
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 758) 	break;
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 759) 
d23eee88b5692 (Finn Thain             2016-12-31 19:56:26 -0500 760)     case TIMER_PACKET:
d23eee88b5692 (Finn Thain             2016-12-31 19:56:26 -0500 761) 	/* Egret sends these periodically. Might be useful as a 'heartbeat'
d23eee88b5692 (Finn Thain             2016-12-31 19:56:26 -0500 762) 	 * to trigger a recovery for the VIA shift register errata.
d23eee88b5692 (Finn Thain             2016-12-31 19:56:26 -0500 763) 	 */
d23eee88b5692 (Finn Thain             2016-12-31 19:56:26 -0500 764) 	break;
d23eee88b5692 (Finn Thain             2016-12-31 19:56:26 -0500 765) 
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 766)     default:
523717d1496c7 (Finn Thain             2016-12-31 19:56:26 -0500 767) 	print_hex_dump(KERN_INFO, "cuda_input: ", DUMP_PREFIX_NONE, 32, 1,
523717d1496c7 (Finn Thain             2016-12-31 19:56:26 -0500 768) 	               buf, nb, false);
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 769)     }
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 770) }
0792a2c8e0bbd (Finn Thain             2018-09-11 20:18:44 -0400 771) 
0792a2c8e0bbd (Finn Thain             2018-09-11 20:18:44 -0400 772) /* Offset between Unix time (1970-based) and Mac time (1904-based) */
0792a2c8e0bbd (Finn Thain             2018-09-11 20:18:44 -0400 773) #define RTC_OFFSET	2082844800
0792a2c8e0bbd (Finn Thain             2018-09-11 20:18:44 -0400 774) 
0792a2c8e0bbd (Finn Thain             2018-09-11 20:18:44 -0400 775) time64_t cuda_get_time(void)
0792a2c8e0bbd (Finn Thain             2018-09-11 20:18:44 -0400 776) {
0792a2c8e0bbd (Finn Thain             2018-09-11 20:18:44 -0400 777) 	struct adb_request req;
0792a2c8e0bbd (Finn Thain             2018-09-11 20:18:44 -0400 778) 	u32 now;
0792a2c8e0bbd (Finn Thain             2018-09-11 20:18:44 -0400 779) 
0792a2c8e0bbd (Finn Thain             2018-09-11 20:18:44 -0400 780) 	if (cuda_request(&req, NULL, 2, CUDA_PACKET, CUDA_GET_TIME) < 0)
0792a2c8e0bbd (Finn Thain             2018-09-11 20:18:44 -0400 781) 		return 0;
0792a2c8e0bbd (Finn Thain             2018-09-11 20:18:44 -0400 782) 	while (!req.complete)
0792a2c8e0bbd (Finn Thain             2018-09-11 20:18:44 -0400 783) 		cuda_poll();
0792a2c8e0bbd (Finn Thain             2018-09-11 20:18:44 -0400 784) 	if (req.reply_len != 7)
0792a2c8e0bbd (Finn Thain             2018-09-11 20:18:44 -0400 785) 		pr_err("%s: got %d byte reply\n", __func__, req.reply_len);
0792a2c8e0bbd (Finn Thain             2018-09-11 20:18:44 -0400 786) 	now = (req.reply[3] << 24) + (req.reply[4] << 16) +
0792a2c8e0bbd (Finn Thain             2018-09-11 20:18:44 -0400 787) 	      (req.reply[5] << 8) + req.reply[6];
0792a2c8e0bbd (Finn Thain             2018-09-11 20:18:44 -0400 788) 	return (time64_t)now - RTC_OFFSET;
0792a2c8e0bbd (Finn Thain             2018-09-11 20:18:44 -0400 789) }
0792a2c8e0bbd (Finn Thain             2018-09-11 20:18:44 -0400 790) 
0792a2c8e0bbd (Finn Thain             2018-09-11 20:18:44 -0400 791) int cuda_set_rtc_time(struct rtc_time *tm)
0792a2c8e0bbd (Finn Thain             2018-09-11 20:18:44 -0400 792) {
0792a2c8e0bbd (Finn Thain             2018-09-11 20:18:44 -0400 793) 	u32 now;
0792a2c8e0bbd (Finn Thain             2018-09-11 20:18:44 -0400 794) 	struct adb_request req;
0792a2c8e0bbd (Finn Thain             2018-09-11 20:18:44 -0400 795) 
0792a2c8e0bbd (Finn Thain             2018-09-11 20:18:44 -0400 796) 	now = lower_32_bits(rtc_tm_to_time64(tm) + RTC_OFFSET);
0792a2c8e0bbd (Finn Thain             2018-09-11 20:18:44 -0400 797) 	if (cuda_request(&req, NULL, 6, CUDA_PACKET, CUDA_SET_TIME,
0792a2c8e0bbd (Finn Thain             2018-09-11 20:18:44 -0400 798) 	                 now >> 24, now >> 16, now >> 8, now) < 0)
0792a2c8e0bbd (Finn Thain             2018-09-11 20:18:44 -0400 799) 		return -ENXIO;
0792a2c8e0bbd (Finn Thain             2018-09-11 20:18:44 -0400 800) 	while (!req.complete)
0792a2c8e0bbd (Finn Thain             2018-09-11 20:18:44 -0400 801) 		cuda_poll();
0792a2c8e0bbd (Finn Thain             2018-09-11 20:18:44 -0400 802) 	if ((req.reply_len != 3) && (req.reply_len != 7))
0792a2c8e0bbd (Finn Thain             2018-09-11 20:18:44 -0400 803) 		pr_err("%s: got %d byte reply\n", __func__, req.reply_len);
0792a2c8e0bbd (Finn Thain             2018-09-11 20:18:44 -0400 804) 	return 0;
0792a2c8e0bbd (Finn Thain             2018-09-11 20:18:44 -0400 805) }