blob: 2b5a48a869fe338bb385666dccd812a39dad4b51 [file] [log] [blame]
Ionela Voinescub3f666b2015-01-18 22:37:11 +00001/*
2 * This file is part of the coreboot project.
3 *
4 * Copyright (C) 2014 Imagination Technologies
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License as
8 * published by the Free Software Foundation; version 2 of
9 * 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.
Ionela Voinescub3f666b2015-01-18 22:37:11 +000015 */
16
17#include <arch/io.h>
18#include <stdint.h>
19#include <soc/clocks.h>
Ionela Voinescu256b1c32015-01-30 17:05:15 +000020#include <assert.h>
Ionela Voinescu2fdc61a2015-03-09 15:31:38 +000021#include <boardid.h>
Ionela Voinescub3f666b2015-01-18 22:37:11 +000022
Julius Wernerec477342017-11-29 14:27:51 -080023#include "urara_boardid.h"
24
Ionela Voinescu1d9515f2015-02-17 18:45:28 +000025#define PADS_FUNCTION_SELECT0_ADDR (0xB8101C00 + 0xC0)
26
Ionela Voinescub3f666b2015-01-18 22:37:11 +000027#define GPIO_BIT_EN_ADDR(bank) (0xB8101C00 + 0x200 + (0x24 * (bank)))
Ionela Voinescu256b1c32015-01-30 17:05:15 +000028#define PAD_DRIVE_STRENGTH_ADDR(bank) (0xB8101C00 + 0x120 + (0x4 * (bank)))
29#define MAX_NO_MFIOS 89
30#define PAD_DRIVE_STRENGTH_LENGTH 2
31#define PAD_DRIVE_STRENGTH_MASK 0x3
32
33typedef enum {
34 DRIVE_STRENGTH_2mA = 0,
35 DRIVE_STRENGTH_4mA = 1,
36 DRIVE_STRENGTH_8mA = 2,
37 DRIVE_STRENGTH_12mA = 3
38} drive_strength;
Ionela Voinescub3f666b2015-01-18 22:37:11 +000039
Ionela Voinescu1d9515f2015-02-17 18:45:28 +000040/* MFIO definitions for UART1 */
Ionela Voinescub3f666b2015-01-18 22:37:11 +000041#define UART1_RXD_MFIO 59
42#define UART1_TXD_MFIO 60
Ionela Voinescub3f666b2015-01-18 22:37:11 +000043
44/* MFIO definitions for SPIM */
45#define SPIM1_D0_TXD_MFIO 5
46#define SPIM1_D1_RXD_MFIO 4
47#define SPIM1_MCLK_MFIO 3
48#define SPIM1_D2_MFIO 6
49#define SPIM1_D3_MFIO 7
50#define SPIM1_CS0_MFIO 0
51
Ionela Voinescud99e0822015-03-05 14:13:54 +000052/* MFIO definitions for I2C */
53#define I2C_DATA_MFIO(i) (28 + (2*(i)))
54#define I2C_CLK_MFIO(i) (29 + (2*(i)))
55#define I2C_DATA_FUNCTION_OFFSET(i) (20 + (2*(i)))
56#define I2C_CLK_FUNCTION_OFFSET(i) (21 + (2*(i)))
57#define I2C_DATA_FUNCTION_MASK 0x1
58#define I2C_CLK_FUNCTION_MASK 0x1
Ionela Voinescu1d9515f2015-02-17 18:45:28 +000059
Ionela Voinescu256b1c32015-01-30 17:05:15 +000060static void pad_drive_strength(u32 pad, drive_strength strength)
61{
62 u32 reg, drive_strength_shift;
63
64 assert(pad <= MAX_NO_MFIOS);
65 assert(!(strength & ~(PAD_DRIVE_STRENGTH_MASK)));
66
67 /* Set drive strength value */
68 drive_strength_shift = (pad % 16) * PAD_DRIVE_STRENGTH_LENGTH;
69 reg = read32(PAD_DRIVE_STRENGTH_ADDR(pad / 16));
70 reg &= ~(PAD_DRIVE_STRENGTH_MASK << drive_strength_shift);
71 reg |= strength << drive_strength_shift;
72 write32(PAD_DRIVE_STRENGTH_ADDR(pad / 16), reg);
73}
74
Ionela Voinescub3f666b2015-01-18 22:37:11 +000075static void uart1_mfio_setup(void)
76{
77 u32 reg, mfio_mask;
78
79 /*
80 * Disable GPIO for UART1 MFIOs
81 * All UART MFIOs have MFIO/16 = 3, therefore we use GPIO pad 3
Ionela Voinescu1d9515f2015-02-17 18:45:28 +000082 * This is the only function (0) of these MFIOs and therfore there
Ionela Voinescub3f666b2015-01-18 22:37:11 +000083 * is no need to set up a function number in the corresponding
84 * function select register.
85 */
86 reg = read32(GPIO_BIT_EN_ADDR(3));
87 mfio_mask = 1 << (UART1_RXD_MFIO % 16);
88 mfio_mask |= 1 << (UART1_TXD_MFIO % 16);
89 /* Clear relevant bits */
90 reg &= ~mfio_mask;
91 /*
92 * Set corresponding bits in the upper half word
93 * in order to be able to modify the chosen pins
94 */
95 reg |= mfio_mask << 16;
96 write32(GPIO_BIT_EN_ADDR(3), reg);
97}
98
99static void spim1_mfio_setup(void)
100{
101 u32 reg, mfio_mask;
102 /*
103 * Disable GPIO for SPIM1 MFIOs
104 * All SPFI1 MFIOs have MFIO/16 = 0, therefore we use GPIO pad 0
Ionela Voinescu1d9515f2015-02-17 18:45:28 +0000105 * This is the only function (0) of these MFIOs and therfore there
Ionela Voinescub3f666b2015-01-18 22:37:11 +0000106 * is no need to set up a function number in the corresponding
107 * function select register.
108 */
109 reg = read32(GPIO_BIT_EN_ADDR(0));
110
Ionela Voinescu1d9515f2015-02-17 18:45:28 +0000111 /* Disable GPIO for SPIM1 MFIOs */
Ionela Voinescub3f666b2015-01-18 22:37:11 +0000112 mfio_mask = 1 << (SPIM1_D0_TXD_MFIO % 16);
113 mfio_mask |= 1 << (SPIM1_D1_RXD_MFIO % 16);
114 mfio_mask |= 1 << (SPIM1_MCLK_MFIO % 16);
115 mfio_mask |= 1 << (SPIM1_D2_MFIO % 16);
116 mfio_mask |= 1 << (SPIM1_D3_MFIO % 16);
Ionela Voinescub3f666b2015-01-18 22:37:11 +0000117 mfio_mask |= 1 << (SPIM1_CS0_MFIO % 16);
118
119 /* Clear relevant bits */
120 reg &= ~mfio_mask;
121 /*
122 * Set corresponding bits in the upper half word
123 * in order to be able to modify the chosen pins
124 */
125 reg |= mfio_mask << 16;
126 write32(GPIO_BIT_EN_ADDR(0), reg);
Ionela Voinescu256b1c32015-01-30 17:05:15 +0000127
128 /* Set drive strength to maximum for these MFIOs */
129 pad_drive_strength(SPIM1_CS0_MFIO, DRIVE_STRENGTH_12mA);
130 pad_drive_strength(SPIM1_D1_RXD_MFIO, DRIVE_STRENGTH_12mA);
131 pad_drive_strength(SPIM1_D0_TXD_MFIO, DRIVE_STRENGTH_12mA);
132 pad_drive_strength(SPIM1_D2_MFIO, DRIVE_STRENGTH_12mA);
133 pad_drive_strength(SPIM1_D3_MFIO, DRIVE_STRENGTH_12mA);
134 pad_drive_strength(SPIM1_MCLK_MFIO, DRIVE_STRENGTH_12mA);
Ionela Voinescub3f666b2015-01-18 22:37:11 +0000135}
136
Ionela Voinescud99e0822015-03-05 14:13:54 +0000137static void i2c_mfio_setup(int interface)
Ionela Voinescu1d9515f2015-02-17 18:45:28 +0000138{
139 u32 reg, mfio_mask;
140
Ionela Voinescud99e0822015-03-05 14:13:54 +0000141 assert(interface < 4);
Ionela Voinescu1d9515f2015-02-17 18:45:28 +0000142 /*
Ionela Voinescud99e0822015-03-05 14:13:54 +0000143 * Disable GPIO for I2C MFIOs
Ionela Voinescu1d9515f2015-02-17 18:45:28 +0000144 */
Ionela Voinescud99e0822015-03-05 14:13:54 +0000145 reg = read32(GPIO_BIT_EN_ADDR(I2C_DATA_MFIO(interface) / 16));
146 mfio_mask = 1 << (I2C_DATA_MFIO(interface) % 16);
147 mfio_mask |= 1 << (I2C_CLK_MFIO(interface) % 16);
Ionela Voinescu1d9515f2015-02-17 18:45:28 +0000148 /* Clear relevant bits */
149 reg &= ~mfio_mask;
150 /*
151 * Set corresponding bits in the upper half word
152 * in order to be able to modify the chosen pins
153 */
154 reg |= mfio_mask << 16;
Ionela Voinescud99e0822015-03-05 14:13:54 +0000155 write32(GPIO_BIT_EN_ADDR(I2C_DATA_MFIO(interface) / 16), reg);
Ionela Voinescu1d9515f2015-02-17 18:45:28 +0000156
Ionela Voinescud99e0822015-03-05 14:13:54 +0000157 /* for I2C0 and I2C1:
158 * Set bits to 0 (clear) which is the primary function
Ionela Voinescu1d9515f2015-02-17 18:45:28 +0000159 * for these MFIOs; those bits will all be set to 1 by
Ionela Voinescud99e0822015-03-05 14:13:54 +0000160 * default.
161 * There is no need to do that for I2C2 and I2C3
Ionela Voinescu1d9515f2015-02-17 18:45:28 +0000162 */
Ionela Voinescud99e0822015-03-05 14:13:54 +0000163 if (interface > 1)
164 return;
Ionela Voinescu1d9515f2015-02-17 18:45:28 +0000165 reg = read32(PADS_FUNCTION_SELECT0_ADDR);
Ionela Voinescud99e0822015-03-05 14:13:54 +0000166 reg &= ~(I2C_DATA_FUNCTION_MASK <<
167 I2C_DATA_FUNCTION_OFFSET(interface));
168 reg &= ~(I2C_CLK_FUNCTION_MASK <<
169 I2C_CLK_FUNCTION_OFFSET(interface));
Ionela Voinescu1d9515f2015-02-17 18:45:28 +0000170 write32(PADS_FUNCTION_SELECT0_ADDR, reg);
171}
172
Ionela Voinescu2fdc61a2015-03-09 15:31:38 +0000173static void bootblock_mainboard_init(void)
Ionela Voinescub3f666b2015-01-18 22:37:11 +0000174{
175 int ret;
176
Ionela Voinescu90d12352015-07-15 12:10:05 +0100177 /* System PLL divided by 2 -> 350 MHz */
Ionela Voinescub3f666b2015-01-18 22:37:11 +0000178 /* The same frequency will be the input frequency for the SPFI block */
179 system_clk_setup(1);
Ionela Voinescu8b1f23e2015-01-26 13:15:12 +0000180
Ionela Voinescu0f58d0b2015-02-03 00:26:08 +0000181 /* MIPS CPU dividers: division by 1 -> 546 MHz
Ionela Voinescu8b1f23e2015-01-26 13:15:12 +0000182 * This is set up as we cannot make any assumption about
183 * the values set or not by the boot ROM code */
184 mips_clk_setup(0, 0);
185
Ionela Voinescu90d12352015-07-15 12:10:05 +0100186 /* Setup system PLL at 700 MHz */
187 ret = sys_pll_setup(2, 1, 13, 350);
Ionela Voinescub3f666b2015-01-18 22:37:11 +0000188 if (ret != CLOCKS_OK)
Ionela Voinescu2fdc61a2015-03-09 15:31:38 +0000189 return;
190 /* Setup MIPS PLL at 546 MHz */
191 ret = mips_pll_setup(2, 1, 1, 21);
192 if (ret != CLOCKS_OK)
193 return;
Ionela Voinescu8b1f23e2015-01-26 13:15:12 +0000194
Ionela Voinescu4f3d4002015-11-01 19:55:48 +0000195 /*
196 * Move peripheral clock control from RPU to MIPS.
197 * The RPU gate register is not managed in Linux so disable its default
198 * values and assign MIPS gate register the default values.
199 * *Note*: All unused clocks will be gated by Linux
200 */
201 setup_clk_gate_defaults();
202
Ionela Voinescu2fdc61a2015-03-09 15:31:38 +0000203 /* Setup SPIM1 MFIOs */
204 spim1_mfio_setup();
205 /* Setup UART1 clock and MFIOs
Ionela Voinescu90d12352015-07-15 12:10:05 +0100206 * System PLL divided by 5 divided by 76 -> 1.8421 Mhz
Ionela Voinescu2fdc61a2015-03-09 15:31:38 +0000207 */
Ionela Voinescu90d12352015-07-15 12:10:05 +0100208 uart1_clk_setup(4, 75);
Ionela Voinescu2fdc61a2015-03-09 15:31:38 +0000209 uart1_mfio_setup();
210}
Ionela Voinescub3f666b2015-01-18 22:37:11 +0000211
Ionela Voinescu2fdc61a2015-03-09 15:31:38 +0000212
213static int init_extra_hardware(void)
214{
215 const struct board_hw *hardware;
216
217 /* Obtain information about current board */
218 hardware = board_get_hw();
219 if (!hardware) {
220 printk(BIOS_ERR, "%s: Invalid hardware information.\n",
221 __func__);
222 return -1;
223 }
224
225 /* Setup USB clock
Ionela Voinescu90d12352015-07-15 12:10:05 +0100226 * System clock divided by 7 -> 50 MHz
Ionela Voinescu2fdc61a2015-03-09 15:31:38 +0000227 */
Ionela Voinescu90d12352015-07-15 12:10:05 +0100228 if (usb_clk_setup(6, 2, 7) != CLOCKS_OK) {
Ionela Voinescu2fdc61a2015-03-09 15:31:38 +0000229 printk(BIOS_ERR, "%s: Failed to set up USB clock.\n",
230 __func__);
231 return -1;
232 }
233
234 /* Setup I2C clocks and MFIOs
Ionela Voinescu90d12352015-07-15 12:10:05 +0100235 * System clock divided by 4 divided by 3 -> 29.1(6) MHz
Ionela Voinescu2fdc61a2015-03-09 15:31:38 +0000236 */
237 i2c_clk_setup(3, 2, hardware->i2c_interface);
238 i2c_mfio_setup(hardware->i2c_interface);
239
Ionela Voinescu8b1f23e2015-01-26 13:15:12 +0000240 /* Ethernet clocks setup: ENET as clock source */
Ionela Voinescu90d12352015-07-15 12:10:05 +0100241 eth_clk_setup(0, 6);
242 /* ROM clock setup: system clock divided by 2 -> 175 MHz */
Ionela Voinescu8b1f23e2015-01-26 13:15:12 +0000243 /* Hash accelerator is driven from the ROM clock */
244 rom_clk_setup(1);
245
Ionela Voinescu2fdc61a2015-03-09 15:31:38 +0000246 return 0;
Ionela Voinescub3f666b2015-01-18 22:37:11 +0000247}