mcp-core.c 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236
  1. // SPDX-License-Identifier: GPL-2.0-only
  2. /*
  3. * linux/drivers/mfd/mcp-core.c
  4. *
  5. * Copyright (C) 2001 Russell King
  6. *
  7. * Generic MCP (Multimedia Communications Port) layer. All MCP locking
  8. * is solely held within this file.
  9. */
  10. #include <linux/module.h>
  11. #include <linux/init.h>
  12. #include <linux/errno.h>
  13. #include <linux/smp.h>
  14. #include <linux/device.h>
  15. #include <linux/slab.h>
  16. #include <linux/string.h>
  17. #include <linux/mfd/mcp.h>
  18. #define to_mcp(d) container_of(d, struct mcp, attached_device)
  19. #define to_mcp_driver(d) container_of(d, struct mcp_driver, drv)
  20. static int mcp_bus_match(struct device *dev, struct device_driver *drv)
  21. {
  22. return 1;
  23. }
  24. static int mcp_bus_probe(struct device *dev)
  25. {
  26. struct mcp *mcp = to_mcp(dev);
  27. struct mcp_driver *drv = to_mcp_driver(dev->driver);
  28. return drv->probe(mcp);
  29. }
  30. static int mcp_bus_remove(struct device *dev)
  31. {
  32. struct mcp *mcp = to_mcp(dev);
  33. struct mcp_driver *drv = to_mcp_driver(dev->driver);
  34. drv->remove(mcp);
  35. return 0;
  36. }
  37. static struct bus_type mcp_bus_type = {
  38. .name = "mcp",
  39. .match = mcp_bus_match,
  40. .probe = mcp_bus_probe,
  41. .remove = mcp_bus_remove,
  42. };
  43. /**
  44. * mcp_set_telecom_divisor - set the telecom divisor
  45. * @mcp: MCP interface structure
  46. * @div: SIB clock divisor
  47. *
  48. * Set the telecom divisor on the MCP interface. The resulting
  49. * sample rate is SIBCLOCK/div.
  50. */
  51. void mcp_set_telecom_divisor(struct mcp *mcp, unsigned int div)
  52. {
  53. unsigned long flags;
  54. spin_lock_irqsave(&mcp->lock, flags);
  55. mcp->ops->set_telecom_divisor(mcp, div);
  56. spin_unlock_irqrestore(&mcp->lock, flags);
  57. }
  58. EXPORT_SYMBOL(mcp_set_telecom_divisor);
  59. /**
  60. * mcp_set_audio_divisor - set the audio divisor
  61. * @mcp: MCP interface structure
  62. * @div: SIB clock divisor
  63. *
  64. * Set the audio divisor on the MCP interface.
  65. */
  66. void mcp_set_audio_divisor(struct mcp *mcp, unsigned int div)
  67. {
  68. unsigned long flags;
  69. spin_lock_irqsave(&mcp->lock, flags);
  70. mcp->ops->set_audio_divisor(mcp, div);
  71. spin_unlock_irqrestore(&mcp->lock, flags);
  72. }
  73. EXPORT_SYMBOL(mcp_set_audio_divisor);
  74. /**
  75. * mcp_reg_write - write a device register
  76. * @mcp: MCP interface structure
  77. * @reg: 4-bit register index
  78. * @val: 16-bit data value
  79. *
  80. * Write a device register. The MCP interface must be enabled
  81. * to prevent this function hanging.
  82. */
  83. void mcp_reg_write(struct mcp *mcp, unsigned int reg, unsigned int val)
  84. {
  85. unsigned long flags;
  86. spin_lock_irqsave(&mcp->lock, flags);
  87. mcp->ops->reg_write(mcp, reg, val);
  88. spin_unlock_irqrestore(&mcp->lock, flags);
  89. }
  90. EXPORT_SYMBOL(mcp_reg_write);
  91. /**
  92. * mcp_reg_read - read a device register
  93. * @mcp: MCP interface structure
  94. * @reg: 4-bit register index
  95. *
  96. * Read a device register and return its value. The MCP interface
  97. * must be enabled to prevent this function hanging.
  98. */
  99. unsigned int mcp_reg_read(struct mcp *mcp, unsigned int reg)
  100. {
  101. unsigned long flags;
  102. unsigned int val;
  103. spin_lock_irqsave(&mcp->lock, flags);
  104. val = mcp->ops->reg_read(mcp, reg);
  105. spin_unlock_irqrestore(&mcp->lock, flags);
  106. return val;
  107. }
  108. EXPORT_SYMBOL(mcp_reg_read);
  109. /**
  110. * mcp_enable - enable the MCP interface
  111. * @mcp: MCP interface to enable
  112. *
  113. * Enable the MCP interface. Each call to mcp_enable will need
  114. * a corresponding call to mcp_disable to disable the interface.
  115. */
  116. void mcp_enable(struct mcp *mcp)
  117. {
  118. unsigned long flags;
  119. spin_lock_irqsave(&mcp->lock, flags);
  120. if (mcp->use_count++ == 0)
  121. mcp->ops->enable(mcp);
  122. spin_unlock_irqrestore(&mcp->lock, flags);
  123. }
  124. EXPORT_SYMBOL(mcp_enable);
  125. /**
  126. * mcp_disable - disable the MCP interface
  127. * @mcp: MCP interface to disable
  128. *
  129. * Disable the MCP interface. The MCP interface will only be
  130. * disabled once the number of calls to mcp_enable matches the
  131. * number of calls to mcp_disable.
  132. */
  133. void mcp_disable(struct mcp *mcp)
  134. {
  135. unsigned long flags;
  136. spin_lock_irqsave(&mcp->lock, flags);
  137. if (--mcp->use_count == 0)
  138. mcp->ops->disable(mcp);
  139. spin_unlock_irqrestore(&mcp->lock, flags);
  140. }
  141. EXPORT_SYMBOL(mcp_disable);
  142. static void mcp_release(struct device *dev)
  143. {
  144. struct mcp *mcp = container_of(dev, struct mcp, attached_device);
  145. kfree(mcp);
  146. }
  147. struct mcp *mcp_host_alloc(struct device *parent, size_t size)
  148. {
  149. struct mcp *mcp;
  150. mcp = kzalloc(sizeof(struct mcp) + size, GFP_KERNEL);
  151. if (mcp) {
  152. spin_lock_init(&mcp->lock);
  153. device_initialize(&mcp->attached_device);
  154. mcp->attached_device.parent = parent;
  155. mcp->attached_device.bus = &mcp_bus_type;
  156. mcp->attached_device.dma_mask = parent->dma_mask;
  157. mcp->attached_device.release = mcp_release;
  158. }
  159. return mcp;
  160. }
  161. EXPORT_SYMBOL(mcp_host_alloc);
  162. int mcp_host_add(struct mcp *mcp, void *pdata)
  163. {
  164. mcp->attached_device.platform_data = pdata;
  165. dev_set_name(&mcp->attached_device, "mcp0");
  166. return device_add(&mcp->attached_device);
  167. }
  168. EXPORT_SYMBOL(mcp_host_add);
  169. void mcp_host_del(struct mcp *mcp)
  170. {
  171. device_del(&mcp->attached_device);
  172. }
  173. EXPORT_SYMBOL(mcp_host_del);
  174. void mcp_host_free(struct mcp *mcp)
  175. {
  176. put_device(&mcp->attached_device);
  177. }
  178. EXPORT_SYMBOL(mcp_host_free);
  179. int mcp_driver_register(struct mcp_driver *mcpdrv)
  180. {
  181. mcpdrv->drv.bus = &mcp_bus_type;
  182. return driver_register(&mcpdrv->drv);
  183. }
  184. EXPORT_SYMBOL(mcp_driver_register);
  185. void mcp_driver_unregister(struct mcp_driver *mcpdrv)
  186. {
  187. driver_unregister(&mcpdrv->drv);
  188. }
  189. EXPORT_SYMBOL(mcp_driver_unregister);
  190. static int __init mcp_init(void)
  191. {
  192. return bus_register(&mcp_bus_type);
  193. }
  194. static void __exit mcp_exit(void)
  195. {
  196. bus_unregister(&mcp_bus_type);
  197. }
  198. module_init(mcp_init);
  199. module_exit(mcp_exit);
  200. MODULE_AUTHOR("Russell King <rmk@arm.linux.org.uk>");
  201. MODULE_DESCRIPTION("Core multimedia communications port driver");
  202. MODULE_LICENSE("GPL");