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);
368 static struct platform_driver b53_srab_driver = {
369 .probe = b53_srab_probe,
370 .remove = b53_srab_remove,
372 .name = "b53-srab-switch",
376 module_platform_driver(b53_srab_driver);
377 MODULE_AUTHOR("Hauke Mehrtens <hauke@hauke-m.de>");
378 MODULE_DESCRIPTION("B53 Switch Register Access Bridge Registers (SRAB) access driver");
379 MODULE_LICENSE("Dual BSD/GPL");