reset-socfpga.c (70c5f93669249886b151812076509f30569aff80) | reset-socfpga.c (b3ca9888f35fa6919569cf27c929dc0ac49e9716) |
---|---|
1// SPDX-License-Identifier: GPL-2.0 |
|
1/* | 2/* |
2 * Socfpga Reset Controller Driver 3 * 4 * Copyright 2014 Steffen Trumtrar <s.trumtrar@pengutronix.de> 5 * 6 * based on 7 * Allwinner SoCs Reset Controller driver 8 * 9 * Copyright 2013 Maxime Ripard 10 * 11 * Maxime Ripard <maxime.ripard@free-electrons.com> 12 * 13 * This program is free software; you can redistribute it and/or modify 14 * it under the terms of the GNU General Public License as published by 15 * the Free Software Foundation; either version 2 of the License, or 16 * (at your option) any later version. | 3 * Copyright (C) 2018, Intel Corporation 4 * Copied from reset-sunxi.c |
17 */ 18 19#include <linux/err.h> 20#include <linux/io.h> 21#include <linux/init.h> 22#include <linux/of.h> | 5 */ 6 7#include <linux/err.h> 8#include <linux/io.h> 9#include <linux/init.h> 10#include <linux/of.h> |
11#include <linux/of_address.h> |
|
23#include <linux/platform_device.h> 24#include <linux/reset-controller.h> | 12#include <linux/platform_device.h> 13#include <linux/reset-controller.h> |
14#include <linux/slab.h> |
|
25#include <linux/spinlock.h> 26#include <linux/types.h> 27 | 15#include <linux/spinlock.h> 16#include <linux/types.h> 17 |
28#define BANK_INCREMENT 4 29#define NR_BANKS 8 | 18#include "reset-simple.h" |
30 | 19 |
31struct socfpga_reset_data { 32 spinlock_t lock; 33 void __iomem *membase; 34 struct reset_controller_dev rcdev; 35}; | 20#define SOCFPGA_NR_BANKS 8 21void __init socfpga_reset_init(void); |
36 | 22 |
37static int socfpga_reset_assert(struct reset_controller_dev *rcdev, 38 unsigned long id) | 23static int a10_reset_init(struct device_node *np) |
39{ | 24{ |
40 struct socfpga_reset_data *data = container_of(rcdev, 41 struct socfpga_reset_data, 42 rcdev); 43 int reg_width = sizeof(u32); 44 int bank = id / (reg_width * BITS_PER_BYTE); 45 int offset = id % (reg_width * BITS_PER_BYTE); 46 unsigned long flags; 47 u32 reg; | 25 struct reset_simple_data *data; 26 struct resource res; 27 resource_size_t size; 28 int ret; 29 u32 reg_offset = 0x10; |
48 | 30 |
49 spin_lock_irqsave(&data->lock, flags); 50 51 reg = readl(data->membase + (bank * BANK_INCREMENT)); 52 writel(reg | BIT(offset), data->membase + (bank * BANK_INCREMENT)); 53 spin_unlock_irqrestore(&data->lock, flags); 54 55 return 0; 56} 57 58static int socfpga_reset_deassert(struct reset_controller_dev *rcdev, 59 unsigned long id) 60{ 61 struct socfpga_reset_data *data = container_of(rcdev, 62 struct socfpga_reset_data, 63 rcdev); 64 65 int reg_width = sizeof(u32); 66 int bank = id / (reg_width * BITS_PER_BYTE); 67 int offset = id % (reg_width * BITS_PER_BYTE); 68 unsigned long flags; 69 u32 reg; 70 71 spin_lock_irqsave(&data->lock, flags); 72 73 reg = readl(data->membase + (bank * BANK_INCREMENT)); 74 writel(reg & ~BIT(offset), data->membase + (bank * BANK_INCREMENT)); 75 76 spin_unlock_irqrestore(&data->lock, flags); 77 78 return 0; 79} 80 81static int socfpga_reset_status(struct reset_controller_dev *rcdev, 82 unsigned long id) 83{ 84 struct socfpga_reset_data *data = container_of(rcdev, 85 struct socfpga_reset_data, rcdev); 86 int reg_width = sizeof(u32); 87 int bank = id / (reg_width * BITS_PER_BYTE); 88 int offset = id % (reg_width * BITS_PER_BYTE); 89 u32 reg; 90 91 reg = readl(data->membase + (bank * BANK_INCREMENT)); 92 93 return !(reg & BIT(offset)); 94} 95 96static const struct reset_control_ops socfpga_reset_ops = { 97 .assert = socfpga_reset_assert, 98 .deassert = socfpga_reset_deassert, 99 .status = socfpga_reset_status, 100}; 101 102static int socfpga_reset_probe(struct platform_device *pdev) 103{ 104 struct socfpga_reset_data *data; 105 struct resource *res; 106 struct device *dev = &pdev->dev; 107 struct device_node *np = dev->of_node; 108 u32 modrst_offset; 109 110 /* 111 * The binding was mainlined without the required property. 112 * Do not continue, when we encounter an old DT. 113 */ 114 if (!of_find_property(pdev->dev.of_node, "#reset-cells", NULL)) { 115 dev_err(&pdev->dev, "%pOF missing #reset-cells property\n", 116 pdev->dev.of_node); 117 return -EINVAL; 118 } 119 120 data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL); | 31 data = kzalloc(sizeof(*data), GFP_KERNEL); |
121 if (!data) 122 return -ENOMEM; 123 | 32 if (!data) 33 return -ENOMEM; 34 |
124 res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 125 data->membase = devm_ioremap_resource(&pdev->dev, res); 126 if (IS_ERR(data->membase)) 127 return PTR_ERR(data->membase); | 35 ret = of_address_to_resource(np, 0, &res); 36 if (ret) 37 goto err_alloc; |
128 | 38 |
129 if (of_property_read_u32(np, "altr,modrst-offset", &modrst_offset)) { 130 dev_warn(dev, "missing altr,modrst-offset property, assuming 0x10!\n"); 131 modrst_offset = 0x10; | 39 size = resource_size(&res); 40 if (!request_mem_region(res.start, size, np->name)) { 41 ret = -EBUSY; 42 goto err_alloc; |
132 } | 43 } |
133 data->membase += modrst_offset; | |
134 | 44 |
45 data->membase = ioremap(res.start, size); 46 if (!data->membase) { 47 ret = -ENOMEM; 48 goto err_alloc; 49 } 50 51 if (of_property_read_u32(np, "altr,modrst-offset", ®_offset)) 52 pr_warn("missing altr,modrst-offset property, assuming 0x10\n"); 53 data->membase += reg_offset; 54 |
|
135 spin_lock_init(&data->lock); 136 137 data->rcdev.owner = THIS_MODULE; | 55 spin_lock_init(&data->lock); 56 57 data->rcdev.owner = THIS_MODULE; |
138 data->rcdev.nr_resets = NR_BANKS * (sizeof(u32) * BITS_PER_BYTE); 139 data->rcdev.ops = &socfpga_reset_ops; 140 data->rcdev.of_node = pdev->dev.of_node; | 58 data->rcdev.nr_resets = SOCFPGA_NR_BANKS * 32; 59 data->rcdev.ops = &reset_simple_ops; 60 data->rcdev.of_node = np; 61 data->status_active_low = true; |
141 | 62 |
142 return devm_reset_controller_register(dev, &data->rcdev); 143} | 63 return reset_controller_register(&data->rcdev); |
144 | 64 |
145static const struct of_device_id socfpga_reset_dt_ids[] = { | 65err_alloc: 66 kfree(data); 67 return ret; 68}; 69 70/* 71 * These are the reset controller we need to initialize early on in 72 * our system, before we can even think of using a regular device 73 * driver for it. 74 * The controllers that we can register through the regular device 75 * model are handled by the simple reset driver directly. 76 */ 77static const struct of_device_id socfpga_early_reset_dt_ids[] __initconst = { |
146 { .compatible = "altr,rst-mgr", }, 147 { /* sentinel */ }, 148}; 149 | 78 { .compatible = "altr,rst-mgr", }, 79 { /* sentinel */ }, 80}; 81 |
150static struct platform_driver socfpga_reset_driver = { 151 .probe = socfpga_reset_probe, 152 .driver = { 153 .name = "socfpga-reset", 154 .of_match_table = socfpga_reset_dt_ids, 155 }, 156}; 157builtin_platform_driver(socfpga_reset_driver); | 82void __init socfpga_reset_init(void) 83{ 84 struct device_node *np; 85 86 for_each_matching_node(np, socfpga_early_reset_dt_ids) 87 a10_reset_init(np); 88} |