0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011 #include <linux/module.h>
0012 #include <linux/io.h>
0013 #include <linux/errno.h>
0014 #include <linux/kernel.h>
0015 #include <linux/delay.h>
0016 #include <linux/spinlock.h>
0017 #include <linux/platform_device.h>
0018 #include <linux/pm.h>
0019 #include <linux/mfd/mcp.h>
0020
0021 #include <mach/hardware.h>
0022 #include <asm/mach-types.h>
0023 #include <linux/platform_data/mfd-mcp-sa11x0.h>
0024
0025 #define DRIVER_NAME "sa11x0-mcp"
0026
0027 struct mcp_sa11x0 {
0028 void __iomem *base0;
0029 void __iomem *base1;
0030 u32 mccr0;
0031 u32 mccr1;
0032 };
0033
0034
0035 #define MCCR0(m) ((m)->base0 + 0x00)
0036 #define MCDR0(m) ((m)->base0 + 0x08)
0037 #define MCDR1(m) ((m)->base0 + 0x0c)
0038 #define MCDR2(m) ((m)->base0 + 0x10)
0039 #define MCSR(m) ((m)->base0 + 0x18)
0040 #define MCCR1(m) ((m)->base1 + 0x00)
0041
0042 #define priv(mcp) ((struct mcp_sa11x0 *)mcp_priv(mcp))
0043
0044 static void
0045 mcp_sa11x0_set_telecom_divisor(struct mcp *mcp, unsigned int divisor)
0046 {
0047 struct mcp_sa11x0 *m = priv(mcp);
0048
0049 divisor /= 32;
0050
0051 m->mccr0 &= ~0x00007f00;
0052 m->mccr0 |= divisor << 8;
0053 writel_relaxed(m->mccr0, MCCR0(m));
0054 }
0055
0056 static void
0057 mcp_sa11x0_set_audio_divisor(struct mcp *mcp, unsigned int divisor)
0058 {
0059 struct mcp_sa11x0 *m = priv(mcp);
0060
0061 divisor /= 32;
0062
0063 m->mccr0 &= ~0x0000007f;
0064 m->mccr0 |= divisor;
0065 writel_relaxed(m->mccr0, MCCR0(m));
0066 }
0067
0068
0069
0070
0071
0072
0073
0074 static void
0075 mcp_sa11x0_write(struct mcp *mcp, unsigned int reg, unsigned int val)
0076 {
0077 struct mcp_sa11x0 *m = priv(mcp);
0078 int ret = -ETIME;
0079 int i;
0080
0081 writel_relaxed(reg << 17 | MCDR2_Wr | (val & 0xffff), MCDR2(m));
0082
0083 for (i = 0; i < 2; i++) {
0084 udelay(mcp->rw_timeout);
0085 if (readl_relaxed(MCSR(m)) & MCSR_CWC) {
0086 ret = 0;
0087 break;
0088 }
0089 }
0090
0091 if (ret < 0)
0092 printk(KERN_WARNING "mcp: write timed out\n");
0093 }
0094
0095
0096
0097
0098
0099
0100
0101 static unsigned int
0102 mcp_sa11x0_read(struct mcp *mcp, unsigned int reg)
0103 {
0104 struct mcp_sa11x0 *m = priv(mcp);
0105 int ret = -ETIME;
0106 int i;
0107
0108 writel_relaxed(reg << 17 | MCDR2_Rd, MCDR2(m));
0109
0110 for (i = 0; i < 2; i++) {
0111 udelay(mcp->rw_timeout);
0112 if (readl_relaxed(MCSR(m)) & MCSR_CRC) {
0113 ret = readl_relaxed(MCDR2(m)) & 0xffff;
0114 break;
0115 }
0116 }
0117
0118 if (ret < 0)
0119 printk(KERN_WARNING "mcp: read timed out\n");
0120
0121 return ret;
0122 }
0123
0124 static void mcp_sa11x0_enable(struct mcp *mcp)
0125 {
0126 struct mcp_sa11x0 *m = priv(mcp);
0127
0128 writel(-1, MCSR(m));
0129 m->mccr0 |= MCCR0_MCE;
0130 writel_relaxed(m->mccr0, MCCR0(m));
0131 }
0132
0133 static void mcp_sa11x0_disable(struct mcp *mcp)
0134 {
0135 struct mcp_sa11x0 *m = priv(mcp);
0136
0137 m->mccr0 &= ~MCCR0_MCE;
0138 writel_relaxed(m->mccr0, MCCR0(m));
0139 }
0140
0141
0142
0143
0144 static struct mcp_ops mcp_sa11x0 = {
0145 .set_telecom_divisor = mcp_sa11x0_set_telecom_divisor,
0146 .set_audio_divisor = mcp_sa11x0_set_audio_divisor,
0147 .reg_write = mcp_sa11x0_write,
0148 .reg_read = mcp_sa11x0_read,
0149 .enable = mcp_sa11x0_enable,
0150 .disable = mcp_sa11x0_disable,
0151 };
0152
0153 static int mcp_sa11x0_probe(struct platform_device *dev)
0154 {
0155 struct mcp_plat_data *data = dev_get_platdata(&dev->dev);
0156 struct resource *mem0, *mem1;
0157 struct mcp_sa11x0 *m;
0158 struct mcp *mcp;
0159 int ret;
0160
0161 if (!data)
0162 return -ENODEV;
0163
0164 mem0 = platform_get_resource(dev, IORESOURCE_MEM, 0);
0165 mem1 = platform_get_resource(dev, IORESOURCE_MEM, 1);
0166 if (!mem0 || !mem1)
0167 return -ENXIO;
0168
0169 if (!request_mem_region(mem0->start, resource_size(mem0),
0170 DRIVER_NAME)) {
0171 ret = -EBUSY;
0172 goto err_mem0;
0173 }
0174
0175 if (!request_mem_region(mem1->start, resource_size(mem1),
0176 DRIVER_NAME)) {
0177 ret = -EBUSY;
0178 goto err_mem1;
0179 }
0180
0181 mcp = mcp_host_alloc(&dev->dev, sizeof(struct mcp_sa11x0));
0182 if (!mcp) {
0183 ret = -ENOMEM;
0184 goto err_alloc;
0185 }
0186
0187 mcp->owner = THIS_MODULE;
0188 mcp->ops = &mcp_sa11x0;
0189 mcp->sclk_rate = data->sclk_rate;
0190
0191 m = priv(mcp);
0192 m->mccr0 = data->mccr0 | 0x7f7f;
0193 m->mccr1 = data->mccr1;
0194
0195 m->base0 = ioremap(mem0->start, resource_size(mem0));
0196 m->base1 = ioremap(mem1->start, resource_size(mem1));
0197 if (!m->base0 || !m->base1) {
0198 ret = -ENOMEM;
0199 goto err_ioremap;
0200 }
0201
0202 platform_set_drvdata(dev, mcp);
0203
0204
0205
0206
0207
0208 writel_relaxed(-1, MCSR(m));
0209 writel_relaxed(m->mccr1, MCCR1(m));
0210 writel_relaxed(m->mccr0, MCCR0(m));
0211
0212
0213
0214
0215
0216
0217 mcp->rw_timeout = DIV_ROUND_UP(64 * 3 * 1000000, mcp->sclk_rate);
0218
0219 ret = mcp_host_add(mcp, data->codec_pdata);
0220 if (ret == 0)
0221 return 0;
0222
0223 err_ioremap:
0224 iounmap(m->base1);
0225 iounmap(m->base0);
0226 mcp_host_free(mcp);
0227 err_alloc:
0228 release_mem_region(mem1->start, resource_size(mem1));
0229 err_mem1:
0230 release_mem_region(mem0->start, resource_size(mem0));
0231 err_mem0:
0232 return ret;
0233 }
0234
0235 static int mcp_sa11x0_remove(struct platform_device *dev)
0236 {
0237 struct mcp *mcp = platform_get_drvdata(dev);
0238 struct mcp_sa11x0 *m = priv(mcp);
0239 struct resource *mem0, *mem1;
0240
0241 if (m->mccr0 & MCCR0_MCE)
0242 dev_warn(&dev->dev,
0243 "device left active (missing disable call?)\n");
0244
0245 mem0 = platform_get_resource(dev, IORESOURCE_MEM, 0);
0246 mem1 = platform_get_resource(dev, IORESOURCE_MEM, 1);
0247
0248 mcp_host_del(mcp);
0249 iounmap(m->base1);
0250 iounmap(m->base0);
0251 mcp_host_free(mcp);
0252 release_mem_region(mem1->start, resource_size(mem1));
0253 release_mem_region(mem0->start, resource_size(mem0));
0254
0255 return 0;
0256 }
0257
0258 #ifdef CONFIG_PM_SLEEP
0259 static int mcp_sa11x0_suspend(struct device *dev)
0260 {
0261 struct mcp_sa11x0 *m = priv(dev_get_drvdata(dev));
0262
0263 if (m->mccr0 & MCCR0_MCE)
0264 dev_warn(dev, "device left active (missing disable call?)\n");
0265
0266 writel(m->mccr0 & ~MCCR0_MCE, MCCR0(m));
0267
0268 return 0;
0269 }
0270
0271 static int mcp_sa11x0_resume(struct device *dev)
0272 {
0273 struct mcp_sa11x0 *m = priv(dev_get_drvdata(dev));
0274
0275 writel_relaxed(m->mccr1, MCCR1(m));
0276 writel_relaxed(m->mccr0, MCCR0(m));
0277
0278 return 0;
0279 }
0280 #endif
0281
0282 static const struct dev_pm_ops mcp_sa11x0_pm_ops = {
0283 #ifdef CONFIG_PM_SLEEP
0284 .suspend = mcp_sa11x0_suspend,
0285 .freeze = mcp_sa11x0_suspend,
0286 .poweroff = mcp_sa11x0_suspend,
0287 .resume_noirq = mcp_sa11x0_resume,
0288 .thaw_noirq = mcp_sa11x0_resume,
0289 .restore_noirq = mcp_sa11x0_resume,
0290 #endif
0291 };
0292
0293 static struct platform_driver mcp_sa11x0_driver = {
0294 .probe = mcp_sa11x0_probe,
0295 .remove = mcp_sa11x0_remove,
0296 .driver = {
0297 .name = DRIVER_NAME,
0298 .pm = &mcp_sa11x0_pm_ops,
0299 },
0300 };
0301
0302
0303
0304
0305 module_platform_driver(mcp_sa11x0_driver);
0306
0307 MODULE_ALIAS("platform:" DRIVER_NAME);
0308 MODULE_AUTHOR("Russell King <rmk@arm.linux.org.uk>");
0309 MODULE_DESCRIPTION("SA11x0 multimedia communications port driver");
0310 MODULE_LICENSE("GPL");