xref: /aosp_15_r20/external/coreboot/src/soc/nvidia/tegra210/funitcfg.c (revision b9411a12aaaa7e1e6a6fb7c5e057f44ee179a49c)
1 /* SPDX-License-Identifier: GPL-2.0-only */
2 
3 #include <console/console.h>
4 #include <soc/addressmap.h>
5 #include <soc/clock.h>
6 #include <soc/funitcfg.h>
7 #include <soc/nvidia/tegra/usb.h>
8 #include <soc/padconfig.h>
9 #include <string.h>
10 
11 struct clk_dev_control {
12 	uint32_t *clk_enb_set;
13 	uint32_t *rst_dev_clr;
14 };
15 
16 struct funit_cfg_data {
17 	const char *name;
18 	void *ctlr_base;
19 	uint32_t *clk_src_reg;
20 	const struct clk_dev_control * const dev_control;
21 	uint32_t clk_enb_val;
22 };
23 
24 enum {
25 	CLK_L_SET = 0,
26 	CLK_H_SET = 1,
27 	CLK_U_SET = 2,
28 	CLK_V_SET = 3,
29 	CLK_W_SET = 4,
30 	CLK_X_SET = 5,
31 	CLK_Y_SET = 6,
32 };
33 
34 #define CLK_SET_REGS(x)					\
35 	{						\
36 		CLK_RST_REG(clk_enb_##x##_set),		\
37 		CLK_RST_REG(rst_dev_##x##_clr),		\
38 	}
39 
40 static const struct clk_dev_control clk_data_arr[] = {
41 	[CLK_L_SET] = CLK_SET_REGS(l),
42 	[CLK_H_SET] = CLK_SET_REGS(h),
43 	[CLK_U_SET] = CLK_SET_REGS(u),
44 	[CLK_V_SET] = CLK_SET_REGS(v),
45 	[CLK_W_SET] = CLK_SET_REGS(w),
46 	[CLK_X_SET] = CLK_SET_REGS(x),
47 	[CLK_Y_SET] = CLK_SET_REGS(y),
48 };
49 
50 #define FUNIT_DATA(funit_, loname_, clk_set_)				\
51 	[FUNIT_INDEX(funit_)] = {					\
52 		.name = STRINGIFY(loname_),				\
53 		.ctlr_base = (void *)(uintptr_t)TEGRA_##funit_##_BASE,	\
54 		.clk_src_reg = CLK_RST_REG(clk_src_##loname_),		\
55 		.dev_control = &clk_data_arr[CLK_##clk_set_##_SET],	\
56 		.clk_enb_val = CLK_##clk_set_##_##funit_,		\
57 	}
58 
59 #define FUNIT_DATA_USB(funit_, clk_set_)				\
60 	[FUNIT_INDEX(funit_)] = {					\
61 		.name = STRINGIFY(funit_),				\
62 		.ctlr_base = (void *)(uintptr_t)TEGRA_##funit_##_BASE,	\
63 		.dev_control = &clk_data_arr[CLK_##clk_set_##_SET],	\
64 		.clk_enb_val = CLK_##clk_set_##_##funit_,		\
65 	}
66 
67 static const struct funit_cfg_data funit_data[] =  {
68 	FUNIT_DATA(I2C1, i2c1, L),
69 	FUNIT_DATA(I2C2, i2c2, H),
70 	FUNIT_DATA(I2C3, i2c3, U),
71 	FUNIT_DATA(I2C5, i2c5, H),
72 	FUNIT_DATA(I2C6, i2c6, X),
73 	FUNIT_DATA(SDMMC1, sdmmc1, L),
74 	FUNIT_DATA(SDMMC4, sdmmc4, L),
75 	FUNIT_DATA_USB(USBD, L),
76 	FUNIT_DATA_USB(USB2, H),
77 	FUNIT_DATA(QSPI, qspi, Y),
78 	FUNIT_DATA(I2S1, i2s1, L),
79 };
80 _Static_assert(ARRAY_SIZE(funit_data) == FUNIT_INDEX_MAX,
81 		"funit_cfg_data array not filled out!");
82 
get_clk_src_freq(uint32_t clk_src_freq_id)83 static inline uint32_t get_clk_src_freq(uint32_t clk_src_freq_id)
84 {
85 	uint32_t freq = 0;
86 
87 	switch (clk_src_freq_id) {
88 	case CLK_M:
89 		freq = TEGRA_CLK_M_KHZ;
90 		break;
91 	case PLLP:
92 		freq = TEGRA_PLLP_KHZ;
93 		break;
94 	default:
95 		printk(BIOS_SPEW, "%s ERROR: Unknown clk_src %d\n",
96 		       __func__, clk_src_freq_id);
97 	}
98 
99 	return freq;
100 }
101 
configure_clock(const struct funit_cfg * const entry,const struct funit_cfg_data * const funit)102 static void configure_clock(const struct funit_cfg * const entry,
103 				const struct funit_cfg_data * const funit)
104 {
105 	const char *funit_i2c = "i2c";
106 	uint32_t clk_div;
107 	uint32_t clk_div_mask;
108 	uint32_t clk_src_freq;
109 
110 	clk_src_freq = get_clk_src_freq(entry->clk_src_freq_id);
111 
112 	if (strncmp(funit->name, funit_i2c, strlen(funit_i2c)) == 0) {
113 		/* I2C funit */
114 		clk_div = get_i2c_clk_div(clk_src_freq,
115 					entry->clk_dev_freq_khz);
116 		clk_div_mask = CLK_DIV_MASK_I2C;
117 	} else {
118 		/* Non I2C */
119 		clk_div = get_clk_div(clk_src_freq, entry->clk_dev_freq_khz);
120 		clk_div_mask = CLK_DIV_MASK;
121 	}
122 
123 	_clock_set_div(funit->clk_src_reg, funit->name, clk_div,
124 			clk_div_mask, entry->clk_src_id);
125 }
126 
is_usb(uint32_t idx)127 static inline int is_usb(uint32_t idx)
128 {
129 	return (idx == FUNIT_USBD || idx == FUNIT_USB2);
130 }
131 
soc_configure_funits(const struct funit_cfg * const entries,size_t num)132 void soc_configure_funits(const struct funit_cfg * const entries, size_t num)
133 {
134 	size_t i;
135 
136 	for (i = 0; i < num; i++) {
137 		const struct funit_cfg * const entry = &entries[i];
138 		const struct funit_cfg_data *funit;
139 		const struct clk_dev_control *dev_control;
140 		int funit_usb = is_usb(entry->funit_index);
141 
142 		if (entry->funit_index >= FUNIT_INDEX_MAX) {
143 			printk(BIOS_ERR, "Index out of bounds\n");
144 			continue;
145 		}
146 
147 		funit = &funit_data[entry->funit_index];
148 		dev_control = funit->dev_control;
149 
150 		/* USB controllers have a fixed clock source. */
151 		if (!funit_usb)
152 			configure_clock(entry, funit);
153 
154 		clock_grp_enable_clear_reset(funit->clk_enb_val,
155 						dev_control->clk_enb_set,
156 						dev_control->rst_dev_clr);
157 
158 		if (funit_usb)
159 			usb_setup_utmip(funit->ctlr_base);
160 
161 		soc_configure_pads(entry->pad_cfg,entry->pad_cfg_size);
162 	}
163 }
164 
usb_setup_utmip(void * usb_base)165 void __weak usb_setup_utmip(void *usb_base)
166 {
167 	/* default empty implementation required if usb.c is not included */
168 	printk(BIOS_ERR, "USB setup is not supported in current stage\n");
169 }
170