xref: /openbmc/u-boot/drivers/reset/reset-socfpga.c (revision 699e831e158a5846778d8bd6af054d4276277cb6)
1 /*
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  * SPDX-License-Identifier:     GPL-2.0+
14  */
15 
16 #include <common.h>
17 #include <dm.h>
18 #include <dm/of_access.h>
19 #include <reset-uclass.h>
20 #include <linux/bitops.h>
21 #include <linux/io.h>
22 #include <linux/sizes.h>
23 
24 #define BANK_INCREMENT		4
25 #define NR_BANKS		8
26 
27 struct socfpga_reset_data {
28 	void __iomem *membase;
29 };
30 
31 static int socfpga_reset_assert(struct reset_ctl *reset_ctl)
32 {
33 	struct socfpga_reset_data *data = dev_get_priv(reset_ctl->dev);
34 	int id = reset_ctl->id;
35 	int reg_width = sizeof(u32);
36 	int bank = id / (reg_width * BITS_PER_BYTE);
37 	int offset = id % (reg_width * BITS_PER_BYTE);
38 
39 	setbits_le32(data->membase + (bank * BANK_INCREMENT), BIT(offset));
40 	return 0;
41 }
42 
43 static int socfpga_reset_deassert(struct reset_ctl *reset_ctl)
44 {
45 	struct socfpga_reset_data *data = dev_get_priv(reset_ctl->dev);
46 	int id = reset_ctl->id;
47 	int reg_width = sizeof(u32);
48 	int bank = id / (reg_width * BITS_PER_BYTE);
49 	int offset = id % (reg_width * BITS_PER_BYTE);
50 
51 	clrbits_le32(data->membase + (bank * BANK_INCREMENT), BIT(offset));
52 	return 0;
53 }
54 
55 static int socfpga_reset_request(struct reset_ctl *reset_ctl)
56 {
57 	debug("%s(reset_ctl=%p) (dev=%p, id=%lu)\n", __func__,
58 	      reset_ctl, reset_ctl->dev, reset_ctl->id);
59 
60 	return 0;
61 }
62 
63 static int socfpga_reset_free(struct reset_ctl *reset_ctl)
64 {
65 	debug("%s(reset_ctl=%p) (dev=%p, id=%lu)\n", __func__, reset_ctl,
66 	      reset_ctl->dev, reset_ctl->id);
67 
68 	return 0;
69 }
70 
71 static const struct reset_ops socfpga_reset_ops = {
72 	.request = socfpga_reset_request,
73 	.free = socfpga_reset_free,
74 	.rst_assert = socfpga_reset_assert,
75 	.rst_deassert = socfpga_reset_deassert,
76 };
77 
78 static int socfpga_reset_probe(struct udevice *dev)
79 {
80 	struct socfpga_reset_data *data = dev_get_priv(dev);
81 	const void *blob = gd->fdt_blob;
82 	int node = dev_of_offset(dev);
83 	u32 modrst_offset;
84 
85 	data->membase = devfdt_get_addr_ptr(dev);
86 
87 	modrst_offset = fdtdec_get_int(blob, node, "altr,modrst-offset", 0x10);
88 	data->membase += modrst_offset;
89 
90 	return 0;
91 }
92 
93 static const struct udevice_id socfpga_reset_match[] = {
94 	{ .compatible = "altr,rst-mgr" },
95 	{ /* sentinel */ },
96 };
97 
98 U_BOOT_DRIVER(socfpga_reset) = {
99 	.name = "socfpga-reset",
100 	.id = UCLASS_RESET,
101 	.of_match = socfpga_reset_match,
102 	.probe = socfpga_reset_probe,
103 	.priv_auto_alloc_size = sizeof(struct socfpga_reset_data),
104 	.ops = &socfpga_reset_ops,
105 };
106