xref: /linux/drivers/bus/imx-aipstz.c (revision 53597deca0e38c30e6cd4ba2114fa42d2bcd85bb)
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 #define IMX_AIPSTZ_OPACR0 0x40
15 #define IMX_AIPSTZ_OPACR1 0x44
16 #define IMX_AIPSTZ_OPACR2 0x48
17 #define IMX_AIPSTZ_OPACR3 0x4c
18 #define IMX_AIPSTZ_OPACR4 0x50
19 
20 struct imx_aipstz_config {
21 	u32 mpr0;
22 	u32 opacr0;
23 	u32 opacr1;
24 	u32 opacr2;
25 	u32 opacr3;
26 	u32 opacr4;
27 };
28 
29 struct imx_aipstz_data {
30 	void __iomem *base;
31 	const struct imx_aipstz_config *default_cfg;
32 };
33 
34 static void imx_aipstz_apply_default(struct imx_aipstz_data *data)
35 {
36 	writel(data->default_cfg->mpr0, data->base + IMX_AIPSTZ_MPR0);
37 	writel(data->default_cfg->opacr0, data->base + IMX_AIPSTZ_OPACR0);
38 	writel(data->default_cfg->opacr1, data->base + IMX_AIPSTZ_OPACR1);
39 	writel(data->default_cfg->opacr2, data->base + IMX_AIPSTZ_OPACR2);
40 	writel(data->default_cfg->opacr3, data->base + IMX_AIPSTZ_OPACR3);
41 	writel(data->default_cfg->opacr4, data->base + IMX_AIPSTZ_OPACR4);
42 }
43 
44 static const struct of_device_id imx_aipstz_match_table[] = {
45 	{ .compatible = "simple-bus", },
46 	{ }
47 };
48 
49 static int imx_aipstz_probe(struct platform_device *pdev)
50 {
51 	struct imx_aipstz_data *data;
52 
53 	data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL);
54 	if (!data)
55 		return dev_err_probe(&pdev->dev, -ENOMEM,
56 				     "failed to allocate data memory\n");
57 
58 	data->base = devm_platform_get_and_ioremap_resource(pdev, 0, NULL);
59 	if (IS_ERR(data->base))
60 		return dev_err_probe(&pdev->dev, -ENOMEM,
61 				     "failed to get/ioremap AC memory\n");
62 
63 	data->default_cfg = of_device_get_match_data(&pdev->dev);
64 
65 	imx_aipstz_apply_default(data);
66 
67 	dev_set_drvdata(&pdev->dev, data);
68 
69 	pm_runtime_set_active(&pdev->dev);
70 	devm_pm_runtime_enable(&pdev->dev);
71 
72 	return of_platform_populate(pdev->dev.of_node, imx_aipstz_match_table,
73 				    NULL, &pdev->dev);
74 }
75 
76 static void imx_aipstz_remove(struct platform_device *pdev)
77 {
78 	of_platform_depopulate(&pdev->dev);
79 }
80 
81 static int imx_aipstz_runtime_resume(struct device *dev)
82 {
83 	struct imx_aipstz_data *data = dev_get_drvdata(dev);
84 
85 	/* restore potentially lost configuration during domain power-off */
86 	imx_aipstz_apply_default(data);
87 
88 	return 0;
89 }
90 
91 static const struct dev_pm_ops imx_aipstz_pm_ops = {
92 	RUNTIME_PM_OPS(NULL, imx_aipstz_runtime_resume, NULL)
93 	SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend, pm_runtime_force_resume)
94 };
95 
96 /*
97  * following configuration is equivalent to:
98  *	masters 0-7 => trusted for R/W + use AHB's HPROT[1] to det. privilege
99  */
100 static const struct imx_aipstz_config imx8mp_aipstz_default_cfg = {
101 	.mpr0 = 0x77777777,
102 };
103 
104 static const struct of_device_id imx_aipstz_of_ids[] = {
105 	{ .compatible = "fsl,imx8mp-aipstz", .data = &imx8mp_aipstz_default_cfg },
106 	{ }
107 };
108 MODULE_DEVICE_TABLE(of, imx_aipstz_of_ids);
109 
110 static struct platform_driver imx_aipstz_of_driver = {
111 	.probe = imx_aipstz_probe,
112 	.remove = imx_aipstz_remove,
113 	.driver = {
114 		.name = "imx-aipstz",
115 		.of_match_table = imx_aipstz_of_ids,
116 		.pm = pm_ptr(&imx_aipstz_pm_ops),
117 	},
118 };
119 module_platform_driver(imx_aipstz_of_driver);
120 
121 MODULE_LICENSE("GPL");
122 MODULE_DESCRIPTION("IMX secure AHB to IP Slave bus (AIPSTZ) bridge driver");
123 MODULE_AUTHOR("Laurentiu Mihalcea <laurentiu.mihalcea@nxp.com>");
124