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

of_device_32.c (9247B)


      1// SPDX-License-Identifier: GPL-2.0
      2#include <linux/string.h>
      3#include <linux/kernel.h>
      4#include <linux/of.h>
      5#include <linux/init.h>
      6#include <linux/mod_devicetable.h>
      7#include <linux/slab.h>
      8#include <linux/errno.h>
      9#include <linux/irq.h>
     10#include <linux/of_device.h>
     11#include <linux/of_platform.h>
     12#include <linux/dma-mapping.h>
     13#include <asm/leon.h>
     14#include <asm/leon_amba.h>
     15
     16#include "of_device_common.h"
     17#include "irq.h"
     18
     19/*
     20 * PCI bus specific translator
     21 */
     22
     23static int of_bus_pci_match(struct device_node *np)
     24{
     25	if (of_node_is_type(np, "pci") || of_node_is_type(np, "pciex")) {
     26		/* Do not do PCI specific frobbing if the
     27		 * PCI bridge lacks a ranges property.  We
     28		 * want to pass it through up to the next
     29		 * parent as-is, not with the PCI translate
     30		 * method which chops off the top address cell.
     31		 */
     32		if (!of_find_property(np, "ranges", NULL))
     33			return 0;
     34
     35		return 1;
     36	}
     37
     38	return 0;
     39}
     40
     41static void of_bus_pci_count_cells(struct device_node *np,
     42				   int *addrc, int *sizec)
     43{
     44	if (addrc)
     45		*addrc = 3;
     46	if (sizec)
     47		*sizec = 2;
     48}
     49
     50static int of_bus_pci_map(u32 *addr, const u32 *range,
     51			  int na, int ns, int pna)
     52{
     53	u32 result[OF_MAX_ADDR_CELLS];
     54	int i;
     55
     56	/* Check address type match */
     57	if ((addr[0] ^ range[0]) & 0x03000000)
     58		return -EINVAL;
     59
     60	if (of_out_of_range(addr + 1, range + 1, range + na + pna,
     61			    na - 1, ns))
     62		return -EINVAL;
     63
     64	/* Start with the parent range base.  */
     65	memcpy(result, range + na, pna * 4);
     66
     67	/* Add in the child address offset, skipping high cell.  */
     68	for (i = 0; i < na - 1; i++)
     69		result[pna - 1 - i] +=
     70			(addr[na - 1 - i] -
     71			 range[na - 1 - i]);
     72
     73	memcpy(addr, result, pna * 4);
     74
     75	return 0;
     76}
     77
     78static unsigned long of_bus_pci_get_flags(const u32 *addr, unsigned long flags)
     79{
     80	u32 w = addr[0];
     81
     82	/* For PCI, we override whatever child busses may have used.  */
     83	flags = 0;
     84	switch((w >> 24) & 0x03) {
     85	case 0x01:
     86		flags |= IORESOURCE_IO;
     87		break;
     88
     89	case 0x02: /* 32 bits */
     90	case 0x03: /* 64 bits */
     91		flags |= IORESOURCE_MEM;
     92		break;
     93	}
     94	if (w & 0x40000000)
     95		flags |= IORESOURCE_PREFETCH;
     96	return flags;
     97}
     98
     99static unsigned long of_bus_sbus_get_flags(const u32 *addr, unsigned long flags)
    100{
    101	return IORESOURCE_MEM;
    102}
    103
    104 /*
    105 * AMBAPP bus specific translator
    106 */
    107
    108static int of_bus_ambapp_match(struct device_node *np)
    109{
    110	return of_node_is_type(np, "ambapp");
    111}
    112
    113static void of_bus_ambapp_count_cells(struct device_node *child,
    114				      int *addrc, int *sizec)
    115{
    116	if (addrc)
    117		*addrc = 1;
    118	if (sizec)
    119		*sizec = 1;
    120}
    121
    122static int of_bus_ambapp_map(u32 *addr, const u32 *range,
    123			     int na, int ns, int pna)
    124{
    125	return of_bus_default_map(addr, range, na, ns, pna);
    126}
    127
    128static unsigned long of_bus_ambapp_get_flags(const u32 *addr,
    129					     unsigned long flags)
    130{
    131	return IORESOURCE_MEM;
    132}
    133
    134/*
    135 * Array of bus specific translators
    136 */
    137
    138static struct of_bus of_busses[] = {
    139	/* PCI */
    140	{
    141		.name = "pci",
    142		.addr_prop_name = "assigned-addresses",
    143		.match = of_bus_pci_match,
    144		.count_cells = of_bus_pci_count_cells,
    145		.map = of_bus_pci_map,
    146		.get_flags = of_bus_pci_get_flags,
    147	},
    148	/* SBUS */
    149	{
    150		.name = "sbus",
    151		.addr_prop_name = "reg",
    152		.match = of_bus_sbus_match,
    153		.count_cells = of_bus_sbus_count_cells,
    154		.map = of_bus_default_map,
    155		.get_flags = of_bus_sbus_get_flags,
    156	},
    157	/* AMBA */
    158	{
    159		.name = "ambapp",
    160		.addr_prop_name = "reg",
    161		.match = of_bus_ambapp_match,
    162		.count_cells = of_bus_ambapp_count_cells,
    163		.map = of_bus_ambapp_map,
    164		.get_flags = of_bus_ambapp_get_flags,
    165	},
    166	/* Default */
    167	{
    168		.name = "default",
    169		.addr_prop_name = "reg",
    170		.match = NULL,
    171		.count_cells = of_bus_default_count_cells,
    172		.map = of_bus_default_map,
    173		.get_flags = of_bus_default_get_flags,
    174	},
    175};
    176
    177static struct of_bus *of_match_bus(struct device_node *np)
    178{
    179	int i;
    180
    181	for (i = 0; i < ARRAY_SIZE(of_busses); i ++)
    182		if (!of_busses[i].match || of_busses[i].match(np))
    183			return &of_busses[i];
    184	BUG();
    185	return NULL;
    186}
    187
    188static int __init build_one_resource(struct device_node *parent,
    189				     struct of_bus *bus,
    190				     struct of_bus *pbus,
    191				     u32 *addr,
    192				     int na, int ns, int pna)
    193{
    194	const u32 *ranges;
    195	unsigned int rlen;
    196	int rone;
    197
    198	ranges = of_get_property(parent, "ranges", &rlen);
    199	if (ranges == NULL || rlen == 0) {
    200		u32 result[OF_MAX_ADDR_CELLS];
    201		int i;
    202
    203		memset(result, 0, pna * 4);
    204		for (i = 0; i < na; i++)
    205			result[pna - 1 - i] =
    206				addr[na - 1 - i];
    207
    208		memcpy(addr, result, pna * 4);
    209		return 0;
    210	}
    211
    212	/* Now walk through the ranges */
    213	rlen /= 4;
    214	rone = na + pna + ns;
    215	for (; rlen >= rone; rlen -= rone, ranges += rone) {
    216		if (!bus->map(addr, ranges, na, ns, pna))
    217			return 0;
    218	}
    219
    220	return 1;
    221}
    222
    223static int __init use_1to1_mapping(struct device_node *pp)
    224{
    225	/* If we have a ranges property in the parent, use it.  */
    226	if (of_find_property(pp, "ranges", NULL) != NULL)
    227		return 0;
    228
    229	/* Some SBUS devices use intermediate nodes to express
    230	 * hierarchy within the device itself.  These aren't
    231	 * real bus nodes, and don't have a 'ranges' property.
    232	 * But, we should still pass the translation work up
    233	 * to the SBUS itself.
    234	 */
    235	if (of_node_name_eq(pp, "dma") ||
    236	    of_node_name_eq(pp, "espdma") ||
    237	    of_node_name_eq(pp, "ledma") ||
    238	    of_node_name_eq(pp, "lebuffer"))
    239		return 0;
    240
    241	return 1;
    242}
    243
    244static int of_resource_verbose;
    245
    246static void __init build_device_resources(struct platform_device *op,
    247					  struct device *parent)
    248{
    249	struct platform_device *p_op;
    250	struct of_bus *bus;
    251	int na, ns;
    252	int index, num_reg;
    253	const void *preg;
    254
    255	if (!parent)
    256		return;
    257
    258	p_op = to_platform_device(parent);
    259	bus = of_match_bus(p_op->dev.of_node);
    260	bus->count_cells(op->dev.of_node, &na, &ns);
    261
    262	preg = of_get_property(op->dev.of_node, bus->addr_prop_name, &num_reg);
    263	if (!preg || num_reg == 0)
    264		return;
    265
    266	/* Convert to num-cells.  */
    267	num_reg /= 4;
    268
    269	/* Conver to num-entries.  */
    270	num_reg /= na + ns;
    271
    272	op->resource = op->archdata.resource;
    273	op->num_resources = num_reg;
    274	for (index = 0; index < num_reg; index++) {
    275		struct resource *r = &op->resource[index];
    276		u32 addr[OF_MAX_ADDR_CELLS];
    277		const u32 *reg = (preg + (index * ((na + ns) * 4)));
    278		struct device_node *dp = op->dev.of_node;
    279		struct device_node *pp = p_op->dev.of_node;
    280		struct of_bus *pbus, *dbus;
    281		u64 size, result = OF_BAD_ADDR;
    282		unsigned long flags;
    283		int dna, dns;
    284		int pna, pns;
    285
    286		size = of_read_addr(reg + na, ns);
    287
    288		memcpy(addr, reg, na * 4);
    289
    290		flags = bus->get_flags(reg, 0);
    291
    292		if (use_1to1_mapping(pp)) {
    293			result = of_read_addr(addr, na);
    294			goto build_res;
    295		}
    296
    297		dna = na;
    298		dns = ns;
    299		dbus = bus;
    300
    301		while (1) {
    302			dp = pp;
    303			pp = dp->parent;
    304			if (!pp) {
    305				result = of_read_addr(addr, dna);
    306				break;
    307			}
    308
    309			pbus = of_match_bus(pp);
    310			pbus->count_cells(dp, &pna, &pns);
    311
    312			if (build_one_resource(dp, dbus, pbus, addr,
    313					       dna, dns, pna))
    314				break;
    315
    316			flags = pbus->get_flags(addr, flags);
    317
    318			dna = pna;
    319			dns = pns;
    320			dbus = pbus;
    321		}
    322
    323	build_res:
    324		memset(r, 0, sizeof(*r));
    325
    326		if (of_resource_verbose)
    327			printk("%pOF reg[%d] -> %llx\n",
    328			       op->dev.of_node, index,
    329			       result);
    330
    331		if (result != OF_BAD_ADDR) {
    332			r->start = result & 0xffffffff;
    333			r->end = result + size - 1;
    334			r->flags = flags | ((result >> 32ULL) & 0xffUL);
    335		}
    336		r->name = op->dev.of_node->full_name;
    337	}
    338}
    339
    340static struct platform_device * __init scan_one_device(struct device_node *dp,
    341						 struct device *parent)
    342{
    343	struct platform_device *op = kzalloc(sizeof(*op), GFP_KERNEL);
    344	const struct linux_prom_irqs *intr;
    345	struct dev_archdata *sd;
    346	int len, i;
    347
    348	if (!op)
    349		return NULL;
    350
    351	sd = &op->dev.archdata;
    352	sd->op = op;
    353
    354	op->dev.of_node = dp;
    355
    356	intr = of_get_property(dp, "intr", &len);
    357	if (intr) {
    358		op->archdata.num_irqs = len / sizeof(struct linux_prom_irqs);
    359		for (i = 0; i < op->archdata.num_irqs; i++)
    360			op->archdata.irqs[i] =
    361			    sparc_config.build_device_irq(op, intr[i].pri);
    362	} else {
    363		const unsigned int *irq =
    364			of_get_property(dp, "interrupts", &len);
    365
    366		if (irq) {
    367			op->archdata.num_irqs = len / sizeof(unsigned int);
    368			for (i = 0; i < op->archdata.num_irqs; i++)
    369				op->archdata.irqs[i] =
    370				    sparc_config.build_device_irq(op, irq[i]);
    371		} else {
    372			op->archdata.num_irqs = 0;
    373		}
    374	}
    375
    376	build_device_resources(op, parent);
    377
    378	op->dev.parent = parent;
    379	op->dev.bus = &platform_bus_type;
    380	if (!parent)
    381		dev_set_name(&op->dev, "root");
    382	else
    383		dev_set_name(&op->dev, "%08x", dp->phandle);
    384
    385	op->dev.coherent_dma_mask = DMA_BIT_MASK(32);
    386	op->dev.dma_mask = &op->dev.coherent_dma_mask;
    387
    388	if (of_device_register(op)) {
    389		printk("%pOF: Could not register of device.\n", dp);
    390		kfree(op);
    391		op = NULL;
    392	}
    393
    394	return op;
    395}
    396
    397static void __init scan_tree(struct device_node *dp, struct device *parent)
    398{
    399	while (dp) {
    400		struct platform_device *op = scan_one_device(dp, parent);
    401
    402		if (op)
    403			scan_tree(dp->child, &op->dev);
    404
    405		dp = dp->sibling;
    406	}
    407}
    408
    409static int __init scan_of_devices(void)
    410{
    411	struct device_node *root = of_find_node_by_path("/");
    412	struct platform_device *parent;
    413
    414	parent = scan_one_device(root, NULL);
    415	if (!parent)
    416		return 0;
    417
    418	scan_tree(root->child, &parent->dev);
    419	return 0;
    420}
    421postcore_initcall(scan_of_devices);
    422
    423static int __init of_debug(char *str)
    424{
    425	int val = 0;
    426
    427	get_option(&str, &val);
    428	if (val & 1)
    429		of_resource_verbose = 1;
    430	return 1;
    431}
    432
    433__setup("of_debug=", of_debug);