2 * B53 register access through Switch Register Access Bridge Registers
4 * Copyright (C) 2013 Hauke Mehrtens <hauke@hauke-m.de>
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.
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.
19 #include <linux/kernel.h>
20 #include <linux/module.h>
21 #include <linux/platform_device.h>
22 #include <linux/platform_data/b53.h>
26 /* command and status register of the SRAB */
27 #define B53_SRAB_CMDSTAT 0x2c
28 #define B53_SRAB_CMDSTAT_RST BIT(2)
29 #define B53_SRAB_CMDSTAT_WRITE BIT(1)
30 #define B53_SRAB_CMDSTAT_GORDYN BIT(0)
31 #define B53_SRAB_CMDSTAT_PAGE 24
32 #define B53_SRAB_CMDSTAT_REG 16
34 /* high order word of write data to switch registe */
35 #define B53_SRAB_WD_H 0x30
37 /* low order word of write data to switch registe */
38 #define B53_SRAB_WD_L 0x34
40 /* high order word of read data from switch register */
41 #define B53_SRAB_RD_H 0x38
43 /* low order word of read data from switch register */
44 #define B53_SRAB_RD_L 0x3c
46 /* command and status register of the SRAB */
47 #define B53_SRAB_CTRLS 0x40
48 #define B53_SRAB_CTRLS_RCAREQ BIT(3)
49 #define B53_SRAB_CTRLS_RCAGNT BIT(4)
50 #define B53_SRAB_CTRLS_SW_INIT_DONE BIT(6)
52 /* the register captures interrupt pulses from the switch */
53 #define B53_SRAB_INTR 0x44
55 static int b53_srab_request_grant(struct b53_device
*dev
)
57 u8 __iomem
*regs
= dev
->priv
;
61 ctrls
= readl(regs
+ B53_SRAB_CTRLS
);
62 ctrls
|= B53_SRAB_CTRLS_RCAREQ
;
63 writel(ctrls
, regs
+ B53_SRAB_CTRLS
);
65 for (i
= 0; i
< 20; i
++) {
66 ctrls
= readl(regs
+ B53_SRAB_CTRLS
);
67 if (ctrls
& B53_SRAB_CTRLS_RCAGNT
)
69 usleep_range(10, 100);
77 static void b53_srab_release_grant(struct b53_device
*dev
)
79 u8 __iomem
*regs
= dev
->priv
;
82 ctrls
= readl(regs
+ B53_SRAB_CTRLS
);
83 ctrls
&= ~B53_SRAB_CTRLS_RCAREQ
;
84 writel(ctrls
, regs
+ B53_SRAB_CTRLS
);
87 static int b53_srab_op(struct b53_device
*dev
, u8 page
, u8 reg
, u32 op
)
91 u8 __iomem
*regs
= dev
->priv
;
93 /* set register address */
94 cmdstat
= (page
<< B53_SRAB_CMDSTAT_PAGE
) |
95 (reg
<< B53_SRAB_CMDSTAT_REG
) |
96 B53_SRAB_CMDSTAT_GORDYN
|
98 writel(cmdstat
, regs
+ B53_SRAB_CMDSTAT
);
100 /* check if operation completed */
101 for (i
= 0; i
< 5; ++i
) {
102 cmdstat
= readl(regs
+ B53_SRAB_CMDSTAT
);
103 if (!(cmdstat
& B53_SRAB_CMDSTAT_GORDYN
))
105 usleep_range(10, 100);
114 static int b53_srab_read8(struct b53_device
*dev
, u8 page
, u8 reg
, u8
*val
)
116 u8 __iomem
*regs
= dev
->priv
;
119 ret
= b53_srab_request_grant(dev
);
123 ret
= b53_srab_op(dev
, page
, reg
, 0);
127 *val
= readl(regs
+ B53_SRAB_RD_L
) & 0xff;
130 b53_srab_release_grant(dev
);
135 static int b53_srab_read16(struct b53_device
*dev
, u8 page
, u8 reg
, u16
*val
)
137 u8 __iomem
*regs
= dev
->priv
;
140 ret
= b53_srab_request_grant(dev
);
144 ret
= b53_srab_op(dev
, page
, reg
, 0);
148 *val
= readl(regs
+ B53_SRAB_RD_L
) & 0xffff;
151 b53_srab_release_grant(dev
);
156 static int b53_srab_read32(struct b53_device
*dev
, u8 page
, u8 reg
, u32
*val
)
158 u8 __iomem
*regs
= dev
->priv
;
161 ret
= b53_srab_request_grant(dev
);
165 ret
= b53_srab_op(dev
, page
, reg
, 0);
169 *val
= readl(regs
+ B53_SRAB_RD_L
);
172 b53_srab_release_grant(dev
);
177 static int b53_srab_read48(struct b53_device
*dev
, u8 page
, u8 reg
, u64
*val
)
179 u8 __iomem
*regs
= dev
->priv
;
182 ret
= b53_srab_request_grant(dev
);
186 ret
= b53_srab_op(dev
, page
, reg
, 0);
190 *val
= readl(regs
+ B53_SRAB_RD_L
);
191 *val
+= ((u64
)readl(regs
+ B53_SRAB_RD_H
) & 0xffff) << 32;
194 b53_srab_release_grant(dev
);
199 static int b53_srab_read64(struct b53_device
*dev
, u8 page
, u8 reg
, u64
*val
)
201 u8 __iomem
*regs
= dev
->priv
;
204 ret
= b53_srab_request_grant(dev
);
208 ret
= b53_srab_op(dev
, page
, reg
, 0);
212 *val
= readl(regs
+ B53_SRAB_RD_L
);
213 *val
+= (u64
)readl(regs
+ B53_SRAB_RD_H
) << 32;
216 b53_srab_release_grant(dev
);
221 static int b53_srab_write8(struct b53_device
*dev
, u8 page
, u8 reg
, u8 value
)
223 u8 __iomem
*regs
= dev
->priv
;
226 ret
= b53_srab_request_grant(dev
);
230 writel(value
, regs
+ B53_SRAB_WD_L
);
232 ret
= b53_srab_op(dev
, page
, reg
, B53_SRAB_CMDSTAT_WRITE
);
235 b53_srab_release_grant(dev
);
240 static int b53_srab_write16(struct b53_device
*dev
, u8 page
, u8 reg
,
243 u8 __iomem
*regs
= dev
->priv
;
246 ret
= b53_srab_request_grant(dev
);
250 writel(value
, regs
+ B53_SRAB_WD_L
);
252 ret
= b53_srab_op(dev
, page
, reg
, B53_SRAB_CMDSTAT_WRITE
);
255 b53_srab_release_grant(dev
);
260 static int b53_srab_write32(struct b53_device
*dev
, u8 page
, u8 reg
,
263 u8 __iomem
*regs
= dev
->priv
;
266 ret
= b53_srab_request_grant(dev
);
270 writel(value
, regs
+ B53_SRAB_WD_L
);
272 ret
= b53_srab_op(dev
, page
, reg
, B53_SRAB_CMDSTAT_WRITE
);
275 b53_srab_release_grant(dev
);
281 static int b53_srab_write48(struct b53_device
*dev
, u8 page
, u8 reg
,
284 u8 __iomem
*regs
= dev
->priv
;
287 ret
= b53_srab_request_grant(dev
);
291 writel((u32
)value
, regs
+ B53_SRAB_WD_L
);
292 writel((u16
)(value
>> 32), regs
+ B53_SRAB_WD_H
);
294 ret
= b53_srab_op(dev
, page
, reg
, B53_SRAB_CMDSTAT_WRITE
);
297 b53_srab_release_grant(dev
);
303 static int b53_srab_write64(struct b53_device
*dev
, u8 page
, u8 reg
,
306 u8 __iomem
*regs
= dev
->priv
;
309 ret
= b53_srab_request_grant(dev
);
313 writel((u32
)value
, regs
+ B53_SRAB_WD_L
);
314 writel((u32
)(value
>> 32), regs
+ B53_SRAB_WD_H
);
316 ret
= b53_srab_op(dev
, page
, reg
, B53_SRAB_CMDSTAT_WRITE
);
319 b53_srab_release_grant(dev
);
324 static struct b53_io_ops b53_srab_ops
= {
325 .read8
= b53_srab_read8
,
326 .read16
= b53_srab_read16
,
327 .read32
= b53_srab_read32
,
328 .read48
= b53_srab_read48
,
329 .read64
= b53_srab_read64
,
330 .write8
= b53_srab_write8
,
331 .write16
= b53_srab_write16
,
332 .write32
= b53_srab_write32
,
333 .write48
= b53_srab_write48
,
334 .write64
= b53_srab_write64
,
337 static int b53_srab_probe(struct platform_device
*pdev
)
339 struct b53_platform_data
*pdata
= pdev
->dev
.platform_data
;
340 struct b53_device
*dev
;
345 dev
= b53_switch_alloc(&pdev
->dev
, &b53_srab_ops
, pdata
->regs
);
352 platform_set_drvdata(pdev
, dev
);
354 return b53_switch_register(dev
);
357 static int b53_srab_remove(struct platform_device
*pdev
)
359 struct b53_device
*dev
= platform_get_drvdata(pdev
);
362 b53_switch_remove(dev
);
367 static struct platform_driver b53_srab_driver
= {
368 .probe
= b53_srab_probe
,
369 .remove
= b53_srab_remove
,
371 .name
= "b53-srab-switch",
375 module_platform_driver(b53_srab_driver
);
376 MODULE_AUTHOR("Hauke Mehrtens <hauke@hauke-m.de>");
377 MODULE_DESCRIPTION("B53 Switch Register Access Bridge Registers (SRAB) access driver");
378 MODULE_LICENSE("Dual BSD/GPL");