Marek Behún | f835bed | 2018-04-24 17:21:31 +0200 | [diff] [blame] | 1 | // SPDX-License-Identifier: GPL-2.0+ |
| 2 | /* |
| 3 | * Copyright (C) 2018 Marek Behun <marek.behun@nic.cz> |
| 4 | */ |
| 5 | |
| 6 | #include <common.h> |
| 7 | #include <dm.h> |
| 8 | #include <clk.h> |
| 9 | #include <spi.h> |
| 10 | #include <linux/string.h> |
| 11 | |
Marek Behún | ceb0593 | 2018-08-17 12:58:53 +0200 | [diff] [blame^] | 12 | #ifdef CONFIG_WDT_ARMADA_37XX |
Marek Behún | f835bed | 2018-04-24 17:21:31 +0200 | [diff] [blame] | 13 | #include <wdt.h> |
| 14 | #endif |
| 15 | |
| 16 | DECLARE_GLOBAL_DATA_PTR; |
| 17 | |
Marek Behún | ceb0593 | 2018-08-17 12:58:53 +0200 | [diff] [blame^] | 18 | #ifdef CONFIG_WDT_ARMADA_37XX |
Marek Behún | f835bed | 2018-04-24 17:21:31 +0200 | [diff] [blame] | 19 | static struct udevice *watchdog_dev; |
| 20 | |
| 21 | void watchdog_reset(void) |
| 22 | { |
| 23 | static ulong next_reset; |
| 24 | ulong now; |
| 25 | |
| 26 | if (!watchdog_dev) |
| 27 | return; |
| 28 | |
| 29 | now = timer_get_us(); |
| 30 | |
| 31 | /* Do not reset the watchdog too often */ |
| 32 | if (now > next_reset) { |
| 33 | wdt_reset(watchdog_dev); |
| 34 | next_reset = now + 100000; |
| 35 | } |
| 36 | } |
| 37 | #endif |
| 38 | |
| 39 | int board_init(void) |
| 40 | { |
| 41 | /* address of boot parameters */ |
| 42 | gd->bd->bi_boot_params = CONFIG_SYS_SDRAM_BASE + 0x100; |
| 43 | |
Marek Behún | ceb0593 | 2018-08-17 12:58:53 +0200 | [diff] [blame^] | 44 | #ifdef CONFIG_WDT_ARMADA_37XX |
Marek Behún | f835bed | 2018-04-24 17:21:31 +0200 | [diff] [blame] | 45 | if (uclass_get_device(UCLASS_WDT, 0, &watchdog_dev)) { |
| 46 | printf("Cannot find Armada 3720 watchdog!\n"); |
| 47 | } else { |
| 48 | printf("Enabling Armada 3720 watchdog (3 minutes timeout).\n"); |
| 49 | wdt_start(watchdog_dev, 180000, 0); |
| 50 | } |
| 51 | #endif |
| 52 | |
| 53 | return 0; |
| 54 | } |
| 55 | |
| 56 | int last_stage_init(void) |
| 57 | { |
| 58 | struct spi_slave *slave; |
| 59 | struct udevice *dev; |
| 60 | u8 din[10], dout[10]; |
| 61 | int ret, i; |
| 62 | size_t len = 0; |
| 63 | char module_topology[128]; |
| 64 | |
| 65 | ret = spi_get_bus_and_cs(0, 1, 20000000, SPI_CPHA, "spi_generic_drv", |
| 66 | "mox-modules@1", &dev, &slave); |
| 67 | if (ret) |
| 68 | goto fail; |
| 69 | |
| 70 | ret = spi_claim_bus(slave); |
| 71 | if (ret) |
| 72 | goto fail_free; |
| 73 | |
| 74 | memset(din, 0, 10); |
| 75 | memset(dout, 0, 10); |
| 76 | |
| 77 | ret = spi_xfer(slave, 80, dout, din, SPI_XFER_ONCE); |
| 78 | if (ret) |
| 79 | goto fail_release; |
| 80 | |
| 81 | if (din[0] != 0x00 && din[0] != 0xff) |
| 82 | goto fail_release; |
| 83 | |
| 84 | printf("Module Topology:\n"); |
| 85 | for (i = 1; i < 10 && din[i] != 0xff; ++i) { |
| 86 | u8 mid = din[i] & 0xf; |
| 87 | size_t mlen; |
| 88 | const char *mname = ""; |
| 89 | |
| 90 | switch (mid) { |
| 91 | case 0x1: |
| 92 | mname = "sfp-"; |
| 93 | printf("% 4i: SFP Module\n", i); |
| 94 | break; |
| 95 | case 0x2: |
| 96 | mname = "pci-"; |
| 97 | printf("% 4i: Mini-PCIe Module\n", i); |
| 98 | break; |
| 99 | case 0x3: |
| 100 | mname = "topaz-"; |
| 101 | printf("% 4i: Topaz Switch Module\n", i); |
| 102 | break; |
| 103 | default: |
| 104 | printf("% 4i: unknown (ID %i)\n", i, mid); |
| 105 | } |
| 106 | |
| 107 | mlen = strlen(mname); |
| 108 | if (len + mlen < sizeof(module_topology)) { |
| 109 | strcpy(module_topology + len, mname); |
| 110 | len += mlen; |
| 111 | } |
| 112 | } |
| 113 | printf("\n"); |
| 114 | |
| 115 | module_topology[len > 0 ? len - 1 : 0] = '\0'; |
| 116 | |
| 117 | env_set("module_topology", module_topology); |
| 118 | |
| 119 | fail_release: |
| 120 | spi_release_bus(slave); |
| 121 | fail_free: |
| 122 | spi_free_slave(slave); |
| 123 | fail: |
| 124 | if (ret) |
| 125 | printf("Cannot read module topology!\n"); |
| 126 | return ret; |
| 127 | } |