Merge remote-tracking branch 'sound-asoc/for-next'
[deliverable/linux.git] / drivers / net / dsa / b53 / b53_srab.c
CommitLineData
967dd82f
FF
1/*
2 * B53 register access through Switch Register Access Bridge Registers
3 *
4 * Copyright (C) 2013 Hauke Mehrtens <hauke@hauke-m.de>
5 *
6 * Permission to use, copy, modify, and/or distribute this software for any
7 * purpose with or without fee is hereby granted, provided that the above
8 * copyright notice and this permission notice appear in all copies.
9 *
10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17 */
18
19#include <linux/kernel.h>
20#include <linux/module.h>
21#include <linux/delay.h>
22#include <linux/platform_device.h>
23#include <linux/platform_data/b53.h>
fefae690 24#include <linux/of.h>
967dd82f
FF
25
26#include "b53_priv.h"
27
28/* command and status register of the SRAB */
29#define B53_SRAB_CMDSTAT 0x2c
30#define B53_SRAB_CMDSTAT_RST BIT(2)
31#define B53_SRAB_CMDSTAT_WRITE BIT(1)
32#define B53_SRAB_CMDSTAT_GORDYN BIT(0)
33#define B53_SRAB_CMDSTAT_PAGE 24
34#define B53_SRAB_CMDSTAT_REG 16
35
36/* high order word of write data to switch registe */
37#define B53_SRAB_WD_H 0x30
38
39/* low order word of write data to switch registe */
40#define B53_SRAB_WD_L 0x34
41
42/* high order word of read data from switch register */
43#define B53_SRAB_RD_H 0x38
44
45/* low order word of read data from switch register */
46#define B53_SRAB_RD_L 0x3c
47
48/* command and status register of the SRAB */
49#define B53_SRAB_CTRLS 0x40
50#define B53_SRAB_CTRLS_RCAREQ BIT(3)
51#define B53_SRAB_CTRLS_RCAGNT BIT(4)
52#define B53_SRAB_CTRLS_SW_INIT_DONE BIT(6)
53
54/* the register captures interrupt pulses from the switch */
55#define B53_SRAB_INTR 0x44
56#define B53_SRAB_INTR_P(x) BIT(x)
57#define B53_SRAB_SWITCH_PHY BIT(8)
58#define B53_SRAB_1588_SYNC BIT(9)
59#define B53_SRAB_IMP1_SLEEP_TIMER BIT(10)
60#define B53_SRAB_P7_SLEEP_TIMER BIT(11)
61#define B53_SRAB_IMP0_SLEEP_TIMER BIT(12)
62
63struct b53_srab_priv {
64 void __iomem *regs;
65};
66
67static int b53_srab_request_grant(struct b53_device *dev)
68{
69 struct b53_srab_priv *priv = dev->priv;
70 u8 __iomem *regs = priv->regs;
71 u32 ctrls;
72 int i;
73
74 ctrls = readl(regs + B53_SRAB_CTRLS);
75 ctrls |= B53_SRAB_CTRLS_RCAREQ;
76 writel(ctrls, regs + B53_SRAB_CTRLS);
77
78 for (i = 0; i < 20; i++) {
79 ctrls = readl(regs + B53_SRAB_CTRLS);
80 if (ctrls & B53_SRAB_CTRLS_RCAGNT)
81 break;
82 usleep_range(10, 100);
83 }
84 if (WARN_ON(i == 5))
85 return -EIO;
86
87 return 0;
88}
89
90static void b53_srab_release_grant(struct b53_device *dev)
91{
92 struct b53_srab_priv *priv = dev->priv;
93 u8 __iomem *regs = priv->regs;
94 u32 ctrls;
95
96 ctrls = readl(regs + B53_SRAB_CTRLS);
97 ctrls &= ~B53_SRAB_CTRLS_RCAREQ;
98 writel(ctrls, regs + B53_SRAB_CTRLS);
99}
100
101static int b53_srab_op(struct b53_device *dev, u8 page, u8 reg, u32 op)
102{
103 struct b53_srab_priv *priv = dev->priv;
104 u8 __iomem *regs = priv->regs;
105 int i;
106 u32 cmdstat;
107
108 /* set register address */
109 cmdstat = (page << B53_SRAB_CMDSTAT_PAGE) |
110 (reg << B53_SRAB_CMDSTAT_REG) |
111 B53_SRAB_CMDSTAT_GORDYN |
112 op;
113 writel(cmdstat, regs + B53_SRAB_CMDSTAT);
114
115 /* check if operation completed */
116 for (i = 0; i < 5; ++i) {
117 cmdstat = readl(regs + B53_SRAB_CMDSTAT);
118 if (!(cmdstat & B53_SRAB_CMDSTAT_GORDYN))
119 break;
120 usleep_range(10, 100);
121 }
122
123 if (WARN_ON(i == 5))
124 return -EIO;
125
126 return 0;
127}
128
129static int b53_srab_read8(struct b53_device *dev, u8 page, u8 reg, u8 *val)
130{
131 struct b53_srab_priv *priv = dev->priv;
132 u8 __iomem *regs = priv->regs;
133 int ret = 0;
134
135 ret = b53_srab_request_grant(dev);
136 if (ret)
137 goto err;
138
139 ret = b53_srab_op(dev, page, reg, 0);
140 if (ret)
141 goto err;
142
143 *val = readl(regs + B53_SRAB_RD_L) & 0xff;
144
145err:
146 b53_srab_release_grant(dev);
147
148 return ret;
149}
150
151static int b53_srab_read16(struct b53_device *dev, u8 page, u8 reg, u16 *val)
152{
153 struct b53_srab_priv *priv = dev->priv;
154 u8 __iomem *regs = priv->regs;
155 int ret = 0;
156
157 ret = b53_srab_request_grant(dev);
158 if (ret)
159 goto err;
160
161 ret = b53_srab_op(dev, page, reg, 0);
162 if (ret)
163 goto err;
164
165 *val = readl(regs + B53_SRAB_RD_L) & 0xffff;
166
167err:
168 b53_srab_release_grant(dev);
169
170 return ret;
171}
172
173static int b53_srab_read32(struct b53_device *dev, u8 page, u8 reg, u32 *val)
174{
175 struct b53_srab_priv *priv = dev->priv;
176 u8 __iomem *regs = priv->regs;
177 int ret = 0;
178
179 ret = b53_srab_request_grant(dev);
180 if (ret)
181 goto err;
182
183 ret = b53_srab_op(dev, page, reg, 0);
184 if (ret)
185 goto err;
186
187 *val = readl(regs + B53_SRAB_RD_L);
188
189err:
190 b53_srab_release_grant(dev);
191
192 return ret;
193}
194
195static int b53_srab_read48(struct b53_device *dev, u8 page, u8 reg, u64 *val)
196{
197 struct b53_srab_priv *priv = dev->priv;
198 u8 __iomem *regs = priv->regs;
199 int ret = 0;
200
201 ret = b53_srab_request_grant(dev);
202 if (ret)
203 goto err;
204
205 ret = b53_srab_op(dev, page, reg, 0);
206 if (ret)
207 goto err;
208
209 *val = readl(regs + B53_SRAB_RD_L);
210 *val += ((u64)readl(regs + B53_SRAB_RD_H) & 0xffff) << 32;
211
212err:
213 b53_srab_release_grant(dev);
214
215 return ret;
216}
217
218static int b53_srab_read64(struct b53_device *dev, u8 page, u8 reg, u64 *val)
219{
220 struct b53_srab_priv *priv = dev->priv;
221 u8 __iomem *regs = priv->regs;
222 int ret = 0;
223
224 ret = b53_srab_request_grant(dev);
225 if (ret)
226 goto err;
227
228 ret = b53_srab_op(dev, page, reg, 0);
229 if (ret)
230 goto err;
231
232 *val = readl(regs + B53_SRAB_RD_L);
233 *val += (u64)readl(regs + B53_SRAB_RD_H) << 32;
234
235err:
236 b53_srab_release_grant(dev);
237
238 return ret;
239}
240
241static int b53_srab_write8(struct b53_device *dev, u8 page, u8 reg, u8 value)
242{
243 struct b53_srab_priv *priv = dev->priv;
244 u8 __iomem *regs = priv->regs;
245 int ret = 0;
246
247 ret = b53_srab_request_grant(dev);
248 if (ret)
249 goto err;
250
251 writel(value, regs + B53_SRAB_WD_L);
252
253 ret = b53_srab_op(dev, page, reg, B53_SRAB_CMDSTAT_WRITE);
254
255err:
256 b53_srab_release_grant(dev);
257
258 return ret;
259}
260
261static int b53_srab_write16(struct b53_device *dev, u8 page, u8 reg,
262 u16 value)
263{
264 struct b53_srab_priv *priv = dev->priv;
265 u8 __iomem *regs = priv->regs;
266 int ret = 0;
267
268 ret = b53_srab_request_grant(dev);
269 if (ret)
270 goto err;
271
272 writel(value, regs + B53_SRAB_WD_L);
273
274 ret = b53_srab_op(dev, page, reg, B53_SRAB_CMDSTAT_WRITE);
275
276err:
277 b53_srab_release_grant(dev);
278
279 return ret;
280}
281
282static int b53_srab_write32(struct b53_device *dev, u8 page, u8 reg,
283 u32 value)
284{
285 struct b53_srab_priv *priv = dev->priv;
286 u8 __iomem *regs = priv->regs;
287 int ret = 0;
288
289 ret = b53_srab_request_grant(dev);
290 if (ret)
291 goto err;
292
293 writel(value, regs + B53_SRAB_WD_L);
294
295 ret = b53_srab_op(dev, page, reg, B53_SRAB_CMDSTAT_WRITE);
296
297err:
298 b53_srab_release_grant(dev);
299
300 return ret;
301}
302
303static int b53_srab_write48(struct b53_device *dev, u8 page, u8 reg,
304 u64 value)
305{
306 struct b53_srab_priv *priv = dev->priv;
307 u8 __iomem *regs = priv->regs;
308 int ret = 0;
309
310 ret = b53_srab_request_grant(dev);
311 if (ret)
312 goto err;
313
314 writel((u32)value, regs + B53_SRAB_WD_L);
315 writel((u16)(value >> 32), regs + B53_SRAB_WD_H);
316
317 ret = b53_srab_op(dev, page, reg, B53_SRAB_CMDSTAT_WRITE);
318
319err:
320 b53_srab_release_grant(dev);
321
322 return ret;
323}
324
325static int b53_srab_write64(struct b53_device *dev, u8 page, u8 reg,
326 u64 value)
327{
328 struct b53_srab_priv *priv = dev->priv;
329 u8 __iomem *regs = priv->regs;
330 int ret = 0;
331
332 ret = b53_srab_request_grant(dev);
333 if (ret)
334 goto err;
335
336 writel((u32)value, regs + B53_SRAB_WD_L);
337 writel((u32)(value >> 32), regs + B53_SRAB_WD_H);
338
339 ret = b53_srab_op(dev, page, reg, B53_SRAB_CMDSTAT_WRITE);
340
341err:
342 b53_srab_release_grant(dev);
343
344 return ret;
345}
346
0dff88d3 347static const struct b53_io_ops b53_srab_ops = {
967dd82f
FF
348 .read8 = b53_srab_read8,
349 .read16 = b53_srab_read16,
350 .read32 = b53_srab_read32,
351 .read48 = b53_srab_read48,
352 .read64 = b53_srab_read64,
353 .write8 = b53_srab_write8,
354 .write16 = b53_srab_write16,
355 .write32 = b53_srab_write32,
356 .write48 = b53_srab_write48,
357 .write64 = b53_srab_write64,
358};
359
fefae690
FF
360static const struct of_device_id b53_srab_of_match[] = {
361 { .compatible = "brcm,bcm53010-srab" },
362 { .compatible = "brcm,bcm53011-srab" },
363 { .compatible = "brcm,bcm53012-srab" },
364 { .compatible = "brcm,bcm53018-srab" },
365 { .compatible = "brcm,bcm53019-srab" },
366 { .compatible = "brcm,bcm5301x-srab" },
991a36bb
FF
367 { .compatible = "brcm,bcm58522-srab", .data = (void *)BCM58XX_DEVICE_ID },
368 { .compatible = "brcm,bcm58525-srab", .data = (void *)BCM58XX_DEVICE_ID },
369 { .compatible = "brcm,bcm58535-srab", .data = (void *)BCM58XX_DEVICE_ID },
370 { .compatible = "brcm,bcm58622-srab", .data = (void *)BCM58XX_DEVICE_ID },
371 { .compatible = "brcm,bcm58623-srab", .data = (void *)BCM58XX_DEVICE_ID },
372 { .compatible = "brcm,bcm58625-srab", .data = (void *)BCM58XX_DEVICE_ID },
373 { .compatible = "brcm,bcm88312-srab", .data = (void *)BCM58XX_DEVICE_ID },
374 { .compatible = "brcm,nsp-srab", .data = (void *)BCM58XX_DEVICE_ID },
fefae690
FF
375 { /* sentinel */ },
376};
377MODULE_DEVICE_TABLE(of, b53_srab_of_match);
378
967dd82f
FF
379static int b53_srab_probe(struct platform_device *pdev)
380{
fefae690
FF
381 struct b53_platform_data *pdata = pdev->dev.platform_data;
382 struct device_node *dn = pdev->dev.of_node;
383 const struct of_device_id *of_id = NULL;
967dd82f
FF
384 struct b53_srab_priv *priv;
385 struct b53_device *dev;
386 struct resource *r;
387
fefae690
FF
388 if (dn)
389 of_id = of_match_node(b53_srab_of_match, dn);
390
391 if (of_id) {
392 pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL);
393 if (!pdata)
394 return -ENOMEM;
395
cf81b2cc 396 pdata->chip_id = (u32)(unsigned long)of_id->data;
fefae690
FF
397 }
398
967dd82f
FF
399 priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);
400 if (!priv)
401 return -ENOMEM;
402
403 r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
404 priv->regs = devm_ioremap_resource(&pdev->dev, r);
405 if (IS_ERR(priv->regs))
406 return -ENOMEM;
407
408 dev = b53_switch_alloc(&pdev->dev, &b53_srab_ops, priv);
409 if (!dev)
410 return -ENOMEM;
411
fefae690
FF
412 if (pdata)
413 dev->pdata = pdata;
414
967dd82f
FF
415 platform_set_drvdata(pdev, dev);
416
417 return b53_switch_register(dev);
418}
419
420static int b53_srab_remove(struct platform_device *pdev)
421{
422 struct b53_device *dev = platform_get_drvdata(pdev);
423
424 if (dev)
425 b53_switch_remove(dev);
426
427 return 0;
428}
429
967dd82f
FF
430static struct platform_driver b53_srab_driver = {
431 .probe = b53_srab_probe,
432 .remove = b53_srab_remove,
433 .driver = {
434 .name = "b53-srab-switch",
435 .of_match_table = b53_srab_of_match,
436 },
437};
438
439module_platform_driver(b53_srab_driver);
440MODULE_AUTHOR("Hauke Mehrtens <hauke@hauke-m.de>");
441MODULE_DESCRIPTION("B53 Switch Register Access Bridge Registers (SRAB) access driver");
442MODULE_LICENSE("Dual BSD/GPL");
This page took 0.06878 seconds and 5 git commands to generate.