blob: e878af6167c94f802978af1230885eeab4137de7 [file] [log] [blame]
Christian Marangi101dce92025-03-14 19:59:23 +01001// SPDX-License-Identifier: GPL-2.0-only
2/*
3 * Based on Linux drivers/clk/clk-en7523.c reworked
4 * and detached to a dedicated driver
5 *
6 * Author: Lorenzo Bianconi <lorenzo@kernel.org> (original driver)
7 * Christian Marangi <ansuelsmth@gmail.com>
8 */
9
10#include <dm.h>
11#include <linux/io.h>
12#include <reset-uclass.h>
13
14#include <dt-bindings/reset/airoha,en7581-reset.h>
15
16#define RST_NR_PER_BANK 32
17
18#define REG_RESET_CONTROL2 0x830
19#define REG_RESET_CONTROL1 0x834
20
21struct airoha_reset_priv {
22 const u16 *bank_ofs;
23 const u16 *idx_map;
24 void __iomem *base;
25};
26
27static const u16 en7581_rst_ofs[] = {
28 REG_RESET_CONTROL2,
29 REG_RESET_CONTROL1,
30};
31
32static const u16 en7581_rst_map[] = {
33 /* RST_CTRL2 */
34 [EN7581_XPON_PHY_RST] = 0,
35 [EN7581_CPU_TIMER2_RST] = 2,
36 [EN7581_HSUART_RST] = 3,
37 [EN7581_UART4_RST] = 4,
38 [EN7581_UART5_RST] = 5,
39 [EN7581_I2C2_RST] = 6,
40 [EN7581_XSI_MAC_RST] = 7,
41 [EN7581_XSI_PHY_RST] = 8,
42 [EN7581_NPU_RST] = 9,
43 [EN7581_I2S_RST] = 10,
44 [EN7581_TRNG_RST] = 11,
45 [EN7581_TRNG_MSTART_RST] = 12,
46 [EN7581_DUAL_HSI0_RST] = 13,
47 [EN7581_DUAL_HSI1_RST] = 14,
48 [EN7581_HSI_RST] = 15,
49 [EN7581_DUAL_HSI0_MAC_RST] = 16,
50 [EN7581_DUAL_HSI1_MAC_RST] = 17,
51 [EN7581_HSI_MAC_RST] = 18,
52 [EN7581_WDMA_RST] = 19,
53 [EN7581_WOE0_RST] = 20,
54 [EN7581_WOE1_RST] = 21,
55 [EN7581_HSDMA_RST] = 22,
56 [EN7581_TDMA_RST] = 24,
57 [EN7581_EMMC_RST] = 25,
58 [EN7581_SOE_RST] = 26,
59 [EN7581_PCIE2_RST] = 27,
60 [EN7581_XFP_MAC_RST] = 28,
61 [EN7581_USB_HOST_P1_RST] = 29,
62 [EN7581_USB_HOST_P1_U3_PHY_RST] = 30,
63 /* RST_CTRL1 */
64 [EN7581_PCM1_ZSI_ISI_RST] = RST_NR_PER_BANK + 0,
65 [EN7581_FE_PDMA_RST] = RST_NR_PER_BANK + 1,
66 [EN7581_FE_QDMA_RST] = RST_NR_PER_BANK + 2,
67 [EN7581_PCM_SPIWP_RST] = RST_NR_PER_BANK + 4,
68 [EN7581_CRYPTO_RST] = RST_NR_PER_BANK + 6,
69 [EN7581_TIMER_RST] = RST_NR_PER_BANK + 8,
70 [EN7581_PCM1_RST] = RST_NR_PER_BANK + 11,
71 [EN7581_UART_RST] = RST_NR_PER_BANK + 12,
72 [EN7581_GPIO_RST] = RST_NR_PER_BANK + 13,
73 [EN7581_GDMA_RST] = RST_NR_PER_BANK + 14,
74 [EN7581_I2C_MASTER_RST] = RST_NR_PER_BANK + 16,
75 [EN7581_PCM2_ZSI_ISI_RST] = RST_NR_PER_BANK + 17,
76 [EN7581_SFC_RST] = RST_NR_PER_BANK + 18,
77 [EN7581_UART2_RST] = RST_NR_PER_BANK + 19,
78 [EN7581_GDMP_RST] = RST_NR_PER_BANK + 20,
79 [EN7581_FE_RST] = RST_NR_PER_BANK + 21,
80 [EN7581_USB_HOST_P0_RST] = RST_NR_PER_BANK + 22,
81 [EN7581_GSW_RST] = RST_NR_PER_BANK + 23,
82 [EN7581_SFC2_PCM_RST] = RST_NR_PER_BANK + 25,
83 [EN7581_PCIE0_RST] = RST_NR_PER_BANK + 26,
84 [EN7581_PCIE1_RST] = RST_NR_PER_BANK + 27,
85 [EN7581_CPU_TIMER_RST] = RST_NR_PER_BANK + 28,
86 [EN7581_PCIE_HB_RST] = RST_NR_PER_BANK + 29,
87 [EN7581_XPON_MAC_RST] = RST_NR_PER_BANK + 31,
88};
89
90static int airoha_reset_update(struct airoha_reset_priv *priv,
91 unsigned long id, bool assert)
92{
93 void __iomem *addr = priv->base + priv->bank_ofs[id / RST_NR_PER_BANK];
94 u32 val;
95
96 val = readl(addr);
97 if (assert)
98 val |= BIT(id % RST_NR_PER_BANK);
99 else
100 val &= ~BIT(id % RST_NR_PER_BANK);
101 writel(val, addr);
102
103 return 0;
104}
105
106static int airoha_reset_assert(struct reset_ctl *reset_ctl)
107{
108 struct airoha_reset_priv *priv = dev_get_priv(reset_ctl->dev);
109 int id = reset_ctl->id;
110
111 return airoha_reset_update(priv, id, true);
112}
113
114static int airoha_reset_deassert(struct reset_ctl *reset_ctl)
115{
116 struct airoha_reset_priv *priv = dev_get_priv(reset_ctl->dev);
117 int id = reset_ctl->id;
118
119 return airoha_reset_update(priv, id, false);
120}
121
122static int airoha_reset_status(struct reset_ctl *reset_ctl)
123{
124 struct airoha_reset_priv *priv = dev_get_priv(reset_ctl->dev);
125 int id = reset_ctl->id;
126 void __iomem *addr;
127
128 addr = priv->base + priv->bank_ofs[id / RST_NR_PER_BANK];
129
130 return !!(readl(addr) & BIT(id % RST_NR_PER_BANK));
131}
132
133static int airoha_reset_xlate(struct reset_ctl *reset_ctl,
134 struct ofnode_phandle_args *args)
135{
136 struct airoha_reset_priv *priv = dev_get_priv(reset_ctl->dev);
137
138 if (args->args[0] >= ARRAY_SIZE(en7581_rst_map))
139 return -EINVAL;
140
141 reset_ctl->id = priv->idx_map[args->args[0]];
142
143 return 0;
144}
145
146static struct reset_ops airoha_reset_ops = {
147 .of_xlate = airoha_reset_xlate,
148 .rst_assert = airoha_reset_assert,
149 .rst_deassert = airoha_reset_deassert,
150 .rst_status = airoha_reset_status,
151};
152
153static int airoha_reset_probe(struct udevice *dev)
154{
155 struct airoha_reset_priv *priv = dev_get_priv(dev);
156
157 priv->base = dev_remap_addr(dev);
158 if (!priv->base)
159 return -ENOMEM;
160
161 priv->bank_ofs = en7581_rst_ofs;
162 priv->idx_map = en7581_rst_map;
163
164 return 0;
165}
166
167U_BOOT_DRIVER(airoha_reset) = {
168 .name = "airoha-reset",
169 .id = UCLASS_RESET,
170 .probe = airoha_reset_probe,
171 .ops = &airoha_reset_ops,
172 .priv_auto = sizeof(struct airoha_reset_priv),
173};