1 /* SPDX-License-Identifier: GPL-2.0-only */
2
3 #include <device/mmio.h>
4 #include <arch/mmu.h>
5 #include <bootmode.h>
6 #include <boot/coreboot_tables.h>
7 #include <delay.h>
8 #include <device/device.h>
9 #include <device/i2c_simple.h>
10 #include <soc/addressmap.h>
11 #include <soc/clk_rst.h>
12 #include <soc/clock.h>
13 #include <soc/funitcfg.h>
14 #include <soc/padconfig.h>
15 #include <soc/nvidia/tegra/i2c.h>
16 #include <soc/nvidia/tegra/pingroup.h>
17 #include <soc/nvidia/tegra/dc.h>
18 #include <soc/display.h>
19 #include <soc/mtc.h>
20 #include <soc/pmc.h>
21 #include <soc/power.h>
22
23 #include "gpio.h"
24 #include "pmic.h"
25
26 static const struct pad_config padcfgs[] = {
27 PAD_CFG_GPIO_INPUT(USB_VBUS_EN1, PINMUX_PULL_NONE | PINMUX_PARKED |
28 PINMUX_INPUT_ENABLE | PINMUX_LPDR | PINMUX_IO_HV),
29 };
30
31 static const struct pad_config audio_codec_pads[] = {
32 /* GPIO_X1_AUD(BB3) is CODEC_RST_L and DMIC1_DAT(E1) is AUDIO_ENABLE */
33 PAD_CFG_GPIO_OUT1(GPIO_X1_AUD, PINMUX_PULL_DOWN),
34 PAD_CFG_GPIO_OUT1(DMIC1_DAT, PINMUX_PULL_DOWN),
35 };
36
37 static const struct pad_config i2s1_pad[] = {
38 /* I2S1 */
39 PAD_CFG_SFIO(DAP1_SCLK, PINMUX_INPUT_ENABLE, I2S1),
40 PAD_CFG_SFIO(DAP1_FS, PINMUX_INPUT_ENABLE, I2S1),
41 PAD_CFG_SFIO(DAP1_DOUT, PINMUX_INPUT_ENABLE, I2S1),
42 PAD_CFG_SFIO(DAP1_DIN, PINMUX_INPUT_ENABLE | PINMUX_TRISTATE, I2S1),
43 /* codec MCLK via AUD SFIO */
44 PAD_CFG_SFIO(AUD_MCLK, PINMUX_PULL_NONE, AUD),
45 };
46
47 static const struct funit_cfg audio_funit[] = {
48 /* We need 1.5MHz for I2S1. So we use CLK_M */
49 FUNIT_CFG(I2S1, CLK_M, 1500, i2s1_pad, ARRAY_SIZE(i2s1_pad)),
50 };
51
52 static const struct funit_cfg funits[] = {
53 FUNIT_CFG_USB(USBD),
54 FUNIT_CFG(SDMMC4, PLLP, 48000, NULL, 0),
55 /* I2C6 for audio, temp sensor, etc. Enable codec via GPIOs/muxes */
56 FUNIT_CFG(I2C6, PLLP, 400, audio_codec_pads, ARRAY_SIZE(audio_codec_pads)),
57 };
58
59 /* Audio init: clocks and enables/resets */
setup_audio(void)60 static void setup_audio(void)
61 {
62 /* Audio codec (RT5677) uses 12MHz CLK1/EXTPERIPH1 */
63 clock_configure_source(extperiph1, PLLP, 12000);
64
65 /* Configure AUD_MCLK pad drive strength */
66 write32((unsigned int *)TEGRA_APB_MISC_GP_BASE + 0xF4,
67 (0x10 << PINGROUP_DRVUP_SHIFT | 0x10 << PINGROUP_DRVDN_SHIFT));
68
69 /* Set up audio peripheral clocks/muxes */
70 soc_configure_funits(audio_funit, ARRAY_SIZE(audio_funit));
71
72 /* Enable CLK1_OUT */
73 clock_external_output(1);
74
75 /*
76 * As per NVIDIA hardware team, we need to take ALL audio devices
77 * connected to AHUB (AUDIO, APB2APE, I2S, SPDIF, etc.) out of reset
78 * and clock-enabled, otherwise reading AHUB devices (in our case,
79 * I2S/APBIF/AUDIO<XBAR>) will hang.
80 */
81 soc_configure_ape();
82 clock_enable_audio();
83 }
84
85 static const struct pad_config lcd_gpio_padcfgs[] = {
86 /* LCD_EN */
87 PAD_CFG_GPIO_OUT0(LCD_BL_EN, PINMUX_PULL_UP),
88 /* LCD_RST_L */
89 PAD_CFG_GPIO_OUT0(LCD_RST, PINMUX_PULL_UP),
90 /* EN_VDD_LCD */
91 PAD_CFG_GPIO_OUT0(LCD_GPIO2, PINMUX_PULL_NONE),
92 /* EN_VDD18_LCD */
93 PAD_CFG_GPIO_OUT0(LCD_GPIO1, PINMUX_PULL_NONE),
94 };
95
configure_display_clocks(void)96 static void configure_display_clocks(void)
97 {
98 u32 lclks = CLK_L_HOST1X | CLK_L_DISP1; /* dc */
99 u32 hclks = CLK_H_MIPI_CAL | CLK_H_DSI; /* mipi phy, mipi-dsi a */
100 u32 uclks = CLK_U_DSIB; /* mipi-dsi b */
101 u32 xclks = CLK_X_UART_FST_MIPI_CAL; /* uart_fst_mipi_cal */
102
103 clock_enable_clear_reset(lclks, hclks, uclks, 0, 0, xclks, 0);
104
105 /* Give clocks time to stabilize. */
106 udelay(IO_STABILIZATION_DELAY);
107
108 /* CLK72MHZ_CLK_SRC */
109 clock_configure_source(uart_fst_mipi_cal, PLLP_OUT3, 68000);
110 }
111
enable_lcd_vdd(void)112 static int enable_lcd_vdd(void)
113 {
114 /* Set 1.20V to power AVDD_DSI_CSI */
115 /* LD0: 1.20v CNF1: 0x0d */
116 pmic_write_reg_77620(I2CPWR_BUS, MAX77620_CNFG1_L0_REG, 0xd0, 1);
117
118 /* Enable VDD_LCD */
119 gpio_set(EN_VDD_LCD, 1);
120 /* wait for 2ms */
121 mdelay(2);
122
123 /* Enable PP1800_LCDIO to panel */
124 gpio_set(EN_VDD18_LCD, 1);
125 /* wait for 1ms */
126 mdelay(1);
127
128 /* Set panel EN and RST signals */
129 gpio_set(LCD_EN, 1); /* enable */
130 /* wait for min 10ms */
131 mdelay(10);
132 gpio_set(LCD_RST_L, 1); /* clear reset */
133 /* wait for min 3ms */
134 mdelay(3);
135
136 return 0;
137 }
138
configure_display_blocks(void)139 static int configure_display_blocks(void)
140 {
141 /* enable display related clocks */
142 configure_display_clocks();
143
144 /* configure panel gpio pads */
145 soc_configure_pads(lcd_gpio_padcfgs, ARRAY_SIZE(lcd_gpio_padcfgs));
146
147 /* set and enable panel related vdd */
148 if (enable_lcd_vdd())
149 return -1;
150
151 return 0;
152 }
153
powergate_unused_partitions(void)154 static void powergate_unused_partitions(void)
155 {
156 static const uint32_t partitions[] = {
157 POWER_PARTID_PCX,
158 POWER_PARTID_SAX,
159 POWER_PARTID_XUSBA,
160 POWER_PARTID_XUSBB,
161 POWER_PARTID_XUSBC,
162 POWER_PARTID_NVDEC,
163 POWER_PARTID_NVJPG,
164 POWER_PARTID_DFD,
165 };
166
167 int i;
168 for (i = 0; i < ARRAY_SIZE(partitions); i++)
169 power_gate_partition(partitions[i]);
170 }
171
mainboard_init(struct device * dev)172 static void mainboard_init(struct device *dev)
173 {
174 soc_configure_pads(padcfgs, ARRAY_SIZE(padcfgs));
175 soc_configure_funits(funits, ARRAY_SIZE(funits));
176
177 /* I2C6 bus (audio, etc.) */
178 soc_configure_i2c6pad();
179 i2c_init(I2C6_BUS);
180 setup_audio();
181
182 /* if panel needs to bringup */
183 if (display_init_required())
184 configure_display_blocks();
185
186 powergate_unused_partitions();
187 }
188
display_startup(struct device * dev)189 void display_startup(struct device *dev)
190 {
191 dsi_display_startup(dev);
192 }
193
mainboard_enable(struct device * dev)194 static void mainboard_enable(struct device *dev)
195 {
196 dev->ops->init = &mainboard_init;
197 }
198
199 struct chip_operations mainboard_ops = {
200 .enable_dev = mainboard_enable,
201 };
202
lb_board(struct lb_header * header)203 void lb_board(struct lb_header *header)
204 {
205 if (CONFIG(CHROMEOS))
206 lb_table_add_serialno_from_vpd(header);
207
208 soc_add_mtc(header);
209 }
210