2 * B53 register access through memory mapped registers
4 * Copyright (C) 2012-2013 Jonas Gorski <jogo@openwrt.org>
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/kconfig.h>
21 #include <linux/module.h>
23 #include <linux/platform_device.h>
24 #include <linux/platform_data/b53.h>
28 struct b53_mmap_priv {
32 static int b53_mmap_read8(struct b53_device *dev, u8 page, u8 reg, u8 *val)
34 u8 __iomem *regs = dev->priv;
36 *val = readb(regs + (page << 8) + reg);
41 static int b53_mmap_read16(struct b53_device *dev, u8 page, u8 reg, u16 *val)
43 u8 __iomem *regs = dev->priv;
48 if (IS_ENABLED(CONFIG_CPU_BIG_ENDIAN) && dev->pdata &&
49 dev->pdata->big_endian)
50 *val = __raw_readw(regs + (page << 8) + reg);
52 *val = readw(regs + (page << 8) + reg);
57 static int b53_mmap_read32(struct b53_device *dev, u8 page, u8 reg, u32 *val)
59 u8 __iomem *regs = dev->priv;
64 if (IS_ENABLED(CONFIG_CPU_BIG_ENDIAN) && dev->pdata &&
65 dev->pdata->big_endian)
66 *val = __raw_readl(regs + (page << 8) + reg);
68 *val = readl(regs + (page << 8) + reg);
73 static int b53_mmap_read48(struct b53_device *dev, u8 page, u8 reg, u64 *val)
82 b53_mmap_read16(dev, page, reg, &lo);
83 b53_mmap_read32(dev, page, reg + 2, &hi);
85 *val = ((u64)hi << 16) | lo;
90 b53_mmap_read32(dev, page, reg, &lo);
91 b53_mmap_read16(dev, page, reg + 4, &hi);
93 *val = ((u64)hi << 32) | lo;
99 static int b53_mmap_read64(struct b53_device *dev, u8 page, u8 reg, u64 *val)
103 if (WARN_ON(reg % 4))
106 b53_mmap_read32(dev, page, reg, &lo);
107 b53_mmap_read32(dev, page, reg + 4, &hi);
109 *val = ((u64)hi << 32) | lo;
114 static int b53_mmap_write8(struct b53_device *dev, u8 page, u8 reg, u8 value)
116 u8 __iomem *regs = dev->priv;
118 writeb(value, regs + (page << 8) + reg);
123 static int b53_mmap_write16(struct b53_device *dev, u8 page, u8 reg,
126 u8 __iomem *regs = dev->priv;
128 if (WARN_ON(reg % 2))
131 if (IS_ENABLED(CONFIG_CPU_BIG_ENDIAN) && dev->pdata &&
132 dev->pdata->big_endian)
133 __raw_writew(value, regs + (page << 8) + reg);
135 writew(value, regs + (page << 8) + reg);
140 static int b53_mmap_write32(struct b53_device *dev, u8 page, u8 reg,
143 u8 __iomem *regs = dev->priv;
145 if (WARN_ON(reg % 4))
148 if (IS_ENABLED(CONFIG_CPU_BIG_ENDIAN) && dev->pdata &&
149 dev->pdata->big_endian)
150 __raw_writel(value, regs + (page << 8) + reg);
152 writel(value, regs + (page << 8) + reg);
157 static int b53_mmap_write48(struct b53_device *dev, u8 page, u8 reg,
160 if (WARN_ON(reg % 2))
164 u32 hi = (u32)(value >> 16);
167 b53_mmap_write16(dev, page, reg, lo);
168 b53_mmap_write32(dev, page, reg + 2, hi);
170 u16 hi = (u16)(value >> 32);
173 b53_mmap_write32(dev, page, reg, lo);
174 b53_mmap_write16(dev, page, reg + 4, hi);
180 static int b53_mmap_write64(struct b53_device *dev, u8 page, u8 reg,
185 hi = upper_32_bits(value);
186 lo = lower_32_bits(value);
188 if (WARN_ON(reg % 4))
191 b53_mmap_write32(dev, page, reg, lo);
192 b53_mmap_write32(dev, page, reg + 4, hi);
197 static struct b53_io_ops b53_mmap_ops = {
198 .read8 = b53_mmap_read8,
199 .read16 = b53_mmap_read16,
200 .read32 = b53_mmap_read32,
201 .read48 = b53_mmap_read48,
202 .read64 = b53_mmap_read64,
203 .write8 = b53_mmap_write8,
204 .write16 = b53_mmap_write16,
205 .write32 = b53_mmap_write32,
206 .write48 = b53_mmap_write48,
207 .write64 = b53_mmap_write64,
210 static int b53_mmap_probe(struct platform_device *pdev)
212 struct b53_platform_data *pdata = pdev->dev.platform_data;
213 struct b53_device *dev;
218 dev = b53_switch_alloc(&pdev->dev, &b53_mmap_ops, pdata->regs);
225 platform_set_drvdata(pdev, dev);
227 return b53_switch_register(dev);
230 static int b53_mmap_remove(struct platform_device *pdev)
232 struct b53_device *dev = platform_get_drvdata(pdev);
235 b53_switch_remove(dev);
240 static const struct of_device_id b53_mmap_of_table[] = {
241 { .compatible = "brcm,bcm3384-switch" },
242 { .compatible = "brcm,bcm6328-switch" },
243 { .compatible = "brcm,bcm6368-switch" },
244 { .compatible = "brcm,bcm63xx-switch" },
248 static struct platform_driver b53_mmap_driver = {
249 .probe = b53_mmap_probe,
250 .remove = b53_mmap_remove,
252 .name = "b53-switch",
253 .of_match_table = b53_mmap_of_table,
257 module_platform_driver(b53_mmap_driver);
258 MODULE_AUTHOR("Jonas Gorski <jogo@openwrt.org>");
259 MODULE_DESCRIPTION("B53 MMAP access driver");
260 MODULE_LICENSE("Dual BSD/GPL");