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 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 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 61 static void imx_aipstz_remove(struct platform_device *pdev) 62 { 63 of_platform_depopulate(&pdev->dev); 64 } 65 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