root/sys/arch/evbmips/ingenic/cpu_startup.S
/*      $NetBSD: cpu_startup.S,v 1.2 2023/02/23 14:56:00 riastradh Exp $ */

/*-
 * Copyright (c) 2015 Michael Lorenz
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 */

#include "opt_cputype.h"
#include "opt_multiprocessor.h"

#include <sys/cdefs.h>
#include <sys/endian.h>

#include <mips/asm.h>
RCSID("$NetBSD: cpu_startup.S,v 1.2 2023/02/23 14:56:00 riastradh Exp $");

#ifdef MULTIPROCESSOR

#include <mips/cpuregs.h>
#include <mips/cache_r4k.h>

#include "assym.h"

#define CACHE_SIZE (32 * 1024)
#define CACHE_LINESIZE 32

NESTED_NOPROFILE(ingenic_trampoline, 0, ra)
        /*
         * We act as the idle lwp so make it CURLWP.  When know
         * that the cpu_info is a KSEG0 address.
         */
        move    a0, a1
        // Loop until idlelwp is filled in.
1:      PTR_L   MIPS_CURLWP, CPU_INFO_IDLELWP(a0)
        nop
        beqz    MIPS_CURLWP, 1b
         nop
        /*
         * No membar needed because we're not switching from a
         * previous lwp, and the idle lwp we're switching to can't be
         * holding locks already; see cpu_switchto.
         */
        PTR_S   MIPS_CURLWP, CPU_INFO_CURLWP(a0)

        li      v0, 0
        mtc0    v0, MIPS_COP_0_STATUS           # reset to known state
        COP0_SYNC

        PTR_L   sp, L_MD_UTF(MIPS_CURLWP)       # fetch KSP

        /*
         * Indicate that no one has called us.
         */
        move    ra, zero
        REG_S   ra, CALLFRAME_RA(sp)

        /*
         * New execution constant needs GP to be loaded.
         */
        PTR_LA  gp, _C_LABEL(_gp)

        /*
         * and off we go.
         */
        j       _C_LABEL(cpu_hatch)             # does everything
         nop
END(ingenic_trampoline)


/*
 * exception vector secondary CPUs take when started
 */
.p2align 16
VECTOR(ingenic_wakeup, unknown)
        .set    noat

        mtc0    zero, MIPS_COP_0_CAUSE
        COP0_SYNC

        /* init caches */
        li      t0, MIPS_KSEG0_START
        ori     t1, t0, CACHE_SIZE
        mtc0    zero, MIPS_COP_0_TAG_LO, 0
        COP0_SYNC
1:      cache   CACHEOP_R4K_INDEX_STORE_TAG | CACHE_R4K_I, 0(t0)
        cache   CACHEOP_R4K_INDEX_STORE_TAG | CACHE_R4K_D, 0(t0)
        addiu   t0, t0, CACHE_LINESIZE
        bne     t0, t1, 1b
         nop

        /* kseg0 cache attribute */
        mfc0    t0, MIPS_COP_0_CONFIG, 0
        ori     t0, t0, MIPS3_TLB_ATTR_WB_NONCOHERENT
        mtc0    t0, MIPS_COP_0_CONFIG, 0
        COP0_SYNC

        /* pagemask */
        mtc0    zero, MIPS_COP_0_TLB_PG_MASK, 0
        COP0_SYNC

        /*
         * - set a1 to corresponding cpu_info
         * - set sp to ci->ci_data.cpu_idlelwp->l_md.md_utf
         * - jump to cpu_trampoline
         */
        PTR_L   a1, _C_LABEL(startup_cpu_info)
        nop

        j       ingenic_trampoline
          nop
        .set    at
VECTOR_END(ingenic_wakeup)

#endif /* MULTIPROCESSOR */