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/slab.h>
21 #include <linux/platform_device.h>
24 #include <asm/hardware.h>
25 #include <asm/mach-types.h>
26 #include <asm/system.h>
27 #include <asm/arch/mcp.h>
29 #include <asm/arch/assabet.h>
38 #define priv(mcp) ((struct mcp_sa11x0 *)mcp_priv(mcp))
41 mcp_sa11x0_set_telecom_divisor(struct mcp
*mcp
, unsigned int divisor
)
47 mccr0
= Ser4MCCR0
& ~0x00007f00;
48 mccr0
|= divisor
<< 8;
53 mcp_sa11x0_set_audio_divisor(struct mcp
*mcp
, unsigned int divisor
)
59 mccr0
= Ser4MCCR0
& ~0x0000007f;
65 * Write data to the device. The bit should be set after 3 subframe
66 * times (each frame is 64 clocks). We wait a maximum of 6 subframes.
67 * We really should try doing something more productive while we
71 mcp_sa11x0_write(struct mcp
*mcp
, unsigned int reg
, unsigned int val
)
76 Ser4MCDR2
= reg
<< 17 | MCDR2_Wr
| (val
& 0xffff);
78 for (i
= 0; i
< 2; i
++) {
79 udelay(mcp
->rw_timeout
);
80 if (Ser4MCSR
& MCSR_CWC
) {
87 printk(KERN_WARNING
"mcp: write timed out\n");
91 * Read data from the device. The bit should be set after 3 subframe
92 * times (each frame is 64 clocks). We wait a maximum of 6 subframes.
93 * We really should try doing something more productive while we
97 mcp_sa11x0_read(struct mcp
*mcp
, unsigned int reg
)
102 Ser4MCDR2
= reg
<< 17 | MCDR2_Rd
;
104 for (i
= 0; i
< 2; i
++) {
105 udelay(mcp
->rw_timeout
);
106 if (Ser4MCSR
& MCSR_CRC
) {
107 ret
= Ser4MCDR2
& 0xffff;
113 printk(KERN_WARNING
"mcp: read timed out\n");
118 static void mcp_sa11x0_enable(struct mcp
*mcp
)
121 Ser4MCCR0
|= MCCR0_MCE
;
124 static void mcp_sa11x0_disable(struct mcp
*mcp
)
126 Ser4MCCR0
&= ~MCCR0_MCE
;
132 static struct mcp_ops mcp_sa11x0
= {
133 .set_telecom_divisor
= mcp_sa11x0_set_telecom_divisor
,
134 .set_audio_divisor
= mcp_sa11x0_set_audio_divisor
,
135 .reg_write
= mcp_sa11x0_write
,
136 .reg_read
= mcp_sa11x0_read
,
137 .enable
= mcp_sa11x0_enable
,
138 .disable
= mcp_sa11x0_disable
,
141 static int mcp_sa11x0_probe(struct platform_device
*pdev
)
143 struct mcp_plat_data
*data
= pdev
->dev
.platform_data
;
150 if (!request_mem_region(0x80060000, 0x60, "sa11x0-mcp"))
153 mcp
= mcp_host_alloc(&pdev
->dev
, sizeof(struct mcp_sa11x0
));
159 mcp
->owner
= THIS_MODULE
;
160 mcp
->ops
= &mcp_sa11x0
;
161 mcp
->sclk_rate
= data
->sclk_rate
;
162 mcp
->dma_audio_rd
= DMA_Ser4MCP0Rd
;
163 mcp
->dma_audio_wr
= DMA_Ser4MCP0Wr
;
164 mcp
->dma_telco_rd
= DMA_Ser4MCP1Rd
;
165 mcp
->dma_telco_wr
= DMA_Ser4MCP1Wr
;
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 static struct platform_driver mcp_sa11x0_driver
= {
246 .probe
= mcp_sa11x0_probe
,
247 .remove
= mcp_sa11x0_remove
,
248 .suspend
= mcp_sa11x0_suspend
,
249 .resume
= mcp_sa11x0_resume
,
251 .name
= "sa11x0-mcp",
256 * This needs re-working
258 static int __init
mcp_sa11x0_init(void)
260 return platform_driver_register(&mcp_sa11x0_driver
);
263 static void __exit
mcp_sa11x0_exit(void)
265 platform_driver_unregister(&mcp_sa11x0_driver
);
268 module_init(mcp_sa11x0_init
);
269 module_exit(mcp_sa11x0_exit
);
271 MODULE_AUTHOR("Russell King <rmk@arm.linux.org.uk>");
272 MODULE_DESCRIPTION("SA11x0 multimedia communications port driver");
273 MODULE_LICENSE("GPL");