18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only
28c2ecf20Sopenharmony_ci/*
38c2ecf20Sopenharmony_ci * PRU-ICSS platform driver for various TI SoCs
48c2ecf20Sopenharmony_ci *
58c2ecf20Sopenharmony_ci * Copyright (C) 2014-2020 Texas Instruments Incorporated - http://www.ti.com/
68c2ecf20Sopenharmony_ci * Author(s):
78c2ecf20Sopenharmony_ci *	Suman Anna <s-anna@ti.com>
88c2ecf20Sopenharmony_ci *	Andrew F. Davis <afd@ti.com>
98c2ecf20Sopenharmony_ci */
108c2ecf20Sopenharmony_ci
118c2ecf20Sopenharmony_ci#include <linux/clk-provider.h>
128c2ecf20Sopenharmony_ci#include <linux/dma-mapping.h>
138c2ecf20Sopenharmony_ci#include <linux/io.h>
148c2ecf20Sopenharmony_ci#include <linux/mfd/syscon.h>
158c2ecf20Sopenharmony_ci#include <linux/module.h>
168c2ecf20Sopenharmony_ci#include <linux/of_address.h>
178c2ecf20Sopenharmony_ci#include <linux/of_device.h>
188c2ecf20Sopenharmony_ci#include <linux/pm_runtime.h>
198c2ecf20Sopenharmony_ci#include <linux/pruss_driver.h>
208c2ecf20Sopenharmony_ci#include <linux/regmap.h>
218c2ecf20Sopenharmony_ci#include <linux/slab.h>
228c2ecf20Sopenharmony_ci
238c2ecf20Sopenharmony_ci/**
248c2ecf20Sopenharmony_ci * struct pruss_private_data - PRUSS driver private data
258c2ecf20Sopenharmony_ci * @has_no_sharedram: flag to indicate the absence of PRUSS Shared Data RAM
268c2ecf20Sopenharmony_ci * @has_core_mux_clock: flag to indicate the presence of PRUSS core clock
278c2ecf20Sopenharmony_ci */
288c2ecf20Sopenharmony_cistruct pruss_private_data {
298c2ecf20Sopenharmony_ci	bool has_no_sharedram;
308c2ecf20Sopenharmony_ci	bool has_core_mux_clock;
318c2ecf20Sopenharmony_ci};
328c2ecf20Sopenharmony_ci
338c2ecf20Sopenharmony_cistatic void pruss_of_free_clk_provider(void *data)
348c2ecf20Sopenharmony_ci{
358c2ecf20Sopenharmony_ci	struct device_node *clk_mux_np = data;
368c2ecf20Sopenharmony_ci
378c2ecf20Sopenharmony_ci	of_clk_del_provider(clk_mux_np);
388c2ecf20Sopenharmony_ci	of_node_put(clk_mux_np);
398c2ecf20Sopenharmony_ci}
408c2ecf20Sopenharmony_ci
418c2ecf20Sopenharmony_cistatic int pruss_clk_mux_setup(struct pruss *pruss, struct clk *clk_mux,
428c2ecf20Sopenharmony_ci			       char *mux_name, struct device_node *clks_np)
438c2ecf20Sopenharmony_ci{
448c2ecf20Sopenharmony_ci	struct device_node *clk_mux_np;
458c2ecf20Sopenharmony_ci	struct device *dev = pruss->dev;
468c2ecf20Sopenharmony_ci	char *clk_mux_name;
478c2ecf20Sopenharmony_ci	unsigned int num_parents;
488c2ecf20Sopenharmony_ci	const char **parent_names;
498c2ecf20Sopenharmony_ci	void __iomem *reg;
508c2ecf20Sopenharmony_ci	u32 reg_offset;
518c2ecf20Sopenharmony_ci	int ret;
528c2ecf20Sopenharmony_ci
538c2ecf20Sopenharmony_ci	clk_mux_np = of_get_child_by_name(clks_np, mux_name);
548c2ecf20Sopenharmony_ci	if (!clk_mux_np) {
558c2ecf20Sopenharmony_ci		dev_err(dev, "%pOF is missing its '%s' node\n", clks_np,
568c2ecf20Sopenharmony_ci			mux_name);
578c2ecf20Sopenharmony_ci		return -ENODEV;
588c2ecf20Sopenharmony_ci	}
598c2ecf20Sopenharmony_ci
608c2ecf20Sopenharmony_ci	num_parents = of_clk_get_parent_count(clk_mux_np);
618c2ecf20Sopenharmony_ci	if (num_parents < 1) {
628c2ecf20Sopenharmony_ci		dev_err(dev, "mux-clock %pOF must have parents\n", clk_mux_np);
638c2ecf20Sopenharmony_ci		ret = -EINVAL;
648c2ecf20Sopenharmony_ci		goto put_clk_mux_np;
658c2ecf20Sopenharmony_ci	}
668c2ecf20Sopenharmony_ci
678c2ecf20Sopenharmony_ci	parent_names = devm_kcalloc(dev, sizeof(*parent_names), num_parents,
688c2ecf20Sopenharmony_ci				    GFP_KERNEL);
698c2ecf20Sopenharmony_ci	if (!parent_names) {
708c2ecf20Sopenharmony_ci		ret = -ENOMEM;
718c2ecf20Sopenharmony_ci		goto put_clk_mux_np;
728c2ecf20Sopenharmony_ci	}
738c2ecf20Sopenharmony_ci
748c2ecf20Sopenharmony_ci	of_clk_parent_fill(clk_mux_np, parent_names, num_parents);
758c2ecf20Sopenharmony_ci
768c2ecf20Sopenharmony_ci	clk_mux_name = devm_kasprintf(dev, GFP_KERNEL, "%s.%pOFn",
778c2ecf20Sopenharmony_ci				      dev_name(dev), clk_mux_np);
788c2ecf20Sopenharmony_ci	if (!clk_mux_name) {
798c2ecf20Sopenharmony_ci		ret = -ENOMEM;
808c2ecf20Sopenharmony_ci		goto put_clk_mux_np;
818c2ecf20Sopenharmony_ci	}
828c2ecf20Sopenharmony_ci
838c2ecf20Sopenharmony_ci	ret = of_property_read_u32(clk_mux_np, "reg", &reg_offset);
848c2ecf20Sopenharmony_ci	if (ret)
858c2ecf20Sopenharmony_ci		goto put_clk_mux_np;
868c2ecf20Sopenharmony_ci
878c2ecf20Sopenharmony_ci	reg = pruss->cfg_base + reg_offset;
888c2ecf20Sopenharmony_ci
898c2ecf20Sopenharmony_ci	clk_mux = clk_register_mux(NULL, clk_mux_name, parent_names,
908c2ecf20Sopenharmony_ci				   num_parents, 0, reg, 0, 1, 0, NULL);
918c2ecf20Sopenharmony_ci	if (IS_ERR(clk_mux)) {
928c2ecf20Sopenharmony_ci		ret = PTR_ERR(clk_mux);
938c2ecf20Sopenharmony_ci		goto put_clk_mux_np;
948c2ecf20Sopenharmony_ci	}
958c2ecf20Sopenharmony_ci
968c2ecf20Sopenharmony_ci	ret = devm_add_action_or_reset(dev, (void(*)(void *))clk_unregister_mux,
978c2ecf20Sopenharmony_ci				       clk_mux);
988c2ecf20Sopenharmony_ci	if (ret) {
998c2ecf20Sopenharmony_ci		dev_err(dev, "failed to add clkmux unregister action %d", ret);
1008c2ecf20Sopenharmony_ci		goto put_clk_mux_np;
1018c2ecf20Sopenharmony_ci	}
1028c2ecf20Sopenharmony_ci
1038c2ecf20Sopenharmony_ci	ret = of_clk_add_provider(clk_mux_np, of_clk_src_simple_get, clk_mux);
1048c2ecf20Sopenharmony_ci	if (ret)
1058c2ecf20Sopenharmony_ci		goto put_clk_mux_np;
1068c2ecf20Sopenharmony_ci
1078c2ecf20Sopenharmony_ci	ret = devm_add_action_or_reset(dev, pruss_of_free_clk_provider,
1088c2ecf20Sopenharmony_ci				       clk_mux_np);
1098c2ecf20Sopenharmony_ci	if (ret) {
1108c2ecf20Sopenharmony_ci		dev_err(dev, "failed to add clkmux free action %d", ret);
1118c2ecf20Sopenharmony_ci		goto put_clk_mux_np;
1128c2ecf20Sopenharmony_ci	}
1138c2ecf20Sopenharmony_ci
1148c2ecf20Sopenharmony_ci	return 0;
1158c2ecf20Sopenharmony_ci
1168c2ecf20Sopenharmony_ciput_clk_mux_np:
1178c2ecf20Sopenharmony_ci	of_node_put(clk_mux_np);
1188c2ecf20Sopenharmony_ci	return ret;
1198c2ecf20Sopenharmony_ci}
1208c2ecf20Sopenharmony_ci
1218c2ecf20Sopenharmony_cistatic int pruss_clk_init(struct pruss *pruss, struct device_node *cfg_node)
1228c2ecf20Sopenharmony_ci{
1238c2ecf20Sopenharmony_ci	const struct pruss_private_data *data;
1248c2ecf20Sopenharmony_ci	struct device_node *clks_np;
1258c2ecf20Sopenharmony_ci	struct device *dev = pruss->dev;
1268c2ecf20Sopenharmony_ci	int ret = 0;
1278c2ecf20Sopenharmony_ci
1288c2ecf20Sopenharmony_ci	data = of_device_get_match_data(dev);
1298c2ecf20Sopenharmony_ci	if (IS_ERR(data))
1308c2ecf20Sopenharmony_ci		return -ENODEV;
1318c2ecf20Sopenharmony_ci
1328c2ecf20Sopenharmony_ci	clks_np = of_get_child_by_name(cfg_node, "clocks");
1338c2ecf20Sopenharmony_ci	if (!clks_np) {
1348c2ecf20Sopenharmony_ci		dev_err(dev, "%pOF is missing its 'clocks' node\n", cfg_node);
1358c2ecf20Sopenharmony_ci		return -ENODEV;
1368c2ecf20Sopenharmony_ci	}
1378c2ecf20Sopenharmony_ci
1388c2ecf20Sopenharmony_ci	if (data && data->has_core_mux_clock) {
1398c2ecf20Sopenharmony_ci		ret = pruss_clk_mux_setup(pruss, pruss->core_clk_mux,
1408c2ecf20Sopenharmony_ci					  "coreclk-mux", clks_np);
1418c2ecf20Sopenharmony_ci		if (ret) {
1428c2ecf20Sopenharmony_ci			dev_err(dev, "failed to setup coreclk-mux\n");
1438c2ecf20Sopenharmony_ci			goto put_clks_node;
1448c2ecf20Sopenharmony_ci		}
1458c2ecf20Sopenharmony_ci	}
1468c2ecf20Sopenharmony_ci
1478c2ecf20Sopenharmony_ci	ret = pruss_clk_mux_setup(pruss, pruss->iep_clk_mux, "iepclk-mux",
1488c2ecf20Sopenharmony_ci				  clks_np);
1498c2ecf20Sopenharmony_ci	if (ret) {
1508c2ecf20Sopenharmony_ci		dev_err(dev, "failed to setup iepclk-mux\n");
1518c2ecf20Sopenharmony_ci		goto put_clks_node;
1528c2ecf20Sopenharmony_ci	}
1538c2ecf20Sopenharmony_ci
1548c2ecf20Sopenharmony_ciput_clks_node:
1558c2ecf20Sopenharmony_ci	of_node_put(clks_np);
1568c2ecf20Sopenharmony_ci
1578c2ecf20Sopenharmony_ci	return ret;
1588c2ecf20Sopenharmony_ci}
1598c2ecf20Sopenharmony_ci
1608c2ecf20Sopenharmony_cistatic struct regmap_config regmap_conf = {
1618c2ecf20Sopenharmony_ci	.reg_bits = 32,
1628c2ecf20Sopenharmony_ci	.val_bits = 32,
1638c2ecf20Sopenharmony_ci	.reg_stride = 4,
1648c2ecf20Sopenharmony_ci};
1658c2ecf20Sopenharmony_ci
1668c2ecf20Sopenharmony_cistatic int pruss_probe(struct platform_device *pdev)
1678c2ecf20Sopenharmony_ci{
1688c2ecf20Sopenharmony_ci	struct device *dev = &pdev->dev;
1698c2ecf20Sopenharmony_ci	struct device_node *np = dev_of_node(dev);
1708c2ecf20Sopenharmony_ci	struct device_node *child;
1718c2ecf20Sopenharmony_ci	struct pruss *pruss;
1728c2ecf20Sopenharmony_ci	struct resource res;
1738c2ecf20Sopenharmony_ci	int ret, i, index;
1748c2ecf20Sopenharmony_ci	const struct pruss_private_data *data;
1758c2ecf20Sopenharmony_ci	const char *mem_names[PRUSS_MEM_MAX] = { "dram0", "dram1", "shrdram2" };
1768c2ecf20Sopenharmony_ci
1778c2ecf20Sopenharmony_ci	data = of_device_get_match_data(&pdev->dev);
1788c2ecf20Sopenharmony_ci	if (IS_ERR(data)) {
1798c2ecf20Sopenharmony_ci		dev_err(dev, "missing private data\n");
1808c2ecf20Sopenharmony_ci		return -ENODEV;
1818c2ecf20Sopenharmony_ci	}
1828c2ecf20Sopenharmony_ci
1838c2ecf20Sopenharmony_ci	ret = dma_set_coherent_mask(dev, DMA_BIT_MASK(32));
1848c2ecf20Sopenharmony_ci	if (ret) {
1858c2ecf20Sopenharmony_ci		dev_err(dev, "failed to set the DMA coherent mask");
1868c2ecf20Sopenharmony_ci		return ret;
1878c2ecf20Sopenharmony_ci	}
1888c2ecf20Sopenharmony_ci
1898c2ecf20Sopenharmony_ci	pruss = devm_kzalloc(dev, sizeof(*pruss), GFP_KERNEL);
1908c2ecf20Sopenharmony_ci	if (!pruss)
1918c2ecf20Sopenharmony_ci		return -ENOMEM;
1928c2ecf20Sopenharmony_ci
1938c2ecf20Sopenharmony_ci	pruss->dev = dev;
1948c2ecf20Sopenharmony_ci
1958c2ecf20Sopenharmony_ci	child = of_get_child_by_name(np, "memories");
1968c2ecf20Sopenharmony_ci	if (!child) {
1978c2ecf20Sopenharmony_ci		dev_err(dev, "%pOF is missing its 'memories' node\n", child);
1988c2ecf20Sopenharmony_ci		return -ENODEV;
1998c2ecf20Sopenharmony_ci	}
2008c2ecf20Sopenharmony_ci
2018c2ecf20Sopenharmony_ci	for (i = 0; i < PRUSS_MEM_MAX; i++) {
2028c2ecf20Sopenharmony_ci		/*
2038c2ecf20Sopenharmony_ci		 * On AM437x one of two PRUSS units don't contain Shared RAM,
2048c2ecf20Sopenharmony_ci		 * skip it
2058c2ecf20Sopenharmony_ci		 */
2068c2ecf20Sopenharmony_ci		if (data && data->has_no_sharedram && i == PRUSS_MEM_SHRD_RAM2)
2078c2ecf20Sopenharmony_ci			continue;
2088c2ecf20Sopenharmony_ci
2098c2ecf20Sopenharmony_ci		index = of_property_match_string(child, "reg-names",
2108c2ecf20Sopenharmony_ci						 mem_names[i]);
2118c2ecf20Sopenharmony_ci		if (index < 0) {
2128c2ecf20Sopenharmony_ci			of_node_put(child);
2138c2ecf20Sopenharmony_ci			return index;
2148c2ecf20Sopenharmony_ci		}
2158c2ecf20Sopenharmony_ci
2168c2ecf20Sopenharmony_ci		if (of_address_to_resource(child, index, &res)) {
2178c2ecf20Sopenharmony_ci			of_node_put(child);
2188c2ecf20Sopenharmony_ci			return -EINVAL;
2198c2ecf20Sopenharmony_ci		}
2208c2ecf20Sopenharmony_ci
2218c2ecf20Sopenharmony_ci		pruss->mem_regions[i].va = devm_ioremap(dev, res.start,
2228c2ecf20Sopenharmony_ci							resource_size(&res));
2238c2ecf20Sopenharmony_ci		if (!pruss->mem_regions[i].va) {
2248c2ecf20Sopenharmony_ci			dev_err(dev, "failed to parse and map memory resource %d %s\n",
2258c2ecf20Sopenharmony_ci				i, mem_names[i]);
2268c2ecf20Sopenharmony_ci			of_node_put(child);
2278c2ecf20Sopenharmony_ci			return -ENOMEM;
2288c2ecf20Sopenharmony_ci		}
2298c2ecf20Sopenharmony_ci		pruss->mem_regions[i].pa = res.start;
2308c2ecf20Sopenharmony_ci		pruss->mem_regions[i].size = resource_size(&res);
2318c2ecf20Sopenharmony_ci
2328c2ecf20Sopenharmony_ci		dev_dbg(dev, "memory %8s: pa %pa size 0x%zx va %pK\n",
2338c2ecf20Sopenharmony_ci			mem_names[i], &pruss->mem_regions[i].pa,
2348c2ecf20Sopenharmony_ci			pruss->mem_regions[i].size, pruss->mem_regions[i].va);
2358c2ecf20Sopenharmony_ci	}
2368c2ecf20Sopenharmony_ci	of_node_put(child);
2378c2ecf20Sopenharmony_ci
2388c2ecf20Sopenharmony_ci	platform_set_drvdata(pdev, pruss);
2398c2ecf20Sopenharmony_ci
2408c2ecf20Sopenharmony_ci	pm_runtime_enable(dev);
2418c2ecf20Sopenharmony_ci	ret = pm_runtime_get_sync(dev);
2428c2ecf20Sopenharmony_ci	if (ret < 0) {
2438c2ecf20Sopenharmony_ci		dev_err(dev, "couldn't enable module\n");
2448c2ecf20Sopenharmony_ci		pm_runtime_put_noidle(dev);
2458c2ecf20Sopenharmony_ci		goto rpm_disable;
2468c2ecf20Sopenharmony_ci	}
2478c2ecf20Sopenharmony_ci
2488c2ecf20Sopenharmony_ci	child = of_get_child_by_name(np, "cfg");
2498c2ecf20Sopenharmony_ci	if (!child) {
2508c2ecf20Sopenharmony_ci		dev_err(dev, "%pOF is missing its 'cfg' node\n", child);
2518c2ecf20Sopenharmony_ci		ret = -ENODEV;
2528c2ecf20Sopenharmony_ci		goto rpm_put;
2538c2ecf20Sopenharmony_ci	}
2548c2ecf20Sopenharmony_ci
2558c2ecf20Sopenharmony_ci	if (of_address_to_resource(child, 0, &res)) {
2568c2ecf20Sopenharmony_ci		ret = -ENOMEM;
2578c2ecf20Sopenharmony_ci		goto node_put;
2588c2ecf20Sopenharmony_ci	}
2598c2ecf20Sopenharmony_ci
2608c2ecf20Sopenharmony_ci	pruss->cfg_base = devm_ioremap(dev, res.start, resource_size(&res));
2618c2ecf20Sopenharmony_ci	if (!pruss->cfg_base) {
2628c2ecf20Sopenharmony_ci		ret = -ENOMEM;
2638c2ecf20Sopenharmony_ci		goto node_put;
2648c2ecf20Sopenharmony_ci	}
2658c2ecf20Sopenharmony_ci
2668c2ecf20Sopenharmony_ci	regmap_conf.name = kasprintf(GFP_KERNEL, "%pOFn@%llx", child,
2678c2ecf20Sopenharmony_ci				     (u64)res.start);
2688c2ecf20Sopenharmony_ci	regmap_conf.max_register = resource_size(&res) - 4;
2698c2ecf20Sopenharmony_ci
2708c2ecf20Sopenharmony_ci	pruss->cfg_regmap = devm_regmap_init_mmio(dev, pruss->cfg_base,
2718c2ecf20Sopenharmony_ci						  &regmap_conf);
2728c2ecf20Sopenharmony_ci	kfree(regmap_conf.name);
2738c2ecf20Sopenharmony_ci	if (IS_ERR(pruss->cfg_regmap)) {
2748c2ecf20Sopenharmony_ci		dev_err(dev, "regmap_init_mmio failed for cfg, ret = %ld\n",
2758c2ecf20Sopenharmony_ci			PTR_ERR(pruss->cfg_regmap));
2768c2ecf20Sopenharmony_ci		ret = PTR_ERR(pruss->cfg_regmap);
2778c2ecf20Sopenharmony_ci		goto node_put;
2788c2ecf20Sopenharmony_ci	}
2798c2ecf20Sopenharmony_ci
2808c2ecf20Sopenharmony_ci	ret = pruss_clk_init(pruss, child);
2818c2ecf20Sopenharmony_ci	if (ret) {
2828c2ecf20Sopenharmony_ci		dev_err(dev, "failed to setup coreclk-mux\n");
2838c2ecf20Sopenharmony_ci		goto node_put;
2848c2ecf20Sopenharmony_ci	}
2858c2ecf20Sopenharmony_ci
2868c2ecf20Sopenharmony_ci	ret = devm_of_platform_populate(dev);
2878c2ecf20Sopenharmony_ci	if (ret) {
2888c2ecf20Sopenharmony_ci		dev_err(dev, "failed to register child devices\n");
2898c2ecf20Sopenharmony_ci		goto node_put;
2908c2ecf20Sopenharmony_ci	}
2918c2ecf20Sopenharmony_ci
2928c2ecf20Sopenharmony_ci	of_node_put(child);
2938c2ecf20Sopenharmony_ci
2948c2ecf20Sopenharmony_ci	return 0;
2958c2ecf20Sopenharmony_ci
2968c2ecf20Sopenharmony_cinode_put:
2978c2ecf20Sopenharmony_ci	of_node_put(child);
2988c2ecf20Sopenharmony_cirpm_put:
2998c2ecf20Sopenharmony_ci	pm_runtime_put_sync(dev);
3008c2ecf20Sopenharmony_cirpm_disable:
3018c2ecf20Sopenharmony_ci	pm_runtime_disable(dev);
3028c2ecf20Sopenharmony_ci	return ret;
3038c2ecf20Sopenharmony_ci}
3048c2ecf20Sopenharmony_ci
3058c2ecf20Sopenharmony_cistatic int pruss_remove(struct platform_device *pdev)
3068c2ecf20Sopenharmony_ci{
3078c2ecf20Sopenharmony_ci	struct device *dev = &pdev->dev;
3088c2ecf20Sopenharmony_ci
3098c2ecf20Sopenharmony_ci	devm_of_platform_depopulate(dev);
3108c2ecf20Sopenharmony_ci
3118c2ecf20Sopenharmony_ci	pm_runtime_put_sync(dev);
3128c2ecf20Sopenharmony_ci	pm_runtime_disable(dev);
3138c2ecf20Sopenharmony_ci
3148c2ecf20Sopenharmony_ci	return 0;
3158c2ecf20Sopenharmony_ci}
3168c2ecf20Sopenharmony_ci
3178c2ecf20Sopenharmony_ci/* instance-specific driver private data */
3188c2ecf20Sopenharmony_cistatic const struct pruss_private_data am437x_pruss1_data = {
3198c2ecf20Sopenharmony_ci	.has_no_sharedram = false,
3208c2ecf20Sopenharmony_ci};
3218c2ecf20Sopenharmony_ci
3228c2ecf20Sopenharmony_cistatic const struct pruss_private_data am437x_pruss0_data = {
3238c2ecf20Sopenharmony_ci	.has_no_sharedram = true,
3248c2ecf20Sopenharmony_ci};
3258c2ecf20Sopenharmony_ci
3268c2ecf20Sopenharmony_cistatic const struct pruss_private_data am65x_j721e_pruss_data = {
3278c2ecf20Sopenharmony_ci	.has_core_mux_clock = true,
3288c2ecf20Sopenharmony_ci};
3298c2ecf20Sopenharmony_ci
3308c2ecf20Sopenharmony_cistatic const struct of_device_id pruss_of_match[] = {
3318c2ecf20Sopenharmony_ci	{ .compatible = "ti,am3356-pruss" },
3328c2ecf20Sopenharmony_ci	{ .compatible = "ti,am4376-pruss0", .data = &am437x_pruss0_data, },
3338c2ecf20Sopenharmony_ci	{ .compatible = "ti,am4376-pruss1", .data = &am437x_pruss1_data, },
3348c2ecf20Sopenharmony_ci	{ .compatible = "ti,am5728-pruss" },
3358c2ecf20Sopenharmony_ci	{ .compatible = "ti,k2g-pruss" },
3368c2ecf20Sopenharmony_ci	{ .compatible = "ti,am654-icssg", .data = &am65x_j721e_pruss_data, },
3378c2ecf20Sopenharmony_ci	{ .compatible = "ti,j721e-icssg", .data = &am65x_j721e_pruss_data, },
3388c2ecf20Sopenharmony_ci	{},
3398c2ecf20Sopenharmony_ci};
3408c2ecf20Sopenharmony_ciMODULE_DEVICE_TABLE(of, pruss_of_match);
3418c2ecf20Sopenharmony_ci
3428c2ecf20Sopenharmony_cistatic struct platform_driver pruss_driver = {
3438c2ecf20Sopenharmony_ci	.driver = {
3448c2ecf20Sopenharmony_ci		.name = "pruss",
3458c2ecf20Sopenharmony_ci		.of_match_table = pruss_of_match,
3468c2ecf20Sopenharmony_ci	},
3478c2ecf20Sopenharmony_ci	.probe  = pruss_probe,
3488c2ecf20Sopenharmony_ci	.remove = pruss_remove,
3498c2ecf20Sopenharmony_ci};
3508c2ecf20Sopenharmony_cimodule_platform_driver(pruss_driver);
3518c2ecf20Sopenharmony_ci
3528c2ecf20Sopenharmony_ciMODULE_AUTHOR("Suman Anna <s-anna@ti.com>");
3538c2ecf20Sopenharmony_ciMODULE_DESCRIPTION("PRU-ICSS Subsystem Driver");
3548c2ecf20Sopenharmony_ciMODULE_LICENSE("GPL v2");
355