Back to home page

OSCL-LXR

 
 

    


0001 /*
0002  * Broadcom specific AMBA
0003  * System on Chip (SoC) Host
0004  *
0005  * Licensed under the GNU/GPL. See COPYING for details.
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 /* CONFIG_BCMA_BLOCKIO */
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     /* iomap only first core. We have to read some register on this core
0173      * to scan the bus.
0174      */
0175     bus->mmio = ioremap(BCMA_ADDR_BASE, BCMA_CORE_SIZE * 1);
0176     if (!bus->mmio)
0177         return -ENOMEM;
0178 
0179     /* Host specific */
0180     bus->hosttype = BCMA_HOSTTYPE_SOC;
0181     bus->ops = &bcma_host_soc_ops;
0182 
0183     /* Initialize struct, detect chip */
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     /* Scan bus and initialize it */
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     /* Alloc */
0211     bus = devm_kzalloc(dev, sizeof(*bus), GFP_KERNEL);
0212     if (!bus)
0213         return -ENOMEM;
0214 
0215     bus->dev = dev;
0216 
0217     /* Map MMIO */
0218     bus->mmio = of_iomap(np, 0);
0219     if (!bus->mmio)
0220         return -ENOMEM;
0221 
0222     /* Host specific */
0223     bus->hosttype = BCMA_HOSTTYPE_SOC;
0224     bus->ops = &bcma_host_soc_ops;
0225 
0226     /* Initialize struct, detect chip */
0227     bcma_init_bus(bus);
0228 
0229     /* Register */
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 /* CONFIG_OF */