mcp-core.c 5.6 KB

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