18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * Copyright (C) 2019 Texas Instruments Incorporated - http://www.ti.com 48c2ecf20Sopenharmony_ci * Author: Peter Ujfalusi <peter.ujfalusi@ti.com> 58c2ecf20Sopenharmony_ci */ 68c2ecf20Sopenharmony_ci 78c2ecf20Sopenharmony_ci#include <linux/kernel.h> 88c2ecf20Sopenharmony_ci#include <linux/device.h> 98c2ecf20Sopenharmony_ci#include <linux/init.h> 108c2ecf20Sopenharmony_ci#include <linux/mutex.h> 118c2ecf20Sopenharmony_ci#include <linux/of.h> 128c2ecf20Sopenharmony_ci#include <linux/sys_soc.h> 138c2ecf20Sopenharmony_ci 148c2ecf20Sopenharmony_ci#include "k3-psil-priv.h" 158c2ecf20Sopenharmony_ci 168c2ecf20Sopenharmony_cistatic DEFINE_MUTEX(ep_map_mutex); 178c2ecf20Sopenharmony_cistatic const struct psil_ep_map *soc_ep_map; 188c2ecf20Sopenharmony_ci 198c2ecf20Sopenharmony_cistatic const struct soc_device_attribute k3_soc_devices[] = { 208c2ecf20Sopenharmony_ci { .family = "AM65X", .data = &am654_ep_map }, 218c2ecf20Sopenharmony_ci { .family = "J721E", .data = &j721e_ep_map }, 228c2ecf20Sopenharmony_ci { .family = "J7200", .data = &j7200_ep_map }, 238c2ecf20Sopenharmony_ci { /* sentinel */ } 248c2ecf20Sopenharmony_ci}; 258c2ecf20Sopenharmony_ci 268c2ecf20Sopenharmony_cistruct psil_endpoint_config *psil_get_ep_config(u32 thread_id) 278c2ecf20Sopenharmony_ci{ 288c2ecf20Sopenharmony_ci int i; 298c2ecf20Sopenharmony_ci 308c2ecf20Sopenharmony_ci mutex_lock(&ep_map_mutex); 318c2ecf20Sopenharmony_ci if (!soc_ep_map) { 328c2ecf20Sopenharmony_ci const struct soc_device_attribute *soc; 338c2ecf20Sopenharmony_ci 348c2ecf20Sopenharmony_ci soc = soc_device_match(k3_soc_devices); 358c2ecf20Sopenharmony_ci if (soc) { 368c2ecf20Sopenharmony_ci soc_ep_map = soc->data; 378c2ecf20Sopenharmony_ci } else { 388c2ecf20Sopenharmony_ci pr_err("PSIL: No compatible machine found for map\n"); 398c2ecf20Sopenharmony_ci mutex_unlock(&ep_map_mutex); 408c2ecf20Sopenharmony_ci return ERR_PTR(-ENOTSUPP); 418c2ecf20Sopenharmony_ci } 428c2ecf20Sopenharmony_ci pr_debug("%s: Using map for %s\n", __func__, soc_ep_map->name); 438c2ecf20Sopenharmony_ci } 448c2ecf20Sopenharmony_ci mutex_unlock(&ep_map_mutex); 458c2ecf20Sopenharmony_ci 468c2ecf20Sopenharmony_ci if (thread_id & K3_PSIL_DST_THREAD_ID_OFFSET && soc_ep_map->dst) { 478c2ecf20Sopenharmony_ci /* check in destination thread map */ 488c2ecf20Sopenharmony_ci for (i = 0; i < soc_ep_map->dst_count; i++) { 498c2ecf20Sopenharmony_ci if (soc_ep_map->dst[i].thread_id == thread_id) 508c2ecf20Sopenharmony_ci return &soc_ep_map->dst[i].ep_config; 518c2ecf20Sopenharmony_ci } 528c2ecf20Sopenharmony_ci } 538c2ecf20Sopenharmony_ci 548c2ecf20Sopenharmony_ci thread_id &= ~K3_PSIL_DST_THREAD_ID_OFFSET; 558c2ecf20Sopenharmony_ci if (soc_ep_map->src) { 568c2ecf20Sopenharmony_ci for (i = 0; i < soc_ep_map->src_count; i++) { 578c2ecf20Sopenharmony_ci if (soc_ep_map->src[i].thread_id == thread_id) 588c2ecf20Sopenharmony_ci return &soc_ep_map->src[i].ep_config; 598c2ecf20Sopenharmony_ci } 608c2ecf20Sopenharmony_ci } 618c2ecf20Sopenharmony_ci 628c2ecf20Sopenharmony_ci return ERR_PTR(-ENOENT); 638c2ecf20Sopenharmony_ci} 648c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(psil_get_ep_config); 658c2ecf20Sopenharmony_ci 668c2ecf20Sopenharmony_ciint psil_set_new_ep_config(struct device *dev, const char *name, 678c2ecf20Sopenharmony_ci struct psil_endpoint_config *ep_config) 688c2ecf20Sopenharmony_ci{ 698c2ecf20Sopenharmony_ci struct psil_endpoint_config *dst_ep_config; 708c2ecf20Sopenharmony_ci struct of_phandle_args dma_spec; 718c2ecf20Sopenharmony_ci u32 thread_id; 728c2ecf20Sopenharmony_ci int index; 738c2ecf20Sopenharmony_ci 748c2ecf20Sopenharmony_ci if (!dev || !dev->of_node) 758c2ecf20Sopenharmony_ci return -EINVAL; 768c2ecf20Sopenharmony_ci 778c2ecf20Sopenharmony_ci index = of_property_match_string(dev->of_node, "dma-names", name); 788c2ecf20Sopenharmony_ci if (index < 0) 798c2ecf20Sopenharmony_ci return index; 808c2ecf20Sopenharmony_ci 818c2ecf20Sopenharmony_ci if (of_parse_phandle_with_args(dev->of_node, "dmas", "#dma-cells", 828c2ecf20Sopenharmony_ci index, &dma_spec)) 838c2ecf20Sopenharmony_ci return -ENOENT; 848c2ecf20Sopenharmony_ci 858c2ecf20Sopenharmony_ci thread_id = dma_spec.args[0]; 868c2ecf20Sopenharmony_ci 878c2ecf20Sopenharmony_ci dst_ep_config = psil_get_ep_config(thread_id); 888c2ecf20Sopenharmony_ci if (IS_ERR(dst_ep_config)) { 898c2ecf20Sopenharmony_ci pr_err("PSIL: thread ID 0x%04x not defined in map\n", 908c2ecf20Sopenharmony_ci thread_id); 918c2ecf20Sopenharmony_ci of_node_put(dma_spec.np); 928c2ecf20Sopenharmony_ci return PTR_ERR(dst_ep_config); 938c2ecf20Sopenharmony_ci } 948c2ecf20Sopenharmony_ci 958c2ecf20Sopenharmony_ci memcpy(dst_ep_config, ep_config, sizeof(*dst_ep_config)); 968c2ecf20Sopenharmony_ci 978c2ecf20Sopenharmony_ci of_node_put(dma_spec.np); 988c2ecf20Sopenharmony_ci return 0; 998c2ecf20Sopenharmony_ci} 1008c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(psil_set_new_ep_config); 101