blob: 8e12b55a87c67c5944132df0ef663d1d2b0beefb [file] [log] [blame]
/****************************************************************************
* arch/risc-v/src/k230/k230_hart.c
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership. The
* ASF licenses this file to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance with the
* License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*
****************************************************************************/
/****************************************************************************
* Included Files
****************************************************************************/
#include <nuttx/config.h>
#include <stdint.h>
#include <stdio.h>
#include <assert.h>
#include <debug.h>
#include <nuttx/arch.h>
#include <nuttx/irq.h>
#include "riscv_internal.h"
#include "chip.h"
/****************************************************************************
* Pre-processor Definitions
****************************************************************************/
#ifdef CONFIG_K230_PBMT_THEAD
#define THEAD_PBMT 0x638000
#define XSTATUS THEAD_PBMT
#else
#define RISCV_PBMT 0x438000
#define XSTATUS RISCV_PBMT
#endif
#define XSTATE_MSK ((1 << 30) - 1)
#define MCOR 0x70013
#define MHCR 0x11ff
#define MHINT 0x6e30c
#define MCCR2 0xe0000009
#define MHINT_BIG 0x16e30c
#define MCCR2_BIG 0xe0410009
#define MSMPR 1
#define MHCR_IE_MSK (1 << 0)
#define MHCR_DE_MSK (1 << 1)
#define RISCV_PMBT_EN (1 << 62)
/* K230 cache flush instructions */
#define K230_DAT_SYNC_B ".long 0x0ff0000f\n"
#define K230_INS_SYNC_B ".long 0x0000100f\n .long 0x0220000f\n"
#define K230_I_IALL ".long 0x0100000b\n"
#define K230_D_CIALL ".long 0x0030000b\n"
#define K230_L2_IALL ".long 0x0170000b\n"
#define K230_SYNC_IS ".long 0x01b0000b\n"
#define ASM __asm__ __volatile__
/* Hart reset control bits and delays */
#define RESET_DONE_BIT (1 << 12)
#define RESET_RQST_BIT (1 << 0)
#define RESET_DONE_ENW (1 << (12 + 16))
#define RESET_RQST_ENW (1 << (0 + 16))
#define RESET_WAIT_USEC 100
/* PMP openall flag */
#define PMP_NAPOT_RWX (PMPCFG_A_NAPOT | PMPCFG_RWX_MASK)
/****************************************************************************
* Private Variables
****************************************************************************/
#if !defined(CONFIG_BUILD_KERNEL) || defined(CONFIG_NUTTSBI)
static volatile uint64_t g_misa locate_data(".data");
/****************************************************************************
* Private Functions
****************************************************************************/
/****************************************************************************
* Name: hart_cleanup
* Description: from cleanup_before_linux() in K230 U-Boot
****************************************************************************/
static void k230_hart_cleanup(void)
{
uintptr_t reg = READ_CSR(CSR_MHCR);
ASM(K230_DAT_SYNC_B);
ASM(K230_INS_SYNC_B);
ASM(K230_I_IALL); /* icache.iall */
ASM(K230_D_CIALL); /* dcache.ciall */
ASM(K230_DAT_SYNC_B);
ASM(K230_INS_SYNC_B);
reg &= ~MHCR_IE_MSK; /* icache.disable */
reg &= ~MHCR_DE_MSK; /* dcache.disable */
WRITE_CSR(CSR_MHCR, reg);
ASM(K230_L2_IALL); /* l2.iall */
ASM(K230_DAT_SYNC_B);
ASM(K230_INS_SYNC_B);
}
/****************************************************************************
* Public Functions
****************************************************************************/
/****************************************************************************
* Name: k230_hart_init()
* Description: K230 M-mode HART setup following K230 SDK
****************************************************************************/
void k230_hart_init(void)
{
bool big;
while (!(g_misa = READ_CSR(CSR_MISA)));
big = g_misa & (1 << 21);
k230_hart_cleanup();
WRITE_CSR(CSR_MXSTATUS, XSTATUS);
WRITE_CSR(CSR_MHCR, MHCR);
WRITE_CSR(CSR_MCOR, MCOR);
WRITE_CSR(CSR_MSMPR, MSMPR);
WRITE_CSR(CSR_MCCR2, big ? MCCR2_BIG : MCCR2);
WRITE_CSR(CSR_MHINT, big ? MHINT_BIG : MHINT);
#ifdef RISCV_PBMT
SET_CSR(CSR_MENVCFG, MENVCFG_PBMT);
#endif
}
/****************************************************************************
* Name: k230_hart_is_big()
* Description: returns true if running on big core.
****************************************************************************/
bool k230_hart_is_big(void)
{
return g_misa & (1 << 21);
}
/****************************************************************************
* Name: k230_hart_big_stop()
* Description: stop big core, can run in S-mode
****************************************************************************/
void k230_hart_big_stop(void)
{
if (!k230_hart_is_big())
{
/* 0x10001 set RESET */
putreg32(RESET_RQST_BIT | RESET_RQST_ENW, K230_CPU1_RESET);
up_udelay(RESET_WAIT_USEC);
sinfo("reg: %" PRIx32 "\n", getreg32(K230_CPU1_RESET));
}
}
/****************************************************************************
* Name: k230_hart_big_boot()
* Description: start big core from given address, can run in S-mode
****************************************************************************/
void k230_hart_big_boot(uintptr_t addr)
{
if (!k230_hart_is_big())
{
/* learned from U-Boot baremetal and RTT sysctl_reset_cpu */
putreg32(addr, K230_CPU1_BOOTA);
sinfo("addr=%"PRIxPTR"\n", addr);
/* 0x10001000 clear DONE bit */
putreg32(RESET_DONE_BIT | RESET_DONE_ENW, K230_CPU1_RESET);
up_udelay(RESET_WAIT_USEC);
/* 0x10001 set RQST bit */
putreg32(RESET_RQST_BIT | RESET_RQST_ENW, K230_CPU1_RESET);
up_udelay(RESET_WAIT_USEC);
/* 0x10000 clear RQST bit */
putreg32(RESET_RQST_ENW, K230_CPU1_RESET);
up_udelay(RESET_WAIT_USEC);
}
}
#endif /* !defined(CONFIG_BUILD_KERNEL) || defined(CONFIG_NUTTSBI) */
#ifdef CONFIG_NUTTSBI_LATE_INIT
/****************************************************************************
* Name: sbi_late_initialize
* Description: K230 specific setup in M-mode.
****************************************************************************/
void sbi_late_initialize(void)
{
/* delegate K230 plic enable to S-mode */
putreg32(1, K230_PLIC_CTRL);
k230_hart_init();
/* Open everything for PMP */
DEBUGASSERT(riscv_append_pmp_region(PMP_NAPOT_RWX, 0, 0) == 0);
}
#endif