blob: 36a9908be91e68b994cde40cb688972190c769a0 [file] [log] [blame]
/*
* Copyright (c) 2017-2020, ARM Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include <assert.h>
#include <stdbool.h>
#include <stddef.h>
#include <lib/mmio.h>
#include <lib/utils_def.h>
#include "uniphier.h"
#define UNIPHIER_PINMON0 0x0
#define UNIPHIER_PINMON2 0x8
static const uintptr_t uniphier_pinmon_base[] = {
[UNIPHIER_SOC_LD11] = 0x5f900100,
[UNIPHIER_SOC_LD20] = 0x5f900100,
[UNIPHIER_SOC_PXS3] = 0x5f900100,
};
static bool uniphier_ld11_is_usb_boot(uint32_t pinmon)
{
return !!(~pinmon & 0x00000080);
}
static bool uniphier_ld20_is_usb_boot(uint32_t pinmon)
{
return !!(~pinmon & 0x00000780);
}
static bool uniphier_pxs3_is_usb_boot(uint32_t pinmon)
{
uintptr_t pinmon_base = uniphier_pinmon_base[UNIPHIER_SOC_PXS3];
uint32_t pinmon2 = mmio_read_32(pinmon_base + UNIPHIER_PINMON2);
return !!(pinmon2 & BIT(31));
}
static const unsigned int uniphier_ld11_boot_device_table[] = {
UNIPHIER_BOOT_DEVICE_NAND,
UNIPHIER_BOOT_DEVICE_NAND,
UNIPHIER_BOOT_DEVICE_NAND,
UNIPHIER_BOOT_DEVICE_NAND,
UNIPHIER_BOOT_DEVICE_NAND,
UNIPHIER_BOOT_DEVICE_NAND,
UNIPHIER_BOOT_DEVICE_NAND,
UNIPHIER_BOOT_DEVICE_NAND,
UNIPHIER_BOOT_DEVICE_NAND,
UNIPHIER_BOOT_DEVICE_NAND,
UNIPHIER_BOOT_DEVICE_NAND,
UNIPHIER_BOOT_DEVICE_NAND,
UNIPHIER_BOOT_DEVICE_NAND,
UNIPHIER_BOOT_DEVICE_NAND,
UNIPHIER_BOOT_DEVICE_NAND,
UNIPHIER_BOOT_DEVICE_NAND,
UNIPHIER_BOOT_DEVICE_NAND,
UNIPHIER_BOOT_DEVICE_NAND,
UNIPHIER_BOOT_DEVICE_NAND,
UNIPHIER_BOOT_DEVICE_NAND,
UNIPHIER_BOOT_DEVICE_NAND,
UNIPHIER_BOOT_DEVICE_NAND,
UNIPHIER_BOOT_DEVICE_NAND,
UNIPHIER_BOOT_DEVICE_NAND,
UNIPHIER_BOOT_DEVICE_EMMC,
UNIPHIER_BOOT_DEVICE_EMMC,
UNIPHIER_BOOT_DEVICE_EMMC,
UNIPHIER_BOOT_DEVICE_EMMC,
UNIPHIER_BOOT_DEVICE_EMMC,
UNIPHIER_BOOT_DEVICE_EMMC,
UNIPHIER_BOOT_DEVICE_EMMC,
UNIPHIER_BOOT_DEVICE_NOR,
};
static unsigned int uniphier_ld11_get_boot_device(uint32_t pinmon)
{
unsigned int boot_sel = (pinmon >> 1) & 0x1f;
assert(boot_sel < ARRAY_SIZE(uniphier_ld11_boot_device_table));
return uniphier_ld11_boot_device_table[boot_sel];
}
static const unsigned int uniphier_pxs3_boot_device_table[] = {
UNIPHIER_BOOT_DEVICE_NAND,
UNIPHIER_BOOT_DEVICE_NAND,
UNIPHIER_BOOT_DEVICE_NAND,
UNIPHIER_BOOT_DEVICE_NAND,
UNIPHIER_BOOT_DEVICE_NAND,
UNIPHIER_BOOT_DEVICE_NAND,
UNIPHIER_BOOT_DEVICE_NAND,
UNIPHIER_BOOT_DEVICE_NAND,
UNIPHIER_BOOT_DEVICE_EMMC,
UNIPHIER_BOOT_DEVICE_EMMC,
UNIPHIER_BOOT_DEVICE_EMMC,
UNIPHIER_BOOT_DEVICE_EMMC,
UNIPHIER_BOOT_DEVICE_EMMC,
UNIPHIER_BOOT_DEVICE_EMMC,
UNIPHIER_BOOT_DEVICE_NAND,
UNIPHIER_BOOT_DEVICE_NAND,
};
static unsigned int uniphier_pxs3_get_boot_device(uint32_t pinmon)
{
unsigned int boot_sel = (pinmon >> 1) & 0xf;
assert(boot_sel < ARRAY_SIZE(uniphier_pxs3_boot_device_table));
return uniphier_pxs3_boot_device_table[boot_sel];
}
struct uniphier_boot_device_info {
bool have_boot_swap;
bool (*is_sd_boot)(uint32_t pinmon);
bool (*is_usb_boot)(uint32_t pinmon);
unsigned int (*get_boot_device)(uint32_t pinmon);
};
static const struct uniphier_boot_device_info uniphier_boot_device_info[] = {
[UNIPHIER_SOC_LD11] = {
.have_boot_swap = true,
.is_usb_boot = uniphier_ld11_is_usb_boot,
.get_boot_device = uniphier_ld11_get_boot_device,
},
[UNIPHIER_SOC_LD20] = {
.have_boot_swap = true,
.is_usb_boot = uniphier_ld20_is_usb_boot,
.get_boot_device = uniphier_ld11_get_boot_device,
},
[UNIPHIER_SOC_PXS3] = {
.have_boot_swap = true,
.is_usb_boot = uniphier_pxs3_is_usb_boot,
.get_boot_device = uniphier_pxs3_get_boot_device,
},
};
unsigned int uniphier_get_boot_device(unsigned int soc)
{
const struct uniphier_boot_device_info *info;
uintptr_t pinmon_base;
uint32_t pinmon;
assert(soc < ARRAY_SIZE(uniphier_boot_device_info));
info = &uniphier_boot_device_info[soc];
assert(soc < ARRAY_SIZE(uniphier_boot_device_info));
pinmon_base = uniphier_pinmon_base[soc];
pinmon = mmio_read_32(pinmon_base + UNIPHIER_PINMON0);
if (info->have_boot_swap && !(pinmon & BIT(29)))
return UNIPHIER_BOOT_DEVICE_NOR;
if (info->is_sd_boot && info->is_sd_boot(pinmon))
return UNIPHIER_BOOT_DEVICE_SD;
if (info->is_usb_boot && info->is_usb_boot(pinmon))
return UNIPHIER_BOOT_DEVICE_USB;
return info->get_boot_device(pinmon);
}
static const bool uniphier_have_onchip_scp[] = {
[UNIPHIER_SOC_LD11] = true,
[UNIPHIER_SOC_LD20] = true,
[UNIPHIER_SOC_PXS3] = false,
};
unsigned int uniphier_get_boot_master(unsigned int soc)
{
assert(soc < ARRAY_SIZE(uniphier_have_onchip_scp));
if (uniphier_have_onchip_scp[soc]) {
uintptr_t pinmon_base;
assert(soc < ARRAY_SIZE(uniphier_boot_device_info));
pinmon_base = uniphier_pinmon_base[soc];
if (mmio_read_32(pinmon_base + UNIPHIER_PINMON0) & BIT(27))
return UNIPHIER_BOOT_MASTER_THIS;
else
return UNIPHIER_BOOT_MASTER_SCP;
} else {
return UNIPHIER_BOOT_MASTER_EXT;
}
}