pdev_bus.c 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240
  1. /*
  2. * Copyright (C) 2007 Google, Inc.
  3. * Copyright (C) 2011 Intel, Inc.
  4. * Copyright (C) 2013 Intel, Inc.
  5. *
  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.
  9. *
  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.
  14. *
  15. */
  16. #include <linux/kernel.h>
  17. #include <linux/init.h>
  18. #include <linux/interrupt.h>
  19. #include <linux/irq.h>
  20. #include <linux/platform_device.h>
  21. #include <linux/slab.h>
  22. #include <linux/io.h>
  23. #define PDEV_BUS_OP_DONE (0x00)
  24. #define PDEV_BUS_OP_REMOVE_DEV (0x04)
  25. #define PDEV_BUS_OP_ADD_DEV (0x08)
  26. #define PDEV_BUS_OP_INIT (0x00)
  27. #define PDEV_BUS_OP (0x00)
  28. #define PDEV_BUS_GET_NAME (0x04)
  29. #define PDEV_BUS_NAME_LEN (0x08)
  30. #define PDEV_BUS_ID (0x0c)
  31. #define PDEV_BUS_IO_BASE (0x10)
  32. #define PDEV_BUS_IO_SIZE (0x14)
  33. #define PDEV_BUS_IRQ (0x18)
  34. #define PDEV_BUS_IRQ_COUNT (0x1c)
  35. struct pdev_bus_dev {
  36. struct list_head list;
  37. struct platform_device pdev;
  38. struct resource resources[0];
  39. };
  40. static void goldfish_pdev_worker(struct work_struct *work);
  41. static void __iomem *pdev_bus_base;
  42. static unsigned long pdev_bus_addr;
  43. static unsigned long pdev_bus_len;
  44. static u32 pdev_bus_irq;
  45. static LIST_HEAD(pdev_bus_new_devices);
  46. static LIST_HEAD(pdev_bus_registered_devices);
  47. static LIST_HEAD(pdev_bus_removed_devices);
  48. static DECLARE_WORK(pdev_bus_worker, goldfish_pdev_worker);
  49. static void goldfish_pdev_worker(struct work_struct *work)
  50. {
  51. int ret;
  52. struct pdev_bus_dev *pos, *n;
  53. list_for_each_entry_safe(pos, n, &pdev_bus_removed_devices, list) {
  54. list_del(&pos->list);
  55. platform_device_unregister(&pos->pdev);
  56. kfree(pos);
  57. }
  58. list_for_each_entry_safe(pos, n, &pdev_bus_new_devices, list) {
  59. list_del(&pos->list);
  60. ret = platform_device_register(&pos->pdev);
  61. if (ret)
  62. pr_err("goldfish_pdev_worker failed to register device, %s\n",
  63. pos->pdev.name);
  64. list_add_tail(&pos->list, &pdev_bus_registered_devices);
  65. }
  66. }
  67. static void goldfish_pdev_remove(void)
  68. {
  69. struct pdev_bus_dev *pos, *n;
  70. u32 base;
  71. base = readl(pdev_bus_base + PDEV_BUS_IO_BASE);
  72. list_for_each_entry_safe(pos, n, &pdev_bus_new_devices, list) {
  73. if (pos->resources[0].start == base) {
  74. list_del(&pos->list);
  75. kfree(pos);
  76. return;
  77. }
  78. }
  79. list_for_each_entry_safe(pos, n, &pdev_bus_registered_devices, list) {
  80. if (pos->resources[0].start == base) {
  81. list_del(&pos->list);
  82. list_add_tail(&pos->list, &pdev_bus_removed_devices);
  83. schedule_work(&pdev_bus_worker);
  84. return;
  85. }
  86. };
  87. pr_err("goldfish_pdev_remove could not find device at %x\n", base);
  88. }
  89. static int goldfish_new_pdev(void)
  90. {
  91. struct pdev_bus_dev *dev;
  92. u32 name_len;
  93. u32 irq = -1, irq_count;
  94. int resource_count = 2;
  95. u32 base;
  96. char *name;
  97. base = readl(pdev_bus_base + PDEV_BUS_IO_BASE);
  98. irq_count = readl(pdev_bus_base + PDEV_BUS_IRQ_COUNT);
  99. name_len = readl(pdev_bus_base + PDEV_BUS_NAME_LEN);
  100. if (irq_count)
  101. resource_count++;
  102. dev = kzalloc(sizeof(*dev) +
  103. sizeof(struct resource) * resource_count +
  104. name_len + 1 + sizeof(*dev->pdev.dev.dma_mask), GFP_ATOMIC);
  105. if (dev == NULL)
  106. return -ENOMEM;
  107. dev->pdev.num_resources = resource_count;
  108. dev->pdev.resource = (struct resource *)(dev + 1);
  109. dev->pdev.name = name = (char *)(dev->pdev.resource + resource_count);
  110. dev->pdev.dev.coherent_dma_mask = ~0;
  111. dev->pdev.dev.dma_mask = (void *)(dev->pdev.name + name_len + 1);
  112. *dev->pdev.dev.dma_mask = ~0;
  113. writel((unsigned long)name, pdev_bus_base + PDEV_BUS_GET_NAME);
  114. name[name_len] = '\0';
  115. dev->pdev.id = readl(pdev_bus_base + PDEV_BUS_ID);
  116. dev->pdev.resource[0].start = base;
  117. dev->pdev.resource[0].end = base +
  118. readl(pdev_bus_base + PDEV_BUS_IO_SIZE) - 1;
  119. dev->pdev.resource[0].flags = IORESOURCE_MEM;
  120. if (irq_count) {
  121. irq = readl(pdev_bus_base + PDEV_BUS_IRQ);
  122. dev->pdev.resource[1].start = irq;
  123. dev->pdev.resource[1].end = irq + irq_count - 1;
  124. dev->pdev.resource[1].flags = IORESOURCE_IRQ;
  125. }
  126. pr_debug("goldfish_new_pdev %s at %x irq %d\n", name, base, irq);
  127. list_add_tail(&dev->list, &pdev_bus_new_devices);
  128. schedule_work(&pdev_bus_worker);
  129. return 0;
  130. }
  131. static irqreturn_t goldfish_pdev_bus_interrupt(int irq, void *dev_id)
  132. {
  133. irqreturn_t ret = IRQ_NONE;
  134. while (1) {
  135. u32 op = readl(pdev_bus_base + PDEV_BUS_OP);
  136. switch (op) {
  137. case PDEV_BUS_OP_DONE:
  138. return IRQ_NONE;
  139. case PDEV_BUS_OP_REMOVE_DEV:
  140. goldfish_pdev_remove();
  141. break;
  142. case PDEV_BUS_OP_ADD_DEV:
  143. goldfish_new_pdev();
  144. break;
  145. }
  146. ret = IRQ_HANDLED;
  147. }
  148. return ret;
  149. }
  150. static int goldfish_pdev_bus_probe(struct platform_device *pdev)
  151. {
  152. int ret;
  153. struct resource *r;
  154. r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
  155. if (r == NULL)
  156. return -EINVAL;
  157. pdev_bus_addr = r->start;
  158. pdev_bus_len = resource_size(r);
  159. if (request_mem_region(pdev_bus_addr, pdev_bus_len, "goldfish")) {
  160. dev_err(&pdev->dev, "unable to reserve Goldfish MMIO.\n");
  161. return -EBUSY;
  162. }
  163. pdev_bus_base = ioremap(pdev_bus_addr, pdev_bus_len);
  164. if (pdev_bus_base == NULL) {
  165. ret = -ENOMEM;
  166. dev_err(&pdev->dev, "unable to map Goldfish MMIO.\n");
  167. goto free_resources;
  168. }
  169. r = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
  170. if (r == NULL) {
  171. ret = -ENOENT;
  172. goto free_map;
  173. }
  174. pdev_bus_irq = r->start;
  175. ret = request_irq(pdev_bus_irq, goldfish_pdev_bus_interrupt,
  176. IRQF_SHARED, "goldfish_pdev_bus", pdev);
  177. if (ret) {
  178. dev_err(&pdev->dev, "unable to request Goldfish IRQ\n");
  179. goto free_map;
  180. }
  181. writel(PDEV_BUS_OP_INIT, pdev_bus_base + PDEV_BUS_OP);
  182. return 0;
  183. free_map:
  184. iounmap(pdev_bus_base);
  185. free_resources:
  186. release_mem_region(pdev_bus_addr, pdev_bus_len);
  187. return ret;
  188. }
  189. static int goldfish_pdev_bus_remove(struct platform_device *pdev)
  190. {
  191. iounmap(pdev_bus_base);
  192. free_irq(pdev_bus_irq, pdev);
  193. release_mem_region(pdev_bus_addr, pdev_bus_len);
  194. return 0;
  195. }
  196. static struct platform_driver goldfish_pdev_bus_driver = {
  197. .probe = goldfish_pdev_bus_probe,
  198. .remove = goldfish_pdev_bus_remove,
  199. .driver = {
  200. .name = "goldfish_pdev_bus"
  201. }
  202. };
  203. module_platform_driver(goldfish_pdev_bus_driver);