uboot/arch/arm/mach-socfpga/wrap_handoff_soc64.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0
   2/*
   3 * Copyright (C) 2020-2021 Intel Corporation <www.intel.com>
   4 *
   5 */
   6
   7#include <asm/arch/handoff_soc64.h>
   8#include <asm/io.h>
   9#include <common.h>
  10#include <errno.h>
  11#include "log.h"
  12
  13static enum endianness check_endianness(u32 handoff)
  14{
  15        switch (handoff) {
  16        case SOC64_HANDOFF_MAGIC_BOOT:
  17        case SOC64_HANDOFF_MAGIC_MUX:
  18        case SOC64_HANDOFF_MAGIC_IOCTL:
  19        case SOC64_HANDOFF_MAGIC_FPGA:
  20        case SOC64_HANDOFF_MAGIC_DELAY:
  21        case SOC64_HANDOFF_MAGIC_CLOCK:
  22        case SOC64_HANDOFF_MAGIC_MISC:
  23                return BIG_ENDIAN;
  24#if IS_ENABLED(CONFIG_TARGET_SOCFPGA_N5X)
  25        case SOC64_HANDOFF_DDR_UMCTL2_MAGIC:
  26                debug("%s: umctl2 handoff data\n", __func__);
  27                return LITTLE_ENDIAN;
  28        case SOC64_HANDOFF_DDR_PHY_MAGIC:
  29                debug("%s: PHY handoff data\n", __func__);
  30                return LITTLE_ENDIAN;
  31        case SOC64_HANDOFF_DDR_PHY_INIT_ENGINE_MAGIC:
  32                debug("%s: PHY engine handoff data\n", __func__);
  33                return LITTLE_ENDIAN;
  34#endif
  35        default:
  36                debug("%s: Unknown endianness!!\n", __func__);
  37                return UNKNOWN_ENDIANNESS;
  38        }
  39}
  40
  41static int getting_endianness(void *handoff_address, enum endianness *endian_t)
  42{
  43        /* Checking handoff data is little endian ? */
  44        *endian_t = check_endianness(readl(handoff_address));
  45
  46        if (*endian_t == UNKNOWN_ENDIANNESS) {
  47                /* Trying to check handoff data is big endian? */
  48                *endian_t = check_endianness(swab32(readl(handoff_address)));
  49                if (*endian_t == UNKNOWN_ENDIANNESS) {
  50                        debug("%s: Cannot find HANDOFF MAGIC ", __func__);
  51                        debug("at addr 0x%p\n", (u32 *)handoff_address);
  52                        return -EPERM;
  53                }
  54        }
  55
  56        return 0;
  57}
  58
  59int socfpga_get_handoff_size(void *handoff_address)
  60{
  61        u32 size;
  62        int ret;
  63        enum endianness endian_t;
  64
  65        ret = getting_endianness(handoff_address, &endian_t);
  66        if (ret)
  67                return ret;
  68
  69        size = readl(handoff_address + SOC64_HANDOFF_OFFSET_LENGTH);
  70        if (endian_t == BIG_ENDIAN)
  71                size = swab32(size);
  72
  73        size = (size - SOC64_HANDOFF_OFFSET_DATA) / sizeof(u32);
  74
  75        debug("%s: handoff address = 0x%p handoff size = 0x%08x\n", __func__,
  76              (u32 *)handoff_address, size);
  77
  78        return size;
  79}
  80
  81int socfpga_handoff_read(void *handoff_address, void *table, u32 table_len)
  82{
  83        u32 temp;
  84        u32 *table_x32 = table;
  85        u32 i = 0;
  86        int ret;
  87        enum endianness endian_t;
  88
  89        ret = getting_endianness(handoff_address, &endian_t);
  90        if (ret)
  91                return ret;
  92
  93        temp = readl(handoff_address + SOC64_HANDOFF_OFFSET_DATA +
  94                    (i * sizeof(u32)));
  95
  96        if (endian_t == BIG_ENDIAN) {
  97                debug("%s: Handoff addr = 0x%p ", __func__, (u32 *)handoff_address);
  98                debug("Handoff table address = 0x%p ", table_x32);
  99                debug("table length = 0x%x\n", table_len);
 100                debug("%s: handoff data =\n{\n", __func__);
 101                *table_x32 = swab32(temp);
 102        } else if (endian_t == LITTLE_ENDIAN) {
 103                debug(" {\n");
 104                *table_x32 = temp;
 105        }
 106
 107        debug(" No.%d Addr 0x%08x: ", i, *table_x32);
 108
 109        for (i = 1; i < table_len; i++) {
 110                table_x32++;
 111
 112                temp = readl(handoff_address +
 113                             SOC64_HANDOFF_OFFSET_DATA +
 114                             (i * sizeof(u32)));
 115
 116                if (endian_t == BIG_ENDIAN)
 117                        *table_x32 = swab32(temp);
 118                else if (endian_t == LITTLE_ENDIAN)
 119                        *table_x32 = temp;
 120
 121                if (!(i % 2))
 122                        debug(" No.%d Addr 0x%08x: ", i,
 123                              *table_x32);
 124                else
 125                        debug(" 0x%08x\n", *table_x32);
 126        }
 127        debug("\n}\n");
 128
 129        return 0;
 130}
 131