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

k3-psil.c (2700B)


      1// SPDX-License-Identifier: GPL-2.0
      2/*
      3 *  Copyright (C) 2019 Texas Instruments Incorporated - http://www.ti.com
      4 *  Author: Peter Ujfalusi <peter.ujfalusi@ti.com>
      5 */
      6
      7#include <linux/kernel.h>
      8#include <linux/device.h>
      9#include <linux/init.h>
     10#include <linux/mutex.h>
     11#include <linux/of.h>
     12#include <linux/sys_soc.h>
     13
     14#include "k3-psil-priv.h"
     15
     16static DEFINE_MUTEX(ep_map_mutex);
     17static const struct psil_ep_map *soc_ep_map;
     18
     19static const struct soc_device_attribute k3_soc_devices[] = {
     20	{ .family = "AM65X", .data = &am654_ep_map },
     21	{ .family = "J721E", .data = &j721e_ep_map },
     22	{ .family = "J7200", .data = &j7200_ep_map },
     23	{ .family = "AM64X", .data = &am64_ep_map },
     24	{ .family = "J721S2", .data = &j721s2_ep_map },
     25	{ .family = "AM62X", .data = &am62_ep_map },
     26	{ /* sentinel */ }
     27};
     28
     29struct psil_endpoint_config *psil_get_ep_config(u32 thread_id)
     30{
     31	int i;
     32
     33	mutex_lock(&ep_map_mutex);
     34	if (!soc_ep_map) {
     35		const struct soc_device_attribute *soc;
     36
     37		soc = soc_device_match(k3_soc_devices);
     38		if (soc) {
     39			soc_ep_map = soc->data;
     40		} else {
     41			pr_err("PSIL: No compatible machine found for map\n");
     42			mutex_unlock(&ep_map_mutex);
     43			return ERR_PTR(-ENOTSUPP);
     44		}
     45		pr_debug("%s: Using map for %s\n", __func__, soc_ep_map->name);
     46	}
     47	mutex_unlock(&ep_map_mutex);
     48
     49	if (thread_id & K3_PSIL_DST_THREAD_ID_OFFSET && soc_ep_map->dst) {
     50		/* check in destination thread map */
     51		for (i = 0; i < soc_ep_map->dst_count; i++) {
     52			if (soc_ep_map->dst[i].thread_id == thread_id)
     53				return &soc_ep_map->dst[i].ep_config;
     54		}
     55	}
     56
     57	thread_id &= ~K3_PSIL_DST_THREAD_ID_OFFSET;
     58	if (soc_ep_map->src) {
     59		for (i = 0; i < soc_ep_map->src_count; i++) {
     60			if (soc_ep_map->src[i].thread_id == thread_id)
     61				return &soc_ep_map->src[i].ep_config;
     62		}
     63	}
     64
     65	return ERR_PTR(-ENOENT);
     66}
     67EXPORT_SYMBOL_GPL(psil_get_ep_config);
     68
     69int psil_set_new_ep_config(struct device *dev, const char *name,
     70			   struct psil_endpoint_config *ep_config)
     71{
     72	struct psil_endpoint_config *dst_ep_config;
     73	struct of_phandle_args dma_spec;
     74	u32 thread_id;
     75	int index;
     76
     77	if (!dev || !dev->of_node)
     78		return -EINVAL;
     79
     80	index = of_property_match_string(dev->of_node, "dma-names", name);
     81	if (index < 0)
     82		return index;
     83
     84	if (of_parse_phandle_with_args(dev->of_node, "dmas", "#dma-cells",
     85				       index, &dma_spec))
     86		return -ENOENT;
     87
     88	thread_id = dma_spec.args[0];
     89
     90	dst_ep_config = psil_get_ep_config(thread_id);
     91	if (IS_ERR(dst_ep_config)) {
     92		pr_err("PSIL: thread ID 0x%04x not defined in map\n",
     93		       thread_id);
     94		of_node_put(dma_spec.np);
     95		return PTR_ERR(dst_ep_config);
     96	}
     97
     98	memcpy(dst_ep_config, ep_config, sizeof(*dst_ep_config));
     99
    100	of_node_put(dma_spec.np);
    101	return 0;
    102}
    103EXPORT_SYMBOL_GPL(psil_set_new_ep_config);