1 // SPDX-License-Identifier: GPL-2.0-or-later 2 /* 3 * AR71xx Reset Controller Driver 4 * Author: Alban Bedel 5 * 6 * Copyright (C) 2015 Alban Bedel <albeu@free.fr> 7 */ 8 9 #include <linux/io.h> 10 #include <linux/init.h> 11 #include <linux/mod_devicetable.h> 12 #include <linux/platform_device.h> 13 #include <linux/reset-controller.h> 14 #include <linux/reboot.h> 15 16 struct ath79_reset { 17 struct reset_controller_dev rcdev; 18 struct notifier_block restart_nb; 19 void __iomem *base; 20 spinlock_t lock; 21 }; 22 23 #define FULL_CHIP_RESET 24 24 25 static int ath79_reset_update(struct reset_controller_dev *rcdev, 26 unsigned long id, bool assert) 27 { 28 struct ath79_reset *ath79_reset = 29 container_of(rcdev, struct ath79_reset, rcdev); 30 unsigned long flags; 31 u32 val; 32 33 spin_lock_irqsave(&ath79_reset->lock, flags); 34 val = readl(ath79_reset->base); 35 if (assert) 36 val |= BIT(id); 37 else 38 val &= ~BIT(id); 39 writel(val, ath79_reset->base); 40 spin_unlock_irqrestore(&ath79_reset->lock, flags); 41 42 return 0; 43 } 44 45 static int ath79_reset_assert(struct reset_controller_dev *rcdev, 46 unsigned long id) 47 { 48 return ath79_reset_update(rcdev, id, true); 49 } 50 51 static int ath79_reset_deassert(struct reset_controller_dev *rcdev, 52 unsigned long id) 53 { 54 return ath79_reset_update(rcdev, id, false); 55 } 56 57 static int ath79_reset_status(struct reset_controller_dev *rcdev, 58 unsigned long id) 59 { 60 struct ath79_reset *ath79_reset = 61 container_of(rcdev, struct ath79_reset, rcdev); 62 u32 val; 63 64 val = readl(ath79_reset->base); 65 66 return !!(val & BIT(id)); 67 } 68 69 static const struct reset_control_ops ath79_reset_ops = { 70 .assert = ath79_reset_assert, 71 .deassert = ath79_reset_deassert, 72 .status = ath79_reset_status, 73 }; 74 75 static int ath79_reset_restart_handler(struct notifier_block *nb, 76 unsigned long action, void *data) 77 { 78 struct ath79_reset *ath79_reset = 79 container_of(nb, struct ath79_reset, restart_nb); 80 81 ath79_reset_assert(&ath79_reset->rcdev, FULL_CHIP_RESET); 82 83 return NOTIFY_DONE; 84 } 85 86 static int ath79_reset_probe(struct platform_device *pdev) 87 { 88 struct ath79_reset *ath79_reset; 89 int err; 90 91 ath79_reset = devm_kzalloc(&pdev->dev, 92 sizeof(*ath79_reset), GFP_KERNEL); 93 if (!ath79_reset) 94 return -ENOMEM; 95 96 platform_set_drvdata(pdev, ath79_reset); 97 98 ath79_reset->base = devm_platform_ioremap_resource(pdev, 0); 99 if (IS_ERR(ath79_reset->base)) 100 return PTR_ERR(ath79_reset->base); 101 102 spin_lock_init(&ath79_reset->lock); 103 ath79_reset->rcdev.ops = &ath79_reset_ops; 104 ath79_reset->rcdev.owner = THIS_MODULE; 105 ath79_reset->rcdev.of_node = pdev->dev.of_node; 106 ath79_reset->rcdev.of_reset_n_cells = 1; 107 ath79_reset->rcdev.nr_resets = 32; 108 109 err = devm_reset_controller_register(&pdev->dev, &ath79_reset->rcdev); 110 if (err) 111 return err; 112 113 ath79_reset->restart_nb.notifier_call = ath79_reset_restart_handler; 114 ath79_reset->restart_nb.priority = 128; 115 116 err = register_restart_handler(&ath79_reset->restart_nb); 117 if (err) 118 dev_warn(&pdev->dev, "Failed to register restart handler\n"); 119 120 return 0; 121 } 122 123 static const struct of_device_id ath79_reset_dt_ids[] = { 124 { .compatible = "qca,ar7100-reset", }, 125 { }, 126 }; 127 128 static struct platform_driver ath79_reset_driver = { 129 .probe = ath79_reset_probe, 130 .driver = { 131 .name = "ath79-reset", 132 .of_match_table = ath79_reset_dt_ids, 133 .suppress_bind_attrs = true, 134 }, 135 }; 136 builtin_platform_driver(ath79_reset_driver); 137