]> git.ipfire.org Git - people/ms/u-boot.git/blame - board/CZ.NIC/turris_omnia/turris_omnia.c
marvell: armada385: Add the Turris Omnia board
[people/ms/u-boot.git] / board / CZ.NIC / turris_omnia / turris_omnia.c
CommitLineData
b6ee860b
MB
1/*
2 * Copyright (C) 2017 Marek Behun <marek.behun@nic.cz>
3 * Copyright (C) 2016 Tomas Hlavacek <tomas.hlavacek@nic.cz>
4 *
5 * Derived from the code for
6 * Marvell/db-88f6820-gp by Stefan Roese <sr@denx.de>
7 *
8 * SPDX-License-Identifier: GPL-2.0+
9 */
10
11#include <common.h>
12#include <i2c.h>
13#include <miiphy.h>
14#include <netdev.h>
15#include <asm/io.h>
16#include <asm/arch/cpu.h>
17#include <asm/arch/soc.h>
18#include <dm/uclass.h>
19#include <fdt_support.h>
20#include <time.h>
21
22#ifdef CONFIG_ATSHA204A
23# include <atsha204a-i2c.h>
24#endif
25
26#ifdef CONFIG_WDT_ORION
27# include <wdt.h>
28#endif
29
30#include "../drivers/ddr/marvell/a38x/ddr3_a38x_topology.h"
31#include <../serdes/a38x/high_speed_env_spec.h>
32
33DECLARE_GLOBAL_DATA_PTR;
34
35#define OMNIA_I2C_EEPROM_DM_NAME "i2c@0"
36#define OMNIA_I2C_EEPROM 0x54
37#define OMNIA_I2C_EEPROM_CONFIG_ADDR 0x0
38#define OMNIA_I2C_EEPROM_ADDRLEN 2
39#define OMNIA_I2C_EEPROM_MAGIC 0x0341a034
40
41#define OMNIA_I2C_MCU_DM_NAME "i2c@0"
42#define OMNIA_I2C_MCU_ADDR_STATUS 0x1
43#define OMNIA_I2C_MCU_SATA 0x20
44#define OMNIA_I2C_MCU_CARDDET 0x10
45#define OMNIA_I2C_MCU 0x2a
46#define OMNIA_I2C_MCU_WDT_ADDR 0x0b
47
48#define OMNIA_ATSHA204_OTP_VERSION 0
49#define OMNIA_ATSHA204_OTP_SERIAL 1
50#define OMNIA_ATSHA204_OTP_MAC0 3
51#define OMNIA_ATSHA204_OTP_MAC1 4
52
53#define MVTWSI_ARMADA_DEBUG_REG 0x8c
54
55/*
56 * Those values and defines are taken from the Marvell U-Boot version
57 * "u-boot-2013.01-2014_T3.0"
58 */
59#define OMNIA_GPP_OUT_ENA_LOW \
60 (~(BIT(1) | BIT(4) | BIT(6) | BIT(7) | BIT(8) | BIT(9) | \
61 BIT(10) | BIT(11) | BIT(19) | BIT(22) | BIT(23) | BIT(25) | \
62 BIT(26) | BIT(27) | BIT(29) | BIT(30) | BIT(31)))
63#define OMNIA_GPP_OUT_ENA_MID \
64 (~(BIT(0) | BIT(1) | BIT(2) | BIT(3) | BIT(4) | BIT(15) | \
65 BIT(16) | BIT(17) | BIT(18)))
66
67#define OMNIA_GPP_OUT_VAL_LOW 0x0
68#define OMNIA_GPP_OUT_VAL_MID 0x0
69#define OMNIA_GPP_POL_LOW 0x0
70#define OMNIA_GPP_POL_MID 0x0
71
72static struct serdes_map board_serdes_map_pex[] = {
73 {PEX0, SERDES_SPEED_5_GBPS, PEX_ROOT_COMPLEX_X1, 0, 0},
74 {USB3_HOST0, SERDES_SPEED_5_GBPS, SERDES_DEFAULT_MODE, 0, 0},
75 {PEX1, SERDES_SPEED_5_GBPS, PEX_ROOT_COMPLEX_X1, 0, 0},
76 {USB3_HOST1, SERDES_SPEED_5_GBPS, SERDES_DEFAULT_MODE, 0, 0},
77 {PEX2, SERDES_SPEED_5_GBPS, PEX_ROOT_COMPLEX_X1, 0, 0},
78 {SGMII2, SERDES_SPEED_1_25_GBPS, SERDES_DEFAULT_MODE, 0, 0}
79};
80
81static struct serdes_map board_serdes_map_sata[] = {
82 {SATA0, SERDES_SPEED_6_GBPS, SERDES_DEFAULT_MODE, 0, 0},
83 {USB3_HOST0, SERDES_SPEED_5_GBPS, SERDES_DEFAULT_MODE, 0, 0},
84 {PEX1, SERDES_SPEED_5_GBPS, PEX_ROOT_COMPLEX_X1, 0, 0},
85 {USB3_HOST1, SERDES_SPEED_5_GBPS, SERDES_DEFAULT_MODE, 0, 0},
86 {PEX2, SERDES_SPEED_5_GBPS, PEX_ROOT_COMPLEX_X1, 0, 0},
87 {SGMII2, SERDES_SPEED_1_25_GBPS, SERDES_DEFAULT_MODE, 0, 0}
88};
89
90static bool omnia_detect_sata(void)
91{
92 struct udevice *bus, *dev;
93 int ret;
94 u16 mode;
95
96 puts("SERDES0 card detect: ");
97
98 if (uclass_get_device_by_name(UCLASS_I2C, OMNIA_I2C_MCU_DM_NAME, &bus)) {
99 puts("Cannot find MCU bus!\n");
100 return false;
101 }
102
103 ret = i2c_get_chip(bus, OMNIA_I2C_MCU, 1, &dev);
104 if (ret) {
105 puts("Cannot get MCU chip!\n");
106 return false;
107 }
108
109 ret = dm_i2c_read(dev, OMNIA_I2C_MCU_ADDR_STATUS, (uchar *) &mode, 2);
110 if (ret) {
111 puts("I2C read failed! Default PEX\n");
112 return false;
113 }
114
115 if (!(mode & OMNIA_I2C_MCU_CARDDET)) {
116 puts("NONE\n");
117 return false;
118 }
119
120 if (mode & OMNIA_I2C_MCU_SATA) {
121 puts("SATA\n");
122 return true;
123 } else {
124 puts("PEX\n");
125 return false;
126 }
127}
128
129int hws_board_topology_load(struct serdes_map **serdes_map_array, u8 *count)
130{
131 if (omnia_detect_sata()) {
132 *serdes_map_array = board_serdes_map_sata;
133 *count = ARRAY_SIZE(board_serdes_map_sata);
134 } else {
135 *serdes_map_array = board_serdes_map_pex;
136 *count = ARRAY_SIZE(board_serdes_map_pex);
137 }
138
139 return 0;
140}
141
142struct omnia_eeprom {
143 u32 magic;
144 u32 ramsize;
145 char region[4];
146 u32 crc;
147};
148
149static bool omnia_read_eeprom(struct omnia_eeprom *oep)
150{
151 struct udevice *bus, *dev;
152 int ret, crc, retry = 3;
153
154 if (uclass_get_device_by_name(UCLASS_I2C, OMNIA_I2C_EEPROM_DM_NAME, &bus)) {
155 puts("Cannot find EEPROM bus\n");
156 return false;
157 }
158
159 ret = i2c_get_chip(bus, OMNIA_I2C_EEPROM, OMNIA_I2C_EEPROM_ADDRLEN, &dev);
160 if (ret) {
161 puts("Cannot get EEPROM chip\n");
162 return false;
163 }
164
165 for (; retry > 0; --retry) {
166 ret = dm_i2c_read(dev, OMNIA_I2C_EEPROM_CONFIG_ADDR, (uchar *) oep, sizeof(struct omnia_eeprom));
167 if (ret)
168 continue;
169
170 if (oep->magic != OMNIA_I2C_EEPROM_MAGIC) {
171 puts("I2C EEPROM missing magic number!\n");
172 continue;
173 }
174
175 crc = crc32(0, (unsigned char *) oep,
176 sizeof(struct omnia_eeprom) - 4);
177 if (crc == oep->crc) {
178 break;
179 } else {
180 printf("CRC of EEPROM memory config failed! "
181 "calc=0x%04x saved=0x%04x\n", crc, oep->crc);
182 }
183 }
184
185 if (!retry) {
186 puts("I2C EEPROM read failed!\n");
187 return false;
188 }
189
190 return true;
191}
192
193/*
194 * Define the DDR layout / topology here in the board file. This will
195 * be used by the DDR3 init code in the SPL U-Boot version to configure
196 * the DDR3 controller.
197 */
198static struct hws_topology_map board_topology_map_1g = {
199 0x1, /* active interfaces */
200 /* cs_mask, mirror, dqs_swap, ck_swap X PUPs */
201 { { { {0x1, 0, 0, 0},
202 {0x1, 0, 0, 0},
203 {0x1, 0, 0, 0},
204 {0x1, 0, 0, 0},
205 {0x1, 0, 0, 0} },
206 SPEED_BIN_DDR_1600K, /* speed_bin */
207 BUS_WIDTH_16, /* memory_width */
208 MEM_4G, /* mem_size */
209 DDR_FREQ_800, /* frequency */
210 0, 0, /* cas_l cas_wl */
211 HWS_TEMP_NORMAL, /* temperature */
212 HWS_TIM_2T} }, /* timing (force 2t) */
213 5, /* Num Of Bus Per Interface*/
214 BUS_MASK_32BIT /* Busses mask */
215};
216
217static struct hws_topology_map board_topology_map_2g = {
218 0x1, /* active interfaces */
219 /* cs_mask, mirror, dqs_swap, ck_swap X PUPs */
220 { { { {0x1, 0, 0, 0},
221 {0x1, 0, 0, 0},
222 {0x1, 0, 0, 0},
223 {0x1, 0, 0, 0},
224 {0x1, 0, 0, 0} },
225 SPEED_BIN_DDR_1600K, /* speed_bin */
226 BUS_WIDTH_16, /* memory_width */
227 MEM_8G, /* mem_size */
228 DDR_FREQ_800, /* frequency */
229 0, 0, /* cas_l cas_wl */
230 HWS_TEMP_NORMAL, /* temperature */
231 HWS_TIM_2T} }, /* timing (force 2t) */
232 5, /* Num Of Bus Per Interface*/
233 BUS_MASK_32BIT /* Busses mask */
234};
235
236struct hws_topology_map *ddr3_get_topology_map(void)
237{
238 static int mem = 0;
239 struct omnia_eeprom oep;
240
241 /* Get the board config from EEPROM */
242 if (mem == 0) {
243 if(!omnia_read_eeprom(&oep))
244 goto out;
245
246 printf("Memory config in EEPROM: 0x%02x\n", oep.ramsize);
247
248 if (oep.ramsize == 0x2)
249 mem = 2;
250 else
251 mem = 1;
252 }
253
254out:
255 /* Hardcoded fallback */
256 if (mem == 0) {
257 puts("WARNING: Memory config from EEPROM read failed.\n");
258 puts("Falling back to default 1GiB map.\n");
259 mem = 1;
260 }
261
262 /* Return the board topology as defined in the board code */
263 if (mem == 1)
264 return &board_topology_map_1g;
265 if (mem == 2)
266 return &board_topology_map_2g;
267
268 return &board_topology_map_1g;
269}
270
271#ifndef CONFIG_SPL_BUILD
272static int set_regdomain(void)
273{
274 struct omnia_eeprom oep;
275 char rd[3] = {' ', ' ', 0};
276
277 if (omnia_read_eeprom(&oep))
278 memcpy(rd, &oep.region, 2);
279 else
280 puts("EEPROM regdomain read failed.\n");
281
282 printf("Regdomain set to %s\n", rd);
283 return setenv("regdomain", rd);
284}
285#endif
286
287int board_early_init_f(void)
288{
289 u32 i2c_debug_reg;
290
291 /* Configure MPP */
292 writel(0x11111111, MVEBU_MPP_BASE + 0x00);
293 writel(0x11111111, MVEBU_MPP_BASE + 0x04);
294 writel(0x11244011, MVEBU_MPP_BASE + 0x08);
295 writel(0x22222111, MVEBU_MPP_BASE + 0x0c);
296 writel(0x22200002, MVEBU_MPP_BASE + 0x10);
297 writel(0x30042022, MVEBU_MPP_BASE + 0x14);
298 writel(0x55550555, MVEBU_MPP_BASE + 0x18);
299 writel(0x00005550, MVEBU_MPP_BASE + 0x1c);
300
301 /* Set GPP Out value */
302 writel(OMNIA_GPP_OUT_VAL_LOW, MVEBU_GPIO0_BASE + 0x00);
303 writel(OMNIA_GPP_OUT_VAL_MID, MVEBU_GPIO1_BASE + 0x00);
304
305 /* Set GPP Polarity */
306 writel(OMNIA_GPP_POL_LOW, MVEBU_GPIO0_BASE + 0x0c);
307 writel(OMNIA_GPP_POL_MID, MVEBU_GPIO1_BASE + 0x0c);
308
309 /* Set GPP Out Enable */
310 writel(OMNIA_GPP_OUT_ENA_LOW, MVEBU_GPIO0_BASE + 0x04);
311 writel(OMNIA_GPP_OUT_ENA_MID, MVEBU_GPIO1_BASE + 0x04);
312
313 /* Disable I2C debug mode blocking 0x64 I2C address */
314 i2c_debug_reg = readl(MVEBU_TWSI_BASE + MVTWSI_ARMADA_DEBUG_REG);
315 i2c_debug_reg &= ~(1<<18);
316 writel(i2c_debug_reg, MVEBU_TWSI_BASE + MVTWSI_ARMADA_DEBUG_REG);
317
318 return 0;
319}
320
321#ifndef CONFIG_SPL_BUILD
322static bool disable_mcu_watchdog(void)
323{
324 struct udevice *bus, *dev;
325 int ret, retry = 3;
326 uchar buf[1] = {0x0};
327
328 if (uclass_get_device_by_name(UCLASS_I2C, OMNIA_I2C_MCU_DM_NAME, &bus)) {
329 puts("Cannot find MCU bus! Can not disable MCU WDT.\n");
330 return false;
331 }
332
333 ret = i2c_get_chip(bus, OMNIA_I2C_MCU, 1, &dev);
334 if (ret) {
335 puts("Cannot get MCU chip! Can not disable MCU WDT.\n");
336 return false;
337 }
338
339 for (; retry > 0; --retry)
340 if (!dm_i2c_write(dev, OMNIA_I2C_MCU_WDT_ADDR, (uchar *) buf, 1))
341 break;
342
343 if (retry <= 0) {
344 puts("I2C MCU watchdog failed to disable!\n");
345 return false;
346 }
347
348 return true;
349}
350#endif
351
352#if !defined(CONFIG_SPL_BUILD) && defined(CONFIG_WDT_ORION)
353static struct udevice *watchdog_dev = NULL;
354#endif
355
356int board_init(void)
357{
358 /* adress of boot parameters */
359 gd->bd->bi_boot_params = mvebu_sdram_bar(0) + 0x100;
360
361#ifndef CONFIG_SPL_BUILD
362# ifdef CONFIG_WDT_ORION
363 if (uclass_get_device(UCLASS_WDT, 0, &watchdog_dev)) {
364 puts("Cannot find Armada 385 watchdog!\n");
365 } else {
366 puts("Enabling Armada 385 watchdog.\n");
367 wdt_start(watchdog_dev, (u32) 25000000 * 120, 0);
368 }
369# endif
370
371 if (disable_mcu_watchdog())
372 puts("Disabled MCU startup watchdog.\n");
373
374 set_regdomain();
375#endif
376
377 return 0;
378}
379
380#ifdef CONFIG_WATCHDOG
381/* Called by macro WATCHDOG_RESET */
382void watchdog_reset(void)
383{
384# if !defined(CONFIG_SPL_BUILD) && defined(CONFIG_WDT_ORION)
385 static ulong next_reset = 0;
386 ulong now;
387
388 if (!watchdog_dev)
389 return;
390
391 now = timer_get_us();
392
393 /* Do not reset the watchdog too often */
394 if (now > next_reset) {
395 wdt_reset(watchdog_dev);
396 next_reset = now + 1000;
397 }
398# endif
399}
400#endif
401
402int board_late_init(void)
403{
404#ifndef CONFIG_SPL_BUILD
405 set_regdomain();
406#endif
407
408 return 0;
409}
410
411#ifdef CONFIG_ATSHA204A
412static struct udevice *get_atsha204a_dev(void)
413{
414 static struct udevice *dev = NULL;
415
416 if (dev != NULL)
417 return dev;
418
419 if (uclass_get_device_by_name(UCLASS_MISC, "atsha204a@64", &dev)) {
420 puts("Cannot find ATSHA204A on I2C bus!\n");
421 dev = NULL;
422 }
423
424 return dev;
425}
426#endif
427
428int checkboard(void)
429{
430 u32 version_num, serial_num;
431 int err = 1;
432
433#ifdef CONFIG_ATSHA204A
434 struct udevice *dev = get_atsha204a_dev();
435
436 if (dev) {
437 err = atsha204a_wakeup(dev);
438 if (err)
439 goto out;
440
441 err = atsha204a_read(dev, ATSHA204A_ZONE_OTP, false,
442 OMNIA_ATSHA204_OTP_VERSION,
443 (u8 *) &version_num);
444 if (err)
445 goto out;
446
447 err = atsha204a_read(dev, ATSHA204A_ZONE_OTP, false,
448 OMNIA_ATSHA204_OTP_SERIAL,
449 (u8 *) &serial_num);
450 if (err)
451 goto out;
452
453 atsha204a_sleep(dev);
454 }
455
456out:
457#endif
458
459 if (err)
460 printf("Board: Turris Omnia (ver N/A). SN: N/A\n");
461 else
462 printf("Board: Turris Omnia SNL %08X%08X\n",
463 be32_to_cpu(version_num), be32_to_cpu(serial_num));
464
465 return 0;
466}
467
468static void increment_mac(u8 *mac)
469{
470 int i;
471
472 for (i = 5; i >= 3; i--) {
473 mac[i] += 1;
474 if (mac[i])
475 break;
476 }
477}
478
479int misc_init_r(void)
480{
481#ifdef CONFIG_ATSHA204A
482 int err;
483 struct udevice *dev = get_atsha204a_dev();
484 u8 mac0[4], mac1[4], mac[6];
485
486 if (!dev)
487 goto out;
488
489 err = atsha204a_wakeup(dev);
490 if (err)
491 goto out;
492
493 err = atsha204a_read(dev, ATSHA204A_ZONE_OTP, false,
494 OMNIA_ATSHA204_OTP_MAC0, mac0);
495 if (err)
496 goto out;
497
498 err = atsha204a_read(dev, ATSHA204A_ZONE_OTP, false,
499 OMNIA_ATSHA204_OTP_MAC1, mac1);
500 if (err)
501 goto out;
502
503 atsha204a_sleep(dev);
504
505 mac[0] = mac0[1];
506 mac[1] = mac0[2];
507 mac[2] = mac0[3];
508 mac[3] = mac1[1];
509 mac[4] = mac1[2];
510 mac[5] = mac1[3];
511
512 if (is_valid_ethaddr(mac))
513 eth_setenv_enetaddr("ethaddr", mac);
514
515 increment_mac(mac);
516
517 if (is_valid_ethaddr(mac))
518 eth_setenv_enetaddr("eth1addr", mac);
519
520 increment_mac(mac);
521
522 if (is_valid_ethaddr(mac))
523 eth_setenv_enetaddr("eth2addr", mac);
524
525out:
526#endif
527
528 return 0;
529}
530