xref: /linux/drivers/platform/goldfish/goldfish_pipe.c (revision d62f324b0ac80c3923ebbf897735c7c24ba887b8)
1c89f2750SDavid 'Digit' Turner /*
2c89f2750SDavid 'Digit' Turner  * Copyright (C) 2011 Google, Inc.
3c89f2750SDavid 'Digit' Turner  * Copyright (C) 2012 Intel, Inc.
4c89f2750SDavid 'Digit' Turner  * Copyright (C) 2013 Intel, Inc.
52f3be882SChristoffer Dall  * Copyright (C) 2014 Linaro Limited
6c89f2750SDavid 'Digit' Turner  *
7c89f2750SDavid 'Digit' Turner  * This software is licensed under the terms of the GNU General Public
8c89f2750SDavid 'Digit' Turner  * License version 2, as published by the Free Software Foundation, and
9c89f2750SDavid 'Digit' Turner  * may be copied, distributed, and modified under those terms.
10c89f2750SDavid 'Digit' Turner  *
11c89f2750SDavid 'Digit' Turner  * This program is distributed in the hope that it will be useful,
12c89f2750SDavid 'Digit' Turner  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13c89f2750SDavid 'Digit' Turner  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14c89f2750SDavid 'Digit' Turner  * GNU General Public License for more details.
15c89f2750SDavid 'Digit' Turner  *
16c89f2750SDavid 'Digit' Turner  */
17c89f2750SDavid 'Digit' Turner 
18c89f2750SDavid 'Digit' Turner /* This source file contains the implementation of a special device driver
19c89f2750SDavid 'Digit' Turner  * that intends to provide a *very* fast communication channel between the
20c89f2750SDavid 'Digit' Turner  * guest system and the QEMU emulator.
21c89f2750SDavid 'Digit' Turner  *
22c89f2750SDavid 'Digit' Turner  * Usage from the guest is simply the following (error handling simplified):
23c89f2750SDavid 'Digit' Turner  *
24c89f2750SDavid 'Digit' Turner  *    int  fd = open("/dev/qemu_pipe",O_RDWR);
25c89f2750SDavid 'Digit' Turner  *    .... write() or read() through the pipe.
26c89f2750SDavid 'Digit' Turner  *
27c89f2750SDavid 'Digit' Turner  * This driver doesn't deal with the exact protocol used during the session.
28c89f2750SDavid 'Digit' Turner  * It is intended to be as simple as something like:
29c89f2750SDavid 'Digit' Turner  *
30c89f2750SDavid 'Digit' Turner  *    // do this _just_ after opening the fd to connect to a specific
31c89f2750SDavid 'Digit' Turner  *    // emulator service.
32c89f2750SDavid 'Digit' Turner  *    const char*  msg = "<pipename>";
33c89f2750SDavid 'Digit' Turner  *    if (write(fd, msg, strlen(msg)+1) < 0) {
34c89f2750SDavid 'Digit' Turner  *       ... could not connect to <pipename> service
35c89f2750SDavid 'Digit' Turner  *       close(fd);
36c89f2750SDavid 'Digit' Turner  *    }
37c89f2750SDavid 'Digit' Turner  *
38c89f2750SDavid 'Digit' Turner  *    // after this, simply read() and write() to communicate with the
39c89f2750SDavid 'Digit' Turner  *    // service. Exact protocol details left as an exercise to the reader.
40c89f2750SDavid 'Digit' Turner  *
41c89f2750SDavid 'Digit' Turner  * This driver is very fast because it doesn't copy any data through
42c89f2750SDavid 'Digit' Turner  * intermediate buffers, since the emulator is capable of translating
43c89f2750SDavid 'Digit' Turner  * guest user addresses into host ones.
44c89f2750SDavid 'Digit' Turner  *
45c89f2750SDavid 'Digit' Turner  * Note that we must however ensure that each user page involved in the
46c89f2750SDavid 'Digit' Turner  * exchange is properly mapped during a transfer.
47c89f2750SDavid 'Digit' Turner  */
48c89f2750SDavid 'Digit' Turner 
49c89f2750SDavid 'Digit' Turner #include <linux/module.h>
50c89f2750SDavid 'Digit' Turner #include <linux/interrupt.h>
51c89f2750SDavid 'Digit' Turner #include <linux/kernel.h>
52c89f2750SDavid 'Digit' Turner #include <linux/spinlock.h>
53c89f2750SDavid 'Digit' Turner #include <linux/miscdevice.h>
54c89f2750SDavid 'Digit' Turner #include <linux/platform_device.h>
55c89f2750SDavid 'Digit' Turner #include <linux/poll.h>
56c89f2750SDavid 'Digit' Turner #include <linux/sched.h>
57c89f2750SDavid 'Digit' Turner #include <linux/bitops.h>
58c89f2750SDavid 'Digit' Turner #include <linux/slab.h>
59c89f2750SDavid 'Digit' Turner #include <linux/io.h>
60a99698faSAlan #include <linux/goldfish.h>
612f3be882SChristoffer Dall #include <linux/mm.h>
62*d62f324bSJason Hu #include <linux/acpi.h>
63c89f2750SDavid 'Digit' Turner 
64c89f2750SDavid 'Digit' Turner /*
65c89f2750SDavid 'Digit' Turner  * IMPORTANT: The following constants must match the ones used and defined
66c89f2750SDavid 'Digit' Turner  * in external/qemu/hw/goldfish_pipe.c in the Android source tree.
67c89f2750SDavid 'Digit' Turner  */
68c89f2750SDavid 'Digit' Turner 
69c89f2750SDavid 'Digit' Turner /* pipe device registers */
70c89f2750SDavid 'Digit' Turner #define PIPE_REG_COMMAND		0x00  /* write: value = command */
71c89f2750SDavid 'Digit' Turner #define PIPE_REG_STATUS			0x04  /* read */
72c89f2750SDavid 'Digit' Turner #define PIPE_REG_CHANNEL		0x08  /* read/write: channel id */
7349a75c44SJun Tian #define PIPE_REG_CHANNEL_HIGH	        0x30  /* read/write: channel id */
74c89f2750SDavid 'Digit' Turner #define PIPE_REG_SIZE			0x0c  /* read/write: buffer size */
75c89f2750SDavid 'Digit' Turner #define PIPE_REG_ADDRESS		0x10  /* write: physical address */
7649a75c44SJun Tian #define PIPE_REG_ADDRESS_HIGH	        0x34  /* write: physical address */
77c89f2750SDavid 'Digit' Turner #define PIPE_REG_WAKES			0x14  /* read: wake flags */
78c89f2750SDavid 'Digit' Turner #define PIPE_REG_PARAMS_ADDR_LOW	0x18  /* read/write: batch data address */
79c89f2750SDavid 'Digit' Turner #define PIPE_REG_PARAMS_ADDR_HIGH	0x1c  /* read/write: batch data address */
80c89f2750SDavid 'Digit' Turner #define PIPE_REG_ACCESS_PARAMS		0x20  /* write: batch access */
814f42071cSYu Ning #define PIPE_REG_VERSION		0x24  /* read: device version */
82c89f2750SDavid 'Digit' Turner 
83c89f2750SDavid 'Digit' Turner /* list of commands for PIPE_REG_COMMAND */
84c89f2750SDavid 'Digit' Turner #define CMD_OPEN			1  /* open new channel */
85c89f2750SDavid 'Digit' Turner #define CMD_CLOSE			2  /* close channel (from guest) */
86c89f2750SDavid 'Digit' Turner #define CMD_POLL			3  /* poll read/write status */
87c89f2750SDavid 'Digit' Turner 
88c89f2750SDavid 'Digit' Turner /* List of bitflags returned in status of CMD_POLL command */
89c89f2750SDavid 'Digit' Turner #define PIPE_POLL_IN			(1 << 0)
90c89f2750SDavid 'Digit' Turner #define PIPE_POLL_OUT			(1 << 1)
91c89f2750SDavid 'Digit' Turner #define PIPE_POLL_HUP			(1 << 2)
92c89f2750SDavid 'Digit' Turner 
93c89f2750SDavid 'Digit' Turner /* The following commands are related to write operations */
94c89f2750SDavid 'Digit' Turner #define CMD_WRITE_BUFFER	4  /* send a user buffer to the emulator */
95c89f2750SDavid 'Digit' Turner #define CMD_WAKE_ON_WRITE	5  /* tell the emulator to wake us when writing
96c89f2750SDavid 'Digit' Turner 				     is possible */
97c89f2750SDavid 'Digit' Turner #define CMD_READ_BUFFER        6  /* receive a user buffer from the emulator */
98c89f2750SDavid 'Digit' Turner #define CMD_WAKE_ON_READ       7  /* tell the emulator to wake us when reading
99c89f2750SDavid 'Digit' Turner 				   * is possible */
100c89f2750SDavid 'Digit' Turner 
101c89f2750SDavid 'Digit' Turner /* Possible status values used to signal errors - see goldfish_pipe_error_convert */
102c89f2750SDavid 'Digit' Turner #define PIPE_ERROR_INVAL       -1
103c89f2750SDavid 'Digit' Turner #define PIPE_ERROR_AGAIN       -2
104c89f2750SDavid 'Digit' Turner #define PIPE_ERROR_NOMEM       -3
105c89f2750SDavid 'Digit' Turner #define PIPE_ERROR_IO          -4
106c89f2750SDavid 'Digit' Turner 
107c89f2750SDavid 'Digit' Turner /* Bit-flags used to signal events from the emulator */
108c89f2750SDavid 'Digit' Turner #define PIPE_WAKE_CLOSED       (1 << 0)  /* emulator closed pipe */
109c89f2750SDavid 'Digit' Turner #define PIPE_WAKE_READ         (1 << 1)  /* pipe can now be read from */
110c89f2750SDavid 'Digit' Turner #define PIPE_WAKE_WRITE        (1 << 2)  /* pipe can now be written to */
111c89f2750SDavid 'Digit' Turner 
112c89f2750SDavid 'Digit' Turner struct access_params {
11349a75c44SJun Tian 	unsigned long channel;
114c89f2750SDavid 'Digit' Turner 	u32 size;
11549a75c44SJun Tian 	unsigned long address;
116c89f2750SDavid 'Digit' Turner 	u32 cmd;
117c89f2750SDavid 'Digit' Turner 	u32 result;
118c89f2750SDavid 'Digit' Turner 	/* reserved for future extension */
119c89f2750SDavid 'Digit' Turner 	u32 flags;
120c89f2750SDavid 'Digit' Turner };
121c89f2750SDavid 'Digit' Turner 
122c89f2750SDavid 'Digit' Turner /* The global driver data. Holds a reference to the i/o page used to
123c89f2750SDavid 'Digit' Turner  * communicate with the emulator, and a wake queue for blocked tasks
124c89f2750SDavid 'Digit' Turner  * waiting to be awoken.
125c89f2750SDavid 'Digit' Turner  */
126c89f2750SDavid 'Digit' Turner struct goldfish_pipe_dev {
127c89f2750SDavid 'Digit' Turner 	spinlock_t lock;
128c89f2750SDavid 'Digit' Turner 	unsigned char __iomem *base;
129c89f2750SDavid 'Digit' Turner 	struct access_params *aps;
130c89f2750SDavid 'Digit' Turner 	int irq;
1314f42071cSYu Ning 	u32 version;
132c89f2750SDavid 'Digit' Turner };
133c89f2750SDavid 'Digit' Turner 
134c89f2750SDavid 'Digit' Turner static struct goldfish_pipe_dev   pipe_dev[1];
135c89f2750SDavid 'Digit' Turner 
136c89f2750SDavid 'Digit' Turner /* This data type models a given pipe instance */
137c89f2750SDavid 'Digit' Turner struct goldfish_pipe {
138c89f2750SDavid 'Digit' Turner 	struct goldfish_pipe_dev *dev;
139c89f2750SDavid 'Digit' Turner 	struct mutex lock;
140c89f2750SDavid 'Digit' Turner 	unsigned long flags;
141c89f2750SDavid 'Digit' Turner 	wait_queue_head_t wake_queue;
142c89f2750SDavid 'Digit' Turner };
143c89f2750SDavid 'Digit' Turner 
144c89f2750SDavid 'Digit' Turner 
145c89f2750SDavid 'Digit' Turner /* Bit flags for the 'flags' field */
146c89f2750SDavid 'Digit' Turner enum {
147c89f2750SDavid 'Digit' Turner 	BIT_CLOSED_ON_HOST = 0,  /* pipe closed by host */
148c89f2750SDavid 'Digit' Turner 	BIT_WAKE_ON_WRITE  = 1,  /* want to be woken on writes */
149c89f2750SDavid 'Digit' Turner 	BIT_WAKE_ON_READ   = 2,  /* want to be woken on reads */
150c89f2750SDavid 'Digit' Turner };
151c89f2750SDavid 'Digit' Turner 
152c89f2750SDavid 'Digit' Turner 
153c89f2750SDavid 'Digit' Turner static u32 goldfish_cmd_status(struct goldfish_pipe *pipe, u32 cmd)
154c89f2750SDavid 'Digit' Turner {
155c89f2750SDavid 'Digit' Turner 	unsigned long flags;
156c89f2750SDavid 'Digit' Turner 	u32 status;
157c89f2750SDavid 'Digit' Turner 	struct goldfish_pipe_dev *dev = pipe->dev;
158c89f2750SDavid 'Digit' Turner 
159c89f2750SDavid 'Digit' Turner 	spin_lock_irqsave(&dev->lock, flags);
16007d783fdSPeter Senna Tschudin 	gf_write_ptr(pipe, dev->base + PIPE_REG_CHANNEL,
161a99698faSAlan 		     dev->base + PIPE_REG_CHANNEL_HIGH);
162c89f2750SDavid 'Digit' Turner 	writel(cmd, dev->base + PIPE_REG_COMMAND);
163c89f2750SDavid 'Digit' Turner 	status = readl(dev->base + PIPE_REG_STATUS);
164c89f2750SDavid 'Digit' Turner 	spin_unlock_irqrestore(&dev->lock, flags);
165c89f2750SDavid 'Digit' Turner 	return status;
166c89f2750SDavid 'Digit' Turner }
167c89f2750SDavid 'Digit' Turner 
168c89f2750SDavid 'Digit' Turner static void goldfish_cmd(struct goldfish_pipe *pipe, u32 cmd)
169c89f2750SDavid 'Digit' Turner {
170c89f2750SDavid 'Digit' Turner 	unsigned long flags;
171c89f2750SDavid 'Digit' Turner 	struct goldfish_pipe_dev *dev = pipe->dev;
172c89f2750SDavid 'Digit' Turner 
173c89f2750SDavid 'Digit' Turner 	spin_lock_irqsave(&dev->lock, flags);
17407d783fdSPeter Senna Tschudin 	gf_write_ptr(pipe, dev->base + PIPE_REG_CHANNEL,
175a99698faSAlan 		     dev->base + PIPE_REG_CHANNEL_HIGH);
176c89f2750SDavid 'Digit' Turner 	writel(cmd, dev->base + PIPE_REG_COMMAND);
177c89f2750SDavid 'Digit' Turner 	spin_unlock_irqrestore(&dev->lock, flags);
178c89f2750SDavid 'Digit' Turner }
179c89f2750SDavid 'Digit' Turner 
180c89f2750SDavid 'Digit' Turner /* This function converts an error code returned by the emulator through
181c89f2750SDavid 'Digit' Turner  * the PIPE_REG_STATUS i/o register into a valid negative errno value.
182c89f2750SDavid 'Digit' Turner  */
183c89f2750SDavid 'Digit' Turner static int goldfish_pipe_error_convert(int status)
184c89f2750SDavid 'Digit' Turner {
185c89f2750SDavid 'Digit' Turner 	switch (status) {
186c89f2750SDavid 'Digit' Turner 	case PIPE_ERROR_AGAIN:
187c89f2750SDavid 'Digit' Turner 		return -EAGAIN;
188c89f2750SDavid 'Digit' Turner 	case PIPE_ERROR_NOMEM:
189c89f2750SDavid 'Digit' Turner 		return -ENOMEM;
190c89f2750SDavid 'Digit' Turner 	case PIPE_ERROR_IO:
191c89f2750SDavid 'Digit' Turner 		return -EIO;
192c89f2750SDavid 'Digit' Turner 	default:
193c89f2750SDavid 'Digit' Turner 		return -EINVAL;
194c89f2750SDavid 'Digit' Turner 	}
195c89f2750SDavid 'Digit' Turner }
196c89f2750SDavid 'Digit' Turner 
197c89f2750SDavid 'Digit' Turner /*
198c89f2750SDavid 'Digit' Turner  * Notice: QEMU will return 0 for un-known register access, indicating
199c89f2750SDavid 'Digit' Turner  * param_acess is supported or not
200c89f2750SDavid 'Digit' Turner  */
201c89f2750SDavid 'Digit' Turner static int valid_batchbuffer_addr(struct goldfish_pipe_dev *dev,
202c89f2750SDavid 'Digit' Turner 				  struct access_params *aps)
203c89f2750SDavid 'Digit' Turner {
204c89f2750SDavid 'Digit' Turner 	u32 aph, apl;
205c89f2750SDavid 'Digit' Turner 	u64 paddr;
206c89f2750SDavid 'Digit' Turner 	aph = readl(dev->base + PIPE_REG_PARAMS_ADDR_HIGH);
207c89f2750SDavid 'Digit' Turner 	apl = readl(dev->base + PIPE_REG_PARAMS_ADDR_LOW);
208c89f2750SDavid 'Digit' Turner 
209c89f2750SDavid 'Digit' Turner 	paddr = ((u64)aph << 32) | apl;
210c89f2750SDavid 'Digit' Turner 	if (paddr != (__pa(aps)))
211c89f2750SDavid 'Digit' Turner 		return 0;
212c89f2750SDavid 'Digit' Turner 	return 1;
213c89f2750SDavid 'Digit' Turner }
214c89f2750SDavid 'Digit' Turner 
215c89f2750SDavid 'Digit' Turner /* 0 on success */
216c89f2750SDavid 'Digit' Turner static int setup_access_params_addr(struct platform_device *pdev,
217c89f2750SDavid 'Digit' Turner 					struct goldfish_pipe_dev *dev)
218c89f2750SDavid 'Digit' Turner {
219c89f2750SDavid 'Digit' Turner 	u64 paddr;
220c89f2750SDavid 'Digit' Turner 	struct access_params *aps;
221c89f2750SDavid 'Digit' Turner 
222c89f2750SDavid 'Digit' Turner 	aps = devm_kzalloc(&pdev->dev, sizeof(struct access_params), GFP_KERNEL);
223c89f2750SDavid 'Digit' Turner 	if (!aps)
224c89f2750SDavid 'Digit' Turner 		return -1;
225c89f2750SDavid 'Digit' Turner 
226c89f2750SDavid 'Digit' Turner 	/* FIXME */
227c89f2750SDavid 'Digit' Turner 	paddr = __pa(aps);
228c89f2750SDavid 'Digit' Turner 	writel((u32)(paddr >> 32), dev->base + PIPE_REG_PARAMS_ADDR_HIGH);
229c89f2750SDavid 'Digit' Turner 	writel((u32)paddr, dev->base + PIPE_REG_PARAMS_ADDR_LOW);
230c89f2750SDavid 'Digit' Turner 
231c89f2750SDavid 'Digit' Turner 	if (valid_batchbuffer_addr(dev, aps)) {
232c89f2750SDavid 'Digit' Turner 		dev->aps = aps;
233c89f2750SDavid 'Digit' Turner 		return 0;
234c89f2750SDavid 'Digit' Turner 	} else
235c89f2750SDavid 'Digit' Turner 		return -1;
236c89f2750SDavid 'Digit' Turner }
237c89f2750SDavid 'Digit' Turner 
238c89f2750SDavid 'Digit' Turner /* A value that will not be set by qemu emulator */
239c89f2750SDavid 'Digit' Turner #define INITIAL_BATCH_RESULT (0xdeadbeaf)
240c89f2750SDavid 'Digit' Turner static int access_with_param(struct goldfish_pipe_dev *dev, const int cmd,
241c89f2750SDavid 'Digit' Turner 				unsigned long address, unsigned long avail,
242c89f2750SDavid 'Digit' Turner 				struct goldfish_pipe *pipe, int *status)
243c89f2750SDavid 'Digit' Turner {
244c89f2750SDavid 'Digit' Turner 	struct access_params *aps = dev->aps;
245c89f2750SDavid 'Digit' Turner 
246c89f2750SDavid 'Digit' Turner 	if (aps == NULL)
247c89f2750SDavid 'Digit' Turner 		return -1;
248c89f2750SDavid 'Digit' Turner 
249c89f2750SDavid 'Digit' Turner 	aps->result = INITIAL_BATCH_RESULT;
250c89f2750SDavid 'Digit' Turner 	aps->channel = (unsigned long)pipe;
251c89f2750SDavid 'Digit' Turner 	aps->size = avail;
252c89f2750SDavid 'Digit' Turner 	aps->address = address;
253c89f2750SDavid 'Digit' Turner 	aps->cmd = cmd;
254c89f2750SDavid 'Digit' Turner 	writel(cmd, dev->base + PIPE_REG_ACCESS_PARAMS);
255c89f2750SDavid 'Digit' Turner 	/*
256c89f2750SDavid 'Digit' Turner 	 * If the aps->result has not changed, that means
257c89f2750SDavid 'Digit' Turner 	 * that the batch command failed
258c89f2750SDavid 'Digit' Turner 	 */
259c89f2750SDavid 'Digit' Turner 	if (aps->result == INITIAL_BATCH_RESULT)
260c89f2750SDavid 'Digit' Turner 		return -1;
261c89f2750SDavid 'Digit' Turner 	*status = aps->result;
262c89f2750SDavid 'Digit' Turner 	return 0;
263c89f2750SDavid 'Digit' Turner }
264c89f2750SDavid 'Digit' Turner 
265c89f2750SDavid 'Digit' Turner static ssize_t goldfish_pipe_read_write(struct file *filp, char __user *buffer,
266c89f2750SDavid 'Digit' Turner 				       size_t bufflen, int is_write)
267c89f2750SDavid 'Digit' Turner {
268c89f2750SDavid 'Digit' Turner 	unsigned long irq_flags;
269c89f2750SDavid 'Digit' Turner 	struct goldfish_pipe *pipe = filp->private_data;
270c89f2750SDavid 'Digit' Turner 	struct goldfish_pipe_dev *dev = pipe->dev;
271c89f2750SDavid 'Digit' Turner 	unsigned long address, address_end;
2722f3be882SChristoffer Dall 	int count = 0, ret = -EINVAL;
273c89f2750SDavid 'Digit' Turner 
274c89f2750SDavid 'Digit' Turner 	/* If the emulator already closed the pipe, no need to go further */
275c89f2750SDavid 'Digit' Turner 	if (test_bit(BIT_CLOSED_ON_HOST, &pipe->flags))
276c89f2750SDavid 'Digit' Turner 		return -EIO;
277c89f2750SDavid 'Digit' Turner 
278c89f2750SDavid 'Digit' Turner 	/* Null reads or writes succeeds */
2793411d035SJoe Perches 	if (unlikely(bufflen == 0))
280c89f2750SDavid 'Digit' Turner 		return 0;
281c89f2750SDavid 'Digit' Turner 
282c89f2750SDavid 'Digit' Turner 	/* Check the buffer range for access */
283c89f2750SDavid 'Digit' Turner 	if (!access_ok(is_write ? VERIFY_WRITE : VERIFY_READ,
284c89f2750SDavid 'Digit' Turner 			buffer, bufflen))
285c89f2750SDavid 'Digit' Turner 		return -EFAULT;
286c89f2750SDavid 'Digit' Turner 
287c89f2750SDavid 'Digit' Turner 	/* Serialize access to the pipe */
288c89f2750SDavid 'Digit' Turner 	if (mutex_lock_interruptible(&pipe->lock))
289c89f2750SDavid 'Digit' Turner 		return -ERESTARTSYS;
290c89f2750SDavid 'Digit' Turner 
291c89f2750SDavid 'Digit' Turner 	address = (unsigned long)(void *)buffer;
292c89f2750SDavid 'Digit' Turner 	address_end = address + bufflen;
293c89f2750SDavid 'Digit' Turner 
294c89f2750SDavid 'Digit' Turner 	while (address < address_end) {
295c89f2750SDavid 'Digit' Turner 		unsigned long page_end = (address & PAGE_MASK) + PAGE_SIZE;
296c89f2750SDavid 'Digit' Turner 		unsigned long next     = page_end < address_end ? page_end
297c89f2750SDavid 'Digit' Turner 								: address_end;
298c89f2750SDavid 'Digit' Turner 		unsigned long avail    = next - address;
299c89f2750SDavid 'Digit' Turner 		int status, wakeBit;
3002f3be882SChristoffer Dall 		struct page *page;
301c89f2750SDavid 'Digit' Turner 
3024f42071cSYu Ning 		/* Either vaddr or paddr depending on the device version */
3034f42071cSYu Ning 		unsigned long xaddr;
3044f42071cSYu Ning 
3052f3be882SChristoffer Dall 		/*
3062f3be882SChristoffer Dall 		 * We grab the pages on a page-by-page basis in case user
3072f3be882SChristoffer Dall 		 * space gives us a potentially huge buffer but the read only
3082f3be882SChristoffer Dall 		 * returns a small amount, then there's no need to pin that
3092f3be882SChristoffer Dall 		 * much memory to the process.
3102f3be882SChristoffer Dall 		 */
3114f42071cSYu Ning 		down_read(&current->mm->mmap_sem);
3122f3be882SChristoffer Dall 		ret = get_user_pages(current, current->mm, address, 1,
3132f3be882SChristoffer Dall 				     !is_write, 0, &page, NULL);
3144f42071cSYu Ning 		up_read(&current->mm->mmap_sem);
3152f3be882SChristoffer Dall 		if (ret < 0)
3162f3be882SChristoffer Dall 			return ret;
317c89f2750SDavid 'Digit' Turner 
3184f42071cSYu Ning 		if (dev->version) {
3194f42071cSYu Ning 			/* Device version 1 or newer (qemu-android) expects the
3204f42071cSYu Ning 			 * physical address.
3214f42071cSYu Ning 			 */
3224f42071cSYu Ning 			xaddr = page_to_phys(page) | (address & ~PAGE_MASK);
3234f42071cSYu Ning 		} else {
3244f42071cSYu Ning 			/* Device version 0 (classic emulator) expects the
3254f42071cSYu Ning 			 * virtual address.
3264f42071cSYu Ning 			 */
3274f42071cSYu Ning 			xaddr = address;
3284f42071cSYu Ning 		}
3294f42071cSYu Ning 
330c89f2750SDavid 'Digit' Turner 		/* Now, try to transfer the bytes in the current page */
331c89f2750SDavid 'Digit' Turner 		spin_lock_irqsave(&dev->lock, irq_flags);
33223c5ee21SAlex Bennée 		if (access_with_param(dev,
33323c5ee21SAlex Bennée 				is_write ? CMD_WRITE_BUFFER : CMD_READ_BUFFER,
3344f42071cSYu Ning 				xaddr, avail, pipe, &status)) {
33507d783fdSPeter Senna Tschudin 			gf_write_ptr(pipe, dev->base + PIPE_REG_CHANNEL,
336a99698faSAlan 				     dev->base + PIPE_REG_CHANNEL_HIGH);
337c89f2750SDavid 'Digit' Turner 			writel(avail, dev->base + PIPE_REG_SIZE);
3384f42071cSYu Ning 			gf_write_ptr((void *)xaddr,
33907d783fdSPeter Senna Tschudin 				     dev->base + PIPE_REG_ADDRESS,
340a99698faSAlan 				     dev->base + PIPE_REG_ADDRESS_HIGH);
34123c5ee21SAlex Bennée 			writel(is_write ? CMD_WRITE_BUFFER : CMD_READ_BUFFER,
342c89f2750SDavid 'Digit' Turner 					dev->base + PIPE_REG_COMMAND);
343c89f2750SDavid 'Digit' Turner 			status = readl(dev->base + PIPE_REG_STATUS);
344c89f2750SDavid 'Digit' Turner 		}
345c89f2750SDavid 'Digit' Turner 		spin_unlock_irqrestore(&dev->lock, irq_flags);
346c89f2750SDavid 'Digit' Turner 
3472f3be882SChristoffer Dall 		if (status > 0 && !is_write)
3482f3be882SChristoffer Dall 			set_page_dirty(page);
3492f3be882SChristoffer Dall 		put_page(page);
3502f3be882SChristoffer Dall 
351c89f2750SDavid 'Digit' Turner 		if (status > 0) { /* Correct transfer */
3522f3be882SChristoffer Dall 			count += status;
353c89f2750SDavid 'Digit' Turner 			address += status;
354c89f2750SDavid 'Digit' Turner 			continue;
3552f3be882SChristoffer Dall 		} else if (status == 0) { /* EOF */
3562f3be882SChristoffer Dall 			ret = 0;
3572f3be882SChristoffer Dall 			break;
3582f3be882SChristoffer Dall 		} else if (status < 0 && count > 0) {
3592f3be882SChristoffer Dall 			/*
3602f3be882SChristoffer Dall 			 * An error occurred and we already transferred
3612f3be882SChristoffer Dall 			 * something on one of the previous pages.
3622f3be882SChristoffer Dall 			 * Just return what we already copied and log this
3632f3be882SChristoffer Dall 			 * err.
3642f3be882SChristoffer Dall 			 *
3652f3be882SChristoffer Dall 			 * Note: This seems like an incorrect approach but
3662f3be882SChristoffer Dall 			 * cannot change it until we check if any user space
3672f3be882SChristoffer Dall 			 * ABI relies on this behavior.
3682f3be882SChristoffer Dall 			 */
36925dd0f40SGreg Hackmann 			if (status != PIPE_ERROR_AGAIN)
37025dd0f40SGreg Hackmann 				pr_info_ratelimited("goldfish_pipe: backend returned error %d on %s\n",
3712f3be882SChristoffer Dall 					status, is_write ? "write" : "read");
3722f3be882SChristoffer Dall 			ret = 0;
3732f3be882SChristoffer Dall 			break;
374c89f2750SDavid 'Digit' Turner 		}
375c89f2750SDavid 'Digit' Turner 
3762f3be882SChristoffer Dall 		/*
3772f3be882SChristoffer Dall 		 * If the error is not PIPE_ERROR_AGAIN, or if we are not in
378c89f2750SDavid 'Digit' Turner 		 * non-blocking mode, just return the error code.
379c89f2750SDavid 'Digit' Turner 		 */
380c89f2750SDavid 'Digit' Turner 		if (status != PIPE_ERROR_AGAIN ||
381c89f2750SDavid 'Digit' Turner 			(filp->f_flags & O_NONBLOCK) != 0) {
382c89f2750SDavid 'Digit' Turner 			ret = goldfish_pipe_error_convert(status);
383c89f2750SDavid 'Digit' Turner 			break;
384c89f2750SDavid 'Digit' Turner 		}
385c89f2750SDavid 'Digit' Turner 
3862f3be882SChristoffer Dall 		/*
3872f3be882SChristoffer Dall 		 * The backend blocked the read/write, wait until the backend
3882f3be882SChristoffer Dall 		 * tells us it's ready to process more data.
389c89f2750SDavid 'Digit' Turner 		 */
390c89f2750SDavid 'Digit' Turner 		wakeBit = is_write ? BIT_WAKE_ON_WRITE : BIT_WAKE_ON_READ;
391c89f2750SDavid 'Digit' Turner 		set_bit(wakeBit, &pipe->flags);
392c89f2750SDavid 'Digit' Turner 
393c89f2750SDavid 'Digit' Turner 		/* Tell the emulator we're going to wait for a wake event */
39423c5ee21SAlex Bennée 		goldfish_cmd(pipe,
39523c5ee21SAlex Bennée 			is_write ? CMD_WAKE_ON_WRITE : CMD_WAKE_ON_READ);
396c89f2750SDavid 'Digit' Turner 
397c89f2750SDavid 'Digit' Turner 		/* Unlock the pipe, then wait for the wake signal */
398c89f2750SDavid 'Digit' Turner 		mutex_unlock(&pipe->lock);
399c89f2750SDavid 'Digit' Turner 
400c89f2750SDavid 'Digit' Turner 		while (test_bit(wakeBit, &pipe->flags)) {
401c89f2750SDavid 'Digit' Turner 			if (wait_event_interruptible(
402c89f2750SDavid 'Digit' Turner 					pipe->wake_queue,
4032f3be882SChristoffer Dall 					!test_bit(wakeBit, &pipe->flags))) {
4042f3be882SChristoffer Dall 				ret = -ERESTARTSYS;
4052f3be882SChristoffer Dall 				break;
4062f3be882SChristoffer Dall 			}
407c89f2750SDavid 'Digit' Turner 
4082f3be882SChristoffer Dall 			if (test_bit(BIT_CLOSED_ON_HOST, &pipe->flags)) {
4092f3be882SChristoffer Dall 				ret = -EIO;
4102f3be882SChristoffer Dall 				break;
4112f3be882SChristoffer Dall 			}
412c89f2750SDavid 'Digit' Turner 		}
413c89f2750SDavid 'Digit' Turner 
414c89f2750SDavid 'Digit' Turner 		/* Try to re-acquire the lock */
4152f3be882SChristoffer Dall 		if (mutex_lock_interruptible(&pipe->lock)) {
4162f3be882SChristoffer Dall 			ret = -ERESTARTSYS;
4172f3be882SChristoffer Dall 			break;
4182f3be882SChristoffer Dall 		}
419c89f2750SDavid 'Digit' Turner 	}
420c89f2750SDavid 'Digit' Turner 	mutex_unlock(&pipe->lock);
4212f3be882SChristoffer Dall 
4222f3be882SChristoffer Dall 	if (ret < 0)
423c89f2750SDavid 'Digit' Turner 		return ret;
4242f3be882SChristoffer Dall 	else
4252f3be882SChristoffer Dall 		return count;
426c89f2750SDavid 'Digit' Turner }
427c89f2750SDavid 'Digit' Turner 
428c89f2750SDavid 'Digit' Turner static ssize_t goldfish_pipe_read(struct file *filp, char __user *buffer,
429c89f2750SDavid 'Digit' Turner 			      size_t bufflen, loff_t *ppos)
430c89f2750SDavid 'Digit' Turner {
431c89f2750SDavid 'Digit' Turner 	return goldfish_pipe_read_write(filp, buffer, bufflen, 0);
432c89f2750SDavid 'Digit' Turner }
433c89f2750SDavid 'Digit' Turner 
434c89f2750SDavid 'Digit' Turner static ssize_t goldfish_pipe_write(struct file *filp,
435c89f2750SDavid 'Digit' Turner 				const char __user *buffer, size_t bufflen,
436c89f2750SDavid 'Digit' Turner 				loff_t *ppos)
437c89f2750SDavid 'Digit' Turner {
438c89f2750SDavid 'Digit' Turner 	return goldfish_pipe_read_write(filp, (char __user *)buffer,
439c89f2750SDavid 'Digit' Turner 								bufflen, 1);
440c89f2750SDavid 'Digit' Turner }
441c89f2750SDavid 'Digit' Turner 
442c89f2750SDavid 'Digit' Turner 
443c89f2750SDavid 'Digit' Turner static unsigned int goldfish_pipe_poll(struct file *filp, poll_table *wait)
444c89f2750SDavid 'Digit' Turner {
445c89f2750SDavid 'Digit' Turner 	struct goldfish_pipe *pipe = filp->private_data;
446c89f2750SDavid 'Digit' Turner 	unsigned int mask = 0;
447c89f2750SDavid 'Digit' Turner 	int status;
448c89f2750SDavid 'Digit' Turner 
449c89f2750SDavid 'Digit' Turner 	mutex_lock(&pipe->lock);
450c89f2750SDavid 'Digit' Turner 
451c89f2750SDavid 'Digit' Turner 	poll_wait(filp, &pipe->wake_queue, wait);
452c89f2750SDavid 'Digit' Turner 
453c89f2750SDavid 'Digit' Turner 	status = goldfish_cmd_status(pipe, CMD_POLL);
454c89f2750SDavid 'Digit' Turner 
455c89f2750SDavid 'Digit' Turner 	mutex_unlock(&pipe->lock);
456c89f2750SDavid 'Digit' Turner 
457c89f2750SDavid 'Digit' Turner 	if (status & PIPE_POLL_IN)
458c89f2750SDavid 'Digit' Turner 		mask |= POLLIN | POLLRDNORM;
459c89f2750SDavid 'Digit' Turner 
460c89f2750SDavid 'Digit' Turner 	if (status & PIPE_POLL_OUT)
461c89f2750SDavid 'Digit' Turner 		mask |= POLLOUT | POLLWRNORM;
462c89f2750SDavid 'Digit' Turner 
463c89f2750SDavid 'Digit' Turner 	if (status & PIPE_POLL_HUP)
464c89f2750SDavid 'Digit' Turner 		mask |= POLLHUP;
465c89f2750SDavid 'Digit' Turner 
466c89f2750SDavid 'Digit' Turner 	if (test_bit(BIT_CLOSED_ON_HOST, &pipe->flags))
467c89f2750SDavid 'Digit' Turner 		mask |= POLLERR;
468c89f2750SDavid 'Digit' Turner 
469c89f2750SDavid 'Digit' Turner 	return mask;
470c89f2750SDavid 'Digit' Turner }
471c89f2750SDavid 'Digit' Turner 
472c89f2750SDavid 'Digit' Turner static irqreturn_t goldfish_pipe_interrupt(int irq, void *dev_id)
473c89f2750SDavid 'Digit' Turner {
474c89f2750SDavid 'Digit' Turner 	struct goldfish_pipe_dev *dev = dev_id;
475c89f2750SDavid 'Digit' Turner 	unsigned long irq_flags;
476c89f2750SDavid 'Digit' Turner 	int count = 0;
477c89f2750SDavid 'Digit' Turner 
4782f3be882SChristoffer Dall 	/*
4792f3be882SChristoffer Dall 	 * We're going to read from the emulator a list of (channel,flags)
4802f3be882SChristoffer Dall 	 * pairs corresponding to the wake events that occurred on each
481c89f2750SDavid 'Digit' Turner 	 * blocked pipe (i.e. channel).
482c89f2750SDavid 'Digit' Turner 	 */
483c89f2750SDavid 'Digit' Turner 	spin_lock_irqsave(&dev->lock, irq_flags);
484c89f2750SDavid 'Digit' Turner 	for (;;) {
485c89f2750SDavid 'Digit' Turner 		/* First read the channel, 0 means the end of the list */
486c89f2750SDavid 'Digit' Turner 		struct goldfish_pipe *pipe;
487c89f2750SDavid 'Digit' Turner 		unsigned long wakes;
48849a75c44SJun Tian 		unsigned long channel = 0;
48949a75c44SJun Tian 
49049a75c44SJun Tian #ifdef CONFIG_64BIT
49149a75c44SJun Tian 		channel = (u64)readl(dev->base + PIPE_REG_CHANNEL_HIGH) << 32;
49225c72c78SJun Tian 
49325c72c78SJun Tian 		if (channel == 0)
49425c72c78SJun Tian 			break;
49549a75c44SJun Tian #endif
49649a75c44SJun Tian 		channel |= readl(dev->base + PIPE_REG_CHANNEL);
497c89f2750SDavid 'Digit' Turner 
498c89f2750SDavid 'Digit' Turner 		if (channel == 0)
499c89f2750SDavid 'Digit' Turner 			break;
500c89f2750SDavid 'Digit' Turner 
501c89f2750SDavid 'Digit' Turner 		/* Convert channel to struct pipe pointer + read wake flags */
502c89f2750SDavid 'Digit' Turner 		wakes = readl(dev->base + PIPE_REG_WAKES);
503c89f2750SDavid 'Digit' Turner 		pipe  = (struct goldfish_pipe *)(ptrdiff_t)channel;
504c89f2750SDavid 'Digit' Turner 
505c89f2750SDavid 'Digit' Turner 		/* Did the emulator just closed a pipe? */
506c89f2750SDavid 'Digit' Turner 		if (wakes & PIPE_WAKE_CLOSED) {
507c89f2750SDavid 'Digit' Turner 			set_bit(BIT_CLOSED_ON_HOST, &pipe->flags);
508c89f2750SDavid 'Digit' Turner 			wakes |= PIPE_WAKE_READ | PIPE_WAKE_WRITE;
509c89f2750SDavid 'Digit' Turner 		}
510c89f2750SDavid 'Digit' Turner 		if (wakes & PIPE_WAKE_READ)
511c89f2750SDavid 'Digit' Turner 			clear_bit(BIT_WAKE_ON_READ, &pipe->flags);
512c89f2750SDavid 'Digit' Turner 		if (wakes & PIPE_WAKE_WRITE)
513c89f2750SDavid 'Digit' Turner 			clear_bit(BIT_WAKE_ON_WRITE, &pipe->flags);
514c89f2750SDavid 'Digit' Turner 
515c89f2750SDavid 'Digit' Turner 		wake_up_interruptible(&pipe->wake_queue);
516c89f2750SDavid 'Digit' Turner 		count++;
517c89f2750SDavid 'Digit' Turner 	}
518c89f2750SDavid 'Digit' Turner 	spin_unlock_irqrestore(&dev->lock, irq_flags);
519c89f2750SDavid 'Digit' Turner 
520c89f2750SDavid 'Digit' Turner 	return (count == 0) ? IRQ_NONE : IRQ_HANDLED;
521c89f2750SDavid 'Digit' Turner }
522c89f2750SDavid 'Digit' Turner 
523c89f2750SDavid 'Digit' Turner /**
524c89f2750SDavid 'Digit' Turner  *	goldfish_pipe_open	-	open a channel to the AVD
525c89f2750SDavid 'Digit' Turner  *	@inode: inode of device
526c89f2750SDavid 'Digit' Turner  *	@file: file struct of opener
527c89f2750SDavid 'Digit' Turner  *
528c89f2750SDavid 'Digit' Turner  *	Create a new pipe link between the emulator and the use application.
529c89f2750SDavid 'Digit' Turner  *	Each new request produces a new pipe.
530c89f2750SDavid 'Digit' Turner  *
531c89f2750SDavid 'Digit' Turner  *	Note: we use the pipe ID as a mux. All goldfish emulations are 32bit
532c89f2750SDavid 'Digit' Turner  *	right now so this is fine. A move to 64bit will need this addressing
533c89f2750SDavid 'Digit' Turner  */
534c89f2750SDavid 'Digit' Turner static int goldfish_pipe_open(struct inode *inode, struct file *file)
535c89f2750SDavid 'Digit' Turner {
536c89f2750SDavid 'Digit' Turner 	struct goldfish_pipe *pipe;
537c89f2750SDavid 'Digit' Turner 	struct goldfish_pipe_dev *dev = pipe_dev;
538c89f2750SDavid 'Digit' Turner 	int32_t status;
539c89f2750SDavid 'Digit' Turner 
540c89f2750SDavid 'Digit' Turner 	/* Allocate new pipe kernel object */
541c89f2750SDavid 'Digit' Turner 	pipe = kzalloc(sizeof(*pipe), GFP_KERNEL);
542c89f2750SDavid 'Digit' Turner 	if (pipe == NULL)
543c89f2750SDavid 'Digit' Turner 		return -ENOMEM;
544c89f2750SDavid 'Digit' Turner 
545c89f2750SDavid 'Digit' Turner 	pipe->dev = dev;
546c89f2750SDavid 'Digit' Turner 	mutex_init(&pipe->lock);
547c89f2750SDavid 'Digit' Turner 	init_waitqueue_head(&pipe->wake_queue);
548c89f2750SDavid 'Digit' Turner 
549c89f2750SDavid 'Digit' Turner 	/*
550c89f2750SDavid 'Digit' Turner 	 * Now, tell the emulator we're opening a new pipe. We use the
551c89f2750SDavid 'Digit' Turner 	 * pipe object's address as the channel identifier for simplicity.
552c89f2750SDavid 'Digit' Turner 	 */
553c89f2750SDavid 'Digit' Turner 
554c89f2750SDavid 'Digit' Turner 	status = goldfish_cmd_status(pipe, CMD_OPEN);
555c89f2750SDavid 'Digit' Turner 	if (status < 0) {
556c89f2750SDavid 'Digit' Turner 		kfree(pipe);
557c89f2750SDavid 'Digit' Turner 		return status;
558c89f2750SDavid 'Digit' Turner 	}
559c89f2750SDavid 'Digit' Turner 
560c89f2750SDavid 'Digit' Turner 	/* All is done, save the pipe into the file's private data field */
561c89f2750SDavid 'Digit' Turner 	file->private_data = pipe;
562c89f2750SDavid 'Digit' Turner 	return 0;
563c89f2750SDavid 'Digit' Turner }
564c89f2750SDavid 'Digit' Turner 
565c89f2750SDavid 'Digit' Turner static int goldfish_pipe_release(struct inode *inode, struct file *filp)
566c89f2750SDavid 'Digit' Turner {
567c89f2750SDavid 'Digit' Turner 	struct goldfish_pipe *pipe = filp->private_data;
568c89f2750SDavid 'Digit' Turner 
569c89f2750SDavid 'Digit' Turner 	/* The guest is closing the channel, so tell the emulator right now */
570c89f2750SDavid 'Digit' Turner 	goldfish_cmd(pipe, CMD_CLOSE);
571c89f2750SDavid 'Digit' Turner 	kfree(pipe);
572c89f2750SDavid 'Digit' Turner 	filp->private_data = NULL;
573c89f2750SDavid 'Digit' Turner 	return 0;
574c89f2750SDavid 'Digit' Turner }
575c89f2750SDavid 'Digit' Turner 
576c89f2750SDavid 'Digit' Turner static const struct file_operations goldfish_pipe_fops = {
577c89f2750SDavid 'Digit' Turner 	.owner = THIS_MODULE,
578c89f2750SDavid 'Digit' Turner 	.read = goldfish_pipe_read,
579c89f2750SDavid 'Digit' Turner 	.write = goldfish_pipe_write,
580c89f2750SDavid 'Digit' Turner 	.poll = goldfish_pipe_poll,
581c89f2750SDavid 'Digit' Turner 	.open = goldfish_pipe_open,
582c89f2750SDavid 'Digit' Turner 	.release = goldfish_pipe_release,
583c89f2750SDavid 'Digit' Turner };
584c89f2750SDavid 'Digit' Turner 
585c89f2750SDavid 'Digit' Turner static struct miscdevice goldfish_pipe_device = {
586c89f2750SDavid 'Digit' Turner 	.minor = MISC_DYNAMIC_MINOR,
587c89f2750SDavid 'Digit' Turner 	.name = "goldfish_pipe",
588c89f2750SDavid 'Digit' Turner 	.fops = &goldfish_pipe_fops,
589c89f2750SDavid 'Digit' Turner };
590c89f2750SDavid 'Digit' Turner 
591c89f2750SDavid 'Digit' Turner static int goldfish_pipe_probe(struct platform_device *pdev)
592c89f2750SDavid 'Digit' Turner {
593c89f2750SDavid 'Digit' Turner 	int err;
594c89f2750SDavid 'Digit' Turner 	struct resource *r;
595c89f2750SDavid 'Digit' Turner 	struct goldfish_pipe_dev *dev = pipe_dev;
596c89f2750SDavid 'Digit' Turner 
597c89f2750SDavid 'Digit' Turner 	/* not thread safe, but this should not happen */
598c89f2750SDavid 'Digit' Turner 	WARN_ON(dev->base != NULL);
599c89f2750SDavid 'Digit' Turner 
600c89f2750SDavid 'Digit' Turner 	spin_lock_init(&dev->lock);
601c89f2750SDavid 'Digit' Turner 
602c89f2750SDavid 'Digit' Turner 	r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
603c89f2750SDavid 'Digit' Turner 	if (r == NULL || resource_size(r) < PAGE_SIZE) {
604c89f2750SDavid 'Digit' Turner 		dev_err(&pdev->dev, "can't allocate i/o page\n");
605c89f2750SDavid 'Digit' Turner 		return -EINVAL;
606c89f2750SDavid 'Digit' Turner 	}
607c89f2750SDavid 'Digit' Turner 	dev->base = devm_ioremap(&pdev->dev, r->start, PAGE_SIZE);
608c89f2750SDavid 'Digit' Turner 	if (dev->base == NULL) {
609c89f2750SDavid 'Digit' Turner 		dev_err(&pdev->dev, "ioremap failed\n");
610c89f2750SDavid 'Digit' Turner 		return -EINVAL;
611c89f2750SDavid 'Digit' Turner 	}
612c89f2750SDavid 'Digit' Turner 
613c89f2750SDavid 'Digit' Turner 	r = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
614c89f2750SDavid 'Digit' Turner 	if (r == NULL) {
615c89f2750SDavid 'Digit' Turner 		err = -EINVAL;
616c89f2750SDavid 'Digit' Turner 		goto error;
617c89f2750SDavid 'Digit' Turner 	}
618c89f2750SDavid 'Digit' Turner 	dev->irq = r->start;
619c89f2750SDavid 'Digit' Turner 
620c89f2750SDavid 'Digit' Turner 	err = devm_request_irq(&pdev->dev, dev->irq, goldfish_pipe_interrupt,
621c89f2750SDavid 'Digit' Turner 				IRQF_SHARED, "goldfish_pipe", dev);
622c89f2750SDavid 'Digit' Turner 	if (err) {
623c89f2750SDavid 'Digit' Turner 		dev_err(&pdev->dev, "unable to allocate IRQ\n");
624c89f2750SDavid 'Digit' Turner 		goto error;
625c89f2750SDavid 'Digit' Turner 	}
626c89f2750SDavid 'Digit' Turner 
627c89f2750SDavid 'Digit' Turner 	err = misc_register(&goldfish_pipe_device);
628c89f2750SDavid 'Digit' Turner 	if (err) {
629c89f2750SDavid 'Digit' Turner 		dev_err(&pdev->dev, "unable to register device\n");
630c89f2750SDavid 'Digit' Turner 		goto error;
631c89f2750SDavid 'Digit' Turner 	}
632c89f2750SDavid 'Digit' Turner 	setup_access_params_addr(pdev, dev);
6334f42071cSYu Ning 
6344f42071cSYu Ning 	/* Although the pipe device in the classic Android emulator does not
6354f42071cSYu Ning 	 * recognize the 'version' register, it won't treat this as an error
6364f42071cSYu Ning 	 * either and will simply return 0, which is fine.
6374f42071cSYu Ning 	 */
6384f42071cSYu Ning 	dev->version = readl(dev->base + PIPE_REG_VERSION);
639c89f2750SDavid 'Digit' Turner 	return 0;
640c89f2750SDavid 'Digit' Turner 
641c89f2750SDavid 'Digit' Turner error:
642c89f2750SDavid 'Digit' Turner 	dev->base = NULL;
643c89f2750SDavid 'Digit' Turner 	return err;
644c89f2750SDavid 'Digit' Turner }
645c89f2750SDavid 'Digit' Turner 
646c89f2750SDavid 'Digit' Turner static int goldfish_pipe_remove(struct platform_device *pdev)
647c89f2750SDavid 'Digit' Turner {
648c89f2750SDavid 'Digit' Turner 	struct goldfish_pipe_dev *dev = pipe_dev;
649c89f2750SDavid 'Digit' Turner 	misc_deregister(&goldfish_pipe_device);
650c89f2750SDavid 'Digit' Turner 	dev->base = NULL;
651c89f2750SDavid 'Digit' Turner 	return 0;
652c89f2750SDavid 'Digit' Turner }
653c89f2750SDavid 'Digit' Turner 
654*d62f324bSJason Hu static const struct acpi_device_id goldfish_pipe_acpi_match[] = {
655*d62f324bSJason Hu 	{ "GFSH0003", 0 },
656*d62f324bSJason Hu 	{ },
657*d62f324bSJason Hu };
658*d62f324bSJason Hu MODULE_DEVICE_TABLE(acpi, goldfish_pipe_acpi_match);
659*d62f324bSJason Hu 
66091a18a41SGreg Hackmann static const struct of_device_id goldfish_pipe_of_match[] = {
66191a18a41SGreg Hackmann 	{ .compatible = "google,android-pipe", },
66291a18a41SGreg Hackmann 	{},
66391a18a41SGreg Hackmann };
66491a18a41SGreg Hackmann MODULE_DEVICE_TABLE(of, goldfish_pipe_of_match);
66591a18a41SGreg Hackmann 
666c89f2750SDavid 'Digit' Turner static struct platform_driver goldfish_pipe = {
667c89f2750SDavid 'Digit' Turner 	.probe = goldfish_pipe_probe,
668c89f2750SDavid 'Digit' Turner 	.remove = goldfish_pipe_remove,
669c89f2750SDavid 'Digit' Turner 	.driver = {
67091a18a41SGreg Hackmann 		.name = "goldfish_pipe",
67191a18a41SGreg Hackmann 		.owner = THIS_MODULE,
67291a18a41SGreg Hackmann 		.of_match_table = goldfish_pipe_of_match,
673*d62f324bSJason Hu 		.acpi_match_table = ACPI_PTR(goldfish_pipe_acpi_match),
674c89f2750SDavid 'Digit' Turner 	}
675c89f2750SDavid 'Digit' Turner };
676c89f2750SDavid 'Digit' Turner 
677c89f2750SDavid 'Digit' Turner module_platform_driver(goldfish_pipe);
678c89f2750SDavid 'Digit' Turner MODULE_AUTHOR("David Turner <digit@google.com>");
679c89f2750SDavid 'Digit' Turner MODULE_LICENSE("GPL");
680