Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

at v4.9-rc2 157 lines 4.1 kB view raw
1/* 2 * Copyright (C) 2015 Alban Bedel <albeu@free.fr> 3 * 4 * This program is free software; you can redistribute it and/or modify 5 * it under the terms of the GNU General Public License as published by 6 * the Free Software Foundation; either version 2 of the License, or 7 * (at your option) any later version. 8 * 9 * This program is distributed in the hope that it will be useful, 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 * GNU General Public License for more details. 13 */ 14 15#include <linux/io.h> 16#include <linux/module.h> 17#include <linux/platform_device.h> 18#include <linux/reset-controller.h> 19#include <linux/reboot.h> 20 21struct ath79_reset { 22 struct reset_controller_dev rcdev; 23 struct notifier_block restart_nb; 24 void __iomem *base; 25 spinlock_t lock; 26}; 27 28#define FULL_CHIP_RESET 24 29 30static int ath79_reset_update(struct reset_controller_dev *rcdev, 31 unsigned long id, bool assert) 32{ 33 struct ath79_reset *ath79_reset = 34 container_of(rcdev, struct ath79_reset, rcdev); 35 unsigned long flags; 36 u32 val; 37 38 spin_lock_irqsave(&ath79_reset->lock, flags); 39 val = readl(ath79_reset->base); 40 if (assert) 41 val |= BIT(id); 42 else 43 val &= ~BIT(id); 44 writel(val, ath79_reset->base); 45 spin_unlock_irqrestore(&ath79_reset->lock, flags); 46 47 return 0; 48} 49 50static int ath79_reset_assert(struct reset_controller_dev *rcdev, 51 unsigned long id) 52{ 53 return ath79_reset_update(rcdev, id, true); 54} 55 56static int ath79_reset_deassert(struct reset_controller_dev *rcdev, 57 unsigned long id) 58{ 59 return ath79_reset_update(rcdev, id, false); 60} 61 62static int ath79_reset_status(struct reset_controller_dev *rcdev, 63 unsigned long id) 64{ 65 struct ath79_reset *ath79_reset = 66 container_of(rcdev, struct ath79_reset, rcdev); 67 u32 val; 68 69 val = readl(ath79_reset->base); 70 71 return !!(val & BIT(id)); 72} 73 74static const struct reset_control_ops ath79_reset_ops = { 75 .assert = ath79_reset_assert, 76 .deassert = ath79_reset_deassert, 77 .status = ath79_reset_status, 78}; 79 80static int ath79_reset_restart_handler(struct notifier_block *nb, 81 unsigned long action, void *data) 82{ 83 struct ath79_reset *ath79_reset = 84 container_of(nb, struct ath79_reset, restart_nb); 85 86 ath79_reset_assert(&ath79_reset->rcdev, FULL_CHIP_RESET); 87 88 return NOTIFY_DONE; 89} 90 91static int ath79_reset_probe(struct platform_device *pdev) 92{ 93 struct ath79_reset *ath79_reset; 94 struct resource *res; 95 int err; 96 97 ath79_reset = devm_kzalloc(&pdev->dev, 98 sizeof(*ath79_reset), GFP_KERNEL); 99 if (!ath79_reset) 100 return -ENOMEM; 101 102 platform_set_drvdata(pdev, ath79_reset); 103 104 res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 105 ath79_reset->base = devm_ioremap_resource(&pdev->dev, res); 106 if (IS_ERR(ath79_reset->base)) 107 return PTR_ERR(ath79_reset->base); 108 109 spin_lock_init(&ath79_reset->lock); 110 ath79_reset->rcdev.ops = &ath79_reset_ops; 111 ath79_reset->rcdev.owner = THIS_MODULE; 112 ath79_reset->rcdev.of_node = pdev->dev.of_node; 113 ath79_reset->rcdev.of_reset_n_cells = 1; 114 ath79_reset->rcdev.nr_resets = 32; 115 116 err = devm_reset_controller_register(&pdev->dev, &ath79_reset->rcdev); 117 if (err) 118 return err; 119 120 ath79_reset->restart_nb.notifier_call = ath79_reset_restart_handler; 121 ath79_reset->restart_nb.priority = 128; 122 123 err = register_restart_handler(&ath79_reset->restart_nb); 124 if (err) 125 dev_warn(&pdev->dev, "Failed to register restart handler\n"); 126 127 return 0; 128} 129 130static int ath79_reset_remove(struct platform_device *pdev) 131{ 132 struct ath79_reset *ath79_reset = platform_get_drvdata(pdev); 133 134 unregister_restart_handler(&ath79_reset->restart_nb); 135 136 return 0; 137} 138 139static const struct of_device_id ath79_reset_dt_ids[] = { 140 { .compatible = "qca,ar7100-reset", }, 141 { }, 142}; 143MODULE_DEVICE_TABLE(of, ath79_reset_dt_ids); 144 145static struct platform_driver ath79_reset_driver = { 146 .probe = ath79_reset_probe, 147 .remove = ath79_reset_remove, 148 .driver = { 149 .name = "ath79-reset", 150 .of_match_table = ath79_reset_dt_ids, 151 }, 152}; 153module_platform_driver(ath79_reset_driver); 154 155MODULE_AUTHOR("Alban Bedel <albeu@free.fr>"); 156MODULE_DESCRIPTION("AR71xx Reset Controller Driver"); 157MODULE_LICENSE("GPL");