blob: bdc2e222b06383d42a0585ef15eaf114d5581516 [file] [log] [blame]
Patrick Georgi40a3e322015-06-22 19:41:29 +02001/*
2 * This file is part of the coreboot project.
3 *
4 * Copyright (c) 2014-2015, NVIDIA CORPORATION.
5 * Copyright 2014 Google Inc.
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; version 2 of the License.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
Patrick Georgi40a3e322015-06-22 19:41:29 +020015 */
16
17#include <delay.h>
18#include <soc/addressmap.h>
19#include <soc/clk_rst.h>
20#include <soc/clock.h>
21#include <soc/nvidia/tegra/i2c.h>
22#include <soc/padconfig.h>
23#include <soc/power.h>
24
25#define I2C6_PADCTL 0xC001
26#define DPAUX_HYBRID_PADCTL 0x545C0124
27#define DPAUX_HYBRID_SPARE 0x545C0134
28
29static void enable_sor_periph_clocks(void)
30{
31 clock_enable(CLK_L_HOST1X, 0, 0, 0, 0, CLK_X_DPAUX, 0);
32
33 /* Give clocks time to stabilize. */
34 udelay(IO_STABILIZATION_DELAY);
35}
36
37static void disable_sor_periph_clocks(void)
38{
39 clock_disable(CLK_L_HOST1X, 0, 0, 0, 0, CLK_X_DPAUX, 0);
40
41 /* Give clocks time to stabilize. */
42 udelay(IO_STABILIZATION_DELAY);
43}
44
45static void unreset_sor_periphs(void)
46{
47 clock_clr_reset(CLK_L_HOST1X, 0, 0, 0, 0, CLK_X_DPAUX, 0);
48}
49
50void soc_configure_i2c6pad(void)
51{
52 /*
53 * I2C6 on Tegra1xx requires some special init.
54 * The SOR block must be unpowergated, and a couple of
55 * display-based peripherals must be clocked and taken
56 * out of reset so that a DPAUX register can be
57 * configured to enable the I2C6 mux routing.
58 * Afterwards, we can disable clocks to the display blocks
59 * and put Host1X back in reset. DPAUX must remain out of
60 * reset and the SOR partition must remained unpowergated.
61 */
62 soc_configure_host1x();
63
Yen Lin13fb7492015-05-29 14:36:19 -070064 /* enable SOR_SAFE and DPAUX_1 clocks */
65 clock_enable_y(CLK_Y_DPAUX1 | CLK_Y_SOR_SAFE);
66
Patrick Georgi40a3e322015-06-22 19:41:29 +020067 /* Now we can write the I2C6 mux in DPAUX */
68 write32((void *)DPAUX_HYBRID_PADCTL, I2C6_PADCTL);
69 /* Finally, power up the pads */
70 write32((void *)DPAUX_HYBRID_SPARE, 0);
71
72 /*
73 * Delay before turning off Host1X/DPAUX clocks.
74 * This delay is needed to keep the sequence from
75 * hanging the system.
76 */
77 udelay(CLOCK_PLL_STABLE_DELAY_US);
78
79 /* Stop Host1X/DPAUX clocks and reset Host1X */
80 disable_sor_periph_clocks();
81 clock_set_reset_l(CLK_L_HOST1X);
82}
83
84void soc_configure_host1x(void)
85{
86 power_ungate_partition(POWER_PARTID_SOR);
87
88 /* Host1X needs a valid clock source so DPAUX can be accessed. */
89 clock_configure_source(host1x, PLLP, 204000);
90
91 enable_sor_periph_clocks();
92 remove_clamps(POWER_PARTID_SOR);
93 unreset_sor_periphs();
94}