aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
Diffstat (limited to 'drivers')
-rw-r--r--drivers/mfd/mcp-sa11x0.c141
1 files changed, 99 insertions, 42 deletions
diff --git a/drivers/mfd/mcp-sa11x0.c b/drivers/mfd/mcp-sa11x0.c
index 703e76a77005..4d06db72bb9c 100644
--- a/drivers/mfd/mcp-sa11x0.c
+++ b/drivers/mfd/mcp-sa11x0.c
@@ -13,6 +13,7 @@
13 */ 13 */
14#include <linux/module.h> 14#include <linux/module.h>
15#include <linux/init.h> 15#include <linux/init.h>
16#include <linux/io.h>
16#include <linux/errno.h> 17#include <linux/errno.h>
17#include <linux/kernel.h> 18#include <linux/kernel.h>
18#include <linux/delay.h> 19#include <linux/delay.h>
@@ -30,34 +31,44 @@
30#define DRIVER_NAME "sa11x0-mcp" 31#define DRIVER_NAME "sa11x0-mcp"
31 32
32struct mcp_sa11x0 { 33struct mcp_sa11x0 {
33 u32 mccr0; 34 void __iomem *base0;
34 u32 mccr1; 35 void __iomem *base1;
36 u32 mccr0;
37 u32 mccr1;
35}; 38};
36 39
40/* Register offsets */
41#define MCCR0(m) ((m)->base0 + 0x00)
42#define MCDR0(m) ((m)->base0 + 0x08)
43#define MCDR1(m) ((m)->base0 + 0x0c)
44#define MCDR2(m) ((m)->base0 + 0x10)
45#define MCSR(m) ((m)->base0 + 0x18)
46#define MCCR1(m) ((m)->base1 + 0x00)
47
37#define priv(mcp) ((struct mcp_sa11x0 *)mcp_priv(mcp)) 48#define priv(mcp) ((struct mcp_sa11x0 *)mcp_priv(mcp))
38 49
39static void 50static void
40mcp_sa11x0_set_telecom_divisor(struct mcp *mcp, unsigned int divisor) 51mcp_sa11x0_set_telecom_divisor(struct mcp *mcp, unsigned int divisor)
41{ 52{
42 unsigned int mccr0; 53 struct mcp_sa11x0 *m = priv(mcp);
43 54
44 divisor /= 32; 55 divisor /= 32;
45 56
46 mccr0 = Ser4MCCR0 & ~0x00007f00; 57 m->mccr0 &= ~0x00007f00;
47 mccr0 |= divisor << 8; 58 m->mccr0 |= divisor << 8;
48 Ser4MCCR0 = mccr0; 59 writel_relaxed(m->mccr0, MCCR0(m));
49} 60}
50 61
51static void 62static void
52mcp_sa11x0_set_audio_divisor(struct mcp *mcp, unsigned int divisor) 63mcp_sa11x0_set_audio_divisor(struct mcp *mcp, unsigned int divisor)
53{ 64{
54 unsigned int mccr0; 65 struct mcp_sa11x0 *m = priv(mcp);
55 66
56 divisor /= 32; 67 divisor /= 32;
57 68
58 mccr0 = Ser4MCCR0 & ~0x0000007f; 69 m->mccr0 &= ~0x0000007f;
59 mccr0 |= divisor; 70 m->mccr0 |= divisor;
60 Ser4MCCR0 = mccr0; 71 writel_relaxed(m->mccr0, MCCR0(m));
61} 72}
62 73
63/* 74/*
@@ -69,14 +80,15 @@ mcp_sa11x0_set_audio_divisor(struct mcp *mcp, unsigned int divisor)
69static void 80static void
70mcp_sa11x0_write(struct mcp *mcp, unsigned int reg, unsigned int val) 81mcp_sa11x0_write(struct mcp *mcp, unsigned int reg, unsigned int val)
71{ 82{
83 struct mcp_sa11x0 *m = priv(mcp);
72 int ret = -ETIME; 84 int ret = -ETIME;
73 int i; 85 int i;
74 86
75 Ser4MCDR2 = reg << 17 | MCDR2_Wr | (val & 0xffff); 87 writel_relaxed(reg << 17 | MCDR2_Wr | (val & 0xffff), MCDR2(m));
76 88
77 for (i = 0; i < 2; i++) { 89 for (i = 0; i < 2; i++) {
78 udelay(mcp->rw_timeout); 90 udelay(mcp->rw_timeout);
79 if (Ser4MCSR & MCSR_CWC) { 91 if (readl_relaxed(MCSR(m)) & MCSR_CWC) {
80 ret = 0; 92 ret = 0;
81 break; 93 break;
82 } 94 }
@@ -95,15 +107,16 @@ mcp_sa11x0_write(struct mcp *mcp, unsigned int reg, unsigned int val)
95static unsigned int 107static unsigned int
96mcp_sa11x0_read(struct mcp *mcp, unsigned int reg) 108mcp_sa11x0_read(struct mcp *mcp, unsigned int reg)
97{ 109{
110 struct mcp_sa11x0 *m = priv(mcp);
98 int ret = -ETIME; 111 int ret = -ETIME;
99 int i; 112 int i;
100 113
101 Ser4MCDR2 = reg << 17 | MCDR2_Rd; 114 writel_relaxed(reg << 17 | MCDR2_Rd, MCDR2(m));
102 115
103 for (i = 0; i < 2; i++) { 116 for (i = 0; i < 2; i++) {
104 udelay(mcp->rw_timeout); 117 udelay(mcp->rw_timeout);
105 if (Ser4MCSR & MCSR_CRC) { 118 if (readl_relaxed(MCSR(m)) & MCSR_CRC) {
106 ret = Ser4MCDR2 & 0xffff; 119 ret = readl_relaxed(MCDR2(m)) & 0xffff;
107 break; 120 break;
108 } 121 }
109 } 122 }
@@ -116,13 +129,19 @@ mcp_sa11x0_read(struct mcp *mcp, unsigned int reg)
116 129
117static void mcp_sa11x0_enable(struct mcp *mcp) 130static void mcp_sa11x0_enable(struct mcp *mcp)
118{ 131{
119 Ser4MCSR = -1; 132 struct mcp_sa11x0 *m = priv(mcp);
120 Ser4MCCR0 |= MCCR0_MCE; 133
134 writel(-1, MCSR(m));
135 m->mccr0 |= MCCR0_MCE;
136 writel_relaxed(m->mccr0, MCCR0(m));
121} 137}
122 138
123static void mcp_sa11x0_disable(struct mcp *mcp) 139static void mcp_sa11x0_disable(struct mcp *mcp)
124{ 140{
125 Ser4MCCR0 &= ~MCCR0_MCE; 141 struct mcp_sa11x0 *m = priv(mcp);
142
143 m->mccr0 &= ~MCCR0_MCE;
144 writel_relaxed(m->mccr0, MCCR0(m));
126} 145}
127 146
128/* 147/*
@@ -137,22 +156,38 @@ static struct mcp_ops mcp_sa11x0 = {
137 .disable = mcp_sa11x0_disable, 156 .disable = mcp_sa11x0_disable,
138}; 157};
139 158
140static int mcp_sa11x0_probe(struct platform_device *pdev) 159static int mcp_sa11x0_probe(struct platform_device *dev)
141{ 160{
142 struct mcp_plat_data *data = pdev->dev.platform_data; 161 struct mcp_plat_data *data = dev->dev.platform_data;
162 struct resource *mem0, *mem1;
163 struct mcp_sa11x0 *m;
143 struct mcp *mcp; 164 struct mcp *mcp;
144 int ret; 165 int ret;
145 166
146 if (!data) 167 if (!data)
147 return -ENODEV; 168 return -ENODEV;
148 169
149 if (!request_mem_region(0x80060000, 0x60, "sa11x0-mcp")) 170 mem0 = platform_get_resource(dev, IORESOURCE_MEM, 0);
150 return -EBUSY; 171 mem1 = platform_get_resource(dev, IORESOURCE_MEM, 1);
172 if (!mem0 || !mem1)
173 return -ENXIO;
174
175 if (!request_mem_region(mem0->start, resource_size(mem0),
176 DRIVER_NAME)) {
177 ret = -EBUSY;
178 goto err_mem0;
179 }
151 180
152 mcp = mcp_host_alloc(&pdev->dev, sizeof(struct mcp_sa11x0)); 181 if (!request_mem_region(mem1->start, resource_size(mem1),
182 DRIVER_NAME)) {
183 ret = -EBUSY;
184 goto err_mem1;
185 }
186
187 mcp = mcp_host_alloc(&dev->dev, sizeof(struct mcp_sa11x0));
153 if (!mcp) { 188 if (!mcp) {
154 ret = -ENOMEM; 189 ret = -ENOMEM;
155 goto release; 190 goto err_alloc;
156 } 191 }
157 192
158 mcp->owner = THIS_MODULE; 193 mcp->owner = THIS_MODULE;
@@ -160,7 +195,18 @@ static int mcp_sa11x0_probe(struct platform_device *pdev)
160 mcp->sclk_rate = data->sclk_rate; 195 mcp->sclk_rate = data->sclk_rate;
161 mcp->gpio_base = data->gpio_base; 196 mcp->gpio_base = data->gpio_base;
162 197
163 platform_set_drvdata(pdev, mcp); 198 m = priv(mcp);
199 m->mccr0 = data->mccr0 | 0x7f7f;
200 m->mccr1 = data->mccr1;
201
202 m->base0 = ioremap(mem0->start, resource_size(mem0));
203 m->base1 = ioremap(mem1->start, resource_size(mem1));
204 if (!m->base0 || !m->base1) {
205 ret = -ENOMEM;
206 goto err_ioremap;
207 }
208
209 platform_set_drvdata(dev, mcp);
164 210
165 if (machine_is_assabet()) { 211 if (machine_is_assabet()) {
166 ASSABET_BCR_set(ASSABET_BCR_CODEC_RST); 212 ASSABET_BCR_set(ASSABET_BCR_CODEC_RST);
@@ -170,9 +216,9 @@ static int mcp_sa11x0_probe(struct platform_device *pdev)
170 * Initialise device. Note that we initially 216 * Initialise device. Note that we initially
171 * set the sampling rate to minimum. 217 * set the sampling rate to minimum.
172 */ 218 */
173 Ser4MCSR = -1; 219 writel_relaxed(-1, MCSR(m));
174 Ser4MCCR1 = data->mccr1; 220 writel_relaxed(m->mccr1, MCCR1(m));
175 Ser4MCCR0 = data->mccr0 | 0x7f7f; 221 writel_relaxed(m->mccr0, MCCR0(m));
176 222
177 /* 223 /*
178 * Calculate the read/write timeout (us) from the bit clock 224 * Calculate the read/write timeout (us) from the bit clock
@@ -184,46 +230,57 @@ static int mcp_sa11x0_probe(struct platform_device *pdev)
184 230
185 ret = mcp_host_add(mcp); 231 ret = mcp_host_add(mcp);
186 if (ret == 0) 232 if (ret == 0)
187 goto out; 233 return 0;
188 234
189 mcp_host_free(mcp); 235 platform_set_drvdata(dev, NULL);
190 release:
191 release_mem_region(0x80060000, 0x60);
192 platform_set_drvdata(pdev, NULL);
193 236
194 out: 237 err_ioremap:
238 iounmap(m->base1);
239 iounmap(m->base0);
240 mcp_host_free(mcp);
241 err_alloc:
242 release_mem_region(mem1->start, resource_size(mem1));
243 err_mem1:
244 release_mem_region(mem0->start, resource_size(mem0));
245 err_mem0:
195 return ret; 246 return ret;
196} 247}
197 248
198static int mcp_sa11x0_remove(struct platform_device *dev) 249static int mcp_sa11x0_remove(struct platform_device *dev)
199{ 250{
200 struct mcp *mcp = platform_get_drvdata(dev); 251 struct mcp *mcp = platform_get_drvdata(dev);
252 struct mcp_sa11x0 *m = priv(mcp);
253 struct resource *mem0, *mem1;
254
255 mem0 = platform_get_resource(dev, IORESOURCE_MEM, 0);
256 mem1 = platform_get_resource(dev, IORESOURCE_MEM, 1);
201 257
202 platform_set_drvdata(dev, NULL); 258 platform_set_drvdata(dev, NULL);
203 mcp_host_del(mcp); 259 mcp_host_del(mcp);
260 iounmap(m->base1);
261 iounmap(m->base0);
204 mcp_host_free(mcp); 262 mcp_host_free(mcp);
205 release_mem_region(0x80060000, 0x60); 263 release_mem_region(mem1->start, resource_size(mem1));
264 release_mem_region(mem0->start, resource_size(mem0));
206 265
207 return 0; 266 return 0;
208} 267}
209 268
210static int mcp_sa11x0_suspend(struct platform_device *dev, pm_message_t state) 269static int mcp_sa11x0_suspend(struct platform_device *dev, pm_message_t state)
211{ 270{
212 struct mcp *mcp = platform_get_drvdata(dev); 271 struct mcp_sa11x0 *m = priv(platform_get_drvdata(dev));
213 272
214 priv(mcp)->mccr0 = Ser4MCCR0; 273 writel(m->mccr0 & ~MCCR0_MCE, MCCR0(m));
215 priv(mcp)->mccr1 = Ser4MCCR1;
216 Ser4MCCR0 &= ~MCCR0_MCE;
217 274
218 return 0; 275 return 0;
219} 276}
220 277
221static int mcp_sa11x0_resume(struct platform_device *dev) 278static int mcp_sa11x0_resume(struct platform_device *dev)
222{ 279{
223 struct mcp *mcp = platform_get_drvdata(dev); 280 struct mcp_sa11x0 *m = priv(platform_get_drvdata(dev));
224 281
225 Ser4MCCR1 = priv(mcp)->mccr1; 282 writel_relaxed(m->mccr1, MCCR1(m));
226 Ser4MCCR0 = priv(mcp)->mccr0; 283 writel_relaxed(m->mccr0, MCCR0(m));
227 284
228 return 0; 285 return 0;
229} 286}