blob: 466455d073991db6ec950550ca12c24551ca2b9c [file] [log] [blame]
Dinh Nguyen2ac71882018-04-04 17:18:20 -05001/*
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
27struct socfpga_reset_data {
28 void __iomem *membase;
29};
30
31static 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
43static 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
55static 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
63static 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
71static 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
78static 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
93static const struct udevice_id socfpga_reset_match[] = {
94 { .compatible = "altr,rst-mgr" },
95 { /* sentinel */ },
96};
97
98U_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};