1 /*
2  * Copyright (c) 2022-2023, Intel Corporation.
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 #define DT_DRV_COMPAT intel_socfpga_reset
8 
9 #include <zephyr/device.h>
10 #include <zephyr/drivers/reset.h>
11 #include <zephyr/kernel.h>
12 
13 /** regwidth 4 for 32 bit register */
14 #define RESET_REG_WIDTH 4
15 
16 struct reset_intel_config {
17 	DEVICE_MMIO_ROM;
18 	/* check peripheral active low / active high */
19 	bool active_low;
20 };
21 
22 struct reset_intel_soc_data {
23 	DEVICE_MMIO_RAM;
24 };
25 
reset_intel_soc_status(const struct device * dev,uint32_t id,uint8_t * status)26 static int32_t reset_intel_soc_status(const struct device *dev, uint32_t id, uint8_t *status)
27 {
28 	const struct reset_intel_config *config = (const struct reset_intel_config *)dev->config;
29 	uintptr_t base_address = DEVICE_MMIO_GET(dev);
30 	uint32_t value;
31 	uint16_t offset;
32 	uint8_t regbit;
33 
34 	regbit = (id & ((RESET_REG_WIDTH << (RESET_REG_WIDTH - 1)) - 1));
35 	offset = (id >> (RESET_REG_WIDTH + 1)) << (RESET_REG_WIDTH >> 1);
36 	value = sys_read32(base_address + offset);
37 	*status = !(value & BIT(regbit)) ^ config->active_low;
38 	return 0;
39 }
40 
reset_intel_soc_update(const struct device * dev,uint32_t id,bool assert)41 static void reset_intel_soc_update(const struct device *dev, uint32_t id, bool assert)
42 {
43 	const struct reset_intel_config *config = (const struct reset_intel_config *)dev->config;
44 	uintptr_t base_address = DEVICE_MMIO_GET(dev);
45 	uint16_t offset;
46 	uint8_t regbit;
47 
48 	regbit = (id & ((RESET_REG_WIDTH << (RESET_REG_WIDTH - 1)) - 1));
49 	offset = (id >> (RESET_REG_WIDTH + 1)) << (RESET_REG_WIDTH >> 1);
50 
51 	if (assert ^ !config->active_low) {
52 		if (sys_test_bit(base_address + offset, regbit) == 0) {
53 			sys_set_bit(base_address + offset, regbit);
54 		}
55 	} else {
56 		if (sys_test_bit(base_address + offset, regbit) != 0) {
57 			sys_clear_bit(base_address + offset, regbit);
58 		}
59 	}
60 }
61 
reset_intel_soc_line_assert(const struct device * dev,uint32_t id)62 static int32_t reset_intel_soc_line_assert(const struct device *dev, uint32_t id)
63 {
64 	reset_intel_soc_update(dev, id, true);
65 
66 	return 0;
67 }
68 
reset_intel_soc_line_deassert(const struct device * dev,uint32_t id)69 static int32_t reset_intel_soc_line_deassert(const struct device *dev, uint32_t id)
70 {
71 	reset_intel_soc_update(dev, id, false);
72 
73 	return 0;
74 }
75 
reset_intel_soc_line_toggle(const struct device * dev,uint32_t id)76 static int32_t reset_intel_soc_line_toggle(const struct device *dev, uint32_t id)
77 {
78 	(void)reset_intel_soc_line_assert(dev, id);
79 	/* TODO: Add required delay once tested on Emulator/Hardware platform. */
80 	(void)reset_intel_soc_line_deassert(dev, id);
81 
82 	return 0;
83 }
84 
reset_intel_soc_init(const struct device * dev)85 static int32_t reset_intel_soc_init(const struct device *dev)
86 {
87 	DEVICE_MMIO_MAP(dev, K_MEM_CACHE_NONE);
88 
89 	return 0;
90 }
91 
92 static const struct reset_driver_api reset_intel_soc_driver_api = {
93 	.status = reset_intel_soc_status,
94 	.line_assert = reset_intel_soc_line_assert,
95 	.line_deassert = reset_intel_soc_line_deassert,
96 	.line_toggle = reset_intel_soc_line_toggle,
97 };
98 
99 #define INTEL_SOC_RESET_INIT(_inst)						\
100 	static struct reset_intel_soc_data reset_intel_soc_data_##_inst;	\
101 	static const struct reset_intel_config reset_intel_config_##_inst = {	\
102 		DEVICE_MMIO_ROM_INIT(DT_DRV_INST(_inst)),			\
103 		.active_low = DT_INST_PROP(_inst, active_low),			\
104 	};									\
105 										\
106 	DEVICE_DT_INST_DEFINE(_inst,						\
107 			reset_intel_soc_init,					\
108 			NULL,							\
109 			&reset_intel_soc_data_##_inst,				\
110 			&reset_intel_config_##_inst,				\
111 			PRE_KERNEL_1,						\
112 			CONFIG_RESET_INIT_PRIORITY,				\
113 			&reset_intel_soc_driver_api);
114 
115 DT_INST_FOREACH_STATUS_OKAY(INTEL_SOC_RESET_INIT);
116