1 // SPDX-License-Identifier: GPL-2.0+ 2 /* 3 * Copyright (C) 2018 Xilinx, Inc. 4 * 5 */ 6 7 #include <linux/err.h> 8 #include <linux/of.h> 9 #include <linux/platform_device.h> 10 #include <linux/reset-controller.h> 11 #include <linux/firmware/xlnx-zynqmp.h> 12 13 #define ZYNQMP_NR_RESETS (ZYNQMP_PM_RESET_END - ZYNQMP_PM_RESET_START) 14 #define ZYNQMP_RESET_ID ZYNQMP_PM_RESET_START 15 16 struct zynqmp_reset_data { 17 struct reset_controller_dev rcdev; 18 }; 19 20 static inline struct zynqmp_reset_data * 21 to_zynqmp_reset_data(struct reset_controller_dev *rcdev) 22 { 23 return container_of(rcdev, struct zynqmp_reset_data, rcdev); 24 } 25 26 static int zynqmp_reset_assert(struct reset_controller_dev *rcdev, 27 unsigned long id) 28 { 29 return zynqmp_pm_reset_assert(ZYNQMP_RESET_ID + id, 30 PM_RESET_ACTION_ASSERT); 31 } 32 33 static int zynqmp_reset_deassert(struct reset_controller_dev *rcdev, 34 unsigned long id) 35 { 36 return zynqmp_pm_reset_assert(ZYNQMP_RESET_ID + id, 37 PM_RESET_ACTION_RELEASE); 38 } 39 40 static int zynqmp_reset_status(struct reset_controller_dev *rcdev, 41 unsigned long id) 42 { 43 int val, err; 44 45 err = zynqmp_pm_reset_get_status(ZYNQMP_RESET_ID + id, &val); 46 if (err) 47 return err; 48 49 return val; 50 } 51 52 static int zynqmp_reset_reset(struct reset_controller_dev *rcdev, 53 unsigned long id) 54 { 55 return zynqmp_pm_reset_assert(ZYNQMP_RESET_ID + id, 56 PM_RESET_ACTION_PULSE); 57 } 58 59 static const struct reset_control_ops zynqmp_reset_ops = { 60 .reset = zynqmp_reset_reset, 61 .assert = zynqmp_reset_assert, 62 .deassert = zynqmp_reset_deassert, 63 .status = zynqmp_reset_status, 64 }; 65 66 static int zynqmp_reset_probe(struct platform_device *pdev) 67 { 68 struct zynqmp_reset_data *priv; 69 70 priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL); 71 if (!priv) 72 return -ENOMEM; 73 74 platform_set_drvdata(pdev, priv); 75 76 priv->rcdev.ops = &zynqmp_reset_ops; 77 priv->rcdev.owner = THIS_MODULE; 78 priv->rcdev.of_node = pdev->dev.of_node; 79 priv->rcdev.nr_resets = ZYNQMP_NR_RESETS; 80 81 return devm_reset_controller_register(&pdev->dev, &priv->rcdev); 82 } 83 84 static const struct of_device_id zynqmp_reset_dt_ids[] = { 85 { .compatible = "xlnx,zynqmp-reset", }, 86 { /* sentinel */ }, 87 }; 88 89 static struct platform_driver zynqmp_reset_driver = { 90 .probe = zynqmp_reset_probe, 91 .driver = { 92 .name = KBUILD_MODNAME, 93 .of_match_table = zynqmp_reset_dt_ids, 94 }, 95 }; 96 97 static int __init zynqmp_reset_init(void) 98 { 99 return platform_driver_register(&zynqmp_reset_driver); 100 } 101 102 arch_initcall(zynqmp_reset_init); 103