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 ath79_reset->base = devm_platform_ioremap_resource(pdev, 0); 97 if (IS_ERR(ath79_reset->base)) 98 return PTR_ERR(ath79_reset->base); 99 100 spin_lock_init(&ath79_reset->lock); 101 ath79_reset->rcdev.ops = &ath79_reset_ops; 102 ath79_reset->rcdev.owner = THIS_MODULE; 103 ath79_reset->rcdev.of_node = pdev->dev.of_node; 104 ath79_reset->rcdev.of_reset_n_cells = 1; 105 ath79_reset->rcdev.nr_resets = 32; 106 107 err = devm_reset_controller_register(&pdev->dev, &ath79_reset->rcdev); 108 if (err) 109 return err; 110 111 ath79_reset->restart_nb.notifier_call = ath79_reset_restart_handler; 112 ath79_reset->restart_nb.priority = 128; 113 114 err = register_restart_handler(&ath79_reset->restart_nb); 115 if (err) 116 dev_warn(&pdev->dev, "Failed to register restart handler\n"); 117 118 return 0; 119 } 120 121 static const struct of_device_id ath79_reset_dt_ids[] = { 122 { .compatible = "qca,ar7100-reset", }, 123 { }, 124 }; 125 126 static struct platform_driver ath79_reset_driver = { 127 .probe = ath79_reset_probe, 128 .driver = { 129 .name = "ath79-reset", 130 .of_match_table = ath79_reset_dt_ids, 131 .suppress_bind_attrs = true, 132 }, 133 }; 134 builtin_platform_driver(ath79_reset_driver); 135