0001
0002
0003
0004
0005
0006
0007
0008 #include "bcma_private.h"
0009 #include "scan.h"
0010 #include <linux/slab.h>
0011 #include <linux/module.h>
0012 #include <linux/of_address.h>
0013 #include <linux/bcma/bcma.h>
0014 #include <linux/bcma/bcma_soc.h>
0015
0016 static u8 bcma_host_soc_read8(struct bcma_device *core, u16 offset)
0017 {
0018 return readb(core->io_addr + offset);
0019 }
0020
0021 static u16 bcma_host_soc_read16(struct bcma_device *core, u16 offset)
0022 {
0023 return readw(core->io_addr + offset);
0024 }
0025
0026 static u32 bcma_host_soc_read32(struct bcma_device *core, u16 offset)
0027 {
0028 return readl(core->io_addr + offset);
0029 }
0030
0031 static void bcma_host_soc_write8(struct bcma_device *core, u16 offset,
0032 u8 value)
0033 {
0034 writeb(value, core->io_addr + offset);
0035 }
0036
0037 static void bcma_host_soc_write16(struct bcma_device *core, u16 offset,
0038 u16 value)
0039 {
0040 writew(value, core->io_addr + offset);
0041 }
0042
0043 static void bcma_host_soc_write32(struct bcma_device *core, u16 offset,
0044 u32 value)
0045 {
0046 writel(value, core->io_addr + offset);
0047 }
0048
0049 #ifdef CONFIG_BCMA_BLOCKIO
0050 static void bcma_host_soc_block_read(struct bcma_device *core, void *buffer,
0051 size_t count, u16 offset, u8 reg_width)
0052 {
0053 void __iomem *addr = core->io_addr + offset;
0054
0055 switch (reg_width) {
0056 case sizeof(u8): {
0057 u8 *buf = buffer;
0058
0059 while (count) {
0060 *buf = __raw_readb(addr);
0061 buf++;
0062 count--;
0063 }
0064 break;
0065 }
0066 case sizeof(u16): {
0067 __le16 *buf = buffer;
0068
0069 WARN_ON(count & 1);
0070 while (count) {
0071 *buf = (__force __le16)__raw_readw(addr);
0072 buf++;
0073 count -= 2;
0074 }
0075 break;
0076 }
0077 case sizeof(u32): {
0078 __le32 *buf = buffer;
0079
0080 WARN_ON(count & 3);
0081 while (count) {
0082 *buf = (__force __le32)__raw_readl(addr);
0083 buf++;
0084 count -= 4;
0085 }
0086 break;
0087 }
0088 default:
0089 WARN_ON(1);
0090 }
0091 }
0092
0093 static void bcma_host_soc_block_write(struct bcma_device *core,
0094 const void *buffer,
0095 size_t count, u16 offset, u8 reg_width)
0096 {
0097 void __iomem *addr = core->io_addr + offset;
0098
0099 switch (reg_width) {
0100 case sizeof(u8): {
0101 const u8 *buf = buffer;
0102
0103 while (count) {
0104 __raw_writeb(*buf, addr);
0105 buf++;
0106 count--;
0107 }
0108 break;
0109 }
0110 case sizeof(u16): {
0111 const __le16 *buf = buffer;
0112
0113 WARN_ON(count & 1);
0114 while (count) {
0115 __raw_writew((__force u16)(*buf), addr);
0116 buf++;
0117 count -= 2;
0118 }
0119 break;
0120 }
0121 case sizeof(u32): {
0122 const __le32 *buf = buffer;
0123
0124 WARN_ON(count & 3);
0125 while (count) {
0126 __raw_writel((__force u32)(*buf), addr);
0127 buf++;
0128 count -= 4;
0129 }
0130 break;
0131 }
0132 default:
0133 WARN_ON(1);
0134 }
0135 }
0136 #endif
0137
0138 static u32 bcma_host_soc_aread32(struct bcma_device *core, u16 offset)
0139 {
0140 if (WARN_ONCE(!core->io_wrap, "Accessed core has no wrapper/agent\n"))
0141 return ~0;
0142 return readl(core->io_wrap + offset);
0143 }
0144
0145 static void bcma_host_soc_awrite32(struct bcma_device *core, u16 offset,
0146 u32 value)
0147 {
0148 if (WARN_ONCE(!core->io_wrap, "Accessed core has no wrapper/agent\n"))
0149 return;
0150 writel(value, core->io_wrap + offset);
0151 }
0152
0153 static const struct bcma_host_ops bcma_host_soc_ops = {
0154 .read8 = bcma_host_soc_read8,
0155 .read16 = bcma_host_soc_read16,
0156 .read32 = bcma_host_soc_read32,
0157 .write8 = bcma_host_soc_write8,
0158 .write16 = bcma_host_soc_write16,
0159 .write32 = bcma_host_soc_write32,
0160 #ifdef CONFIG_BCMA_BLOCKIO
0161 .block_read = bcma_host_soc_block_read,
0162 .block_write = bcma_host_soc_block_write,
0163 #endif
0164 .aread32 = bcma_host_soc_aread32,
0165 .awrite32 = bcma_host_soc_awrite32,
0166 };
0167
0168 int __init bcma_host_soc_register(struct bcma_soc *soc)
0169 {
0170 struct bcma_bus *bus = &soc->bus;
0171
0172
0173
0174
0175 bus->mmio = ioremap(BCMA_ADDR_BASE, BCMA_CORE_SIZE * 1);
0176 if (!bus->mmio)
0177 return -ENOMEM;
0178
0179
0180 bus->hosttype = BCMA_HOSTTYPE_SOC;
0181 bus->ops = &bcma_host_soc_ops;
0182
0183
0184 bcma_init_bus(bus);
0185
0186 return 0;
0187 }
0188
0189 int __init bcma_host_soc_init(struct bcma_soc *soc)
0190 {
0191 struct bcma_bus *bus = &soc->bus;
0192 int err;
0193
0194
0195 err = bcma_bus_early_register(bus);
0196 if (err)
0197 iounmap(bus->mmio);
0198
0199 return err;
0200 }
0201
0202 #ifdef CONFIG_OF
0203 static int bcma_host_soc_probe(struct platform_device *pdev)
0204 {
0205 struct device *dev = &pdev->dev;
0206 struct device_node *np = dev->of_node;
0207 struct bcma_bus *bus;
0208 int err;
0209
0210
0211 bus = devm_kzalloc(dev, sizeof(*bus), GFP_KERNEL);
0212 if (!bus)
0213 return -ENOMEM;
0214
0215 bus->dev = dev;
0216
0217
0218 bus->mmio = of_iomap(np, 0);
0219 if (!bus->mmio)
0220 return -ENOMEM;
0221
0222
0223 bus->hosttype = BCMA_HOSTTYPE_SOC;
0224 bus->ops = &bcma_host_soc_ops;
0225
0226
0227 bcma_init_bus(bus);
0228
0229
0230 err = bcma_bus_register(bus);
0231 if (err)
0232 goto err_unmap_mmio;
0233
0234 platform_set_drvdata(pdev, bus);
0235
0236 return err;
0237
0238 err_unmap_mmio:
0239 iounmap(bus->mmio);
0240 return err;
0241 }
0242
0243 static int bcma_host_soc_remove(struct platform_device *pdev)
0244 {
0245 struct bcma_bus *bus = platform_get_drvdata(pdev);
0246
0247 bcma_bus_unregister(bus);
0248 iounmap(bus->mmio);
0249 platform_set_drvdata(pdev, NULL);
0250
0251 return 0;
0252 }
0253
0254 static const struct of_device_id bcma_host_soc_of_match[] = {
0255 { .compatible = "brcm,bus-axi", },
0256 {},
0257 };
0258 MODULE_DEVICE_TABLE(of, bcma_host_soc_of_match);
0259
0260 static struct platform_driver bcma_host_soc_driver = {
0261 .driver = {
0262 .name = "bcma-host-soc",
0263 .of_match_table = bcma_host_soc_of_match,
0264 },
0265 .probe = bcma_host_soc_probe,
0266 .remove = bcma_host_soc_remove,
0267 };
0268
0269 int __init bcma_host_soc_register_driver(void)
0270 {
0271 return platform_driver_register(&bcma_host_soc_driver);
0272 }
0273
0274 void __exit bcma_host_soc_unregister_driver(void)
0275 {
0276 platform_driver_unregister(&bcma_host_soc_driver);
0277 }
0278 #endif