blob: af43ee23d97c6e018980fe4c56b5b56aa21ff964 [file] [log] [blame]
Tom Rini10e47792018-05-06 17:58:06 -04001// SPDX-License-Identifier: GPL-2.0+
Marek Behún09e16b82017-06-09 19:28:45 +02002/*
3 * Copyright (C) 2017 Marek Behun <marek.behun@nic.cz>
4 * Copyright (C) 2016 Tomas Hlavacek <tomas.hlavacek@nic.cz>
5 *
6 * Derived from the code for
7 * Marvell/db-88f6820-gp by Stefan Roese <sr@denx.de>
Marek Behún09e16b82017-06-09 19:28:45 +02008 */
9
10#include <common.h>
Alex Kiernan9c215492018-04-01 09:22:38 +000011#include <environment.h>
Marek Behún09e16b82017-06-09 19:28:45 +020012#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>
Marek Behún09e16b82017-06-09 19:28:45 +020021# include <atsha204a-i2c.h>
Marek Behún09e16b82017-06-09 19:28:45 +020022
Chris Packham1a07d212018-05-10 13:28:29 +120023#include "../drivers/ddr/marvell/a38x/ddr3_init.h"
Marek Behún09e16b82017-06-09 19:28:45 +020024#include <../serdes/a38x/high_speed_env_spec.h>
25
26DECLARE_GLOBAL_DATA_PTR;
27
Marek Behúnba53b6b2019-05-02 16:53:30 +020028#define OMNIA_I2C_BUS_NAME "i2c@11000->i2cmux@70->i2c@0"
29
30#define OMNIA_I2C_MCU_CHIP_ADDR 0x2a
31#define OMNIA_I2C_MCU_CHIP_LEN 1
32
33#define OMNIA_I2C_EEPROM_CHIP_ADDR 0x54
34#define OMNIA_I2C_EEPROM_CHIP_LEN 2
Marek Behún09e16b82017-06-09 19:28:45 +020035#define OMNIA_I2C_EEPROM_MAGIC 0x0341a034
36
Marek Behúnba53b6b2019-05-02 16:53:30 +020037enum mcu_commands {
38 CMD_GET_STATUS_WORD = 0x01,
39 CMD_GET_RESET = 0x09,
40 CMD_WATCHDOG_STATE = 0x0b,
41};
42
43enum status_word_bits {
44 CARD_DET_STSBIT = 0x0010,
45 MSATA_IND_STSBIT = 0x0020,
46};
Marek Behún09e16b82017-06-09 19:28:45 +020047
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
Marek Behún09e16b82017-06-09 19:28:45 +020053/*
54 * Those values and defines are taken from the Marvell U-Boot version
55 * "u-boot-2013.01-2014_T3.0"
56 */
57#define OMNIA_GPP_OUT_ENA_LOW \
58 (~(BIT(1) | BIT(4) | BIT(6) | BIT(7) | BIT(8) | BIT(9) | \
59 BIT(10) | BIT(11) | BIT(19) | BIT(22) | BIT(23) | BIT(25) | \
60 BIT(26) | BIT(27) | BIT(29) | BIT(30) | BIT(31)))
61#define OMNIA_GPP_OUT_ENA_MID \
62 (~(BIT(0) | BIT(1) | BIT(2) | BIT(3) | BIT(4) | BIT(15) | \
63 BIT(16) | BIT(17) | BIT(18)))
64
65#define OMNIA_GPP_OUT_VAL_LOW 0x0
66#define OMNIA_GPP_OUT_VAL_MID 0x0
67#define OMNIA_GPP_POL_LOW 0x0
68#define OMNIA_GPP_POL_MID 0x0
69
70static struct serdes_map board_serdes_map_pex[] = {
71 {PEX0, SERDES_SPEED_5_GBPS, PEX_ROOT_COMPLEX_X1, 0, 0},
72 {USB3_HOST0, SERDES_SPEED_5_GBPS, SERDES_DEFAULT_MODE, 0, 0},
73 {PEX1, SERDES_SPEED_5_GBPS, PEX_ROOT_COMPLEX_X1, 0, 0},
74 {USB3_HOST1, SERDES_SPEED_5_GBPS, SERDES_DEFAULT_MODE, 0, 0},
75 {PEX2, SERDES_SPEED_5_GBPS, PEX_ROOT_COMPLEX_X1, 0, 0},
76 {SGMII2, SERDES_SPEED_1_25_GBPS, SERDES_DEFAULT_MODE, 0, 0}
77};
78
79static struct serdes_map board_serdes_map_sata[] = {
80 {SATA0, SERDES_SPEED_6_GBPS, SERDES_DEFAULT_MODE, 0, 0},
81 {USB3_HOST0, SERDES_SPEED_5_GBPS, SERDES_DEFAULT_MODE, 0, 0},
82 {PEX1, SERDES_SPEED_5_GBPS, PEX_ROOT_COMPLEX_X1, 0, 0},
83 {USB3_HOST1, SERDES_SPEED_5_GBPS, SERDES_DEFAULT_MODE, 0, 0},
84 {PEX2, SERDES_SPEED_5_GBPS, PEX_ROOT_COMPLEX_X1, 0, 0},
85 {SGMII2, SERDES_SPEED_1_25_GBPS, SERDES_DEFAULT_MODE, 0, 0}
86};
87
Marek Behúnba53b6b2019-05-02 16:53:30 +020088static struct udevice *omnia_get_i2c_chip(const char *name, uint addr,
89 uint offset_len)
Marek Behún09e16b82017-06-09 19:28:45 +020090{
91 struct udevice *bus, *dev;
Marek Behúnba53b6b2019-05-02 16:53:30 +020092 int ret;
Marek Behún09e16b82017-06-09 19:28:45 +020093
Marek Behúnba53b6b2019-05-02 16:53:30 +020094 ret = uclass_get_device_by_name(UCLASS_I2C, OMNIA_I2C_BUS_NAME, &bus);
95 if (ret) {
96 printf("Cannot get I2C bus %s: uclass_get_device_by_name failed: %i\n",
97 OMNIA_I2C_BUS_NAME, ret);
98 return NULL;
Marek Behún09e16b82017-06-09 19:28:45 +020099 }
100
Marek Behúnba53b6b2019-05-02 16:53:30 +0200101 ret = i2c_get_chip(bus, addr, offset_len, &dev);
Marek Behún09e16b82017-06-09 19:28:45 +0200102 if (ret) {
Marek Behúnba53b6b2019-05-02 16:53:30 +0200103 printf("Cannot get %s I2C chip: i2c_get_chip failed: %i\n",
104 name, ret);
105 return NULL;
Marek Behún09e16b82017-06-09 19:28:45 +0200106 }
107
Marek Behúnba53b6b2019-05-02 16:53:30 +0200108 return dev;
109}
Marek Behúnd0b374d2017-08-04 15:28:25 +0200110
Marek Behúnba53b6b2019-05-02 16:53:30 +0200111static int omnia_mcu_read(u8 cmd, void *buf, int len)
112{
113 struct udevice *chip;
114
115 chip = omnia_get_i2c_chip("MCU", OMNIA_I2C_MCU_CHIP_ADDR,
116 OMNIA_I2C_MCU_CHIP_LEN);
117 if (!chip)
118 return -ENODEV;
119
120 return dm_i2c_read(chip, cmd, buf, len);
121}
122
123#ifndef CONFIG_SPL_BUILD
124static int omnia_mcu_write(u8 cmd, const void *buf, int len)
125{
126 struct udevice *chip;
127
128 chip = omnia_get_i2c_chip("MCU", OMNIA_I2C_MCU_CHIP_ADDR,
129 OMNIA_I2C_MCU_CHIP_LEN);
130 if (!chip)
131 return -ENODEV;
132
133 return dm_i2c_write(chip, cmd, buf, len);
134}
135
136static bool disable_mcu_watchdog(void)
137{
138 int ret;
139
140 puts("Disabling MCU watchdog... ");
141
142 ret = omnia_mcu_write(CMD_WATCHDOG_STATE, "\x00", 1);
143 if (ret) {
144 printf("omnia_mcu_write failed: %i\n", ret);
Marek Behún09e16b82017-06-09 19:28:45 +0200145 return false;
146 }
147
Marek Behúnba53b6b2019-05-02 16:53:30 +0200148 puts("disabled\n");
149
150 return true;
151}
152#endif
153
154static bool omnia_detect_sata(void)
155{
156 int ret;
157 u16 stsword;
158
159 puts("MiniPCIe/mSATA card detection... ");
160
161 ret = omnia_mcu_read(CMD_GET_STATUS_WORD, &stsword, sizeof(stsword));
162 if (ret) {
163 printf("omnia_mcu_read failed: %i, defaulting to MiniPCIe card\n",
164 ret);
Marek Behún09e16b82017-06-09 19:28:45 +0200165 return false;
166 }
167
Marek Behúnba53b6b2019-05-02 16:53:30 +0200168 if (!(stsword & CARD_DET_STSBIT)) {
169 puts("none\n");
Marek Behún09e16b82017-06-09 19:28:45 +0200170 return false;
171 }
Marek Behúnba53b6b2019-05-02 16:53:30 +0200172
173 if (stsword & MSATA_IND_STSBIT)
174 puts("mSATA\n");
175 else
176 puts("MiniPCIe\n");
177
178 return stsword & MSATA_IND_STSBIT ? true : false;
Marek Behún09e16b82017-06-09 19:28:45 +0200179}
180
181int hws_board_topology_load(struct serdes_map **serdes_map_array, u8 *count)
182{
183 if (omnia_detect_sata()) {
184 *serdes_map_array = board_serdes_map_sata;
185 *count = ARRAY_SIZE(board_serdes_map_sata);
186 } else {
187 *serdes_map_array = board_serdes_map_pex;
188 *count = ARRAY_SIZE(board_serdes_map_pex);
189 }
190
191 return 0;
192}
193
194struct omnia_eeprom {
195 u32 magic;
196 u32 ramsize;
197 char region[4];
198 u32 crc;
199};
200
201static bool omnia_read_eeprom(struct omnia_eeprom *oep)
202{
Marek Behúnba53b6b2019-05-02 16:53:30 +0200203 struct udevice *chip;
204 u32 crc;
205 int ret;
Marek Behún09e16b82017-06-09 19:28:45 +0200206
Marek Behúnba53b6b2019-05-02 16:53:30 +0200207 chip = omnia_get_i2c_chip("EEPROM", OMNIA_I2C_EEPROM_CHIP_ADDR,
208 OMNIA_I2C_EEPROM_CHIP_LEN);
209
210 if (!chip)
Marek Behún09e16b82017-06-09 19:28:45 +0200211 return false;
Marek Behún09e16b82017-06-09 19:28:45 +0200212
Marek Behúnba53b6b2019-05-02 16:53:30 +0200213 ret = dm_i2c_read(chip, 0, (void *)oep, sizeof(*oep));
Marek Behún09e16b82017-06-09 19:28:45 +0200214 if (ret) {
Marek Behúnba53b6b2019-05-02 16:53:30 +0200215 printf("dm_i2c_read failed: %i, cannot read EEPROM\n", ret);
Marek Behún09e16b82017-06-09 19:28:45 +0200216 return false;
217 }
218
Marek Behúnba53b6b2019-05-02 16:53:30 +0200219 if (oep->magic != OMNIA_I2C_EEPROM_MAGIC) {
220 printf("bad EEPROM magic number (%08x, should be %08x)\n",
221 oep->magic, OMNIA_I2C_EEPROM_MAGIC);
222 return false;
Marek Behún09e16b82017-06-09 19:28:45 +0200223 }
224
Marek Behúnba53b6b2019-05-02 16:53:30 +0200225 crc = crc32(0, (void *)oep, sizeof(*oep) - 4);
226 if (crc != oep->crc) {
227 printf("bad EEPROM CRC (stored %08x, computed %08x)\n",
228 oep->crc, crc);
Marek Behún09e16b82017-06-09 19:28:45 +0200229 return false;
230 }
231
232 return true;
233}
234
Marek Behún77652c72019-05-02 16:53:33 +0200235static int omnia_get_ram_size_gb(void)
236{
237 static int ram_size;
238 struct omnia_eeprom oep;
239
240 if (!ram_size) {
241 /* Get the board config from EEPROM */
242 if (omnia_read_eeprom(&oep)) {
243 debug("Memory config in EEPROM: 0x%02x\n", oep.ramsize);
244
245 if (oep.ramsize == 0x2)
246 ram_size = 2;
247 else
248 ram_size = 1;
249 } else {
250 /* Hardcoded fallback */
251 puts("Memory config from EEPROM read failed!\n");
252 puts("Falling back to default 1 GiB!\n");
253 ram_size = 1;
254 }
255 }
256
257 return ram_size;
258}
259
Marek Behún09e16b82017-06-09 19:28:45 +0200260/*
261 * Define the DDR layout / topology here in the board file. This will
262 * be used by the DDR3 init code in the SPL U-Boot version to configure
263 * the DDR3 controller.
264 */
Chris Packham1a07d212018-05-10 13:28:29 +1200265static struct mv_ddr_topology_map board_topology_map_1g = {
266 DEBUG_LEVEL_ERROR,
Marek Behún09e16b82017-06-09 19:28:45 +0200267 0x1, /* active interfaces */
268 /* cs_mask, mirror, dqs_swap, ck_swap X PUPs */
269 { { { {0x1, 0, 0, 0},
270 {0x1, 0, 0, 0},
271 {0x1, 0, 0, 0},
272 {0x1, 0, 0, 0},
273 {0x1, 0, 0, 0} },
274 SPEED_BIN_DDR_1600K, /* speed_bin */
Chris Packham1a07d212018-05-10 13:28:29 +1200275 MV_DDR_DEV_WIDTH_16BIT, /* memory_width */
276 MV_DDR_DIE_CAP_4GBIT, /* mem_size */
Chris Packham4bf81db2018-12-03 14:26:49 +1300277 MV_DDR_FREQ_800, /* frequency */
Chris Packhamdd092bd2017-11-29 10:38:34 +1300278 0, 0, /* cas_wl cas_l */
Chris Packham3a09e132018-05-10 13:28:30 +1200279 MV_DDR_TEMP_NORMAL, /* temperature */
280 MV_DDR_TIM_2T} }, /* timing */
Chris Packham1a07d212018-05-10 13:28:29 +1200281 BUS_MASK_32BIT, /* Busses mask */
282 MV_DDR_CFG_DEFAULT, /* ddr configuration data source */
283 { {0} }, /* raw spd data */
284 {0} /* timing parameters */
Marek Behún09e16b82017-06-09 19:28:45 +0200285};
286
Chris Packham1a07d212018-05-10 13:28:29 +1200287static struct mv_ddr_topology_map board_topology_map_2g = {
288 DEBUG_LEVEL_ERROR,
Marek Behún09e16b82017-06-09 19:28:45 +0200289 0x1, /* active interfaces */
290 /* cs_mask, mirror, dqs_swap, ck_swap X PUPs */
291 { { { {0x1, 0, 0, 0},
292 {0x1, 0, 0, 0},
293 {0x1, 0, 0, 0},
294 {0x1, 0, 0, 0},
295 {0x1, 0, 0, 0} },
296 SPEED_BIN_DDR_1600K, /* speed_bin */
Chris Packham1a07d212018-05-10 13:28:29 +1200297 MV_DDR_DEV_WIDTH_16BIT, /* memory_width */
298 MV_DDR_DIE_CAP_8GBIT, /* mem_size */
Chris Packham4bf81db2018-12-03 14:26:49 +1300299 MV_DDR_FREQ_800, /* frequency */
Chris Packhamdd092bd2017-11-29 10:38:34 +1300300 0, 0, /* cas_wl cas_l */
Chris Packham3a09e132018-05-10 13:28:30 +1200301 MV_DDR_TEMP_NORMAL, /* temperature */
302 MV_DDR_TIM_2T} }, /* timing */
Chris Packham1a07d212018-05-10 13:28:29 +1200303 BUS_MASK_32BIT, /* Busses mask */
304 MV_DDR_CFG_DEFAULT, /* ddr configuration data source */
305 { {0} }, /* raw spd data */
306 {0} /* timing parameters */
Marek Behún09e16b82017-06-09 19:28:45 +0200307};
308
Chris Packham1a07d212018-05-10 13:28:29 +1200309struct mv_ddr_topology_map *mv_ddr_topology_map_get(void)
Marek Behún09e16b82017-06-09 19:28:45 +0200310{
Marek Behún77652c72019-05-02 16:53:33 +0200311 if (omnia_get_ram_size_gb() == 2)
Marek Behún09e16b82017-06-09 19:28:45 +0200312 return &board_topology_map_2g;
Marek Behún77652c72019-05-02 16:53:33 +0200313 else
314 return &board_topology_map_1g;
Marek Behún09e16b82017-06-09 19:28:45 +0200315}
316
317#ifndef CONFIG_SPL_BUILD
318static int set_regdomain(void)
319{
320 struct omnia_eeprom oep;
321 char rd[3] = {' ', ' ', 0};
322
323 if (omnia_read_eeprom(&oep))
324 memcpy(rd, &oep.region, 2);
325 else
326 puts("EEPROM regdomain read failed.\n");
327
328 printf("Regdomain set to %s\n", rd);
Simon Glass6a38e412017-08-03 12:22:09 -0600329 return env_set("regdomain", rd);
Marek Behún09e16b82017-06-09 19:28:45 +0200330}
331#endif
332
333int board_early_init_f(void)
334{
Marek Behún09e16b82017-06-09 19:28:45 +0200335 /* Configure MPP */
336 writel(0x11111111, MVEBU_MPP_BASE + 0x00);
337 writel(0x11111111, MVEBU_MPP_BASE + 0x04);
338 writel(0x11244011, MVEBU_MPP_BASE + 0x08);
339 writel(0x22222111, MVEBU_MPP_BASE + 0x0c);
340 writel(0x22200002, MVEBU_MPP_BASE + 0x10);
341 writel(0x30042022, MVEBU_MPP_BASE + 0x14);
342 writel(0x55550555, MVEBU_MPP_BASE + 0x18);
343 writel(0x00005550, MVEBU_MPP_BASE + 0x1c);
344
345 /* Set GPP Out value */
346 writel(OMNIA_GPP_OUT_VAL_LOW, MVEBU_GPIO0_BASE + 0x00);
347 writel(OMNIA_GPP_OUT_VAL_MID, MVEBU_GPIO1_BASE + 0x00);
348
349 /* Set GPP Polarity */
350 writel(OMNIA_GPP_POL_LOW, MVEBU_GPIO0_BASE + 0x0c);
351 writel(OMNIA_GPP_POL_MID, MVEBU_GPIO1_BASE + 0x0c);
352
353 /* Set GPP Out Enable */
354 writel(OMNIA_GPP_OUT_ENA_LOW, MVEBU_GPIO0_BASE + 0x04);
355 writel(OMNIA_GPP_OUT_ENA_MID, MVEBU_GPIO1_BASE + 0x04);
356
Marek Behún09e16b82017-06-09 19:28:45 +0200357 return 0;
358}
359
Marek Behún09e16b82017-06-09 19:28:45 +0200360int board_init(void)
361{
Marek Behún4dfc57e2019-05-02 16:53:31 +0200362 /* address of boot parameters */
Marek Behún09e16b82017-06-09 19:28:45 +0200363 gd->bd->bi_boot_params = mvebu_sdram_bar(0) + 0x100;
364
365#ifndef CONFIG_SPL_BUILD
Marek Behúnba53b6b2019-05-02 16:53:30 +0200366 disable_mcu_watchdog();
Marek Behún09e16b82017-06-09 19:28:45 +0200367#endif
368
369 return 0;
370}
Marek Behún09e16b82017-06-09 19:28:45 +0200371
372int board_late_init(void)
373{
374#ifndef CONFIG_SPL_BUILD
375 set_regdomain();
376#endif
377
378 return 0;
379}
380
Marek Behún09e16b82017-06-09 19:28:45 +0200381static struct udevice *get_atsha204a_dev(void)
382{
Marek Behún4dfc57e2019-05-02 16:53:31 +0200383 static struct udevice *dev;
Marek Behún09e16b82017-06-09 19:28:45 +0200384
Marek Behún4dfc57e2019-05-02 16:53:31 +0200385 if (dev)
Marek Behún09e16b82017-06-09 19:28:45 +0200386 return dev;
387
388 if (uclass_get_device_by_name(UCLASS_MISC, "atsha204a@64", &dev)) {
389 puts("Cannot find ATSHA204A on I2C bus!\n");
390 dev = NULL;
391 }
392
393 return dev;
394}
Marek Behún09e16b82017-06-09 19:28:45 +0200395
396int checkboard(void)
397{
398 u32 version_num, serial_num;
399 int err = 1;
400
Marek Behún09e16b82017-06-09 19:28:45 +0200401 struct udevice *dev = get_atsha204a_dev();
402
403 if (dev) {
404 err = atsha204a_wakeup(dev);
405 if (err)
406 goto out;
407
408 err = atsha204a_read(dev, ATSHA204A_ZONE_OTP, false,
409 OMNIA_ATSHA204_OTP_VERSION,
Marek Behún4dfc57e2019-05-02 16:53:31 +0200410 (u8 *)&version_num);
Marek Behún09e16b82017-06-09 19:28:45 +0200411 if (err)
412 goto out;
413
414 err = atsha204a_read(dev, ATSHA204A_ZONE_OTP, false,
415 OMNIA_ATSHA204_OTP_SERIAL,
Marek Behún4dfc57e2019-05-02 16:53:31 +0200416 (u8 *)&serial_num);
Marek Behún09e16b82017-06-09 19:28:45 +0200417 if (err)
418 goto out;
419
420 atsha204a_sleep(dev);
421 }
422
423out:
Marek Behúnc4ba72a2019-05-02 16:53:34 +0200424 printf("Turris Omnia:\n");
425 printf(" RAM size: %i MiB\n", omnia_get_ram_size_gb() * 1024);
Marek Behún09e16b82017-06-09 19:28:45 +0200426 if (err)
Marek Behúnc4ba72a2019-05-02 16:53:34 +0200427 printf(" Serial Number: unknown\n");
Marek Behún09e16b82017-06-09 19:28:45 +0200428 else
Marek Behúnc4ba72a2019-05-02 16:53:34 +0200429 printf(" Serial Number: %08X%08X\n", be32_to_cpu(version_num),
430 be32_to_cpu(serial_num));
Marek Behún09e16b82017-06-09 19:28:45 +0200431
432 return 0;
433}
434
435static void increment_mac(u8 *mac)
436{
437 int i;
438
439 for (i = 5; i >= 3; i--) {
440 mac[i] += 1;
441 if (mac[i])
442 break;
443 }
444}
445
446int misc_init_r(void)
447{
Marek Behún09e16b82017-06-09 19:28:45 +0200448 int err;
449 struct udevice *dev = get_atsha204a_dev();
450 u8 mac0[4], mac1[4], mac[6];
451
452 if (!dev)
453 goto out;
454
455 err = atsha204a_wakeup(dev);
456 if (err)
457 goto out;
458
459 err = atsha204a_read(dev, ATSHA204A_ZONE_OTP, false,
460 OMNIA_ATSHA204_OTP_MAC0, mac0);
461 if (err)
462 goto out;
463
464 err = atsha204a_read(dev, ATSHA204A_ZONE_OTP, false,
465 OMNIA_ATSHA204_OTP_MAC1, mac1);
466 if (err)
467 goto out;
468
469 atsha204a_sleep(dev);
470
471 mac[0] = mac0[1];
472 mac[1] = mac0[2];
473 mac[2] = mac0[3];
474 mac[3] = mac1[1];
475 mac[4] = mac1[2];
476 mac[5] = mac1[3];
477
478 if (is_valid_ethaddr(mac))
Simon Glass8551d552017-08-03 12:22:11 -0600479 eth_env_set_enetaddr("ethaddr", mac);
Marek Behún09e16b82017-06-09 19:28:45 +0200480
481 increment_mac(mac);
482
483 if (is_valid_ethaddr(mac))
Simon Glass8551d552017-08-03 12:22:11 -0600484 eth_env_set_enetaddr("eth1addr", mac);
Marek Behún09e16b82017-06-09 19:28:45 +0200485
486 increment_mac(mac);
487
488 if (is_valid_ethaddr(mac))
Simon Glass8551d552017-08-03 12:22:11 -0600489 eth_env_set_enetaddr("eth2addr", mac);
Marek Behún09e16b82017-06-09 19:28:45 +0200490
491out:
Marek Behún09e16b82017-06-09 19:28:45 +0200492 return 0;
493}
494