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 void __iomem *base; 19 spinlock_t lock; 20 }; 21 22 #define FULL_CHIP_RESET 24 23 24 static int ath79_reset_update(struct reset_controller_dev *rcdev, 25 unsigned long id, bool assert) 26 { 27 struct ath79_reset *ath79_reset = 28 container_of(rcdev, struct ath79_reset, rcdev); 29 unsigned long flags; 30 u32 val; 31 32 spin_lock_irqsave(&ath79_reset->lock, flags); 33 val = readl(ath79_reset->base); 34 if (assert) 35 val |= BIT(id); 36 else 37 val &= ~BIT(id); 38 writel(val, ath79_reset->base); 39 spin_unlock_irqrestore(&ath79_reset->lock, flags); 40 41 return 0; 42 } 43 44 static int ath79_reset_assert(struct reset_controller_dev *rcdev, 45 unsigned long id) 46 { 47 return ath79_reset_update(rcdev, id, true); 48 } 49 50 static int ath79_reset_deassert(struct reset_controller_dev *rcdev, 51 unsigned long id) 52 { 53 return ath79_reset_update(rcdev, id, false); 54 } 55 56 static int ath79_reset_status(struct reset_controller_dev *rcdev, 57 unsigned long id) 58 { 59 struct ath79_reset *ath79_reset = 60 container_of(rcdev, struct ath79_reset, rcdev); 61 u32 val; 62 63 val = readl(ath79_reset->base); 64 65 return !!(val & BIT(id)); 66 } 67 68 static const struct reset_control_ops ath79_reset_ops = { 69 .assert = ath79_reset_assert, 70 .deassert = ath79_reset_deassert, 71 .status = ath79_reset_status, 72 }; 73 74 static int ath79_reset_restart_handler(struct sys_off_data *data) 75 { 76 struct ath79_reset *ath79_reset = data->cb_data; 77 78 ath79_reset_assert(&ath79_reset->rcdev, FULL_CHIP_RESET); 79 80 return NOTIFY_DONE; 81 } 82 83 static int ath79_reset_probe(struct platform_device *pdev) 84 { 85 struct ath79_reset *ath79_reset; 86 int err; 87 88 ath79_reset = devm_kzalloc(&pdev->dev, 89 sizeof(*ath79_reset), GFP_KERNEL); 90 if (!ath79_reset) 91 return -ENOMEM; 92 93 ath79_reset->base = devm_platform_ioremap_resource(pdev, 0); 94 if (IS_ERR(ath79_reset->base)) 95 return PTR_ERR(ath79_reset->base); 96 97 spin_lock_init(&ath79_reset->lock); 98 ath79_reset->rcdev.ops = &ath79_reset_ops; 99 ath79_reset->rcdev.owner = THIS_MODULE; 100 ath79_reset->rcdev.of_node = pdev->dev.of_node; 101 ath79_reset->rcdev.of_reset_n_cells = 1; 102 ath79_reset->rcdev.nr_resets = 32; 103 104 err = devm_reset_controller_register(&pdev->dev, &ath79_reset->rcdev); 105 if (err) 106 return err; 107 108 err = devm_register_restart_handler(&pdev->dev, ath79_reset_restart_handler, ath79_reset); 109 if (err) 110 dev_warn(&pdev->dev, "Failed to register restart handler\n"); 111 112 return 0; 113 } 114 115 static const struct of_device_id ath79_reset_dt_ids[] = { 116 { .compatible = "qca,ar7100-reset", }, 117 { }, 118 }; 119 120 static struct platform_driver ath79_reset_driver = { 121 .probe = ath79_reset_probe, 122 .driver = { 123 .name = "ath79-reset", 124 .of_match_table = ath79_reset_dt_ids, 125 .suppress_bind_attrs = true, 126 }, 127 }; 128 builtin_platform_driver(ath79_reset_driver); 129