1 /* 2 * This file is provided under a dual BSD/GPLv2 license. When using or 3 * redistributing this file, you may do so under either license. 4 * 5 * GPL LICENSE SUMMARY 6 * 7 * Copyright (c) 2016 BayLibre, SAS. 8 * Author: Neil Armstrong <narmstrong@baylibre.com> 9 * 10 * This program is free software; you can redistribute it and/or modify 11 * it under the terms of version 2 of the GNU General Public License as 12 * published by the Free Software Foundation. 13 * 14 * This program is distributed in the hope that it will be useful, but 15 * WITHOUT ANY WARRANTY; without even the implied warranty of 16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 17 * General Public License for more details. 18 * 19 * You should have received a copy of the GNU General Public License 20 * along with this program; if not, see <http://www.gnu.org/licenses/>. 21 * The full GNU General Public License is included in this distribution 22 * in the file called COPYING. 23 * 24 * BSD LICENSE 25 * 26 * Copyright (c) 2016 BayLibre, SAS. 27 * Author: Neil Armstrong <narmstrong@baylibre.com> 28 * 29 * Redistribution and use in source and binary forms, with or without 30 * modification, are permitted provided that the following conditions 31 * are met: 32 * 33 * * Redistributions of source code must retain the above copyright 34 * notice, this list of conditions and the following disclaimer. 35 * * Redistributions in binary form must reproduce the above copyright 36 * notice, this list of conditions and the following disclaimer in 37 * the documentation and/or other materials provided with the 38 * distribution. 39 * * Neither the name of Intel Corporation nor the names of its 40 * contributors may be used to endorse or promote products derived 41 * from this software without specific prior written permission. 42 * 43 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 44 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 45 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 46 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 47 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 48 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 49 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 50 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 51 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 52 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 53 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 54 */ 55 #include <linux/err.h> 56 #include <linux/module.h> 57 #include <linux/io.h> 58 #include <linux/of.h> 59 #include <linux/platform_device.h> 60 #include <linux/reset-controller.h> 61 #include <linux/slab.h> 62 #include <linux/types.h> 63 64 #define REG_COUNT 8 65 #define BITS_PER_REG 32 66 67 struct meson_reset { 68 void __iomem *reg_base; 69 struct reset_controller_dev rcdev; 70 }; 71 72 static int meson_reset_reset(struct reset_controller_dev *rcdev, 73 unsigned long id) 74 { 75 struct meson_reset *data = 76 container_of(rcdev, struct meson_reset, rcdev); 77 unsigned int bank = id / BITS_PER_REG; 78 unsigned int offset = id % BITS_PER_REG; 79 void __iomem *reg_addr = data->reg_base + (bank << 2); 80 81 if (bank >= REG_COUNT) 82 return -EINVAL; 83 84 writel(BIT(offset), reg_addr); 85 86 return 0; 87 } 88 89 static const struct reset_control_ops meson_reset_ops = { 90 .reset = meson_reset_reset, 91 }; 92 93 static const struct of_device_id meson_reset_dt_ids[] = { 94 { .compatible = "amlogic,meson8b-reset", }, 95 { .compatible = "amlogic,meson-gxbb-reset", }, 96 { /* sentinel */ }, 97 }; 98 MODULE_DEVICE_TABLE(of, meson_reset_dt_ids); 99 100 static int meson_reset_probe(struct platform_device *pdev) 101 { 102 struct meson_reset *data; 103 struct resource *res; 104 105 data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL); 106 if (!data) 107 return -ENOMEM; 108 109 res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 110 data->reg_base = devm_ioremap_resource(&pdev->dev, res); 111 if (IS_ERR(data->reg_base)) 112 return PTR_ERR(data->reg_base); 113 114 platform_set_drvdata(pdev, data); 115 116 data->rcdev.owner = THIS_MODULE; 117 data->rcdev.nr_resets = REG_COUNT * BITS_PER_REG; 118 data->rcdev.ops = &meson_reset_ops; 119 data->rcdev.of_node = pdev->dev.of_node; 120 121 return devm_reset_controller_register(&pdev->dev, &data->rcdev); 122 } 123 124 static struct platform_driver meson_reset_driver = { 125 .probe = meson_reset_probe, 126 .driver = { 127 .name = "meson_reset", 128 .of_match_table = meson_reset_dt_ids, 129 }, 130 }; 131 132 module_platform_driver(meson_reset_driver); 133 134 MODULE_AUTHOR("Neil Armstrong <narmstrong@baylibre.com>"); 135 MODULE_DESCRIPTION("Amlogic Meson Reset Controller driver"); 136 MODULE_LICENSE("Dual BSD/GPL"); 137