2 * linux/drivers/mfd/mcp-sa11x0.c
4 * Copyright (C) 2001-2005 Russell King
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.
10 * SA11x0 MCP (Multimedia Communications Port) driver.
12 * MCP read/write timeouts from Jordi Colomer, rehacked by rmk.
14 #include <linux/module.h>
15 #include <linux/init.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/mfd/mcp.h>
24 #include <mach/hardware.h>
25 #include <asm/mach-types.h>
26 #include <asm/system.h>
29 #include <mach/assabet.h>
37 #define priv(mcp) ((struct mcp_sa11x0 *)mcp_priv(mcp))
40 mcp_sa11x0_set_telecom_divisor(struct mcp
*mcp
, unsigned int divisor
)
46 mccr0
= Ser4MCCR0
& ~0x00007f00;
47 mccr0
|= divisor
<< 8;
52 mcp_sa11x0_set_audio_divisor(struct mcp
*mcp
, unsigned int divisor
)
58 mccr0
= Ser4MCCR0
& ~0x0000007f;
64 * Write data to the device. The bit should be set after 3 subframe
65 * times (each frame is 64 clocks). We wait a maximum of 6 subframes.
66 * We really should try doing something more productive while we
70 mcp_sa11x0_write(struct mcp
*mcp
, unsigned int reg
, unsigned int val
)
75 Ser4MCDR2
= reg
<< 17 | MCDR2_Wr
| (val
& 0xffff);
77 for (i
= 0; i
< 2; i
++) {
78 udelay(mcp
->rw_timeout
);
79 if (Ser4MCSR
& MCSR_CWC
) {
86 printk(KERN_WARNING
"mcp: write timed out\n");
90 * Read data from the device. The bit should be set after 3 subframe
91 * times (each frame is 64 clocks). We wait a maximum of 6 subframes.
92 * We really should try doing something more productive while we
96 mcp_sa11x0_read(struct mcp
*mcp
, unsigned int reg
)
101 Ser4MCDR2
= reg
<< 17 | MCDR2_Rd
;
103 for (i
= 0; i
< 2; i
++) {
104 udelay(mcp
->rw_timeout
);
105 if (Ser4MCSR
& MCSR_CRC
) {
106 ret
= Ser4MCDR2
& 0xffff;
112 printk(KERN_WARNING
"mcp: read timed out\n");
117 static void mcp_sa11x0_enable(struct mcp
*mcp
)
120 Ser4MCCR0
|= MCCR0_MCE
;
123 static void mcp_sa11x0_disable(struct mcp
*mcp
)
125 Ser4MCCR0
&= ~MCCR0_MCE
;
131 static struct mcp_ops mcp_sa11x0
= {
132 .set_telecom_divisor
= mcp_sa11x0_set_telecom_divisor
,
133 .set_audio_divisor
= mcp_sa11x0_set_audio_divisor
,
134 .reg_write
= mcp_sa11x0_write
,
135 .reg_read
= mcp_sa11x0_read
,
136 .enable
= mcp_sa11x0_enable
,
137 .disable
= mcp_sa11x0_disable
,
140 static int mcp_sa11x0_probe(struct platform_device
*pdev
)
142 struct mcp_plat_data
*data
= pdev
->dev
.platform_data
;
149 if (!request_mem_region(0x80060000, 0x60, "sa11x0-mcp"))
152 mcp
= mcp_host_alloc(&pdev
->dev
, sizeof(struct mcp_sa11x0
));
158 mcp
->owner
= THIS_MODULE
;
159 mcp
->ops
= &mcp_sa11x0
;
160 mcp
->sclk_rate
= data
->sclk_rate
;
161 mcp
->dma_audio_rd
= DMA_Ser4MCP0Rd
;
162 mcp
->dma_audio_wr
= DMA_Ser4MCP0Wr
;
163 mcp
->dma_telco_rd
= DMA_Ser4MCP1Rd
;
164 mcp
->dma_telco_wr
= DMA_Ser4MCP1Wr
;
165 mcp
->gpio_base
= data
->gpio_base
;
167 platform_set_drvdata(pdev
, mcp
);
169 if (machine_is_assabet()) {
170 ASSABET_BCR_set(ASSABET_BCR_CODEC_RST
);
174 * Setup the PPC unit correctly.
177 PPDR
|= PPC_TXD4
| PPC_SCLK
| PPC_SFRM
;
179 PSDR
&= ~(PPC_TXD4
| PPC_SCLK
| PPC_SFRM
);
180 PPSR
&= ~(PPC_TXD4
| PPC_SCLK
| PPC_SFRM
);
183 * Initialise device. Note that we initially
184 * set the sampling rate to minimum.
187 Ser4MCCR1
= data
->mccr1
;
188 Ser4MCCR0
= data
->mccr0
| 0x7f7f;
191 * Calculate the read/write timeout (us) from the bit clock
192 * rate. This is the period for 3 64-bit frames. Always
193 * round this time up.
195 mcp
->rw_timeout
= (64 * 3 * 1000000 + mcp
->sclk_rate
- 1) /
198 ret
= mcp_host_register(mcp
);
203 release_mem_region(0x80060000, 0x60);
204 platform_set_drvdata(pdev
, NULL
);
210 static int mcp_sa11x0_remove(struct platform_device
*dev
)
212 struct mcp
*mcp
= platform_get_drvdata(dev
);
214 platform_set_drvdata(dev
, NULL
);
215 mcp_host_unregister(mcp
);
216 release_mem_region(0x80060000, 0x60);
221 static int mcp_sa11x0_suspend(struct platform_device
*dev
, pm_message_t state
)
223 struct mcp
*mcp
= platform_get_drvdata(dev
);
225 priv(mcp
)->mccr0
= Ser4MCCR0
;
226 priv(mcp
)->mccr1
= Ser4MCCR1
;
227 Ser4MCCR0
&= ~MCCR0_MCE
;
232 static int mcp_sa11x0_resume(struct platform_device
*dev
)
234 struct mcp
*mcp
= platform_get_drvdata(dev
);
236 Ser4MCCR1
= priv(mcp
)->mccr1
;
237 Ser4MCCR0
= priv(mcp
)->mccr0
;
243 * The driver for the SA11x0 MCP port.
245 MODULE_ALIAS("platform:sa11x0-mcp");
247 static struct platform_driver mcp_sa11x0_driver
= {
248 .probe
= mcp_sa11x0_probe
,
249 .remove
= mcp_sa11x0_remove
,
250 .suspend
= mcp_sa11x0_suspend
,
251 .resume
= mcp_sa11x0_resume
,
253 .name
= "sa11x0-mcp",
258 * This needs re-working
260 static int __init
mcp_sa11x0_init(void)
262 return platform_driver_register(&mcp_sa11x0_driver
);
265 static void __exit
mcp_sa11x0_exit(void)
267 platform_driver_unregister(&mcp_sa11x0_driver
);
270 module_init(mcp_sa11x0_init
);
271 module_exit(mcp_sa11x0_exit
);
273 MODULE_AUTHOR("Russell King <rmk@arm.linux.org.uk>");
274 MODULE_DESCRIPTION("SA11x0 multimedia communications port driver");
275 MODULE_LICENSE("GPL");