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 22 #include <mach/dma.h> 23 #include <asm/system.h> 24 25 26 #define to_mcp(d) container_of(d, struct mcp, attached_device) 27 #define to_mcp_driver(d) container_of(d, struct mcp_driver, drv) 28 29 static int mcp_bus_match(struct device *dev, struct device_driver *drv) 30 { 31 return 1; 32 } 33 34 static int mcp_bus_probe(struct device *dev) 35 { 36 struct mcp *mcp = to_mcp(dev); 37 struct mcp_driver *drv = to_mcp_driver(dev->driver); 38 39 return drv->probe(mcp); 40 } 41 42 static int mcp_bus_remove(struct device *dev) 43 { 44 struct mcp *mcp = to_mcp(dev); 45 struct mcp_driver *drv = to_mcp_driver(dev->driver); 46 47 drv->remove(mcp); 48 return 0; 49 } 50 51 static int mcp_bus_suspend(struct device *dev, pm_message_t state) 52 { 53 struct mcp *mcp = to_mcp(dev); 54 int ret = 0; 55 56 if (dev->driver) { 57 struct mcp_driver *drv = to_mcp_driver(dev->driver); 58 59 ret = drv->suspend(mcp, state); 60 } 61 return ret; 62 } 63 64 static int mcp_bus_resume(struct device *dev) 65 { 66 struct mcp *mcp = to_mcp(dev); 67 int ret = 0; 68 69 if (dev->driver) { 70 struct mcp_driver *drv = to_mcp_driver(dev->driver); 71 72 ret = drv->resume(mcp); 73 } 74 return ret; 75 } 76 77 static struct bus_type mcp_bus_type = { 78 .name = "mcp", 79 .match = mcp_bus_match, 80 .probe = mcp_bus_probe, 81 .remove = mcp_bus_remove, 82 .suspend = mcp_bus_suspend, 83 .resume = mcp_bus_resume, 84 }; 85 86 /** 87 * mcp_set_telecom_divisor - set the telecom divisor 88 * @mcp: MCP interface structure 89 * @div: SIB clock divisor 90 * 91 * Set the telecom divisor on the MCP interface. The resulting 92 * sample rate is SIBCLOCK/div. 93 */ 94 void mcp_set_telecom_divisor(struct mcp *mcp, unsigned int div) 95 { 96 unsigned long flags; 97 98 spin_lock_irqsave(&mcp->lock, flags); 99 mcp->ops->set_telecom_divisor(mcp, div); 100 spin_unlock_irqrestore(&mcp->lock, flags); 101 } 102 EXPORT_SYMBOL(mcp_set_telecom_divisor); 103 104 /** 105 * mcp_set_audio_divisor - set the audio divisor 106 * @mcp: MCP interface structure 107 * @div: SIB clock divisor 108 * 109 * Set the audio divisor on the MCP interface. 110 */ 111 void mcp_set_audio_divisor(struct mcp *mcp, unsigned int div) 112 { 113 unsigned long flags; 114 115 spin_lock_irqsave(&mcp->lock, flags); 116 mcp->ops->set_audio_divisor(mcp, div); 117 spin_unlock_irqrestore(&mcp->lock, flags); 118 } 119 EXPORT_SYMBOL(mcp_set_audio_divisor); 120 121 /** 122 * mcp_reg_write - write a device register 123 * @mcp: MCP interface structure 124 * @reg: 4-bit register index 125 * @val: 16-bit data value 126 * 127 * Write a device register. The MCP interface must be enabled 128 * to prevent this function hanging. 129 */ 130 void mcp_reg_write(struct mcp *mcp, unsigned int reg, unsigned int val) 131 { 132 unsigned long flags; 133 134 spin_lock_irqsave(&mcp->lock, flags); 135 mcp->ops->reg_write(mcp, reg, val); 136 spin_unlock_irqrestore(&mcp->lock, flags); 137 } 138 EXPORT_SYMBOL(mcp_reg_write); 139 140 /** 141 * mcp_reg_read - read a device register 142 * @mcp: MCP interface structure 143 * @reg: 4-bit register index 144 * 145 * Read a device register and return its value. The MCP interface 146 * must be enabled to prevent this function hanging. 147 */ 148 unsigned int mcp_reg_read(struct mcp *mcp, unsigned int reg) 149 { 150 unsigned long flags; 151 unsigned int val; 152 153 spin_lock_irqsave(&mcp->lock, flags); 154 val = mcp->ops->reg_read(mcp, reg); 155 spin_unlock_irqrestore(&mcp->lock, flags); 156 157 return val; 158 } 159 EXPORT_SYMBOL(mcp_reg_read); 160 161 /** 162 * mcp_enable - enable the MCP interface 163 * @mcp: MCP interface to enable 164 * 165 * Enable the MCP interface. Each call to mcp_enable will need 166 * a corresponding call to mcp_disable to disable the interface. 167 */ 168 void mcp_enable(struct mcp *mcp) 169 { 170 unsigned long flags; 171 spin_lock_irqsave(&mcp->lock, flags); 172 if (mcp->use_count++ == 0) 173 mcp->ops->enable(mcp); 174 spin_unlock_irqrestore(&mcp->lock, flags); 175 } 176 EXPORT_SYMBOL(mcp_enable); 177 178 /** 179 * mcp_disable - disable the MCP interface 180 * @mcp: MCP interface to disable 181 * 182 * Disable the MCP interface. The MCP interface will only be 183 * disabled once the number of calls to mcp_enable matches the 184 * number of calls to mcp_disable. 185 */ 186 void mcp_disable(struct mcp *mcp) 187 { 188 unsigned long flags; 189 190 spin_lock_irqsave(&mcp->lock, flags); 191 if (--mcp->use_count == 0) 192 mcp->ops->disable(mcp); 193 spin_unlock_irqrestore(&mcp->lock, flags); 194 } 195 EXPORT_SYMBOL(mcp_disable); 196 197 static void mcp_release(struct device *dev) 198 { 199 struct mcp *mcp = container_of(dev, struct mcp, attached_device); 200 201 kfree(mcp); 202 } 203 204 struct mcp *mcp_host_alloc(struct device *parent, size_t size) 205 { 206 struct mcp *mcp; 207 208 mcp = kzalloc(sizeof(struct mcp) + size, GFP_KERNEL); 209 if (mcp) { 210 spin_lock_init(&mcp->lock); 211 mcp->attached_device.parent = parent; 212 mcp->attached_device.bus = &mcp_bus_type; 213 mcp->attached_device.dma_mask = parent->dma_mask; 214 mcp->attached_device.release = mcp_release; 215 } 216 return mcp; 217 } 218 EXPORT_SYMBOL(mcp_host_alloc); 219 220 int mcp_host_register(struct mcp *mcp) 221 { 222 dev_set_name(&mcp->attached_device, "mcp0"); 223 return device_register(&mcp->attached_device); 224 } 225 EXPORT_SYMBOL(mcp_host_register); 226 227 void mcp_host_unregister(struct mcp *mcp) 228 { 229 device_unregister(&mcp->attached_device); 230 } 231 EXPORT_SYMBOL(mcp_host_unregister); 232 233 int mcp_driver_register(struct mcp_driver *mcpdrv) 234 { 235 mcpdrv->drv.bus = &mcp_bus_type; 236 return driver_register(&mcpdrv->drv); 237 } 238 EXPORT_SYMBOL(mcp_driver_register); 239 240 void mcp_driver_unregister(struct mcp_driver *mcpdrv) 241 { 242 driver_unregister(&mcpdrv->drv); 243 } 244 EXPORT_SYMBOL(mcp_driver_unregister); 245 246 static int __init mcp_init(void) 247 { 248 return bus_register(&mcp_bus_type); 249 } 250 251 static void __exit mcp_exit(void) 252 { 253 bus_unregister(&mcp_bus_type); 254 } 255 256 module_init(mcp_init); 257 module_exit(mcp_exit); 258 259 MODULE_AUTHOR("Russell King <rmk@arm.linux.org.uk>"); 260 MODULE_DESCRIPTION("Core multimedia communications port driver"); 261 MODULE_LICENSE("GPL"); 262