blob: 165c87acdc44be2f6c93b557c2ba98227280c540 [file] [log] [blame]
Sergiu Mogabdcfc7d2023-01-04 16:03:18 +02001// SPDX-License-Identifier: GPL-2.0+
2/*
3 * Support for Atmel/Microchip Reset Controller.
4 *
5 * Copyright (C) 2022 Microchip Technology Inc. and its subsidiaries
6 *
7 * Author: Sergiu Moga <sergiu.moga@microchip.com>
8 */
9
10#include <clk.h>
11#include <asm/io.h>
12#include <dm.h>
13#include <dm/lists.h>
14#include <reset-uclass.h>
15#include <asm/arch/at91_rstc.h>
16#include <dt-bindings/reset/sama7g5-reset.h>
17
18struct at91_reset {
19 void __iomem *dev_base;
20 struct at91_reset_data *data;
21};
22
23struct at91_reset_data {
24 u32 n_device_reset;
25 u8 device_reset_min_id;
26 u8 device_reset_max_id;
27};
28
29static const struct at91_reset_data sama7g5_data = {
30 .n_device_reset = 3,
31 .device_reset_min_id = SAMA7G5_RESET_USB_PHY1,
32 .device_reset_max_id = SAMA7G5_RESET_USB_PHY3,
33};
34
35static int at91_rst_update(struct at91_reset *reset, unsigned long id,
36 bool assert)
37{
38 u32 val;
39
40 if (!reset->dev_base)
41 return 0;
42
43 val = readl(reset->dev_base);
44 if (assert)
45 val |= BIT(id);
46 else
47 val &= ~BIT(id);
48 writel(val, reset->dev_base);
49
50 return 0;
51}
52
53static int at91_reset_of_xlate(struct reset_ctl *reset_ctl,
54 struct ofnode_phandle_args *args)
55{
56 struct at91_reset *reset = dev_get_priv(reset_ctl->dev);
57
58 if (!reset->data->n_device_reset ||
59 args->args[0] < reset->data->device_reset_min_id ||
60 args->args[0] > reset->data->device_reset_max_id)
61 return -EINVAL;
62
63 reset_ctl->id = args->args[0];
64
65 return 0;
66}
67
68static int at91_rst_assert(struct reset_ctl *reset_ctl)
69{
70 struct at91_reset *reset = dev_get_priv(reset_ctl->dev);
71
72 return at91_rst_update(reset, reset_ctl->id, true);
73}
74
75static int at91_rst_deassert(struct reset_ctl *reset_ctl)
76{
77 struct at91_reset *reset = dev_get_priv(reset_ctl->dev);
78
79 return at91_rst_update(reset, reset_ctl->id, false);
80}
81
82struct reset_ops at91_reset_ops = {
83 .of_xlate = at91_reset_of_xlate,
84 .rst_assert = at91_rst_assert,
85 .rst_deassert = at91_rst_deassert,
86};
87
88static int at91_reset_probe(struct udevice *dev)
89{
90 struct at91_reset *reset = dev_get_priv(dev);
91 struct clk sclk;
92 int ret;
93
94 reset->data = (struct at91_reset_data *)dev_get_driver_data(dev);
95 reset->dev_base = dev_remap_addr_index(dev, 1);
96 if (reset->data && reset->data->n_device_reset && !reset->dev_base)
97 return -EINVAL;
98
99 ret = clk_get_by_index(dev, 0, &sclk);
100 if (ret)
101 return ret;
102
103 return clk_prepare_enable(&sclk);
104}
105
106static int at91_reset_bind(struct udevice *dev)
107{
108 struct udevice *at91_sysreset;
109
110 if (CONFIG_IS_ENABLED(SYSRESET_AT91))
111 return device_bind_driver_to_node(dev, "at91_sysreset",
112 "at91_sysreset",
113 dev_ofnode(dev),
114 &at91_sysreset);
115
116 return 0;
117}
118
119static const struct udevice_id at91_reset_ids[] = {
120 {
121 .compatible = "microchip,sama7g5-rstc",
122 .data = (ulong)&sama7g5_data,
123 },
124 {
125 .compatible = "atmel,sama5d3-rstc",
126 },
127 {
128 .compatible = "microchip,sam9x60-rstc",
129 },
130 { }
131};
132
133U_BOOT_DRIVER(at91_reset) = {
134 .name = "at91_reset",
135 .id = UCLASS_RESET,
136 .of_match = at91_reset_ids,
137 .bind = at91_reset_bind,
138 .probe = at91_reset_probe,
139 .priv_auto = sizeof(struct at91_reset),
140 .ops = &at91_reset_ops,
141};