| .. | .. |
|---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-or-later |
|---|
| 1 | 2 | /* |
|---|
| 2 | 3 | * Simple Reset Controller Driver |
|---|
| 3 | 4 | * |
|---|
| .. | .. |
|---|
| 8 | 9 | * Copyright 2013 Maxime Ripard |
|---|
| 9 | 10 | * |
|---|
| 10 | 11 | * Maxime Ripard <maxime.ripard@free-electrons.com> |
|---|
| 11 | | - * |
|---|
| 12 | | - * This program is free software; you can redistribute it and/or modify |
|---|
| 13 | | - * it under the terms of the GNU General Public License as published by |
|---|
| 14 | | - * the Free Software Foundation; either version 2 of the License, or |
|---|
| 15 | | - * (at your option) any later version. |
|---|
| 16 | 12 | */ |
|---|
| 17 | 13 | |
|---|
| 14 | +#include <linux/delay.h> |
|---|
| 18 | 15 | #include <linux/device.h> |
|---|
| 19 | 16 | #include <linux/err.h> |
|---|
| 20 | 17 | #include <linux/io.h> |
|---|
| .. | .. |
|---|
| 22 | 19 | #include <linux/of_device.h> |
|---|
| 23 | 20 | #include <linux/platform_device.h> |
|---|
| 24 | 21 | #include <linux/reset-controller.h> |
|---|
| 22 | +#include <linux/reset/reset-simple.h> |
|---|
| 25 | 23 | #include <linux/spinlock.h> |
|---|
| 26 | | - |
|---|
| 27 | | -#include "reset-simple.h" |
|---|
| 28 | 24 | |
|---|
| 29 | 25 | static inline struct reset_simple_data * |
|---|
| 30 | 26 | to_reset_simple_data(struct reset_controller_dev *rcdev) |
|---|
| .. | .. |
|---|
| 68 | 64 | return reset_simple_update(rcdev, id, false); |
|---|
| 69 | 65 | } |
|---|
| 70 | 66 | |
|---|
| 67 | +static int reset_simple_reset(struct reset_controller_dev *rcdev, |
|---|
| 68 | + unsigned long id) |
|---|
| 69 | +{ |
|---|
| 70 | + struct reset_simple_data *data = to_reset_simple_data(rcdev); |
|---|
| 71 | + int ret; |
|---|
| 72 | + |
|---|
| 73 | + if (!data->reset_us) |
|---|
| 74 | + return -ENOTSUPP; |
|---|
| 75 | + |
|---|
| 76 | + ret = reset_simple_assert(rcdev, id); |
|---|
| 77 | + if (ret) |
|---|
| 78 | + return ret; |
|---|
| 79 | + |
|---|
| 80 | + usleep_range(data->reset_us, data->reset_us * 2); |
|---|
| 81 | + |
|---|
| 82 | + return reset_simple_deassert(rcdev, id); |
|---|
| 83 | +} |
|---|
| 84 | + |
|---|
| 71 | 85 | static int reset_simple_status(struct reset_controller_dev *rcdev, |
|---|
| 72 | 86 | unsigned long id) |
|---|
| 73 | 87 | { |
|---|
| .. | .. |
|---|
| 85 | 99 | const struct reset_control_ops reset_simple_ops = { |
|---|
| 86 | 100 | .assert = reset_simple_assert, |
|---|
| 87 | 101 | .deassert = reset_simple_deassert, |
|---|
| 102 | + .reset = reset_simple_reset, |
|---|
| 88 | 103 | .status = reset_simple_status, |
|---|
| 89 | 104 | }; |
|---|
| 90 | 105 | EXPORT_SYMBOL_GPL(reset_simple_ops); |
|---|
| .. | .. |
|---|
| 109 | 124 | #define SOCFPGA_NR_BANKS 8 |
|---|
| 110 | 125 | |
|---|
| 111 | 126 | static const struct reset_simple_devdata reset_simple_socfpga = { |
|---|
| 112 | | - .reg_offset = 0x10, |
|---|
| 127 | + .reg_offset = 0x20, |
|---|
| 113 | 128 | .nr_resets = SOCFPGA_NR_BANKS * 32, |
|---|
| 114 | 129 | .status_active_low = true, |
|---|
| 115 | 130 | }; |
|---|
| .. | .. |
|---|
| 120 | 135 | }; |
|---|
| 121 | 136 | |
|---|
| 122 | 137 | static const struct of_device_id reset_simple_dt_ids[] = { |
|---|
| 123 | | - { .compatible = "altr,rst-mgr", .data = &reset_simple_socfpga }, |
|---|
| 138 | + { .compatible = "altr,stratix10-rst-mgr", |
|---|
| 139 | + .data = &reset_simple_socfpga }, |
|---|
| 124 | 140 | { .compatible = "st,stm32-rcc", }, |
|---|
| 125 | 141 | { .compatible = "allwinner,sun6i-a31-clock-reset", |
|---|
| 126 | 142 | .data = &reset_simple_active_low }, |
|---|
| .. | .. |
|---|
| 128 | 144 | .data = &reset_simple_active_low }, |
|---|
| 129 | 145 | { .compatible = "aspeed,ast2400-lpc-reset" }, |
|---|
| 130 | 146 | { .compatible = "aspeed,ast2500-lpc-reset" }, |
|---|
| 147 | + { .compatible = "bitmain,bm1880-reset", |
|---|
| 148 | + .data = &reset_simple_active_low }, |
|---|
| 149 | + { .compatible = "snps,dw-high-reset" }, |
|---|
| 150 | + { .compatible = "snps,dw-low-reset", |
|---|
| 151 | + .data = &reset_simple_active_low }, |
|---|
| 131 | 152 | { /* sentinel */ }, |
|---|
| 132 | 153 | }; |
|---|
| 133 | 154 | |
|---|
| .. | .. |
|---|
| 164 | 185 | data->rcdev.nr_resets = devdata->nr_resets; |
|---|
| 165 | 186 | data->active_low = devdata->active_low; |
|---|
| 166 | 187 | data->status_active_low = devdata->status_active_low; |
|---|
| 167 | | - } |
|---|
| 168 | | - |
|---|
| 169 | | - if (of_device_is_compatible(dev->of_node, "altr,rst-mgr") && |
|---|
| 170 | | - of_property_read_u32(dev->of_node, "altr,modrst-offset", |
|---|
| 171 | | - ®_offset)) { |
|---|
| 172 | | - dev_warn(dev, |
|---|
| 173 | | - "missing altr,modrst-offset property, assuming 0x%x!\n", |
|---|
| 174 | | - reg_offset); |
|---|
| 175 | 188 | } |
|---|
| 176 | 189 | |
|---|
| 177 | 190 | data->membase += reg_offset; |
|---|