coreboot
coreboot is an Open Source project aimed at replacing the proprietary BIOS found in most computers.
funitcfg.c
Go to the documentation of this file.
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 
14 };
15 
17  const char *name;
18  void *ctlr_base;
20  const struct clk_dev_control * const dev_control;
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),
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 };
81  "funit_cfg_data array not filled out!");
82 
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:
90  break;
91  case PLLP:
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 
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 
127 static inline int is_usb(uint32_t idx)
128 {
129  return (idx == FUNIT_USBD || idx == FUNIT_USB2);
130 }
131 
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 
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 
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 }
#define ARRAY_SIZE(a)
Definition: helpers.h:12
#define printk(level,...)
Definition: stdlib.h:16
static uint32_t get_clk_src_freq(uint32_t clk_src_freq_id)
Definition: funitcfg.c:83
@ CLK_V_SET
Definition: funitcfg.c:28
@ CLK_Y_SET
Definition: funitcfg.c:31
@ CLK_W_SET
Definition: funitcfg.c:29
@ CLK_X_SET
Definition: funitcfg.c:30
@ CLK_H_SET
Definition: funitcfg.c:26
@ CLK_U_SET
Definition: funitcfg.c:27
@ CLK_L_SET
Definition: funitcfg.c:25
#define FUNIT_DATA(funit_, loname_, clk_set_)
Definition: funitcfg.c:50
static const struct funit_cfg_data funit_data[]
Definition: funitcfg.c:67
void soc_configure_funits(const struct funit_cfg *const entries, size_t num)
Definition: funitcfg.c:132
#define CLK_SET_REGS(x)
Definition: funitcfg.c:34
#define FUNIT_DATA_USB(funit_, clk_set_)
Definition: funitcfg.c:59
static void configure_clock(const struct funit_cfg *const entry, const struct funit_cfg_data *const funit)
Definition: funitcfg.c:102
_Static_assert(ARRAY_SIZE(funit_data)==FUNIT_INDEX_MAX, "funit_cfg_data array not filled out!")
static const struct clk_dev_control clk_data_arr[]
Definition: funitcfg.c:40
void __weak usb_setup_utmip(void *usb_base)
Definition: funitcfg.c:165
static int is_usb(uint32_t idx)
Definition: funitcfg.c:127
@ FUNIT_INDEX_MAX
Definition: funitcfg.h:25
int y
Definition: edid.c:994
int x
Definition: edid.c:994
#define BIOS_ERR
BIOS_ERR - System in incomplete state.
Definition: loglevel.h:72
#define BIOS_SPEW
BIOS_SPEW - Excessively verbose output.
Definition: loglevel.h:142
void soc_configure_pads(const struct pad_config *const entries, size_t num)
Definition: padconfig.c:105
const struct smm_save_state_ops *legacy_ops __weak
Definition: save_state.c:8
@ I2C5
Definition: i2c.h:55
@ I2C3
Definition: i2c.h:53
@ I2C2
Definition: i2c.h:52
@ I2C1
Definition: i2c.h:51
@ I2C6
Definition: i2c.h:56
static void _clock_set_div(u32 *reg, const char *name, u32 div, u32 div_mask, u32 src)
Definition: clock.h:209
#define TEGRA_PLLP_KHZ
Definition: clock.h:259
@ PLLP
Definition: clock.h:245
@ CLK_M
Definition: clock.h:253
#define TEGRA_CLK_M_KHZ
Definition: clock.h:257
void clock_grp_enable_clear_reset(u32 val, u32 *clk_enb_set_reg, u32 *rst_dev_clr_reg)
Definition: clock.c:634
#define get_i2c_clk_div(src, freq)
Definition: clock.h:312
#define CLK_DIV_MASK_I2C
Definition: clock.h:316
#define CLK_DIV_MASK
Definition: clock.h:315
#define get_clk_div(src, freq)
Definition: clock.h:314
unsigned int uint32_t
Definition: stdint.h:14
int strncmp(const char *s1, const char *s2, int maxlen)
Definition: string.c:114
size_t strlen(const char *src)
Definition: string.c:42
uint32_t * rst_dev_clr
Definition: funitcfg.c:13
uint32_t * clk_enb_set
Definition: funitcfg.c:12
Definition: dw_i2c.c:39
uint32_t * clk_src_reg
Definition: funitcfg.c:19
void * ctlr_base
Definition: funitcfg.c:18
uint32_t clk_enb_val
Definition: funitcfg.c:21
const struct clk_dev_control *const dev_control
Definition: funitcfg.c:20
const char * name
Definition: funitcfg.c:17
uint32_t funit_index
Definition: funitcfg.h:47
uint32_t clk_src_id
Definition: funitcfg.h:48
uint32_t clk_dev_freq_khz
Definition: funitcfg.h:50
uint32_t clk_src_freq_id
Definition: funitcfg.h:49
struct pad_config const * pad_cfg
Definition: funitcfg.h:51
size_t pad_cfg_size
Definition: funitcfg.h:52