2 * Copyright (C) 2007 Google, Inc.
3 * Copyright (C) 2011 Intel, Inc.
4 * Copyright (C) 2013 Intel, Inc.
6 * This software is licensed under the terms of the GNU General Public
7 * License version 2, as published by the Free Software Foundation, and
8 * may be copied, distributed, and modified under those terms.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
17 #include <linux/kernel.h>
18 #include <linux/init.h>
19 #include <linux/interrupt.h>
20 #include <linux/irq.h>
21 #include <linux/platform_device.h>
22 #include <linux/slab.h>
25 #define PDEV_BUS_OP_DONE (0x00)
26 #define PDEV_BUS_OP_REMOVE_DEV (0x04)
27 #define PDEV_BUS_OP_ADD_DEV (0x08)
29 #define PDEV_BUS_OP_INIT (0x00)
31 #define PDEV_BUS_OP (0x00)
32 #define PDEV_BUS_GET_NAME (0x04)
33 #define PDEV_BUS_NAME_LEN (0x08)
34 #define PDEV_BUS_ID (0x0c)
35 #define PDEV_BUS_IO_BASE (0x10)
36 #define PDEV_BUS_IO_SIZE (0x14)
37 #define PDEV_BUS_IRQ (0x18)
38 #define PDEV_BUS_IRQ_COUNT (0x1c)
39 #define PDEV_BUS_GET_NAME_HIGH (0x20)
42 struct list_head list
;
43 struct platform_device pdev
;
44 struct resource resources
[0];
47 static void goldfish_pdev_worker(struct work_struct
*work
);
49 static void __iomem
*pdev_bus_base
;
50 static unsigned long pdev_bus_addr
;
51 static unsigned long pdev_bus_len
;
52 static u32 pdev_bus_irq
;
53 static LIST_HEAD(pdev_bus_new_devices
);
54 static LIST_HEAD(pdev_bus_registered_devices
);
55 static LIST_HEAD(pdev_bus_removed_devices
);
56 static DECLARE_WORK(pdev_bus_worker
, goldfish_pdev_worker
);
59 static void goldfish_pdev_worker(struct work_struct
*work
)
62 struct pdev_bus_dev
*pos
, *n
;
64 list_for_each_entry_safe(pos
, n
, &pdev_bus_removed_devices
, list
) {
66 platform_device_unregister(&pos
->pdev
);
69 list_for_each_entry_safe(pos
, n
, &pdev_bus_new_devices
, list
) {
71 ret
= platform_device_register(&pos
->pdev
);
73 pr_err("goldfish_pdev_worker failed to register device, %s\n",
75 list_add_tail(&pos
->list
, &pdev_bus_registered_devices
);
79 static void goldfish_pdev_remove(void)
81 struct pdev_bus_dev
*pos
, *n
;
84 base
= readl(pdev_bus_base
+ PDEV_BUS_IO_BASE
);
86 list_for_each_entry_safe(pos
, n
, &pdev_bus_new_devices
, list
) {
87 if (pos
->resources
[0].start
== base
) {
93 list_for_each_entry_safe(pos
, n
, &pdev_bus_registered_devices
, list
) {
94 if (pos
->resources
[0].start
== base
) {
96 list_add_tail(&pos
->list
, &pdev_bus_removed_devices
);
97 schedule_work(&pdev_bus_worker
);
101 pr_err("goldfish_pdev_remove could not find device at %x\n", base
);
104 static int goldfish_new_pdev(void)
106 struct pdev_bus_dev
*dev
;
108 u32 irq
= -1, irq_count
;
109 int resource_count
= 2;
113 base
= readl(pdev_bus_base
+ PDEV_BUS_IO_BASE
);
115 irq_count
= readl(pdev_bus_base
+ PDEV_BUS_IRQ_COUNT
);
116 name_len
= readl(pdev_bus_base
+ PDEV_BUS_NAME_LEN
);
120 dev
= kzalloc(sizeof(*dev
) +
121 sizeof(struct resource
) * resource_count
+
122 name_len
+ 1 + sizeof(*dev
->pdev
.dev
.dma_mask
), GFP_ATOMIC
);
126 dev
->pdev
.num_resources
= resource_count
;
127 dev
->pdev
.resource
= (struct resource
*)(dev
+ 1);
128 dev
->pdev
.name
= name
= (char *)(dev
->pdev
.resource
+ resource_count
);
129 dev
->pdev
.dev
.coherent_dma_mask
= ~0;
130 dev
->pdev
.dev
.dma_mask
= (void *)(dev
->pdev
.name
+ name_len
+ 1);
131 *dev
->pdev
.dev
.dma_mask
= ~0;
134 writel((u32
)((u64
)name
>>32), pdev_bus_base
+ PDEV_BUS_GET_NAME_HIGH
);
136 writel((u32
)(unsigned long)name
, pdev_bus_base
+ PDEV_BUS_GET_NAME
);
137 name
[name_len
] = '\0';
138 dev
->pdev
.id
= readl(pdev_bus_base
+ PDEV_BUS_ID
);
139 dev
->pdev
.resource
[0].start
= base
;
140 dev
->pdev
.resource
[0].end
= base
+
141 readl(pdev_bus_base
+ PDEV_BUS_IO_SIZE
) - 1;
142 dev
->pdev
.resource
[0].flags
= IORESOURCE_MEM
;
144 irq
= readl(pdev_bus_base
+ PDEV_BUS_IRQ
);
145 dev
->pdev
.resource
[1].start
= irq
;
146 dev
->pdev
.resource
[1].end
= irq
+ irq_count
- 1;
147 dev
->pdev
.resource
[1].flags
= IORESOURCE_IRQ
;
150 pr_debug("goldfish_new_pdev %s at %x irq %d\n", name
, base
, irq
);
151 list_add_tail(&dev
->list
, &pdev_bus_new_devices
);
152 schedule_work(&pdev_bus_worker
);
157 static irqreturn_t
goldfish_pdev_bus_interrupt(int irq
, void *dev_id
)
159 irqreturn_t ret
= IRQ_NONE
;
161 u32 op
= readl(pdev_bus_base
+ PDEV_BUS_OP
);
163 case PDEV_BUS_OP_DONE
:
166 case PDEV_BUS_OP_REMOVE_DEV
:
167 goldfish_pdev_remove();
170 case PDEV_BUS_OP_ADD_DEV
:
179 static int goldfish_pdev_bus_probe(struct platform_device
*pdev
)
184 r
= platform_get_resource(pdev
, IORESOURCE_MEM
, 0);
188 pdev_bus_addr
= r
->start
;
189 pdev_bus_len
= resource_size(r
);
191 pdev_bus_base
= ioremap(pdev_bus_addr
, pdev_bus_len
);
192 if (pdev_bus_base
== NULL
) {
194 dev_err(&pdev
->dev
, "unable to map Goldfish MMIO.\n");
198 r
= platform_get_resource(pdev
, IORESOURCE_IRQ
, 0);
204 pdev_bus_irq
= r
->start
;
206 ret
= request_irq(pdev_bus_irq
, goldfish_pdev_bus_interrupt
,
207 IRQF_SHARED
, "goldfish_pdev_bus", pdev
);
209 dev_err(&pdev
->dev
, "unable to request Goldfish IRQ\n");
213 writel(PDEV_BUS_OP_INIT
, pdev_bus_base
+ PDEV_BUS_OP
);
217 iounmap(pdev_bus_base
);
219 release_mem_region(pdev_bus_addr
, pdev_bus_len
);
223 static int goldfish_pdev_bus_remove(struct platform_device
*pdev
)
225 iounmap(pdev_bus_base
);
226 free_irq(pdev_bus_irq
, pdev
);
227 release_mem_region(pdev_bus_addr
, pdev_bus_len
);
231 static struct platform_driver goldfish_pdev_bus_driver
= {
232 .probe
= goldfish_pdev_bus_probe
,
233 .remove
= goldfish_pdev_bus_remove
,
235 .name
= "goldfish_pdev_bus"
239 module_platform_driver(goldfish_pdev_bus_driver
);