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) /*
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700   3)  * Device driver for the Apple Desktop Bus
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700   4)  * and the /dev/adb device on macintoshes.
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700   5)  *
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700   6)  * Copyright (C) 1996 Paul Mackerras.
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700   7)  *
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700   8)  * Modified to declare controllers as structures, added
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700   9)  * client notification of bus reset and handles PowerBook
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700  10)  * sleep, by Benjamin Herrenschmidt.
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700  11)  *
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700  12)  * To do:
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700  13)  *
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700  14)  * - /sys/bus/adb to list the devices and infos
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700  15)  * - more /dev/adb to allow userland to receive the
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700  16)  *   flow of auto-polling datas from a given device.
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700  17)  * - move bus probe to a kernel thread
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700  18)  */
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700  19) 
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700  20) #include <linux/types.h>
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700  21) #include <linux/errno.h>
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700  22) #include <linux/kernel.h>
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700  23) #include <linux/slab.h>
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700  24) #include <linux/module.h>
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700  25) #include <linux/fs.h>
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700  26) #include <linux/mm.h>
174cd4b1e5fbd (Ingo Molnar            2017-02-02 19:15:33 +0100  27) #include <linux/sched/signal.h>
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700  28) #include <linux/adb.h>
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700  29) #include <linux/cuda.h>
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700  30) #include <linux/pmu.h>
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700  31) #include <linux/notifier.h>
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700  32) #include <linux/wait.h>
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700  33) #include <linux/init.h>
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700  34) #include <linux/delay.h>
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700  35) #include <linux/spinlock.h>
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700  36) #include <linux/completion.h>
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700  37) #include <linux/device.h>
c61dace9a10a4 (Paul Mackerras         2007-12-13 15:11:22 +1100  38) #include <linux/kthread.h>
fe2528b96b021 (Geert Uytterhoeven     2008-02-03 16:49:09 +0100  39) #include <linux/platform_device.h>
af3ce514ade2f (Daniel Walker          2008-05-03 06:34:03 +1000  40) #include <linux/mutex.h>
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700  41) 
74e7cd432c3d1 (Brandon Stewart        2014-01-27 19:43:17 -0600  42) #include <linux/uaccess.h>
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700  43) #ifdef CONFIG_PPC
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700  44) #include <asm/prom.h>
e8222502ee615 (Benjamin Herrenschmidt 2006-03-28 23:15:54 +1100  45) #include <asm/machdep.h>
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700  46) #endif
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700  47) 
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700  48) 
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700  49) EXPORT_SYMBOL(adb_client_list);
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700  50) 
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700  51) extern struct adb_driver via_macii_driver;
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700  52) extern struct adb_driver via_cuda_driver;
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700  53) extern struct adb_driver adb_iop_driver;
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700  54) extern struct adb_driver via_pmu_driver;
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700  55) extern struct adb_driver macio_adb_driver;
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700  56) 
d851b6e04ee97 (Arnd Bergmann          2010-06-02 14:28:52 +0200  57) static DEFINE_MUTEX(adb_mutex);
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700  58) static struct adb_driver *adb_driver_list[] = {
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700  59) #ifdef CONFIG_ADB_MACII
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700  60) 	&via_macii_driver,
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700  61) #endif
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700  62) #ifdef CONFIG_ADB_CUDA
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700  63) 	&via_cuda_driver,
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700  64) #endif
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700  65) #ifdef CONFIG_ADB_IOP
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700  66) 	&adb_iop_driver,
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700  67) #endif
ebd722275f9cf (Finn Thain             2018-07-02 04:21:19 -0400  68) #ifdef CONFIG_ADB_PMU
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700  69) 	&via_pmu_driver,
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700  70) #endif
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700  71) #ifdef CONFIG_ADB_MACIO
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700  72) 	&macio_adb_driver,
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700  73) #endif
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700  74) 	NULL
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700  75) };
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700  76) 
56b2293595b2e (Greg Kroah-Hartman     2005-03-23 10:01:41 -0800  77) static struct class *adb_dev_class;
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700  78) 
9b4a8dd2e9f8a (Adrian Bunk            2008-06-24 03:46:57 +1000  79) static struct adb_driver *adb_controller;
e041c683412d5 (Alan Stern             2006-03-27 01:16:30 -0800  80) BLOCKING_NOTIFIER_HEAD(adb_client_list);
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700  81) static int adb_got_sleep;
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700  82) static int adb_inited;
8192b1f6b1a46 (Thomas Gleixner        2010-09-07 14:33:40 +0000  83) static DEFINE_SEMAPHORE(adb_probe_mutex);
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700  84) static int sleepy_trackpad;
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700  85) static int autopoll_devs;
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700  86) int __adb_probe_sync;
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700  87) 
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700  88) static int adb_scan_bus(void);
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700  89) static int do_adb_reset_bus(void);
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700  90) static void adbdev_init(void);
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700  91) static int try_handler_change(int, int);
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700  92) 
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700  93) static struct adb_handler {
7d12e780e003f (David Howells          2006-10-05 14:55:46 +0100  94) 	void (*handler)(unsigned char *, int, int);
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700  95) 	int original_address;
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700  96) 	int handler_id;
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700  97) 	int busy;
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700  98) } adb_handler[16];
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700  99) 
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 100) /*
af3ce514ade2f (Daniel Walker          2008-05-03 06:34:03 +1000 101)  * The adb_handler_mutex mutex protects all accesses to the original_address
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 102)  * and handler_id fields of adb_handler[i] for all i, and changes to the
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 103)  * handler field.
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 104)  * Accesses to the handler field are protected by the adb_handler_lock
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 105)  * rwlock.  It is held across all calls to any handler, so that by the
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 106)  * time adb_unregister returns, we know that the old handler isn't being
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 107)  * called.
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 108)  */
af3ce514ade2f (Daniel Walker          2008-05-03 06:34:03 +1000 109) static DEFINE_MUTEX(adb_handler_mutex);
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 110) static DEFINE_RWLOCK(adb_handler_lock);
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 111) 
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 112) #if 0
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 113) static void printADBreply(struct adb_request *req)
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 114) {
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 115)         int i;
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 116) 
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 117)         printk("adb reply (%d)", req->reply_len);
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 118)         for(i = 0; i < req->reply_len; i++)
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 119)                 printk(" %x", req->reply[i]);
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 120)         printk("\n");
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 121) 
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 122) }
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 123) #endif
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 124) 
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 125) static int adb_scan_bus(void)
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 126) {
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 127) 	int i, highFree=0, noMovement;
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 128) 	int devmask = 0;
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 129) 	struct adb_request req;
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 130) 	
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 131) 	/* assumes adb_handler[] is all zeroes at this point */
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 132) 	for (i = 1; i < 16; i++) {
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 133) 		/* see if there is anything at address i */
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 134) 		adb_request(&req, NULL, ADBREQ_SYNC | ADBREQ_REPLY, 1,
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 135)                             (i << 4) | 0xf);
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 136) 		if (req.reply_len > 1)
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 137) 			/* one or more devices at this address */
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 138) 			adb_handler[i].original_address = i;
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 139) 		else if (i > highFree)
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 140) 			highFree = i;
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 141) 	}
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 142) 
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 143) 	/* Note we reset noMovement to 0 each time we move a device */
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 144) 	for (noMovement = 1; noMovement < 2 && highFree > 0; noMovement++) {
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 145) 		for (i = 1; i < 16; i++) {
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 146) 			if (adb_handler[i].original_address == 0)
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 147) 				continue;
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 148) 			/*
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 149) 			 * Send a "talk register 3" command to address i
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 150) 			 * to provoke a collision if there is more than
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 151) 			 * one device at this address.
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 152) 			 */
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 153) 			adb_request(&req, NULL, ADBREQ_SYNC | ADBREQ_REPLY, 1,
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 154) 				    (i << 4) | 0xf);
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 155) 			/*
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 156) 			 * Move the device(s) which didn't detect a
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 157) 			 * collision to address `highFree'.  Hopefully
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 158) 			 * this only moves one device.
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 159) 			 */
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 160) 			adb_request(&req, NULL, ADBREQ_SYNC, 3,
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 161) 				    (i<< 4) | 0xb, (highFree | 0x60), 0xfe);
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 162) 			/*
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 163) 			 * See if anybody actually moved. This is suggested
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 164) 			 * by HW TechNote 01:
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 165) 			 *
a7beab413e2e6 (Alexander A. Klimov    2020-07-17 20:35:22 +0200 166) 			 * https://developer.apple.com/technotes/hw/hw_01.html
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 167) 			 */
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 168) 			adb_request(&req, NULL, ADBREQ_SYNC | ADBREQ_REPLY, 1,
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 169) 				    (highFree << 4) | 0xf);
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 170) 			if (req.reply_len <= 1) continue;
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 171) 			/*
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 172) 			 * Test whether there are any device(s) left
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 173) 			 * at address i.
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 174) 			 */
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 175) 			adb_request(&req, NULL, ADBREQ_SYNC | ADBREQ_REPLY, 1,
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 176) 				    (i << 4) | 0xf);
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 177) 			if (req.reply_len > 1) {
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 178) 				/*
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 179) 				 * There are still one or more devices
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 180) 				 * left at address i.  Register the one(s)
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 181) 				 * we moved to `highFree', and find a new
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 182) 				 * value for highFree.
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 183) 				 */
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 184) 				adb_handler[highFree].original_address =
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 185) 					adb_handler[i].original_address;
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 186) 				while (highFree > 0 &&
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 187) 				       adb_handler[highFree].original_address)
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 188) 					highFree--;
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 189) 				if (highFree <= 0)
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 190) 					break;
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 191) 
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 192) 				noMovement = 0;
74e7cd432c3d1 (Brandon Stewart        2014-01-27 19:43:17 -0600 193) 			} else {
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 194) 				/*
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 195) 				 * No devices left at address i; move the
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 196) 				 * one(s) we moved to `highFree' back to i.
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 197) 				 */
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 198) 				adb_request(&req, NULL, ADBREQ_SYNC, 3,
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 199) 					    (highFree << 4) | 0xb,
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 200) 					    (i | 0x60), 0xfe);
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 201) 			}
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 202) 		}	
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 203) 	}
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 204) 
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 205) 	/* Now fill in the handler_id field of the adb_handler entries. */
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 206) 	for (i = 1; i < 16; i++) {
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 207) 		if (adb_handler[i].original_address == 0)
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 208) 			continue;
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 209) 		adb_request(&req, NULL, ADBREQ_SYNC | ADBREQ_REPLY, 1,
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 210) 			    (i << 4) | 0xf);
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 211) 		adb_handler[i].handler_id = req.reply[2];
2341629eadc4a (Finn Thain             2018-09-11 20:18:44 -0400 212) 		printk(KERN_DEBUG "adb device [%d]: %d 0x%X\n", i,
2341629eadc4a (Finn Thain             2018-09-11 20:18:44 -0400 213) 		       adb_handler[i].original_address,
2341629eadc4a (Finn Thain             2018-09-11 20:18:44 -0400 214) 		       adb_handler[i].handler_id);
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 215) 		devmask |= 1 << i;
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 216) 	}
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 217) 	return devmask;
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 218) }
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 219) 
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 220) /*
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 221)  * This kernel task handles ADB probing. It dies once probing is
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 222)  * completed.
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 223)  */
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 224) static int
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 225) adb_probe_task(void *x)
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 226) {
f2be6295684b0 (Andreas Schwab         2016-11-28 21:29:07 +0100 227) 	pr_debug("adb: starting probe task...\n");
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 228) 	do_adb_reset_bus();
f2be6295684b0 (Andreas Schwab         2016-11-28 21:29:07 +0100 229) 	pr_debug("adb: finished probe task...\n");
1b6dd9baa728d (Oleg Nesterov          2007-07-15 23:41:29 -0700 230) 
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 231) 	up(&adb_probe_mutex);
1b6dd9baa728d (Oleg Nesterov          2007-07-15 23:41:29 -0700 232) 
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 233) 	return 0;
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 234) }
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 235) 
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 236) static void
3e577a80ea85e (Al Viro                2006-12-06 18:41:45 +0000 237) __adb_probe_task(struct work_struct *bullshit)
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 238) {
c61dace9a10a4 (Paul Mackerras         2007-12-13 15:11:22 +1100 239) 	kthread_run(adb_probe_task, NULL, "kadbprobe");
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 240) }
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 241) 
3e577a80ea85e (Al Viro                2006-12-06 18:41:45 +0000 242) static DECLARE_WORK(adb_reset_work, __adb_probe_task);
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 243) 
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 244) int
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 245) adb_reset_bus(void)
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 246) {
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 247) 	if (__adb_probe_sync) {
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 248) 		do_adb_reset_bus();
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 249) 		return 0;
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 250) 	}
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 251) 
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 252) 	down(&adb_probe_mutex);
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 253) 	schedule_work(&adb_reset_work);
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 254) 	return 0;
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 255) }
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 256) 
c9f6d3d5c6d4f (Johannes Berg          2007-12-12 01:21:25 +1100 257) #ifdef CONFIG_PM
c9f6d3d5c6d4f (Johannes Berg          2007-12-12 01:21:25 +1100 258) /*
c9f6d3d5c6d4f (Johannes Berg          2007-12-12 01:21:25 +1100 259)  * notify clients before sleep
c9f6d3d5c6d4f (Johannes Berg          2007-12-12 01:21:25 +1100 260)  */
639291f263c14 (Shuah Khan             2014-02-10 09:12:27 -0700 261) static int __adb_suspend(struct platform_device *dev, pm_message_t state)
c9f6d3d5c6d4f (Johannes Berg          2007-12-12 01:21:25 +1100 262) {
c9f6d3d5c6d4f (Johannes Berg          2007-12-12 01:21:25 +1100 263) 	adb_got_sleep = 1;
c9f6d3d5c6d4f (Johannes Berg          2007-12-12 01:21:25 +1100 264) 	/* We need to get a lock on the probe thread */
c9f6d3d5c6d4f (Johannes Berg          2007-12-12 01:21:25 +1100 265) 	down(&adb_probe_mutex);
c9f6d3d5c6d4f (Johannes Berg          2007-12-12 01:21:25 +1100 266) 	/* Stop autopoll */
c9f6d3d5c6d4f (Johannes Berg          2007-12-12 01:21:25 +1100 267) 	if (adb_controller->autopoll)
c9f6d3d5c6d4f (Johannes Berg          2007-12-12 01:21:25 +1100 268) 		adb_controller->autopoll(0);
c9f6d3d5c6d4f (Johannes Berg          2007-12-12 01:21:25 +1100 269) 	blocking_notifier_call_chain(&adb_client_list, ADB_MSG_POWERDOWN, NULL);
c9f6d3d5c6d4f (Johannes Berg          2007-12-12 01:21:25 +1100 270) 
c9f6d3d5c6d4f (Johannes Berg          2007-12-12 01:21:25 +1100 271) 	return 0;
c9f6d3d5c6d4f (Johannes Berg          2007-12-12 01:21:25 +1100 272) }
c9f6d3d5c6d4f (Johannes Berg          2007-12-12 01:21:25 +1100 273) 
639291f263c14 (Shuah Khan             2014-02-10 09:12:27 -0700 274) static int adb_suspend(struct device *dev)
639291f263c14 (Shuah Khan             2014-02-10 09:12:27 -0700 275) {
639291f263c14 (Shuah Khan             2014-02-10 09:12:27 -0700 276) 	return __adb_suspend(to_platform_device(dev), PMSG_SUSPEND);
639291f263c14 (Shuah Khan             2014-02-10 09:12:27 -0700 277) }
639291f263c14 (Shuah Khan             2014-02-10 09:12:27 -0700 278) 
639291f263c14 (Shuah Khan             2014-02-10 09:12:27 -0700 279) static int adb_freeze(struct device *dev)
639291f263c14 (Shuah Khan             2014-02-10 09:12:27 -0700 280) {
639291f263c14 (Shuah Khan             2014-02-10 09:12:27 -0700 281) 	return __adb_suspend(to_platform_device(dev), PMSG_FREEZE);
639291f263c14 (Shuah Khan             2014-02-10 09:12:27 -0700 282) }
639291f263c14 (Shuah Khan             2014-02-10 09:12:27 -0700 283) 
639291f263c14 (Shuah Khan             2014-02-10 09:12:27 -0700 284) static int adb_poweroff(struct device *dev)
639291f263c14 (Shuah Khan             2014-02-10 09:12:27 -0700 285) {
639291f263c14 (Shuah Khan             2014-02-10 09:12:27 -0700 286) 	return __adb_suspend(to_platform_device(dev), PMSG_HIBERNATE);
639291f263c14 (Shuah Khan             2014-02-10 09:12:27 -0700 287) }
639291f263c14 (Shuah Khan             2014-02-10 09:12:27 -0700 288) 
c9f6d3d5c6d4f (Johannes Berg          2007-12-12 01:21:25 +1100 289) /*
c9f6d3d5c6d4f (Johannes Berg          2007-12-12 01:21:25 +1100 290)  * reset bus after sleep
c9f6d3d5c6d4f (Johannes Berg          2007-12-12 01:21:25 +1100 291)  */
639291f263c14 (Shuah Khan             2014-02-10 09:12:27 -0700 292) static int __adb_resume(struct platform_device *dev)
c9f6d3d5c6d4f (Johannes Berg          2007-12-12 01:21:25 +1100 293) {
c9f6d3d5c6d4f (Johannes Berg          2007-12-12 01:21:25 +1100 294) 	adb_got_sleep = 0;
c9f6d3d5c6d4f (Johannes Berg          2007-12-12 01:21:25 +1100 295) 	up(&adb_probe_mutex);
c9f6d3d5c6d4f (Johannes Berg          2007-12-12 01:21:25 +1100 296) 	adb_reset_bus();
c9f6d3d5c6d4f (Johannes Berg          2007-12-12 01:21:25 +1100 297) 
c9f6d3d5c6d4f (Johannes Berg          2007-12-12 01:21:25 +1100 298) 	return 0;
c9f6d3d5c6d4f (Johannes Berg          2007-12-12 01:21:25 +1100 299) }
639291f263c14 (Shuah Khan             2014-02-10 09:12:27 -0700 300) 
639291f263c14 (Shuah Khan             2014-02-10 09:12:27 -0700 301) static int adb_resume(struct device *dev)
639291f263c14 (Shuah Khan             2014-02-10 09:12:27 -0700 302) {
639291f263c14 (Shuah Khan             2014-02-10 09:12:27 -0700 303) 	return __adb_resume(to_platform_device(dev));
639291f263c14 (Shuah Khan             2014-02-10 09:12:27 -0700 304) }
c9f6d3d5c6d4f (Johannes Berg          2007-12-12 01:21:25 +1100 305) #endif /* CONFIG_PM */
c9f6d3d5c6d4f (Johannes Berg          2007-12-12 01:21:25 +1100 306) 
9b4a8dd2e9f8a (Adrian Bunk            2008-06-24 03:46:57 +1000 307) static int __init adb_init(void)
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 308) {
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 309) 	struct adb_driver *driver;
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 310) 	int i;
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 311) 
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 312) #ifdef CONFIG_PPC32
e8222502ee615 (Benjamin Herrenschmidt 2006-03-28 23:15:54 +1100 313) 	if (!machine_is(chrp) && !machine_is(powermac))
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 314) 		return 0;
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 315) #endif
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 316) #ifdef CONFIG_MAC
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 317) 	if (!MACH_IS_MAC)
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 318) 		return 0;
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 319) #endif
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 320) 
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 321) 	/* xmon may do early-init */
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 322) 	if (adb_inited)
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 323) 		return 0;
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 324) 	adb_inited = 1;
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 325) 		
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 326) 	adb_controller = NULL;
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 327) 
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 328) 	i = 0;
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 329) 	while ((driver = adb_driver_list[i++]) != NULL) {
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 330) 		if (!driver->probe()) {
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 331) 			adb_controller = driver;
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 332) 			break;
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 333) 		}
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 334) 	}
18814ee846357 (Finn Thain             2009-11-17 20:03:05 +1100 335) 	if (adb_controller != NULL && adb_controller->init &&
18814ee846357 (Finn Thain             2009-11-17 20:03:05 +1100 336) 	    adb_controller->init())
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 337) 		adb_controller = NULL;
18814ee846357 (Finn Thain             2009-11-17 20:03:05 +1100 338) 	if (adb_controller == NULL) {
f2be6295684b0 (Andreas Schwab         2016-11-28 21:29:07 +0100 339) 		pr_warn("Warning: no ADB interface detected\n");
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 340) 	} else {
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 341) #ifdef CONFIG_PPC
71a157e8edca5 (Grant Likely           2010-02-01 21:34:14 -0700 342) 		if (of_machine_is_compatible("AAPL,PowerBook1998") ||
71a157e8edca5 (Grant Likely           2010-02-01 21:34:14 -0700 343) 			of_machine_is_compatible("PowerBook1,1"))
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 344) 			sleepy_trackpad = 1;
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 345) #endif /* CONFIG_PPC */
c9f6d3d5c6d4f (Johannes Berg          2007-12-12 01:21:25 +1100 346) 
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 347) 		adbdev_init();
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 348) 		adb_reset_bus();
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 349) 	}
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 350) 	return 0;
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 351) }
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 352) 
faa5b9daa8bd8 (Robert P. J. Day       2008-05-15 09:12:53 +1000 353) device_initcall(adb_init);
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 354) 
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 355) static int
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 356) do_adb_reset_bus(void)
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 357) {
70b52b3869a31 (Johannes Berg          2007-03-19 11:53:55 +0100 358) 	int ret;
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 359) 	
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 360) 	if (adb_controller == NULL)
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 361) 		return -ENXIO;
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 362) 		
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 363) 	if (adb_controller->autopoll)
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 364) 		adb_controller->autopoll(0);
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 365) 
70b52b3869a31 (Johannes Berg          2007-03-19 11:53:55 +0100 366) 	blocking_notifier_call_chain(&adb_client_list,
70b52b3869a31 (Johannes Berg          2007-03-19 11:53:55 +0100 367) 		ADB_MSG_PRE_RESET, NULL);
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 368) 
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 369) 	if (sleepy_trackpad) {
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 370) 		/* Let the trackpad settle down */
c61dace9a10a4 (Paul Mackerras         2007-12-13 15:11:22 +1100 371) 		msleep(500);
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 372) 	}
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 373) 
af3ce514ade2f (Daniel Walker          2008-05-03 06:34:03 +1000 374) 	mutex_lock(&adb_handler_mutex);
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 375) 	write_lock_irq(&adb_handler_lock);
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 376) 	memset(adb_handler, 0, sizeof(adb_handler));
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 377) 	write_unlock_irq(&adb_handler_lock);
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 378) 
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 379) 	/* That one is still a bit synchronous, oh well... */
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 380) 	if (adb_controller->reset_bus)
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 381) 		ret = adb_controller->reset_bus();
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 382) 	else
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 383) 		ret = 0;
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 384) 
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 385) 	if (sleepy_trackpad) {
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 386) 		/* Let the trackpad settle down */
c61dace9a10a4 (Paul Mackerras         2007-12-13 15:11:22 +1100 387) 		msleep(1500);
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 388) 	}
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 389) 
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 390) 	if (!ret) {
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 391) 		autopoll_devs = adb_scan_bus();
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 392) 		if (adb_controller->autopoll)
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 393) 			adb_controller->autopoll(autopoll_devs);
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 394) 	}
af3ce514ade2f (Daniel Walker          2008-05-03 06:34:03 +1000 395) 	mutex_unlock(&adb_handler_mutex);
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 396) 
70b52b3869a31 (Johannes Berg          2007-03-19 11:53:55 +0100 397) 	blocking_notifier_call_chain(&adb_client_list,
70b52b3869a31 (Johannes Berg          2007-03-19 11:53:55 +0100 398) 		ADB_MSG_POST_RESET, NULL);
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 399) 	
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 400) 	return ret;
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 401) }
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 402) 
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 403) void
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 404) adb_poll(void)
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 405) {
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 406) 	if ((adb_controller == NULL)||(adb_controller->poll == NULL))
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 407) 		return;
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 408) 	adb_controller->poll();
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 409) }
370a3abdbba85 (Anton Blanchard        2014-08-20 08:00:00 +1000 410) EXPORT_SYMBOL(adb_poll);
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 411) 
c61dace9a10a4 (Paul Mackerras         2007-12-13 15:11:22 +1100 412) static void adb_sync_req_done(struct adb_request *req)
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 413) {
c61dace9a10a4 (Paul Mackerras         2007-12-13 15:11:22 +1100 414) 	struct completion *comp = req->arg;
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 415) 
c61dace9a10a4 (Paul Mackerras         2007-12-13 15:11:22 +1100 416) 	complete(comp);
c61dace9a10a4 (Paul Mackerras         2007-12-13 15:11:22 +1100 417) }
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 418) 
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 419) int
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 420) adb_request(struct adb_request *req, void (*done)(struct adb_request *),
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 421) 	    int flags, int nbytes, ...)
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 422) {
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 423) 	va_list list;
c61dace9a10a4 (Paul Mackerras         2007-12-13 15:11:22 +1100 424) 	int i;
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 425) 	int rc;
c61dace9a10a4 (Paul Mackerras         2007-12-13 15:11:22 +1100 426) 	struct completion comp;
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 427) 
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 428) 	if ((adb_controller == NULL) || (adb_controller->send_request == NULL))
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 429) 		return -ENXIO;
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 430) 	if (nbytes < 1)
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 431) 		return -EINVAL;
c61dace9a10a4 (Paul Mackerras         2007-12-13 15:11:22 +1100 432) 
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 433) 	req->nbytes = nbytes+1;
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 434) 	req->done = done;
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 435) 	req->reply_expected = flags & ADBREQ_REPLY;
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 436) 	req->data[0] = ADB_PACKET;
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 437) 	va_start(list, nbytes);
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 438) 	for (i = 0; i < nbytes; ++i)
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 439) 		req->data[i+1] = va_arg(list, int);
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 440) 	va_end(list);
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 441) 
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 442) 	if (flags & ADBREQ_NOSEND)
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 443) 		return 0;
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 444) 
c61dace9a10a4 (Paul Mackerras         2007-12-13 15:11:22 +1100 445) 	/* Synchronous requests block using an on-stack completion */
c61dace9a10a4 (Paul Mackerras         2007-12-13 15:11:22 +1100 446) 	if (flags & ADBREQ_SYNC) {
c61dace9a10a4 (Paul Mackerras         2007-12-13 15:11:22 +1100 447) 		WARN_ON(done);
c61dace9a10a4 (Paul Mackerras         2007-12-13 15:11:22 +1100 448) 		req->done = adb_sync_req_done;
c61dace9a10a4 (Paul Mackerras         2007-12-13 15:11:22 +1100 449) 		req->arg = &comp;
c61dace9a10a4 (Paul Mackerras         2007-12-13 15:11:22 +1100 450) 		init_completion(&comp);
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 451) 	}
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 452) 
c61dace9a10a4 (Paul Mackerras         2007-12-13 15:11:22 +1100 453) 	rc = adb_controller->send_request(req, 0);
c61dace9a10a4 (Paul Mackerras         2007-12-13 15:11:22 +1100 454) 
c61dace9a10a4 (Paul Mackerras         2007-12-13 15:11:22 +1100 455) 	if ((flags & ADBREQ_SYNC) && !rc && !req->complete)
c61dace9a10a4 (Paul Mackerras         2007-12-13 15:11:22 +1100 456) 		wait_for_completion(&comp);
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 457) 
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 458) 	return rc;
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 459) }
370a3abdbba85 (Anton Blanchard        2014-08-20 08:00:00 +1000 460) EXPORT_SYMBOL(adb_request);
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 461) 
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 462)  /* Ultimately this should return the number of devices with
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 463)     the given default id.
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 464)     And it does it now ! Note: changed behaviour: This function
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 465)     will now register if default_id _and_ handler_id both match
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 466)     but handler_id can be left to 0 to match with default_id only.
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 467)     When handler_id is set, this function will try to adjust
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 468)     the handler_id id it doesn't match. */
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 469) int
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 470) adb_register(int default_id, int handler_id, struct adb_ids *ids,
7d12e780e003f (David Howells          2006-10-05 14:55:46 +0100 471) 	     void (*handler)(unsigned char *, int, int))
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 472) {
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 473) 	int i;
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 474) 
af3ce514ade2f (Daniel Walker          2008-05-03 06:34:03 +1000 475) 	mutex_lock(&adb_handler_mutex);
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 476) 	ids->nids = 0;
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 477) 	for (i = 1; i < 16; i++) {
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 478) 		if ((adb_handler[i].original_address == default_id) &&
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 479) 		    (!handler_id || (handler_id == adb_handler[i].handler_id) || 
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 480) 		    try_handler_change(i, handler_id))) {
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 481) 			if (adb_handler[i].handler != 0) {
f2be6295684b0 (Andreas Schwab         2016-11-28 21:29:07 +0100 482) 				pr_err("Two handlers for ADB device %d\n",
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 483) 				       default_id);
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 484) 				continue;
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 485) 			}
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 486) 			write_lock_irq(&adb_handler_lock);
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 487) 			adb_handler[i].handler = handler;
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 488) 			write_unlock_irq(&adb_handler_lock);
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 489) 			ids->id[ids->nids++] = i;
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 490) 		}
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 491) 	}
af3ce514ade2f (Daniel Walker          2008-05-03 06:34:03 +1000 492) 	mutex_unlock(&adb_handler_mutex);
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 493) 	return ids->nids;
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 494) }
370a3abdbba85 (Anton Blanchard        2014-08-20 08:00:00 +1000 495) EXPORT_SYMBOL(adb_register);
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 496) 
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 497) int
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 498) adb_unregister(int index)
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 499) {
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 500) 	int ret = -ENODEV;
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 501) 
af3ce514ade2f (Daniel Walker          2008-05-03 06:34:03 +1000 502) 	mutex_lock(&adb_handler_mutex);
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 503) 	write_lock_irq(&adb_handler_lock);
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 504) 	if (adb_handler[index].handler) {
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 505) 		while(adb_handler[index].busy) {
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 506) 			write_unlock_irq(&adb_handler_lock);
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 507) 			yield();
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 508) 			write_lock_irq(&adb_handler_lock);
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 509) 		}
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 510) 		ret = 0;
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 511) 		adb_handler[index].handler = NULL;
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 512) 	}
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 513) 	write_unlock_irq(&adb_handler_lock);
af3ce514ade2f (Daniel Walker          2008-05-03 06:34:03 +1000 514) 	mutex_unlock(&adb_handler_mutex);
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 515) 	return ret;
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 516) }
370a3abdbba85 (Anton Blanchard        2014-08-20 08:00:00 +1000 517) EXPORT_SYMBOL(adb_unregister);
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 518) 
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 519) void
7d12e780e003f (David Howells          2006-10-05 14:55:46 +0100 520) adb_input(unsigned char *buf, int nb, int autopoll)
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 521) {
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 522) 	int i, id;
74e7cd432c3d1 (Brandon Stewart        2014-01-27 19:43:17 -0600 523) 	static int dump_adb_input;
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 524) 	unsigned long flags;
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 525) 	
7d12e780e003f (David Howells          2006-10-05 14:55:46 +0100 526) 	void (*handler)(unsigned char *, int, int);
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 527) 
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 528) 	/* We skip keystrokes and mouse moves when the sleep process
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 529) 	 * has been started. We stop autopoll, but this is another security
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 530) 	 */
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 531) 	if (adb_got_sleep)
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 532) 		return;
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 533) 		
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 534) 	id = buf[0] >> 4;
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 535) 	if (dump_adb_input) {
f2be6295684b0 (Andreas Schwab         2016-11-28 21:29:07 +0100 536) 		pr_info("adb packet: ");
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 537) 		for (i = 0; i < nb; ++i)
f2be6295684b0 (Andreas Schwab         2016-11-28 21:29:07 +0100 538) 			pr_cont(" %x", buf[i]);
f2be6295684b0 (Andreas Schwab         2016-11-28 21:29:07 +0100 539) 		pr_cont(", id = %d\n", id);
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 540) 	}
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 541) 	write_lock_irqsave(&adb_handler_lock, flags);
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 542) 	handler = adb_handler[id].handler;
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 543) 	if (handler != NULL)
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 544) 		adb_handler[id].busy = 1;
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 545) 	write_unlock_irqrestore(&adb_handler_lock, flags);
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 546) 	if (handler != NULL) {
7d12e780e003f (David Howells          2006-10-05 14:55:46 +0100 547) 		(*handler)(buf, nb, autopoll);
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 548) 		wmb();
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 549) 		adb_handler[id].busy = 0;
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 550) 	}
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 551) 		
^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) /* Try to change handler to new_id. Will return 1 if successful. */
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 555) static int try_handler_change(int address, int new_id)
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 556) {
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 557) 	struct adb_request req;
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 558) 
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 559) 	if (adb_handler[address].handler_id == new_id)
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 560) 	    return 1;
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 561) 	adb_request(&req, NULL, ADBREQ_SYNC, 3,
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 562) 	    ADB_WRITEREG(address, 3), address | 0x20, new_id);
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 563) 	adb_request(&req, NULL, ADBREQ_SYNC | ADBREQ_REPLY, 1,
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 564) 	    ADB_READREG(address, 3));
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 565) 	if (req.reply_len < 2)
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 566) 	    return 0;
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 567) 	if (req.reply[2] != new_id)
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 568) 	    return 0;
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 569) 	adb_handler[address].handler_id = req.reply[2];
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 570) 
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 571) 	return 1;
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 572) }
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 573) 
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 574) int
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 575) adb_try_handler_change(int address, int new_id)
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 576) {
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 577) 	int ret;
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 578) 
af3ce514ade2f (Daniel Walker          2008-05-03 06:34:03 +1000 579) 	mutex_lock(&adb_handler_mutex);
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 580) 	ret = try_handler_change(address, new_id);
af3ce514ade2f (Daniel Walker          2008-05-03 06:34:03 +1000 581) 	mutex_unlock(&adb_handler_mutex);
2341629eadc4a (Finn Thain             2018-09-11 20:18:44 -0400 582) 	if (ret)
2341629eadc4a (Finn Thain             2018-09-11 20:18:44 -0400 583) 		pr_debug("adb handler change: [%d] 0x%X\n", address, new_id);
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 584) 	return ret;
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 585) }
370a3abdbba85 (Anton Blanchard        2014-08-20 08:00:00 +1000 586) EXPORT_SYMBOL(adb_try_handler_change);
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 587) 
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 588) int
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 589) adb_get_infos(int address, int *original_address, int *handler_id)
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 590) {
af3ce514ade2f (Daniel Walker          2008-05-03 06:34:03 +1000 591) 	mutex_lock(&adb_handler_mutex);
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 592) 	*original_address = adb_handler[address].original_address;
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 593) 	*handler_id = adb_handler[address].handler_id;
af3ce514ade2f (Daniel Walker          2008-05-03 06:34:03 +1000 594) 	mutex_unlock(&adb_handler_mutex);
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 595) 
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 596) 	return (*original_address != 0);
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 597) }
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 598) 
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 599) 
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 600) /*
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 601)  * /dev/adb device driver.
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 602)  */
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 603) 
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 604) #define ADB_MAJOR	56	/* major number for /dev/adb */
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 605) 
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 606) struct adbdev_state {
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 607) 	spinlock_t	lock;
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 608) 	atomic_t	n_pending;
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 609) 	struct adb_request *completed;
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 610)   	wait_queue_head_t wait_queue;
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 611) 	int		inuse;
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 612) };
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 613) 
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 614) static void adb_write_done(struct adb_request *req)
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 615) {
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 616) 	struct adbdev_state *state = (struct adbdev_state *) req->arg;
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 617) 	unsigned long flags;
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 618) 
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 619) 	if (!req->complete) {
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 620) 		req->reply_len = 0;
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 621) 		req->complete = 1;
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 622) 	}
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 623) 	spin_lock_irqsave(&state->lock, flags);
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 624) 	atomic_dec(&state->n_pending);
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 625) 	if (!state->inuse) {
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 626) 		kfree(req);
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 627) 		if (atomic_read(&state->n_pending) == 0) {
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 628) 			spin_unlock_irqrestore(&state->lock, flags);
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 629) 			kfree(state);
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 630) 			return;
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 631) 		}
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 632) 	} else {
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 633) 		struct adb_request **ap = &state->completed;
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 634) 		while (*ap != NULL)
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 635) 			ap = &(*ap)->next;
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 636) 		req->next = NULL;
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 637) 		*ap = req;
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 638) 		wake_up_interruptible(&state->wait_queue);
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 639) 	}
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 640) 	spin_unlock_irqrestore(&state->lock, flags);
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 641) }
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 642) 
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 643) static int
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 644) do_adb_query(struct adb_request *req)
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 645) {
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 646) 	int	ret = -EINVAL;
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 647) 
74e7cd432c3d1 (Brandon Stewart        2014-01-27 19:43:17 -0600 648) 	switch(req->data[1]) {
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 649) 	case ADB_QUERY_GETDEVINFO:
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 650) 		if (req->nbytes < 3)
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 651) 			break;
af3ce514ade2f (Daniel Walker          2008-05-03 06:34:03 +1000 652) 		mutex_lock(&adb_handler_mutex);
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 653) 		req->reply[0] = adb_handler[req->data[2]].original_address;
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 654) 		req->reply[1] = adb_handler[req->data[2]].handler_id;
af3ce514ade2f (Daniel Walker          2008-05-03 06:34:03 +1000 655) 		mutex_unlock(&adb_handler_mutex);
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 656) 		req->complete = 1;
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 657) 		req->reply_len = 2;
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 658) 		adb_write_done(req);
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 659) 		ret = 0;
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 660) 		break;
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 661) 	}
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 662) 	return ret;
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 663) }
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 664) 
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 665) static int adb_open(struct inode *inode, struct file *file)
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 666) {
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 667) 	struct adbdev_state *state;
26ce4f0684ef4 (Jonathan Corbet        2008-05-16 14:19:56 -0600 668) 	int ret = 0;
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 669) 
d851b6e04ee97 (Arnd Bergmann          2010-06-02 14:28:52 +0200 670) 	mutex_lock(&adb_mutex);
26ce4f0684ef4 (Jonathan Corbet        2008-05-16 14:19:56 -0600 671) 	if (iminor(inode) > 0 || adb_controller == NULL) {
26ce4f0684ef4 (Jonathan Corbet        2008-05-16 14:19:56 -0600 672) 		ret = -ENXIO;
26ce4f0684ef4 (Jonathan Corbet        2008-05-16 14:19:56 -0600 673) 		goto out;
26ce4f0684ef4 (Jonathan Corbet        2008-05-16 14:19:56 -0600 674) 	}
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 675) 	state = kmalloc(sizeof(struct adbdev_state), GFP_KERNEL);
26ce4f0684ef4 (Jonathan Corbet        2008-05-16 14:19:56 -0600 676) 	if (state == 0) {
26ce4f0684ef4 (Jonathan Corbet        2008-05-16 14:19:56 -0600 677) 		ret = -ENOMEM;
26ce4f0684ef4 (Jonathan Corbet        2008-05-16 14:19:56 -0600 678) 		goto out;
26ce4f0684ef4 (Jonathan Corbet        2008-05-16 14:19:56 -0600 679) 	}
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 680) 	file->private_data = state;
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 681) 	spin_lock_init(&state->lock);
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 682) 	atomic_set(&state->n_pending, 0);
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 683) 	state->completed = NULL;
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 684) 	init_waitqueue_head(&state->wait_queue);
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 685) 	state->inuse = 1;
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 686) 
26ce4f0684ef4 (Jonathan Corbet        2008-05-16 14:19:56 -0600 687) out:
d851b6e04ee97 (Arnd Bergmann          2010-06-02 14:28:52 +0200 688) 	mutex_unlock(&adb_mutex);
26ce4f0684ef4 (Jonathan Corbet        2008-05-16 14:19:56 -0600 689) 	return ret;
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 690) }
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 691) 
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 692) static int adb_release(struct inode *inode, struct file *file)
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 693) {
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 694) 	struct adbdev_state *state = file->private_data;
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 695) 	unsigned long flags;
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 696) 
d851b6e04ee97 (Arnd Bergmann          2010-06-02 14:28:52 +0200 697) 	mutex_lock(&adb_mutex);
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 698) 	if (state) {
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 699) 		file->private_data = NULL;
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 700) 		spin_lock_irqsave(&state->lock, flags);
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 701) 		if (atomic_read(&state->n_pending) == 0
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 702) 		    && state->completed == NULL) {
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 703) 			spin_unlock_irqrestore(&state->lock, flags);
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 704) 			kfree(state);
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 705) 		} else {
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 706) 			state->inuse = 0;
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 707) 			spin_unlock_irqrestore(&state->lock, flags);
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 708) 		}
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 709) 	}
d851b6e04ee97 (Arnd Bergmann          2010-06-02 14:28:52 +0200 710) 	mutex_unlock(&adb_mutex);
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 711) 	return 0;
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 712) }
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 713) 
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 714) static ssize_t adb_read(struct file *file, char __user *buf,
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 715) 			size_t count, loff_t *ppos)
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 716) {
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 717) 	int ret = 0;
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 718) 	struct adbdev_state *state = file->private_data;
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 719) 	struct adb_request *req;
74e7cd432c3d1 (Brandon Stewart        2014-01-27 19:43:17 -0600 720) 	DECLARE_WAITQUEUE(wait, current);
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 721) 	unsigned long flags;
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 722) 
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 723) 	if (count < 2)
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 724) 		return -EINVAL;
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 725) 	if (count > sizeof(req->reply))
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 726) 		count = sizeof(req->reply);
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 727) 
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 728) 	req = NULL;
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 729) 	spin_lock_irqsave(&state->lock, flags);
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 730) 	add_wait_queue(&state->wait_queue, &wait);
64f8c13561fbd (majianpeng             2012-02-03 14:35:59 +0000 731) 	set_current_state(TASK_INTERRUPTIBLE);
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 732) 
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 733) 	for (;;) {
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 734) 		req = state->completed;
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 735) 		if (req != NULL)
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 736) 			state->completed = req->next;
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 737) 		else if (atomic_read(&state->n_pending) == 0)
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 738) 			ret = -EIO;
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 739) 		if (req != NULL || ret != 0)
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 740) 			break;
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 741) 		
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 742) 		if (file->f_flags & O_NONBLOCK) {
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 743) 			ret = -EAGAIN;
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 744) 			break;
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 745) 		}
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 746) 		if (signal_pending(current)) {
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 747) 			ret = -ERESTARTSYS;
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 748) 			break;
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 749) 		}
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 750) 		spin_unlock_irqrestore(&state->lock, flags);
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 751) 		schedule();
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 752) 		spin_lock_irqsave(&state->lock, flags);
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 753) 	}
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 754) 
64f8c13561fbd (majianpeng             2012-02-03 14:35:59 +0000 755) 	set_current_state(TASK_RUNNING);
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 756) 	remove_wait_queue(&state->wait_queue, &wait);
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 757) 	spin_unlock_irqrestore(&state->lock, flags);
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 758) 	
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 759) 	if (ret)
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 760) 		return ret;
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 761) 
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 762) 	ret = req->reply_len;
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 763) 	if (ret > count)
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 764) 		ret = count;
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 765) 	if (ret > 0 && copy_to_user(buf, req->reply, ret))
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 766) 		ret = -EFAULT;
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 767) 
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 768) 	kfree(req);
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 769) 	return ret;
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 770) }
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 771) 
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 772) static ssize_t adb_write(struct file *file, const char __user *buf,
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 773) 			 size_t count, loff_t *ppos)
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 774) {
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 775) 	int ret/*, i*/;
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 776) 	struct adbdev_state *state = file->private_data;
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 777) 	struct adb_request *req;
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 778) 
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 779) 	if (count < 2 || count > sizeof(req->data))
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 780) 		return -EINVAL;
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 781) 	if (adb_controller == NULL)
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 782) 		return -ENXIO;
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 783) 
5cbded585d129 (Robert P. J. Day       2006-12-13 00:35:56 -0800 784) 	req = kmalloc(sizeof(struct adb_request),
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 785) 					     GFP_KERNEL);
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 786) 	if (req == NULL)
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 787) 		return -ENOMEM;
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 788) 
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 789) 	req->nbytes = count;
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 790) 	req->done = adb_write_done;
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 791) 	req->arg = (void *) state;
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 792) 	req->complete = 0;
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 793) 	
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 794) 	ret = -EFAULT;
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 795) 	if (copy_from_user(req->data, buf, count))
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 796) 		goto out;
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 797) 
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 798) 	atomic_inc(&state->n_pending);
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 799) 
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 800) 	/* If a probe is in progress or we are sleeping, wait for it to complete */
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 801) 	down(&adb_probe_mutex);
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 802) 
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 803) 	/* Queries are special requests sent to the ADB driver itself */
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 804) 	if (req->data[0] == ADB_QUERY) {
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 805) 		if (count > 1)
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 806) 			ret = do_adb_query(req);
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 807) 		else
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 808) 			ret = -EINVAL;
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 809) 		up(&adb_probe_mutex);
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 810) 	}
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 811) 	/* Special case for ADB_BUSRESET request, all others are sent to
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 812) 	   the controller */
74e7cd432c3d1 (Brandon Stewart        2014-01-27 19:43:17 -0600 813) 	else if ((req->data[0] == ADB_PACKET) && (count > 1)
74e7cd432c3d1 (Brandon Stewart        2014-01-27 19:43:17 -0600 814) 		&& (req->data[1] == ADB_BUSRESET)) {
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 815) 		ret = do_adb_reset_bus();
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 816) 		up(&adb_probe_mutex);
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 817) 		atomic_dec(&state->n_pending);
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 818) 		if (ret == 0)
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 819) 			ret = count;
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 820) 		goto out;
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 821) 	} else {	
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 822) 		req->reply_expected = ((req->data[1] & 0xc) == 0xc);
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 823) 		if (adb_controller && adb_controller->send_request)
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 824) 			ret = adb_controller->send_request(req, 0);
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 825) 		else
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 826) 			ret = -ENXIO;
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 827) 		up(&adb_probe_mutex);
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 828) 	}
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 829) 
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 830) 	if (ret != 0) {
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 831) 		atomic_dec(&state->n_pending);
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 832) 		goto out;
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 833) 	}
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 834) 	return count;
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 835) 
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 836) out:
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 837) 	kfree(req);
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 838) 	return ret;
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 839) }
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 840) 
fa027c2a0a0d6 (Arjan van de Ven       2007-02-12 00:55:33 -0800 841) static const struct file_operations adb_fops = {
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 842) 	.owner		= THIS_MODULE,
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 843) 	.llseek		= no_llseek,
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 844) 	.read		= adb_read,
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 845) 	.write		= adb_write,
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 846) 	.open		= adb_open,
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 847) 	.release	= adb_release,
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 848) };
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 849) 
639291f263c14 (Shuah Khan             2014-02-10 09:12:27 -0700 850) #ifdef CONFIG_PM
639291f263c14 (Shuah Khan             2014-02-10 09:12:27 -0700 851) static const struct dev_pm_ops adb_dev_pm_ops = {
639291f263c14 (Shuah Khan             2014-02-10 09:12:27 -0700 852) 	.suspend = adb_suspend,
639291f263c14 (Shuah Khan             2014-02-10 09:12:27 -0700 853) 	.resume = adb_resume,
639291f263c14 (Shuah Khan             2014-02-10 09:12:27 -0700 854) 	/* Hibernate hooks */
639291f263c14 (Shuah Khan             2014-02-10 09:12:27 -0700 855) 	.freeze = adb_freeze,
639291f263c14 (Shuah Khan             2014-02-10 09:12:27 -0700 856) 	.thaw = adb_resume,
639291f263c14 (Shuah Khan             2014-02-10 09:12:27 -0700 857) 	.poweroff = adb_poweroff,
639291f263c14 (Shuah Khan             2014-02-10 09:12:27 -0700 858) 	.restore = adb_resume,
639291f263c14 (Shuah Khan             2014-02-10 09:12:27 -0700 859) };
639291f263c14 (Shuah Khan             2014-02-10 09:12:27 -0700 860) #endif
639291f263c14 (Shuah Khan             2014-02-10 09:12:27 -0700 861) 
c9f6d3d5c6d4f (Johannes Berg          2007-12-12 01:21:25 +1100 862) static struct platform_driver adb_pfdrv = {
c9f6d3d5c6d4f (Johannes Berg          2007-12-12 01:21:25 +1100 863) 	.driver = {
c9f6d3d5c6d4f (Johannes Berg          2007-12-12 01:21:25 +1100 864) 		.name = "adb",
c9f6d3d5c6d4f (Johannes Berg          2007-12-12 01:21:25 +1100 865) #ifdef CONFIG_PM
639291f263c14 (Shuah Khan             2014-02-10 09:12:27 -0700 866) 		.pm = &adb_dev_pm_ops,
c9f6d3d5c6d4f (Johannes Berg          2007-12-12 01:21:25 +1100 867) #endif
639291f263c14 (Shuah Khan             2014-02-10 09:12:27 -0700 868) 	},
c9f6d3d5c6d4f (Johannes Berg          2007-12-12 01:21:25 +1100 869) };
c9f6d3d5c6d4f (Johannes Berg          2007-12-12 01:21:25 +1100 870) 
c9f6d3d5c6d4f (Johannes Berg          2007-12-12 01:21:25 +1100 871) static struct platform_device adb_pfdev = {
c9f6d3d5c6d4f (Johannes Berg          2007-12-12 01:21:25 +1100 872) 	.name = "adb",
c9f6d3d5c6d4f (Johannes Berg          2007-12-12 01:21:25 +1100 873) };
c9f6d3d5c6d4f (Johannes Berg          2007-12-12 01:21:25 +1100 874) 
c9f6d3d5c6d4f (Johannes Berg          2007-12-12 01:21:25 +1100 875) static int __init
c9f6d3d5c6d4f (Johannes Berg          2007-12-12 01:21:25 +1100 876) adb_dummy_probe(struct platform_device *dev)
c9f6d3d5c6d4f (Johannes Berg          2007-12-12 01:21:25 +1100 877) {
c9f6d3d5c6d4f (Johannes Berg          2007-12-12 01:21:25 +1100 878) 	if (dev == &adb_pfdev)
c9f6d3d5c6d4f (Johannes Berg          2007-12-12 01:21:25 +1100 879) 		return 0;
c9f6d3d5c6d4f (Johannes Berg          2007-12-12 01:21:25 +1100 880) 	return -ENODEV;
c9f6d3d5c6d4f (Johannes Berg          2007-12-12 01:21:25 +1100 881) }
c9f6d3d5c6d4f (Johannes Berg          2007-12-12 01:21:25 +1100 882) 
c9f6d3d5c6d4f (Johannes Berg          2007-12-12 01:21:25 +1100 883) static void __init
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 884) adbdev_init(void)
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 885) {
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 886) 	if (register_chrdev(ADB_MAJOR, "adb", &adb_fops)) {
f2be6295684b0 (Andreas Schwab         2016-11-28 21:29:07 +0100 887) 		pr_err("adb: unable to get major %d\n", ADB_MAJOR);
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 888) 		return;
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 889) 	}
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 890) 
56b2293595b2e (Greg Kroah-Hartman     2005-03-23 10:01:41 -0800 891) 	adb_dev_class = class_create(THIS_MODULE, "adb");
56b2293595b2e (Greg Kroah-Hartman     2005-03-23 10:01:41 -0800 892) 	if (IS_ERR(adb_dev_class))
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 893) 		return;
a9b12619f7b6f (Greg Kroah-Hartman     2008-07-21 20:03:34 -0700 894) 	device_create(adb_dev_class, NULL, MKDEV(ADB_MAJOR, 0), NULL, "adb");
c9f6d3d5c6d4f (Johannes Berg          2007-12-12 01:21:25 +1100 895) 
c9f6d3d5c6d4f (Johannes Berg          2007-12-12 01:21:25 +1100 896) 	platform_device_register(&adb_pfdev);
c9f6d3d5c6d4f (Johannes Berg          2007-12-12 01:21:25 +1100 897) 	platform_driver_probe(&adb_pfdrv, adb_dummy_probe);
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 898) }