1 /*
2  * Copyright (c) 2022-2023 IoT.bzh
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 #ifndef ZEPHYR_DRIVERS_RENESAS_RENESAS_CPG_MSSR_H_
8 #define ZEPHYR_DRIVERS_RENESAS_RENESAS_CPG_MSSR_H_
9 
10 #include <zephyr/spinlock.h>
11 #include <zephyr/sys/sys_io.h>
12 #include <zephyr/drivers/clock_control.h>
13 #include <zephyr/sys/device_mmio.h>
14 
15 #define CPG_NUM_DOMAINS 2
16 
17 struct cpg_clk_info_table {
18 	uint32_t domain;
19 	uint32_t module;
20 	mem_addr_t offset;
21 	uint32_t parent_id;
22 
23 	int64_t in_freq;
24 	int64_t out_freq;
25 
26 	/* TODO: add setting of this field and add function for getting status */
27 	enum clock_control_status status;
28 
29 	struct cpg_clk_info_table *parent;
30 	struct cpg_clk_info_table *children_list;
31 	struct cpg_clk_info_table *next_sibling;
32 };
33 
34 struct rcar_cpg_mssr_data {
35 	DEVICE_MMIO_RAM; /* Must be first */
36 
37 	struct cpg_clk_info_table *clk_info_table[CPG_NUM_DOMAINS];
38 	const uint32_t clk_info_table_size[CPG_NUM_DOMAINS];
39 
40 	struct k_spinlock lock;
41 
42 	uint32_t (*get_div_helper)(uint32_t reg, uint32_t module);
43 	int (*set_rate_helper)(uint32_t module, uint32_t *div, uint32_t *div_mask);
44 };
45 
46 #define RCAR_CPG_NONE -1
47 #define RCAR_CPG_KHZ(khz) ((khz) * 1000U)
48 #define RCAR_CPG_MHZ(mhz) (RCAR_CPG_KHZ(mhz) * 1000U)
49 
50 #define RCAR_CORE_CLK_INFO_ITEM(id, off, par_id, in_frq)	\
51 	{							\
52 		.domain		= CPG_CORE,			\
53 		.module		= id,				\
54 		.offset		= off,				\
55 		.parent_id	= par_id,			\
56 		.in_freq	= in_frq,			\
57 		.out_freq	= RCAR_CPG_NONE,		\
58 		.status		= CLOCK_CONTROL_STATUS_UNKNOWN,	\
59 		.parent		= NULL,				\
60 		.children_list	= NULL,				\
61 		.next_sibling	= NULL,				\
62 	}
63 
64 #define RCAR_MOD_CLK_INFO_ITEM(id, par_id)			\
65 	{							\
66 		.domain		= CPG_MOD,			\
67 		.module		= id,				\
68 		.offset		= RCAR_CPG_NONE,		\
69 		.parent_id	= par_id,			\
70 		.in_freq	= RCAR_CPG_NONE,		\
71 		.out_freq	= RCAR_CPG_NONE,		\
72 		.status		= CLOCK_CONTROL_STATUS_UNKNOWN,	\
73 		.parent		= NULL,				\
74 		.children_list	= NULL,				\
75 		.next_sibling	= NULL,				\
76 	}
77 
78 #ifdef CONFIG_SOC_SERIES_RCAR_GEN3
79 /* Software Reset Clearing Register offsets */
80 #define SRSTCLR(i)      (0x940 + (i) * 4)
81 
82 /* CPG write protect offset */
83 #define CPGWPR          0x900
84 
85 /* Realtime Module Stop Control Register offsets */
86 static const uint16_t mstpcr[] = {
87 	0x110, 0x114, 0x118, 0x11c,
88 	0x120, 0x124, 0x128, 0x12c,
89 	0x980, 0x984, 0x988, 0x98c,
90 };
91 
92 /* Software Reset Register offsets */
93 static const uint16_t srcr[] = {
94 	0x0A0, 0x0A8, 0x0B0, 0x0B8,
95 	0x0BC, 0x0C4, 0x1C8, 0x1CC,
96 	0x920, 0x924, 0x928, 0x92C,
97 };
98 #elif defined(CONFIG_SOC_SERIES_RCAR_GEN4)
99 /* Software Reset Clearing Register offsets */
100 #define SRSTCLR(i) (0x2C80 + (i) * 4)
101 
102 /* CPG write protect offset */
103 #define CPGWPR      0x0
104 
105 /* Realtime Module Stop Control Register offsets */
106 static const uint16_t mstpcr[] = {
107 	0x2D00, 0x2D04, 0x2D08, 0x2D0C,
108 	0x2D10, 0x2D14, 0x2D18, 0x2D1C,
109 	0x2D20, 0x2D24, 0x2D28, 0x2D2C,
110 	0x2D30, 0x2D34, 0x2D38, 0x2D3C,
111 	0x2D40, 0x2D44, 0x2D48, 0x2D4C,
112 	0x2D50, 0x2D54, 0x2D58, 0x2D5C,
113 	0x2D60, 0x2D64, 0x2D68, 0x2D6C,
114 };
115 
116 /* Software Reset Register offsets */
117 static const uint16_t srcr[] = {
118 	0x2C00, 0x2C04, 0x2C08, 0x2C0C,
119 	0x2C10, 0x2C14, 0x2C18, 0x2C1C,
120 	0x2C20, 0x2C24, 0x2C28, 0x2C2C,
121 	0x2C30, 0x2C34, 0x2C38, 0x2C3C,
122 	0x2C40, 0x2C44, 0x2C48, 0x2C4C,
123 	0x2C50, 0x2C54, 0x2C58, 0x2C5C,
124 	0x2C60, 0x2C64, 0x2C68, 0x2C6C,
125 };
126 #endif /* CONFIG_SOC_SERIES_RCAR_GEN3 */
127 
128 void rcar_cpg_write(uint32_t base_address, uint32_t reg, uint32_t val);
129 
130 int rcar_cpg_mstp_clock_endisable(uint32_t base_address, uint32_t module, bool enable);
131 
132 struct cpg_clk_info_table *rcar_cpg_find_clk_info_by_module_id(const struct device *dev,
133 							       uint32_t domain,
134 							       uint32_t id);
135 
136 void rcar_cpg_build_clock_relationship(const struct device *dev);
137 
138 void rcar_cpg_update_all_in_out_freq(const struct device *dev);
139 
140 int rcar_cpg_get_rate(const struct device *dev, clock_control_subsys_t sys, uint32_t *rate);
141 
142 int rcar_cpg_set_rate(const struct device *dev, clock_control_subsys_t sys,
143 		      clock_control_subsys_rate_t rate);
144 
145 #endif /* ZEPHYR_DRIVERS_RENESAS_RENESAS_CPG_MSSR_H_ */
146