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

board.c (4654B)


      1// SPDX-License-Identifier: GPL-2.0
      2/*
      3 * Copyright (C) 2014 Magnus Damm
      4 * Copyright (C) 2015 Glider bvba
      5 */
      6
      7#define pr_fmt(fmt)	"board_staging: "  fmt
      8
      9#include <linux/clkdev.h>
     10#include <linux/init.h>
     11#include <linux/irq.h>
     12#include <linux/device.h>
     13#include <linux/kernel.h>
     14#include <linux/of.h>
     15#include <linux/of_address.h>
     16#include <linux/of_irq.h>
     17#include <linux/platform_device.h>
     18#include <linux/pm_domain.h>
     19
     20#include "board.h"
     21
     22static struct device_node *irqc_node __initdata;
     23static unsigned int irqc_base __initdata;
     24
     25static bool find_by_address(u64 base_address)
     26{
     27	struct device_node *dn = of_find_all_nodes(NULL);
     28	struct resource res;
     29
     30	while (dn) {
     31		if (!of_address_to_resource(dn, 0, &res)) {
     32			if (res.start == base_address) {
     33				of_node_put(dn);
     34				return true;
     35			}
     36		}
     37		dn = of_find_all_nodes(dn);
     38	}
     39
     40	return false;
     41}
     42
     43bool __init board_staging_dt_node_available(const struct resource *resource,
     44					    unsigned int num_resources)
     45{
     46	unsigned int i;
     47
     48	for (i = 0; i < num_resources; i++) {
     49		const struct resource *r = resource + i;
     50
     51		if (resource_type(r) == IORESOURCE_MEM)
     52			if (find_by_address(r->start))
     53				return true; /* DT node available */
     54	}
     55
     56	return false; /* Nothing found */
     57}
     58
     59int __init board_staging_gic_setup_xlate(const char *gic_match,
     60					 unsigned int base)
     61{
     62	WARN_ON(irqc_node);
     63
     64	irqc_node = of_find_compatible_node(NULL, NULL, gic_match);
     65
     66	WARN_ON(!irqc_node);
     67	if (!irqc_node)
     68		return -ENOENT;
     69
     70	irqc_base = base;
     71	return 0;
     72}
     73
     74static void __init gic_fixup_resource(struct resource *res)
     75{
     76	struct of_phandle_args irq_data;
     77	unsigned int hwirq = res->start;
     78	unsigned int virq;
     79
     80	if (resource_type(res) != IORESOURCE_IRQ || !irqc_node)
     81		return;
     82
     83	irq_data.np = irqc_node;
     84	irq_data.args_count = 3;
     85	irq_data.args[0] = 0;
     86	irq_data.args[1] = hwirq - irqc_base;
     87	switch (res->flags &
     88		(IORESOURCE_IRQ_LOWEDGE | IORESOURCE_IRQ_HIGHEDGE |
     89		 IORESOURCE_IRQ_LOWLEVEL | IORESOURCE_IRQ_HIGHLEVEL)) {
     90	case IORESOURCE_IRQ_LOWEDGE:
     91		irq_data.args[2] = IRQ_TYPE_EDGE_FALLING;
     92		break;
     93	case IORESOURCE_IRQ_HIGHEDGE:
     94		irq_data.args[2] = IRQ_TYPE_EDGE_RISING;
     95		break;
     96	case IORESOURCE_IRQ_LOWLEVEL:
     97		irq_data.args[2] = IRQ_TYPE_LEVEL_LOW;
     98		break;
     99	case IORESOURCE_IRQ_HIGHLEVEL:
    100	default:
    101		irq_data.args[2] = IRQ_TYPE_LEVEL_HIGH;
    102		break;
    103	}
    104
    105	virq = irq_create_of_mapping(&irq_data);
    106	if (WARN_ON(!virq))
    107		return;
    108
    109	pr_debug("hwirq %u -> virq %u\n", hwirq, virq);
    110	res->start = virq;
    111}
    112
    113void __init board_staging_gic_fixup_resources(struct resource *res,
    114					      unsigned int nres)
    115{
    116	unsigned int i;
    117
    118	for (i = 0; i < nres; i++)
    119		gic_fixup_resource(&res[i]);
    120}
    121
    122int __init board_staging_register_clock(const struct board_staging_clk *bsc)
    123{
    124	int error;
    125
    126	pr_debug("Aliasing clock %s for con_id %s dev_id %s\n", bsc->clk,
    127		 bsc->con_id, bsc->dev_id);
    128	error = clk_add_alias(bsc->con_id, bsc->dev_id, bsc->clk, NULL);
    129	if (error)
    130		pr_err("Failed to alias clock %s (%d)\n", bsc->clk, error);
    131
    132	return error;
    133}
    134
    135#ifdef CONFIG_PM_GENERIC_DOMAINS_OF
    136static int board_staging_add_dev_domain(struct platform_device *pdev,
    137					const char *domain)
    138{
    139	struct device *dev = &pdev->dev;
    140	struct of_phandle_args pd_args;
    141	struct device_node *np;
    142
    143	np = of_find_node_by_path(domain);
    144	if (!np) {
    145		pr_err("Cannot find domain node %s\n", domain);
    146		return -ENOENT;
    147	}
    148
    149	pd_args.np = np;
    150	pd_args.args_count = 0;
    151
    152	/* Initialization similar to device_pm_init_common() */
    153	spin_lock_init(&dev->power.lock);
    154	dev->power.early_init = true;
    155
    156	return of_genpd_add_device(&pd_args, dev);
    157}
    158#else
    159static inline int board_staging_add_dev_domain(struct platform_device *pdev,
    160					       const char *domain)
    161{
    162	return 0;
    163}
    164#endif
    165
    166int __init board_staging_register_device(const struct board_staging_dev *dev)
    167{
    168	struct platform_device *pdev = dev->pdev;
    169	unsigned int i;
    170	int error;
    171
    172	pr_debug("Trying to register device %s\n", pdev->name);
    173	if (board_staging_dt_node_available(pdev->resource,
    174					    pdev->num_resources)) {
    175		pr_warn("Skipping %s, already in DT\n", pdev->name);
    176		return -EEXIST;
    177	}
    178
    179	board_staging_gic_fixup_resources(pdev->resource, pdev->num_resources);
    180
    181	for (i = 0; i < dev->nclocks; i++)
    182		board_staging_register_clock(&dev->clocks[i]);
    183
    184	if (dev->domain)
    185		board_staging_add_dev_domain(pdev, dev->domain);
    186
    187	error = platform_device_register(pdev);
    188	if (error) {
    189		pr_err("Failed to register device %s (%d)\n", pdev->name,
    190		       error);
    191		return error;
    192	}
    193
    194	return error;
    195}
    196
    197void __init board_staging_register_devices(const struct board_staging_dev *devs,
    198					   unsigned int ndevs)
    199{
    200	unsigned int i;
    201
    202	for (i = 0; i < ndevs; i++)
    203		board_staging_register_device(&devs[i]);
    204}