1 // SPDX-License-Identifier: GPL-2.0-only
3 * Copyright (C) 2023 Nuvoton Technology Corp.
4 * Author: Chi-Fang Li <cfli0@nuvoton.com>
7 #include <linux/bits.h>
8 #include <linux/container_of.h>
9 #include <linux/device.h>
10 #include <linux/err.h>
12 #include <linux/kernel.h>
14 #include <linux/platform_device.h>
15 #include <linux/reboot.h>
16 #include <linux/reset-controller.h>
17 #include <linux/spinlock.h>
18 #include <dt-bindings/reset/nuvoton,ma35d1-reset.h>
20 struct ma35d1_reset_data
{
21 struct reset_controller_dev rcdev
;
22 struct notifier_block restart_handler
;
24 /* protect registers against concurrent read-modify-write */
31 } ma35d1_reset_map
[] = {
32 [MA35D1_RESET_CHIP
] = {0x20, 0},
33 [MA35D1_RESET_CA35CR0
] = {0x20, 1},
34 [MA35D1_RESET_CA35CR1
] = {0x20, 2},
35 [MA35D1_RESET_CM4
] = {0x20, 3},
36 [MA35D1_RESET_PDMA0
] = {0x20, 4},
37 [MA35D1_RESET_PDMA1
] = {0x20, 5},
38 [MA35D1_RESET_PDMA2
] = {0x20, 6},
39 [MA35D1_RESET_PDMA3
] = {0x20, 7},
40 [MA35D1_RESET_DISP
] = {0x20, 9},
41 [MA35D1_RESET_VCAP0
] = {0x20, 10},
42 [MA35D1_RESET_VCAP1
] = {0x20, 11},
43 [MA35D1_RESET_GFX
] = {0x20, 12},
44 [MA35D1_RESET_VDEC
] = {0x20, 13},
45 [MA35D1_RESET_WHC0
] = {0x20, 14},
46 [MA35D1_RESET_WHC1
] = {0x20, 15},
47 [MA35D1_RESET_GMAC0
] = {0x20, 16},
48 [MA35D1_RESET_GMAC1
] = {0x20, 17},
49 [MA35D1_RESET_HWSEM
] = {0x20, 18},
50 [MA35D1_RESET_EBI
] = {0x20, 19},
51 [MA35D1_RESET_HSUSBH0
] = {0x20, 20},
52 [MA35D1_RESET_HSUSBH1
] = {0x20, 21},
53 [MA35D1_RESET_HSUSBD
] = {0x20, 22},
54 [MA35D1_RESET_USBHL
] = {0x20, 23},
55 [MA35D1_RESET_SDH0
] = {0x20, 24},
56 [MA35D1_RESET_SDH1
] = {0x20, 25},
57 [MA35D1_RESET_NAND
] = {0x20, 26},
58 [MA35D1_RESET_GPIO
] = {0x20, 27},
59 [MA35D1_RESET_MCTLP
] = {0x20, 28},
60 [MA35D1_RESET_MCTLC
] = {0x20, 29},
61 [MA35D1_RESET_DDRPUB
] = {0x20, 30},
62 [MA35D1_RESET_TMR0
] = {0x24, 2},
63 [MA35D1_RESET_TMR1
] = {0x24, 3},
64 [MA35D1_RESET_TMR2
] = {0x24, 4},
65 [MA35D1_RESET_TMR3
] = {0x24, 5},
66 [MA35D1_RESET_I2C0
] = {0x24, 8},
67 [MA35D1_RESET_I2C1
] = {0x24, 9},
68 [MA35D1_RESET_I2C2
] = {0x24, 10},
69 [MA35D1_RESET_I2C3
] = {0x24, 11},
70 [MA35D1_RESET_QSPI0
] = {0x24, 12},
71 [MA35D1_RESET_SPI0
] = {0x24, 13},
72 [MA35D1_RESET_SPI1
] = {0x24, 14},
73 [MA35D1_RESET_SPI2
] = {0x24, 15},
74 [MA35D1_RESET_UART0
] = {0x24, 16},
75 [MA35D1_RESET_UART1
] = {0x24, 17},
76 [MA35D1_RESET_UART2
] = {0x24, 18},
77 [MA35D1_RESET_UART3
] = {0x24, 19},
78 [MA35D1_RESET_UART4
] = {0x24, 20},
79 [MA35D1_RESET_UART5
] = {0x24, 21},
80 [MA35D1_RESET_UART6
] = {0x24, 22},
81 [MA35D1_RESET_UART7
] = {0x24, 23},
82 [MA35D1_RESET_CANFD0
] = {0x24, 24},
83 [MA35D1_RESET_CANFD1
] = {0x24, 25},
84 [MA35D1_RESET_EADC0
] = {0x24, 28},
85 [MA35D1_RESET_I2S0
] = {0x24, 29},
86 [MA35D1_RESET_SC0
] = {0x28, 0},
87 [MA35D1_RESET_SC1
] = {0x28, 1},
88 [MA35D1_RESET_QSPI1
] = {0x28, 4},
89 [MA35D1_RESET_SPI3
] = {0x28, 6},
90 [MA35D1_RESET_EPWM0
] = {0x28, 16},
91 [MA35D1_RESET_EPWM1
] = {0x28, 17},
92 [MA35D1_RESET_QEI0
] = {0x28, 22},
93 [MA35D1_RESET_QEI1
] = {0x28, 23},
94 [MA35D1_RESET_ECAP0
] = {0x28, 26},
95 [MA35D1_RESET_ECAP1
] = {0x28, 27},
96 [MA35D1_RESET_CANFD2
] = {0x28, 28},
97 [MA35D1_RESET_ADC0
] = {0x28, 31},
98 [MA35D1_RESET_TMR4
] = {0x2C, 0},
99 [MA35D1_RESET_TMR5
] = {0x2C, 1},
100 [MA35D1_RESET_TMR6
] = {0x2C, 2},
101 [MA35D1_RESET_TMR7
] = {0x2C, 3},
102 [MA35D1_RESET_TMR8
] = {0x2C, 4},
103 [MA35D1_RESET_TMR9
] = {0x2C, 5},
104 [MA35D1_RESET_TMR10
] = {0x2C, 6},
105 [MA35D1_RESET_TMR11
] = {0x2C, 7},
106 [MA35D1_RESET_UART8
] = {0x2C, 8},
107 [MA35D1_RESET_UART9
] = {0x2C, 9},
108 [MA35D1_RESET_UART10
] = {0x2C, 10},
109 [MA35D1_RESET_UART11
] = {0x2C, 11},
110 [MA35D1_RESET_UART12
] = {0x2C, 12},
111 [MA35D1_RESET_UART13
] = {0x2C, 13},
112 [MA35D1_RESET_UART14
] = {0x2C, 14},
113 [MA35D1_RESET_UART15
] = {0x2C, 15},
114 [MA35D1_RESET_UART16
] = {0x2C, 16},
115 [MA35D1_RESET_I2S1
] = {0x2C, 17},
116 [MA35D1_RESET_I2C4
] = {0x2C, 18},
117 [MA35D1_RESET_I2C5
] = {0x2C, 19},
118 [MA35D1_RESET_EPWM2
] = {0x2C, 20},
119 [MA35D1_RESET_ECAP2
] = {0x2C, 21},
120 [MA35D1_RESET_QEI2
] = {0x2C, 22},
121 [MA35D1_RESET_CANFD3
] = {0x2C, 23},
122 [MA35D1_RESET_KPI
] = {0x2C, 24},
123 [MA35D1_RESET_GIC
] = {0x2C, 28},
124 [MA35D1_RESET_SSMCC
] = {0x2C, 30},
125 [MA35D1_RESET_SSPCC
] = {0x2C, 31}
128 static int ma35d1_restart_handler(struct notifier_block
*this, unsigned long mode
, void *cmd
)
130 struct ma35d1_reset_data
*data
=
131 container_of(this, struct ma35d1_reset_data
, restart_handler
);
132 u32 id
= MA35D1_RESET_CHIP
;
134 writel_relaxed(BIT(ma35d1_reset_map
[id
].bit
),
135 data
->base
+ ma35d1_reset_map
[id
].reg_ofs
);
139 static int ma35d1_reset_update(struct reset_controller_dev
*rcdev
, unsigned long id
, bool assert)
141 struct ma35d1_reset_data
*data
= container_of(rcdev
, struct ma35d1_reset_data
, rcdev
);
145 if (WARN_ON_ONCE(id
>= ARRAY_SIZE(ma35d1_reset_map
)))
148 spin_lock_irqsave(&data
->lock
, flags
);
149 reg
= readl_relaxed(data
->base
+ ma35d1_reset_map
[id
].reg_ofs
);
151 reg
|= BIT(ma35d1_reset_map
[id
].bit
);
153 reg
&= ~(BIT(ma35d1_reset_map
[id
].bit
));
154 writel_relaxed(reg
, data
->base
+ ma35d1_reset_map
[id
].reg_ofs
);
155 spin_unlock_irqrestore(&data
->lock
, flags
);
160 static int ma35d1_reset_assert(struct reset_controller_dev
*rcdev
, unsigned long id
)
162 return ma35d1_reset_update(rcdev
, id
, true);
165 static int ma35d1_reset_deassert(struct reset_controller_dev
*rcdev
, unsigned long id
)
167 return ma35d1_reset_update(rcdev
, id
, false);
170 static int ma35d1_reset_status(struct reset_controller_dev
*rcdev
, unsigned long id
)
172 struct ma35d1_reset_data
*data
= container_of(rcdev
, struct ma35d1_reset_data
, rcdev
);
175 if (WARN_ON_ONCE(id
>= ARRAY_SIZE(ma35d1_reset_map
)))
178 reg
= readl_relaxed(data
->base
+ ma35d1_reset_map
[id
].reg_ofs
);
179 return !!(reg
& BIT(ma35d1_reset_map
[id
].bit
));
182 static const struct reset_control_ops ma35d1_reset_ops
= {
183 .assert = ma35d1_reset_assert
,
184 .deassert
= ma35d1_reset_deassert
,
185 .status
= ma35d1_reset_status
,
188 static const struct of_device_id ma35d1_reset_dt_ids
[] = {
189 { .compatible
= "nuvoton,ma35d1-reset" },
193 static int ma35d1_reset_probe(struct platform_device
*pdev
)
195 struct ma35d1_reset_data
*reset_data
;
196 struct device
*dev
= &pdev
->dev
;
199 if (!pdev
->dev
.of_node
) {
200 dev_err(&pdev
->dev
, "Device tree node not found\n");
204 reset_data
= devm_kzalloc(dev
, sizeof(*reset_data
), GFP_KERNEL
);
208 reset_data
->base
= devm_platform_ioremap_resource(pdev
, 0);
209 if (IS_ERR(reset_data
->base
))
210 return PTR_ERR(reset_data
->base
);
212 reset_data
->rcdev
.owner
= THIS_MODULE
;
213 reset_data
->rcdev
.nr_resets
= MA35D1_RESET_COUNT
;
214 reset_data
->rcdev
.ops
= &ma35d1_reset_ops
;
215 reset_data
->rcdev
.of_node
= dev
->of_node
;
216 reset_data
->restart_handler
.notifier_call
= ma35d1_restart_handler
;
217 reset_data
->restart_handler
.priority
= 192;
218 spin_lock_init(&reset_data
->lock
);
220 err
= register_restart_handler(&reset_data
->restart_handler
);
222 dev_warn(&pdev
->dev
, "failed to register restart handler\n");
224 return devm_reset_controller_register(dev
, &reset_data
->rcdev
);
227 static struct platform_driver ma35d1_reset_driver
= {
228 .probe
= ma35d1_reset_probe
,
230 .name
= "ma35d1-reset",
231 .of_match_table
= ma35d1_reset_dt_ids
,
235 builtin_platform_driver(ma35d1_reset_driver
);