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