xref: /linux/drivers/bus/imx-aipstz.c (revision 0f46f50845ce75bfaba62df0421084d23bb6a72f)
1 // SPDX-License-Identifier: GPL-2.0
2 /*
3  * Copyright 2025 NXP
4  */
5 
6 #include <linux/module.h>
7 #include <linux/of.h>
8 #include <linux/of_platform.h>
9 #include <linux/platform_device.h>
10 #include <linux/pm_runtime.h>
11 #include <linux/regmap.h>
12 
13 #define IMX_AIPSTZ_MPR0 0x0
14 
15 struct imx_aipstz_config {
16 	u32 mpr0;
17 };
18 
19 struct imx_aipstz_data {
20 	void __iomem *base;
21 	const struct imx_aipstz_config *default_cfg;
22 };
23 
imx_aipstz_apply_default(struct imx_aipstz_data * data)24 static void imx_aipstz_apply_default(struct imx_aipstz_data *data)
25 {
26 	writel(data->default_cfg->mpr0, data->base + IMX_AIPSTZ_MPR0);
27 }
28 
29 static const struct of_device_id imx_aipstz_match_table[] = {
30 	{ .compatible = "simple-bus", },
31 	{ }
32 };
33 
imx_aipstz_probe(struct platform_device * pdev)34 static int imx_aipstz_probe(struct platform_device *pdev)
35 {
36 	struct imx_aipstz_data *data;
37 
38 	data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL);
39 	if (!data)
40 		return dev_err_probe(&pdev->dev, -ENOMEM,
41 				     "failed to allocate data memory\n");
42 
43 	data->base = devm_platform_get_and_ioremap_resource(pdev, 0, NULL);
44 	if (IS_ERR(data->base))
45 		return dev_err_probe(&pdev->dev, -ENOMEM,
46 				     "failed to get/ioremap AC memory\n");
47 
48 	data->default_cfg = of_device_get_match_data(&pdev->dev);
49 
50 	imx_aipstz_apply_default(data);
51 
52 	dev_set_drvdata(&pdev->dev, data);
53 
54 	pm_runtime_set_active(&pdev->dev);
55 	devm_pm_runtime_enable(&pdev->dev);
56 
57 	return of_platform_populate(pdev->dev.of_node, imx_aipstz_match_table,
58 				    NULL, &pdev->dev);
59 }
60 
imx_aipstz_remove(struct platform_device * pdev)61 static void imx_aipstz_remove(struct platform_device *pdev)
62 {
63 	of_platform_depopulate(&pdev->dev);
64 }
65 
imx_aipstz_runtime_resume(struct device * dev)66 static int imx_aipstz_runtime_resume(struct device *dev)
67 {
68 	struct imx_aipstz_data *data = dev_get_drvdata(dev);
69 
70 	/* restore potentially lost configuration during domain power-off */
71 	imx_aipstz_apply_default(data);
72 
73 	return 0;
74 }
75 
76 static const struct dev_pm_ops imx_aipstz_pm_ops = {
77 	RUNTIME_PM_OPS(NULL, imx_aipstz_runtime_resume, NULL)
78 	SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend, pm_runtime_force_resume)
79 };
80 
81 /*
82  * following configuration is equivalent to:
83  *	masters 0-7 => trusted for R/W + use AHB's HPROT[1] to det. privilege
84  */
85 static const struct imx_aipstz_config imx8mp_aipstz_default_cfg = {
86 	.mpr0 = 0x77777777,
87 };
88 
89 static const struct of_device_id imx_aipstz_of_ids[] = {
90 	{ .compatible = "fsl,imx8mp-aipstz", .data = &imx8mp_aipstz_default_cfg },
91 	{ }
92 };
93 MODULE_DEVICE_TABLE(of, imx_aipstz_of_ids);
94 
95 static struct platform_driver imx_aipstz_of_driver = {
96 	.probe = imx_aipstz_probe,
97 	.remove = imx_aipstz_remove,
98 	.driver = {
99 		.name = "imx-aipstz",
100 		.of_match_table = imx_aipstz_of_ids,
101 		.pm = pm_ptr(&imx_aipstz_pm_ops),
102 	},
103 };
104 module_platform_driver(imx_aipstz_of_driver);
105 
106 MODULE_LICENSE("GPL");
107 MODULE_DESCRIPTION("IMX secure AHB to IP Slave bus (AIPSTZ) bridge driver");
108 MODULE_AUTHOR("Laurentiu Mihalcea <laurentiu.mihalcea@nxp.com>");
109