mcp-core.c 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235
  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 void 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. }
  36. static struct bus_type mcp_bus_type = {
  37. .name = "mcp",
  38. .match = mcp_bus_match,
  39. .probe = mcp_bus_probe,
  40. .remove = mcp_bus_remove,
  41. };
  42. /**
  43. * mcp_set_telecom_divisor - set the telecom divisor
  44. * @mcp: MCP interface structure
  45. * @div: SIB clock divisor
  46. *
  47. * Set the telecom divisor on the MCP interface. The resulting
  48. * sample rate is SIBCLOCK/div.
  49. */
  50. void mcp_set_telecom_divisor(struct mcp *mcp, unsigned int div)
  51. {
  52. unsigned long flags;
  53. spin_lock_irqsave(&mcp->lock, flags);
  54. mcp->ops->set_telecom_divisor(mcp, div);
  55. spin_unlock_irqrestore(&mcp->lock, flags);
  56. }
  57. EXPORT_SYMBOL(mcp_set_telecom_divisor);
  58. /**
  59. * mcp_set_audio_divisor - set the audio divisor
  60. * @mcp: MCP interface structure
  61. * @div: SIB clock divisor
  62. *
  63. * Set the audio divisor on the MCP interface.
  64. */
  65. void mcp_set_audio_divisor(struct mcp *mcp, unsigned int div)
  66. {
  67. unsigned long flags;
  68. spin_lock_irqsave(&mcp->lock, flags);
  69. mcp->ops->set_audio_divisor(mcp, div);
  70. spin_unlock_irqrestore(&mcp->lock, flags);
  71. }
  72. EXPORT_SYMBOL(mcp_set_audio_divisor);
  73. /**
  74. * mcp_reg_write - write a device register
  75. * @mcp: MCP interface structure
  76. * @reg: 4-bit register index
  77. * @val: 16-bit data value
  78. *
  79. * Write a device register. The MCP interface must be enabled
  80. * to prevent this function hanging.
  81. */
  82. void mcp_reg_write(struct mcp *mcp, unsigned int reg, unsigned int val)
  83. {
  84. unsigned long flags;
  85. spin_lock_irqsave(&mcp->lock, flags);
  86. mcp->ops->reg_write(mcp, reg, val);
  87. spin_unlock_irqrestore(&mcp->lock, flags);
  88. }
  89. EXPORT_SYMBOL(mcp_reg_write);
  90. /**
  91. * mcp_reg_read - read a device register
  92. * @mcp: MCP interface structure
  93. * @reg: 4-bit register index
  94. *
  95. * Read a device register and return its value. The MCP interface
  96. * must be enabled to prevent this function hanging.
  97. */
  98. unsigned int mcp_reg_read(struct mcp *mcp, unsigned int reg)
  99. {
  100. unsigned long flags;
  101. unsigned int val;
  102. spin_lock_irqsave(&mcp->lock, flags);
  103. val = mcp->ops->reg_read(mcp, reg);
  104. spin_unlock_irqrestore(&mcp->lock, flags);
  105. return val;
  106. }
  107. EXPORT_SYMBOL(mcp_reg_read);
  108. /**
  109. * mcp_enable - enable the MCP interface
  110. * @mcp: MCP interface to enable
  111. *
  112. * Enable the MCP interface. Each call to mcp_enable will need
  113. * a corresponding call to mcp_disable to disable the interface.
  114. */
  115. void mcp_enable(struct mcp *mcp)
  116. {
  117. unsigned long flags;
  118. spin_lock_irqsave(&mcp->lock, flags);
  119. if (mcp->use_count++ == 0)
  120. mcp->ops->enable(mcp);
  121. spin_unlock_irqrestore(&mcp->lock, flags);
  122. }
  123. EXPORT_SYMBOL(mcp_enable);
  124. /**
  125. * mcp_disable - disable the MCP interface
  126. * @mcp: MCP interface to disable
  127. *
  128. * Disable the MCP interface. The MCP interface will only be
  129. * disabled once the number of calls to mcp_enable matches the
  130. * number of calls to mcp_disable.
  131. */
  132. void mcp_disable(struct mcp *mcp)
  133. {
  134. unsigned long flags;
  135. spin_lock_irqsave(&mcp->lock, flags);
  136. if (--mcp->use_count == 0)
  137. mcp->ops->disable(mcp);
  138. spin_unlock_irqrestore(&mcp->lock, flags);
  139. }
  140. EXPORT_SYMBOL(mcp_disable);
  141. static void mcp_release(struct device *dev)
  142. {
  143. struct mcp *mcp = container_of(dev, struct mcp, attached_device);
  144. kfree(mcp);
  145. }
  146. struct mcp *mcp_host_alloc(struct device *parent, size_t size)
  147. {
  148. struct mcp *mcp;
  149. mcp = kzalloc(sizeof(struct mcp) + size, GFP_KERNEL);
  150. if (mcp) {
  151. spin_lock_init(&mcp->lock);
  152. device_initialize(&mcp->attached_device);
  153. mcp->attached_device.parent = parent;
  154. mcp->attached_device.bus = &mcp_bus_type;
  155. mcp->attached_device.dma_mask = parent->dma_mask;
  156. mcp->attached_device.release = mcp_release;
  157. }
  158. return mcp;
  159. }
  160. EXPORT_SYMBOL(mcp_host_alloc);
  161. int mcp_host_add(struct mcp *mcp, void *pdata)
  162. {
  163. mcp->attached_device.platform_data = pdata;
  164. dev_set_name(&mcp->attached_device, "mcp0");
  165. return device_add(&mcp->attached_device);
  166. }
  167. EXPORT_SYMBOL(mcp_host_add);
  168. void mcp_host_del(struct mcp *mcp)
  169. {
  170. device_del(&mcp->attached_device);
  171. }
  172. EXPORT_SYMBOL(mcp_host_del);
  173. void mcp_host_free(struct mcp *mcp)
  174. {
  175. put_device(&mcp->attached_device);
  176. }
  177. EXPORT_SYMBOL(mcp_host_free);
  178. int mcp_driver_register(struct mcp_driver *mcpdrv)
  179. {
  180. mcpdrv->drv.bus = &mcp_bus_type;
  181. return driver_register(&mcpdrv->drv);
  182. }
  183. EXPORT_SYMBOL(mcp_driver_register);
  184. void mcp_driver_unregister(struct mcp_driver *mcpdrv)
  185. {
  186. driver_unregister(&mcpdrv->drv);
  187. }
  188. EXPORT_SYMBOL(mcp_driver_unregister);
  189. static int __init mcp_init(void)
  190. {
  191. return bus_register(&mcp_bus_type);
  192. }
  193. static void __exit mcp_exit(void)
  194. {
  195. bus_unregister(&mcp_bus_type);
  196. }
  197. module_init(mcp_init);
  198. module_exit(mcp_exit);
  199. MODULE_AUTHOR("Russell King <[email protected]>");
  200. MODULE_DESCRIPTION("Core multimedia communications port driver");
  201. MODULE_LICENSE("GPL");