0001
0002
0003
0004
0005
0006
0007 #include <linux/err.h>
0008 #include <linux/of.h>
0009 #include <linux/platform_device.h>
0010 #include <linux/reset-controller.h>
0011 #include <linux/firmware/xlnx-zynqmp.h>
0012 #include <linux/of_device.h>
0013
0014 #define ZYNQMP_NR_RESETS (ZYNQMP_PM_RESET_END - ZYNQMP_PM_RESET_START)
0015 #define ZYNQMP_RESET_ID ZYNQMP_PM_RESET_START
0016 #define VERSAL_NR_RESETS 95
0017
0018 struct zynqmp_reset_soc_data {
0019 u32 reset_id;
0020 u32 num_resets;
0021 };
0022
0023 struct zynqmp_reset_data {
0024 struct reset_controller_dev rcdev;
0025 const struct zynqmp_reset_soc_data *data;
0026 };
0027
0028 static inline struct zynqmp_reset_data *
0029 to_zynqmp_reset_data(struct reset_controller_dev *rcdev)
0030 {
0031 return container_of(rcdev, struct zynqmp_reset_data, rcdev);
0032 }
0033
0034 static int zynqmp_reset_assert(struct reset_controller_dev *rcdev,
0035 unsigned long id)
0036 {
0037 struct zynqmp_reset_data *priv = to_zynqmp_reset_data(rcdev);
0038
0039 return zynqmp_pm_reset_assert(priv->data->reset_id + id,
0040 PM_RESET_ACTION_ASSERT);
0041 }
0042
0043 static int zynqmp_reset_deassert(struct reset_controller_dev *rcdev,
0044 unsigned long id)
0045 {
0046 struct zynqmp_reset_data *priv = to_zynqmp_reset_data(rcdev);
0047
0048 return zynqmp_pm_reset_assert(priv->data->reset_id + id,
0049 PM_RESET_ACTION_RELEASE);
0050 }
0051
0052 static int zynqmp_reset_status(struct reset_controller_dev *rcdev,
0053 unsigned long id)
0054 {
0055 struct zynqmp_reset_data *priv = to_zynqmp_reset_data(rcdev);
0056 int err;
0057 u32 val;
0058
0059 err = zynqmp_pm_reset_get_status(priv->data->reset_id + id, &val);
0060 if (err)
0061 return err;
0062
0063 return val;
0064 }
0065
0066 static int zynqmp_reset_reset(struct reset_controller_dev *rcdev,
0067 unsigned long id)
0068 {
0069 struct zynqmp_reset_data *priv = to_zynqmp_reset_data(rcdev);
0070
0071 return zynqmp_pm_reset_assert(priv->data->reset_id + id,
0072 PM_RESET_ACTION_PULSE);
0073 }
0074
0075 static int zynqmp_reset_of_xlate(struct reset_controller_dev *rcdev,
0076 const struct of_phandle_args *reset_spec)
0077 {
0078 return reset_spec->args[0];
0079 }
0080
0081 static const struct zynqmp_reset_soc_data zynqmp_reset_data = {
0082 .reset_id = ZYNQMP_RESET_ID,
0083 .num_resets = ZYNQMP_NR_RESETS,
0084 };
0085
0086 static const struct zynqmp_reset_soc_data versal_reset_data = {
0087 .reset_id = 0,
0088 .num_resets = VERSAL_NR_RESETS,
0089 };
0090
0091 static const struct reset_control_ops zynqmp_reset_ops = {
0092 .reset = zynqmp_reset_reset,
0093 .assert = zynqmp_reset_assert,
0094 .deassert = zynqmp_reset_deassert,
0095 .status = zynqmp_reset_status,
0096 };
0097
0098 static int zynqmp_reset_probe(struct platform_device *pdev)
0099 {
0100 struct zynqmp_reset_data *priv;
0101
0102 priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);
0103 if (!priv)
0104 return -ENOMEM;
0105
0106 priv->data = of_device_get_match_data(&pdev->dev);
0107 if (!priv->data)
0108 return -EINVAL;
0109
0110 platform_set_drvdata(pdev, priv);
0111
0112 priv->rcdev.ops = &zynqmp_reset_ops;
0113 priv->rcdev.owner = THIS_MODULE;
0114 priv->rcdev.of_node = pdev->dev.of_node;
0115 priv->rcdev.nr_resets = priv->data->num_resets;
0116 priv->rcdev.of_reset_n_cells = 1;
0117 priv->rcdev.of_xlate = zynqmp_reset_of_xlate;
0118
0119 return devm_reset_controller_register(&pdev->dev, &priv->rcdev);
0120 }
0121
0122 static const struct of_device_id zynqmp_reset_dt_ids[] = {
0123 { .compatible = "xlnx,zynqmp-reset", .data = &zynqmp_reset_data, },
0124 { .compatible = "xlnx,versal-reset", .data = &versal_reset_data, },
0125 { },
0126 };
0127
0128 static struct platform_driver zynqmp_reset_driver = {
0129 .probe = zynqmp_reset_probe,
0130 .driver = {
0131 .name = KBUILD_MODNAME,
0132 .of_match_table = zynqmp_reset_dt_ids,
0133 },
0134 };
0135
0136 static int __init zynqmp_reset_init(void)
0137 {
0138 return platform_driver_register(&zynqmp_reset_driver);
0139 }
0140
0141 arch_initcall(zynqmp_reset_init);