cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

host_soc.c (5611B)


      1/*
      2 * Broadcom specific AMBA
      3 * System on Chip (SoC) Host
      4 *
      5 * Licensed under the GNU/GPL. See COPYING for details.
      6 */
      7
      8#include "bcma_private.h"
      9#include "scan.h"
     10#include <linux/slab.h>
     11#include <linux/module.h>
     12#include <linux/of_address.h>
     13#include <linux/bcma/bcma.h>
     14#include <linux/bcma/bcma_soc.h>
     15
     16static u8 bcma_host_soc_read8(struct bcma_device *core, u16 offset)
     17{
     18	return readb(core->io_addr + offset);
     19}
     20
     21static u16 bcma_host_soc_read16(struct bcma_device *core, u16 offset)
     22{
     23	return readw(core->io_addr + offset);
     24}
     25
     26static u32 bcma_host_soc_read32(struct bcma_device *core, u16 offset)
     27{
     28	return readl(core->io_addr + offset);
     29}
     30
     31static void bcma_host_soc_write8(struct bcma_device *core, u16 offset,
     32				 u8 value)
     33{
     34	writeb(value, core->io_addr + offset);
     35}
     36
     37static void bcma_host_soc_write16(struct bcma_device *core, u16 offset,
     38				 u16 value)
     39{
     40	writew(value, core->io_addr + offset);
     41}
     42
     43static void bcma_host_soc_write32(struct bcma_device *core, u16 offset,
     44				 u32 value)
     45{
     46	writel(value, core->io_addr + offset);
     47}
     48
     49#ifdef CONFIG_BCMA_BLOCKIO
     50static void bcma_host_soc_block_read(struct bcma_device *core, void *buffer,
     51				     size_t count, u16 offset, u8 reg_width)
     52{
     53	void __iomem *addr = core->io_addr + offset;
     54
     55	switch (reg_width) {
     56	case sizeof(u8): {
     57		u8 *buf = buffer;
     58
     59		while (count) {
     60			*buf = __raw_readb(addr);
     61			buf++;
     62			count--;
     63		}
     64		break;
     65	}
     66	case sizeof(u16): {
     67		__le16 *buf = buffer;
     68
     69		WARN_ON(count & 1);
     70		while (count) {
     71			*buf = (__force __le16)__raw_readw(addr);
     72			buf++;
     73			count -= 2;
     74		}
     75		break;
     76	}
     77	case sizeof(u32): {
     78		__le32 *buf = buffer;
     79
     80		WARN_ON(count & 3);
     81		while (count) {
     82			*buf = (__force __le32)__raw_readl(addr);
     83			buf++;
     84			count -= 4;
     85		}
     86		break;
     87	}
     88	default:
     89		WARN_ON(1);
     90	}
     91}
     92
     93static void bcma_host_soc_block_write(struct bcma_device *core,
     94				      const void *buffer,
     95				      size_t count, u16 offset, u8 reg_width)
     96{
     97	void __iomem *addr = core->io_addr + offset;
     98
     99	switch (reg_width) {
    100	case sizeof(u8): {
    101		const u8 *buf = buffer;
    102
    103		while (count) {
    104			__raw_writeb(*buf, addr);
    105			buf++;
    106			count--;
    107		}
    108		break;
    109	}
    110	case sizeof(u16): {
    111		const __le16 *buf = buffer;
    112
    113		WARN_ON(count & 1);
    114		while (count) {
    115			__raw_writew((__force u16)(*buf), addr);
    116			buf++;
    117			count -= 2;
    118		}
    119		break;
    120	}
    121	case sizeof(u32): {
    122		const __le32 *buf = buffer;
    123
    124		WARN_ON(count & 3);
    125		while (count) {
    126			__raw_writel((__force u32)(*buf), addr);
    127			buf++;
    128			count -= 4;
    129		}
    130		break;
    131	}
    132	default:
    133		WARN_ON(1);
    134	}
    135}
    136#endif /* CONFIG_BCMA_BLOCKIO */
    137
    138static u32 bcma_host_soc_aread32(struct bcma_device *core, u16 offset)
    139{
    140	if (WARN_ONCE(!core->io_wrap, "Accessed core has no wrapper/agent\n"))
    141		return ~0;
    142	return readl(core->io_wrap + offset);
    143}
    144
    145static void bcma_host_soc_awrite32(struct bcma_device *core, u16 offset,
    146				  u32 value)
    147{
    148	if (WARN_ONCE(!core->io_wrap, "Accessed core has no wrapper/agent\n"))
    149		return;
    150	writel(value, core->io_wrap + offset);
    151}
    152
    153static const struct bcma_host_ops bcma_host_soc_ops = {
    154	.read8		= bcma_host_soc_read8,
    155	.read16		= bcma_host_soc_read16,
    156	.read32		= bcma_host_soc_read32,
    157	.write8		= bcma_host_soc_write8,
    158	.write16	= bcma_host_soc_write16,
    159	.write32	= bcma_host_soc_write32,
    160#ifdef CONFIG_BCMA_BLOCKIO
    161	.block_read	= bcma_host_soc_block_read,
    162	.block_write	= bcma_host_soc_block_write,
    163#endif
    164	.aread32	= bcma_host_soc_aread32,
    165	.awrite32	= bcma_host_soc_awrite32,
    166};
    167
    168int __init bcma_host_soc_register(struct bcma_soc *soc)
    169{
    170	struct bcma_bus *bus = &soc->bus;
    171
    172	/* iomap only first core. We have to read some register on this core
    173	 * to scan the bus.
    174	 */
    175	bus->mmio = ioremap(BCMA_ADDR_BASE, BCMA_CORE_SIZE * 1);
    176	if (!bus->mmio)
    177		return -ENOMEM;
    178
    179	/* Host specific */
    180	bus->hosttype = BCMA_HOSTTYPE_SOC;
    181	bus->ops = &bcma_host_soc_ops;
    182
    183	/* Initialize struct, detect chip */
    184	bcma_init_bus(bus);
    185
    186	return 0;
    187}
    188
    189int __init bcma_host_soc_init(struct bcma_soc *soc)
    190{
    191	struct bcma_bus *bus = &soc->bus;
    192	int err;
    193
    194	/* Scan bus and initialize it */
    195	err = bcma_bus_early_register(bus);
    196	if (err)
    197		iounmap(bus->mmio);
    198
    199	return err;
    200}
    201
    202#ifdef CONFIG_OF
    203static int bcma_host_soc_probe(struct platform_device *pdev)
    204{
    205	struct device *dev = &pdev->dev;
    206	struct device_node *np = dev->of_node;
    207	struct bcma_bus *bus;
    208	int err;
    209
    210	/* Alloc */
    211	bus = devm_kzalloc(dev, sizeof(*bus), GFP_KERNEL);
    212	if (!bus)
    213		return -ENOMEM;
    214
    215	bus->dev = dev;
    216
    217	/* Map MMIO */
    218	bus->mmio = of_iomap(np, 0);
    219	if (!bus->mmio)
    220		return -ENOMEM;
    221
    222	/* Host specific */
    223	bus->hosttype = BCMA_HOSTTYPE_SOC;
    224	bus->ops = &bcma_host_soc_ops;
    225
    226	/* Initialize struct, detect chip */
    227	bcma_init_bus(bus);
    228
    229	/* Register */
    230	err = bcma_bus_register(bus);
    231	if (err)
    232		goto err_unmap_mmio;
    233
    234	platform_set_drvdata(pdev, bus);
    235
    236	return err;
    237
    238err_unmap_mmio:
    239	iounmap(bus->mmio);
    240	return err;
    241}
    242
    243static int bcma_host_soc_remove(struct platform_device *pdev)
    244{
    245	struct bcma_bus *bus = platform_get_drvdata(pdev);
    246
    247	bcma_bus_unregister(bus);
    248	iounmap(bus->mmio);
    249	platform_set_drvdata(pdev, NULL);
    250
    251	return 0;
    252}
    253
    254static const struct of_device_id bcma_host_soc_of_match[] = {
    255	{ .compatible = "brcm,bus-axi", },
    256	{},
    257};
    258MODULE_DEVICE_TABLE(of, bcma_host_soc_of_match);
    259
    260static struct platform_driver bcma_host_soc_driver = {
    261	.driver = {
    262		.name = "bcma-host-soc",
    263		.of_match_table = bcma_host_soc_of_match,
    264	},
    265	.probe		= bcma_host_soc_probe,
    266	.remove		= bcma_host_soc_remove,
    267};
    268
    269int __init bcma_host_soc_register_driver(void)
    270{
    271	return platform_driver_register(&bcma_host_soc_driver);
    272}
    273
    274void __exit bcma_host_soc_unregister_driver(void)
    275{
    276	platform_driver_unregister(&bcma_host_soc_driver);
    277}
    278#endif /* CONFIG_OF */