1 /*
2  * SPDX-License-Identifier: Apache-2.0
3  *
4  *  Copyright (c) 2023 Nuvoton Technology Corporation.
5  */
6 
7 #define DT_DRV_COMPAT nuvoton_numaker_rst
8 
9 #include <zephyr/arch/cpu.h>
10 #include <zephyr/device.h>
11 #include <zephyr/devicetree.h>
12 #include <zephyr/drivers/reset.h>
13 
14 #if defined(CONFIG_SOC_SERIES_M55M1X)
15 #define NUMAKER_RESET_IP_OFFSET(id) (((id) >> 20UL) & 0xfffUL)
16 #define NUMAKER_RESET_IP_BIT(id)    (id & 0x000fffffUL)
17 #else
18 /* Reset controller module IPRST offset */
19 #define NUMAKER_RESET_IPRST0_OFFSET (8UL)
20 #define NUMAKER_RESET_IP_OFFSET(id) (NUMAKER_RESET_IPRST0_OFFSET + (((id) >> 24UL) & 0xffUL))
21 /* Reset controller module configuration bit */
22 #define NUMAKER_RESET_IP_BIT(id)    (id & 0x00ffffffUL)
23 #endif
24 
25 struct reset_numaker_config {
26 	uint32_t base;
27 };
28 
reset_numaker_status(const struct device * dev,uint32_t id,uint8_t * status)29 static int reset_numaker_status(const struct device *dev, uint32_t id, uint8_t *status)
30 {
31 	const struct reset_numaker_config *config = dev->config;
32 
33 	*status = !!sys_test_bit(config->base + NUMAKER_RESET_IP_OFFSET(id),
34 				 NUMAKER_RESET_IP_BIT(id));
35 
36 	return 0;
37 }
38 
reset_numaker_line_assert(const struct device * dev,uint32_t id)39 static int reset_numaker_line_assert(const struct device *dev, uint32_t id)
40 {
41 	const struct reset_numaker_config *config = dev->config;
42 
43 	/* Generate reset signal to the corresponding module */
44 	sys_set_bit(config->base + NUMAKER_RESET_IP_OFFSET(id), NUMAKER_RESET_IP_BIT(id));
45 
46 	return 0;
47 }
48 
reset_numaker_line_deassert(const struct device * dev,uint32_t id)49 static int reset_numaker_line_deassert(const struct device *dev, uint32_t id)
50 {
51 	const struct reset_numaker_config *config = dev->config;
52 
53 	/* Release corresponding module from reset state */
54 	sys_clear_bit(config->base + NUMAKER_RESET_IP_OFFSET(id), NUMAKER_RESET_IP_BIT(id));
55 
56 	return 0;
57 }
58 
reset_numaker_line_toggle(const struct device * dev,uint32_t id)59 static int reset_numaker_line_toggle(const struct device *dev, uint32_t id)
60 {
61 	(void)reset_numaker_line_assert(dev, id);
62 	(void)reset_numaker_line_deassert(dev, id);
63 
64 	return 0;
65 }
66 
67 static DEVICE_API(reset, reset_numaker_driver_api) = {
68 	.status = reset_numaker_status,
69 	.line_assert = reset_numaker_line_assert,
70 	.line_deassert = reset_numaker_line_deassert,
71 	.line_toggle = reset_numaker_line_toggle,
72 };
73 
74 static const struct reset_numaker_config config = {
75 	.base = (uint32_t)DT_INST_REG_ADDR(0),
76 };
77 
78 DEVICE_DT_INST_DEFINE(0, NULL, NULL, NULL, &config, PRE_KERNEL_1,
79 		      CONFIG_RESET_INIT_PRIORITY, &reset_numaker_driver_api);
80