1  /*
2   *  linux/drivers/mfd/mcp-sa11x0.c
3   *
4   *  Copyright (C) 2001-2005 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   *  SA11x0 MCP (Multimedia Communications Port) driver.
11   *
12   *  MCP read/write timeouts from Jordi Colomer, rehacked by rmk.
13   */
14  #include <linux/module.h>
15  #include <linux/io.h>
16  #include <linux/errno.h>
17  #include <linux/kernel.h>
18  #include <linux/delay.h>
19  #include <linux/spinlock.h>
20  #include <linux/platform_device.h>
21  #include <linux/pm.h>
22  #include <linux/mfd/mcp.h>
23  
24  #include <mach/hardware.h>
25  #include <asm/mach-types.h>
26  #include <linux/platform_data/mfd-mcp-sa11x0.h>
27  
28  #define DRIVER_NAME "sa11x0-mcp"
29  
30  struct mcp_sa11x0 {
31  	void __iomem	*base0;
32  	void __iomem	*base1;
33  	u32		mccr0;
34  	u32		mccr1;
35  };
36  
37  /* Register offsets */
38  #define MCCR0(m)	((m)->base0 + 0x00)
39  #define MCDR0(m)	((m)->base0 + 0x08)
40  #define MCDR1(m)	((m)->base0 + 0x0c)
41  #define MCDR2(m)	((m)->base0 + 0x10)
42  #define MCSR(m)		((m)->base0 + 0x18)
43  #define MCCR1(m)	((m)->base1 + 0x00)
44  
45  #define priv(mcp)	((struct mcp_sa11x0 *)mcp_priv(mcp))
46  
47  static void
mcp_sa11x0_set_telecom_divisor(struct mcp * mcp,unsigned int divisor)48  mcp_sa11x0_set_telecom_divisor(struct mcp *mcp, unsigned int divisor)
49  {
50  	struct mcp_sa11x0 *m = priv(mcp);
51  
52  	divisor /= 32;
53  
54  	m->mccr0 &= ~0x00007f00;
55  	m->mccr0 |= divisor << 8;
56  	writel_relaxed(m->mccr0, MCCR0(m));
57  }
58  
59  static void
mcp_sa11x0_set_audio_divisor(struct mcp * mcp,unsigned int divisor)60  mcp_sa11x0_set_audio_divisor(struct mcp *mcp, unsigned int divisor)
61  {
62  	struct mcp_sa11x0 *m = priv(mcp);
63  
64  	divisor /= 32;
65  
66  	m->mccr0 &= ~0x0000007f;
67  	m->mccr0 |= divisor;
68  	writel_relaxed(m->mccr0, MCCR0(m));
69  }
70  
71  /*
72   * Write data to the device.  The bit should be set after 3 subframe
73   * times (each frame is 64 clocks).  We wait a maximum of 6 subframes.
74   * We really should try doing something more productive while we
75   * wait.
76   */
77  static void
mcp_sa11x0_write(struct mcp * mcp,unsigned int reg,unsigned int val)78  mcp_sa11x0_write(struct mcp *mcp, unsigned int reg, unsigned int val)
79  {
80  	struct mcp_sa11x0 *m = priv(mcp);
81  	int ret = -ETIME;
82  	int i;
83  
84  	writel_relaxed(reg << 17 | MCDR2_Wr | (val & 0xffff), MCDR2(m));
85  
86  	for (i = 0; i < 2; i++) {
87  		udelay(mcp->rw_timeout);
88  		if (readl_relaxed(MCSR(m)) & MCSR_CWC) {
89  			ret = 0;
90  			break;
91  		}
92  	}
93  
94  	if (ret < 0)
95  		printk(KERN_WARNING "mcp: write timed out\n");
96  }
97  
98  /*
99   * Read data from the device.  The bit should be set after 3 subframe
100   * times (each frame is 64 clocks).  We wait a maximum of 6 subframes.
101   * We really should try doing something more productive while we
102   * wait.
103   */
104  static unsigned int
mcp_sa11x0_read(struct mcp * mcp,unsigned int reg)105  mcp_sa11x0_read(struct mcp *mcp, unsigned int reg)
106  {
107  	struct mcp_sa11x0 *m = priv(mcp);
108  	int ret = -ETIME;
109  	int i;
110  
111  	writel_relaxed(reg << 17 | MCDR2_Rd, MCDR2(m));
112  
113  	for (i = 0; i < 2; i++) {
114  		udelay(mcp->rw_timeout);
115  		if (readl_relaxed(MCSR(m)) & MCSR_CRC) {
116  			ret = readl_relaxed(MCDR2(m)) & 0xffff;
117  			break;
118  		}
119  	}
120  
121  	if (ret < 0)
122  		printk(KERN_WARNING "mcp: read timed out\n");
123  
124  	return ret;
125  }
126  
mcp_sa11x0_enable(struct mcp * mcp)127  static void mcp_sa11x0_enable(struct mcp *mcp)
128  {
129  	struct mcp_sa11x0 *m = priv(mcp);
130  
131  	writel(-1, MCSR(m));
132  	m->mccr0 |= MCCR0_MCE;
133  	writel_relaxed(m->mccr0, MCCR0(m));
134  }
135  
mcp_sa11x0_disable(struct mcp * mcp)136  static void mcp_sa11x0_disable(struct mcp *mcp)
137  {
138  	struct mcp_sa11x0 *m = priv(mcp);
139  
140  	m->mccr0 &= ~MCCR0_MCE;
141  	writel_relaxed(m->mccr0, MCCR0(m));
142  }
143  
144  /*
145   * Our methods.
146   */
147  static struct mcp_ops mcp_sa11x0 = {
148  	.set_telecom_divisor	= mcp_sa11x0_set_telecom_divisor,
149  	.set_audio_divisor	= mcp_sa11x0_set_audio_divisor,
150  	.reg_write		= mcp_sa11x0_write,
151  	.reg_read		= mcp_sa11x0_read,
152  	.enable			= mcp_sa11x0_enable,
153  	.disable		= mcp_sa11x0_disable,
154  };
155  
mcp_sa11x0_probe(struct platform_device * dev)156  static int mcp_sa11x0_probe(struct platform_device *dev)
157  {
158  	struct mcp_plat_data *data = dev_get_platdata(&dev->dev);
159  	struct resource *mem0, *mem1;
160  	struct mcp_sa11x0 *m;
161  	struct mcp *mcp;
162  	int ret;
163  
164  	if (!data)
165  		return -ENODEV;
166  
167  	mem0 = platform_get_resource(dev, IORESOURCE_MEM, 0);
168  	mem1 = platform_get_resource(dev, IORESOURCE_MEM, 1);
169  	if (!mem0 || !mem1)
170  		return -ENXIO;
171  
172  	if (!request_mem_region(mem0->start, resource_size(mem0),
173  				DRIVER_NAME)) {
174  		ret = -EBUSY;
175  		goto err_mem0;
176  	}
177  
178  	if (!request_mem_region(mem1->start, resource_size(mem1),
179  				DRIVER_NAME)) {
180  		ret = -EBUSY;
181  		goto err_mem1;
182  	}
183  
184  	mcp = mcp_host_alloc(&dev->dev, sizeof(struct mcp_sa11x0));
185  	if (!mcp) {
186  		ret = -ENOMEM;
187  		goto err_alloc;
188  	}
189  
190  	mcp->owner		= THIS_MODULE;
191  	mcp->ops		= &mcp_sa11x0;
192  	mcp->sclk_rate		= data->sclk_rate;
193  
194  	m = priv(mcp);
195  	m->mccr0 = data->mccr0 | 0x7f7f;
196  	m->mccr1 = data->mccr1;
197  
198  	m->base0 = ioremap(mem0->start, resource_size(mem0));
199  	m->base1 = ioremap(mem1->start, resource_size(mem1));
200  	if (!m->base0 || !m->base1) {
201  		ret = -ENOMEM;
202  		goto err_ioremap;
203  	}
204  
205  	platform_set_drvdata(dev, mcp);
206  
207  	/*
208  	 * Initialise device.  Note that we initially
209  	 * set the sampling rate to minimum.
210  	 */
211  	writel_relaxed(-1, MCSR(m));
212  	writel_relaxed(m->mccr1, MCCR1(m));
213  	writel_relaxed(m->mccr0, MCCR0(m));
214  
215  	/*
216  	 * Calculate the read/write timeout (us) from the bit clock
217  	 * rate.  This is the period for 3 64-bit frames.  Always
218  	 * round this time up.
219  	 */
220  	mcp->rw_timeout = (64 * 3 * 1000000 + mcp->sclk_rate - 1) /
221  			  mcp->sclk_rate;
222  
223  	ret = mcp_host_add(mcp, data->codec_pdata);
224  	if (ret == 0)
225  		return 0;
226  
227   err_ioremap:
228  	iounmap(m->base1);
229  	iounmap(m->base0);
230  	mcp_host_free(mcp);
231   err_alloc:
232  	release_mem_region(mem1->start, resource_size(mem1));
233   err_mem1:
234  	release_mem_region(mem0->start, resource_size(mem0));
235   err_mem0:
236  	return ret;
237  }
238  
mcp_sa11x0_remove(struct platform_device * dev)239  static int mcp_sa11x0_remove(struct platform_device *dev)
240  {
241  	struct mcp *mcp = platform_get_drvdata(dev);
242  	struct mcp_sa11x0 *m = priv(mcp);
243  	struct resource *mem0, *mem1;
244  
245  	if (m->mccr0 & MCCR0_MCE)
246  		dev_warn(&dev->dev,
247  			 "device left active (missing disable call?)\n");
248  
249  	mem0 = platform_get_resource(dev, IORESOURCE_MEM, 0);
250  	mem1 = platform_get_resource(dev, IORESOURCE_MEM, 1);
251  
252  	mcp_host_del(mcp);
253  	iounmap(m->base1);
254  	iounmap(m->base0);
255  	mcp_host_free(mcp);
256  	release_mem_region(mem1->start, resource_size(mem1));
257  	release_mem_region(mem0->start, resource_size(mem0));
258  
259  	return 0;
260  }
261  
262  #ifdef CONFIG_PM_SLEEP
mcp_sa11x0_suspend(struct device * dev)263  static int mcp_sa11x0_suspend(struct device *dev)
264  {
265  	struct mcp_sa11x0 *m = priv(dev_get_drvdata(dev));
266  
267  	if (m->mccr0 & MCCR0_MCE)
268  		dev_warn(dev, "device left active (missing disable call?)\n");
269  
270  	writel(m->mccr0 & ~MCCR0_MCE, MCCR0(m));
271  
272  	return 0;
273  }
274  
mcp_sa11x0_resume(struct device * dev)275  static int mcp_sa11x0_resume(struct device *dev)
276  {
277  	struct mcp_sa11x0 *m = priv(dev_get_drvdata(dev));
278  
279  	writel_relaxed(m->mccr1, MCCR1(m));
280  	writel_relaxed(m->mccr0, MCCR0(m));
281  
282  	return 0;
283  }
284  #endif
285  
286  static const struct dev_pm_ops mcp_sa11x0_pm_ops = {
287  #ifdef CONFIG_PM_SLEEP
288  	.suspend = mcp_sa11x0_suspend,
289  	.freeze = mcp_sa11x0_suspend,
290  	.poweroff = mcp_sa11x0_suspend,
291  	.resume_noirq = mcp_sa11x0_resume,
292  	.thaw_noirq = mcp_sa11x0_resume,
293  	.restore_noirq = mcp_sa11x0_resume,
294  #endif
295  };
296  
297  static struct platform_driver mcp_sa11x0_driver = {
298  	.probe		= mcp_sa11x0_probe,
299  	.remove		= mcp_sa11x0_remove,
300  	.driver		= {
301  		.name	= DRIVER_NAME,
302  		.pm	= &mcp_sa11x0_pm_ops,
303  	},
304  };
305  
306  /*
307   * This needs re-working
308   */
309  module_platform_driver(mcp_sa11x0_driver);
310  
311  MODULE_ALIAS("platform:" DRIVER_NAME);
312  MODULE_AUTHOR("Russell King <rmk@arm.linux.org.uk>");
313  MODULE_DESCRIPTION("SA11x0 multimedia communications port driver");
314  MODULE_LICENSE("GPL");
315