1*4882a593Smuzhiyun /*
2*4882a593Smuzhiyun * Copyright (c) 2010-2014, NVIDIA CORPORATION. All rights reserved.
3*4882a593Smuzhiyun *
4*4882a593Smuzhiyun * SPDX-License-Identifier: GPL-2.0
5*4882a593Smuzhiyun */
6*4882a593Smuzhiyun
7*4882a593Smuzhiyun #include <common.h>
8*4882a593Smuzhiyun #include <asm/io.h>
9*4882a593Smuzhiyun #include <asm/arch/clock.h>
10*4882a593Smuzhiyun #include <asm/arch/flow.h>
11*4882a593Smuzhiyun #include <asm/arch/tegra.h>
12*4882a593Smuzhiyun #include <asm/arch-tegra/clk_rst.h>
13*4882a593Smuzhiyun #include <asm/arch-tegra/pmc.h>
14*4882a593Smuzhiyun #include <asm/arch-tegra/tegra_i2c.h>
15*4882a593Smuzhiyun #include "../cpu.h"
16*4882a593Smuzhiyun
17*4882a593Smuzhiyun /* Tegra30-specific CPU init code */
tegra_i2c_ll_write_addr(uint addr,uint config)18*4882a593Smuzhiyun void tegra_i2c_ll_write_addr(uint addr, uint config)
19*4882a593Smuzhiyun {
20*4882a593Smuzhiyun struct i2c_ctlr *reg = (struct i2c_ctlr *)TEGRA_DVC_BASE;
21*4882a593Smuzhiyun
22*4882a593Smuzhiyun writel(addr, ®->cmd_addr0);
23*4882a593Smuzhiyun writel(config, ®->cnfg);
24*4882a593Smuzhiyun }
25*4882a593Smuzhiyun
tegra_i2c_ll_write_data(uint data,uint config)26*4882a593Smuzhiyun void tegra_i2c_ll_write_data(uint data, uint config)
27*4882a593Smuzhiyun {
28*4882a593Smuzhiyun struct i2c_ctlr *reg = (struct i2c_ctlr *)TEGRA_DVC_BASE;
29*4882a593Smuzhiyun
30*4882a593Smuzhiyun writel(data, ®->cmd_data1);
31*4882a593Smuzhiyun writel(config, ®->cnfg);
32*4882a593Smuzhiyun }
33*4882a593Smuzhiyun
34*4882a593Smuzhiyun #define TPS62366A_I2C_ADDR 0xC0
35*4882a593Smuzhiyun #define TPS62366A_SET1_REG 0x01
36*4882a593Smuzhiyun #define TPS62366A_SET1_DATA (0x4600 | TPS62366A_SET1_REG)
37*4882a593Smuzhiyun
38*4882a593Smuzhiyun #define TPS62361B_I2C_ADDR 0xC0
39*4882a593Smuzhiyun #define TPS62361B_SET3_REG 0x03
40*4882a593Smuzhiyun #define TPS62361B_SET3_DATA (0x4600 | TPS62361B_SET3_REG)
41*4882a593Smuzhiyun
42*4882a593Smuzhiyun #define TPS65911_I2C_ADDR 0x5A
43*4882a593Smuzhiyun #define TPS65911_VDDCTRL_OP_REG 0x28
44*4882a593Smuzhiyun #define TPS65911_VDDCTRL_SR_REG 0x27
45*4882a593Smuzhiyun #define TPS65911_VDDCTRL_OP_DATA (0x2400 | TPS65911_VDDCTRL_OP_REG)
46*4882a593Smuzhiyun #define TPS65911_VDDCTRL_SR_DATA (0x0100 | TPS65911_VDDCTRL_SR_REG)
47*4882a593Smuzhiyun #define I2C_SEND_2_BYTES 0x0A02
48*4882a593Smuzhiyun
enable_cpu_power_rail(void)49*4882a593Smuzhiyun static void enable_cpu_power_rail(void)
50*4882a593Smuzhiyun {
51*4882a593Smuzhiyun struct pmc_ctlr *pmc = (struct pmc_ctlr *)NV_PA_PMC_BASE;
52*4882a593Smuzhiyun u32 reg;
53*4882a593Smuzhiyun
54*4882a593Smuzhiyun debug("enable_cpu_power_rail entry\n");
55*4882a593Smuzhiyun reg = readl(&pmc->pmc_cntrl);
56*4882a593Smuzhiyun reg |= CPUPWRREQ_OE;
57*4882a593Smuzhiyun writel(reg, &pmc->pmc_cntrl);
58*4882a593Smuzhiyun
59*4882a593Smuzhiyun /* Set VDD_CORE to 1.200V. */
60*4882a593Smuzhiyun #ifdef CONFIG_TEGRA_VDD_CORE_TPS62366A_SET1
61*4882a593Smuzhiyun tegra_i2c_ll_write_addr(TPS62366A_I2C_ADDR, 2);
62*4882a593Smuzhiyun tegra_i2c_ll_write_data(TPS62366A_SET1_DATA, I2C_SEND_2_BYTES);
63*4882a593Smuzhiyun #endif
64*4882a593Smuzhiyun #ifdef CONFIG_TEGRA_VDD_CORE_TPS62361B_SET3
65*4882a593Smuzhiyun tegra_i2c_ll_write_addr(TPS62361B_I2C_ADDR, 2);
66*4882a593Smuzhiyun tegra_i2c_ll_write_data(TPS62361B_SET3_DATA, I2C_SEND_2_BYTES);
67*4882a593Smuzhiyun #endif
68*4882a593Smuzhiyun udelay(1000);
69*4882a593Smuzhiyun
70*4882a593Smuzhiyun /*
71*4882a593Smuzhiyun * Bring up CPU VDD via the TPS65911x PMIC on the DVC I2C bus.
72*4882a593Smuzhiyun * First set VDD to 1.0125V, then enable the VDD regulator.
73*4882a593Smuzhiyun */
74*4882a593Smuzhiyun tegra_i2c_ll_write_addr(TPS65911_I2C_ADDR, 2);
75*4882a593Smuzhiyun tegra_i2c_ll_write_data(TPS65911_VDDCTRL_OP_DATA, I2C_SEND_2_BYTES);
76*4882a593Smuzhiyun udelay(1000);
77*4882a593Smuzhiyun tegra_i2c_ll_write_data(TPS65911_VDDCTRL_SR_DATA, I2C_SEND_2_BYTES);
78*4882a593Smuzhiyun udelay(10 * 1000);
79*4882a593Smuzhiyun }
80*4882a593Smuzhiyun
81*4882a593Smuzhiyun /**
82*4882a593Smuzhiyun * The T30 requires some special clock initialization, including setting up
83*4882a593Smuzhiyun * the dvc i2c, turning on mselect and selecting the G CPU cluster
84*4882a593Smuzhiyun */
t30_init_clocks(void)85*4882a593Smuzhiyun void t30_init_clocks(void)
86*4882a593Smuzhiyun {
87*4882a593Smuzhiyun struct clk_rst_ctlr *clkrst =
88*4882a593Smuzhiyun (struct clk_rst_ctlr *)NV_PA_CLK_RST_BASE;
89*4882a593Smuzhiyun struct flow_ctlr *flow = (struct flow_ctlr *)NV_PA_FLOW_BASE;
90*4882a593Smuzhiyun u32 val;
91*4882a593Smuzhiyun
92*4882a593Smuzhiyun debug("t30_init_clocks entry\n");
93*4882a593Smuzhiyun /* Set active CPU cluster to G */
94*4882a593Smuzhiyun clrbits_le32(flow->cluster_control, 1 << 0);
95*4882a593Smuzhiyun
96*4882a593Smuzhiyun writel(SUPER_SCLK_ENB_MASK, &clkrst->crc_super_sclk_div);
97*4882a593Smuzhiyun
98*4882a593Smuzhiyun val = (0 << CLK_SYS_RATE_HCLK_DISABLE_SHIFT) |
99*4882a593Smuzhiyun (1 << CLK_SYS_RATE_AHB_RATE_SHIFT) |
100*4882a593Smuzhiyun (0 << CLK_SYS_RATE_PCLK_DISABLE_SHIFT) |
101*4882a593Smuzhiyun (0 << CLK_SYS_RATE_APB_RATE_SHIFT);
102*4882a593Smuzhiyun writel(val, &clkrst->crc_clk_sys_rate);
103*4882a593Smuzhiyun
104*4882a593Smuzhiyun /* Put i2c, mselect in reset and enable clocks */
105*4882a593Smuzhiyun reset_set_enable(PERIPH_ID_DVC_I2C, 1);
106*4882a593Smuzhiyun clock_set_enable(PERIPH_ID_DVC_I2C, 1);
107*4882a593Smuzhiyun reset_set_enable(PERIPH_ID_MSELECT, 1);
108*4882a593Smuzhiyun clock_set_enable(PERIPH_ID_MSELECT, 1);
109*4882a593Smuzhiyun
110*4882a593Smuzhiyun /* Switch MSELECT clock to PLLP (00) and use a divisor of 2 */
111*4882a593Smuzhiyun clock_ll_set_source_divisor(PERIPH_ID_MSELECT, 0, 2);
112*4882a593Smuzhiyun
113*4882a593Smuzhiyun /*
114*4882a593Smuzhiyun * Our high-level clock routines are not available prior to
115*4882a593Smuzhiyun * relocation. We use the low-level functions which require a
116*4882a593Smuzhiyun * hard-coded divisor. Use CLK_M with divide by (n + 1 = 17)
117*4882a593Smuzhiyun */
118*4882a593Smuzhiyun clock_ll_set_source_divisor(PERIPH_ID_DVC_I2C, 3, 16);
119*4882a593Smuzhiyun
120*4882a593Smuzhiyun /*
121*4882a593Smuzhiyun * Give clocks time to stabilize, then take i2c and mselect out of
122*4882a593Smuzhiyun * reset
123*4882a593Smuzhiyun */
124*4882a593Smuzhiyun udelay(1000);
125*4882a593Smuzhiyun reset_set_enable(PERIPH_ID_DVC_I2C, 0);
126*4882a593Smuzhiyun reset_set_enable(PERIPH_ID_MSELECT, 0);
127*4882a593Smuzhiyun }
128*4882a593Smuzhiyun
set_cpu_running(int run)129*4882a593Smuzhiyun static void set_cpu_running(int run)
130*4882a593Smuzhiyun {
131*4882a593Smuzhiyun struct flow_ctlr *flow = (struct flow_ctlr *)NV_PA_FLOW_BASE;
132*4882a593Smuzhiyun
133*4882a593Smuzhiyun debug("set_cpu_running entry, run = %d\n", run);
134*4882a593Smuzhiyun writel(run ? FLOW_MODE_NONE : FLOW_MODE_STOP, &flow->halt_cpu_events);
135*4882a593Smuzhiyun }
136*4882a593Smuzhiyun
start_cpu(u32 reset_vector)137*4882a593Smuzhiyun void start_cpu(u32 reset_vector)
138*4882a593Smuzhiyun {
139*4882a593Smuzhiyun debug("start_cpu entry, reset_vector = %x\n", reset_vector);
140*4882a593Smuzhiyun t30_init_clocks();
141*4882a593Smuzhiyun
142*4882a593Smuzhiyun /* Enable VDD_CPU */
143*4882a593Smuzhiyun enable_cpu_power_rail();
144*4882a593Smuzhiyun
145*4882a593Smuzhiyun set_cpu_running(0);
146*4882a593Smuzhiyun
147*4882a593Smuzhiyun /* Hold the CPUs in reset */
148*4882a593Smuzhiyun reset_A9_cpu(1);
149*4882a593Smuzhiyun
150*4882a593Smuzhiyun /* Disable the CPU clock */
151*4882a593Smuzhiyun enable_cpu_clock(0);
152*4882a593Smuzhiyun
153*4882a593Smuzhiyun /* Enable CoreSight */
154*4882a593Smuzhiyun clock_enable_coresight(1);
155*4882a593Smuzhiyun
156*4882a593Smuzhiyun /*
157*4882a593Smuzhiyun * Set the entry point for CPU execution from reset,
158*4882a593Smuzhiyun * if it's a non-zero value.
159*4882a593Smuzhiyun */
160*4882a593Smuzhiyun if (reset_vector)
161*4882a593Smuzhiyun writel(reset_vector, EXCEP_VECTOR_CPU_RESET_VECTOR);
162*4882a593Smuzhiyun
163*4882a593Smuzhiyun /* Enable the CPU clock */
164*4882a593Smuzhiyun enable_cpu_clock(1);
165*4882a593Smuzhiyun
166*4882a593Smuzhiyun /* If the CPU doesn't already have power, power it up */
167*4882a593Smuzhiyun powerup_cpu();
168*4882a593Smuzhiyun
169*4882a593Smuzhiyun /* Take the CPU out of reset */
170*4882a593Smuzhiyun reset_A9_cpu(0);
171*4882a593Smuzhiyun
172*4882a593Smuzhiyun set_cpu_running(1);
173*4882a593Smuzhiyun }
174