Newer
Older
uwuboot / source / arm11 / hardware / cpu.c
/*
 *   This file is part of fastboot 3DS
 *   Copyright (C) 2017 derrek, profi200
 *
 *   This program is free software: you can redistribute it and/or modify
 *   it under the terms of the GNU General Public License as published by
 *   the Free Software Foundation, either version 3 of the License, or
 *   (at your option) any later version.
 *
 *   This program is distributed in the hope that it will be useful,
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *   GNU General Public License for more details.
 *
 *   You should have received a copy of the GNU General Public License
 *   along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

#include "types.h"
#include "arm.h"
#include "arm11/start.h"
#include "arm11/hardware/interrupt.h"
#include "arm11/hardware/scu.h"


#define REG_CFG11_SOCINFO              *((vu16*)0x10140FFC)
#define REG_CFG11_MPCORE_CLKCNT        *((vu16*)0x10141300)
#define REG_CFG11_MPCORE_CNT           *((vu16*)0x10141304)
#define REG_UNK_10140400               *((vu8* )0x10140400)
#define REG_UNK_10140410               *((vu32*)0x10140410)
#define REG_CFG11_BOOTROM_OVERLAY_CNT  *((vu8* )0x10140420)
#define REG_CFG11_BOOTROM_OVERLAY_VAL  *((vu32*)0x10140424)
#define REGs_CFG11_MPCORE_BOOTCNT       ((vu8* )0x10141310)



/*static void NAKED core23Entry(void)
{
	__cpsid(aif);
	*((vu32*)0x17E00100) = 1; // REG_CPU_II_CNT

	const u32 cpuId = __getCpuId();
	// Tell core 0 we are here
	if(cpuId == 3) REGs_CFG11_MPCORE_BOOTCNT[3] = 1;
	else           REGs_CFG11_MPCORE_BOOTCNT[2] = 1;

	// Wait for IPI 2 (core 2) or IPI 3 (core 3)
	u32 tmp;
	do
	{
		__wfi();
		tmp = *((vu32*)0x17E0010C);
		*((vu32*)0x17E00110) = tmp;
	} while(tmp != cpuId);

	// Jump to real entrypoint
	_start();
}*/

void core123Init(void)
{
	/*if(REG_CFG11_SOCINFO & 2)
	{
		*((vu32*)0x17E00100) = 1;         // REG_CPU_II_CNT
		*((vu32*)0x17E01288) = 0x1000000; // REGs_GID_PEN_CLR
		*((vu8* )0x17E01458) = 0;         // REGs_GID_IPRIO
		*((vu8* )0x17E01858) = 1;         // REGs_GID_ITARG
		*((vu32*)0x17E01108) = 0x1000000; // REGs_GID_ENA_SET

		u16 clkCnt;
		// If clock modifier is 3x use clock 3x. Also enables FCRAM extension?
		if(REG_CFG11_SOCINFO & 4) clkCnt = 2<<1 | 1;
		else                      clkCnt = 1<<1 | 1;

		if((REG_CFG11_MPCORE_CLKCNT & 7) != clkCnt)
		{
			// Poweron core 3 if available
			if(REG_CFG11_SOCINFO & 4) REG_CFG11_MPCORE_CNT = 0x101; // Poweron core 2 and 3
			else                      REG_CFG11_MPCORE_CNT = 1;     // Poweron core 2

			//waitCycles(403);
			// Necessary delay
			for(vu32 i = 403; i > 0; i--);

			REG_CFG11_MPCORE_CLKCNT = (clkCnt & 7) | 0x8000;
			do
			{
				__wfi();
			} while(!(REG_CFG11_MPCORE_CLKCNT & 0x8000));
			*((vu32*)0x17E01288) = 0x1000000; // REGs_GID_PEN_CLR
			REG_UNK_10140400 = 3;   // Clock related?
		}
		REG_UNK_10140410 = 0x3FFFF; // Clock related?

		if((REG_SCU_CONFIG & 3) == 3)
		{
			// Set core 2/3 to normal mode (running)
			REG_SCU_CPU_STAT &= ~0xF0;

			const u16 clkCnt = REG_CFG11_MPCORE_CLKCNT & 7;
			u16 tmpClkCnt;
			if(REG_CFG11_SOCINFO & 4) tmpClkCnt = 1;
			else                      tmpClkCnt = 2;

			if(clkCnt != tmpClkCnt)
			{
				REG_CFG11_MPCORE_CLKCNT = (tmpClkCnt & 7) | 0x8000;
				do
				{
					__wfi();
				} while(!(REG_CFG11_MPCORE_CLKCNT & 0x8000));
				*((vu32*)0x17E01288) = 0x1000000; // REGs_GID_PEN_CLR
			}

			REG_CFG11_BOOTROM_OVERLAY_CNT = 1;
			REG_CFG11_BOOTROM_OVERLAY_VAL = (u32)core23Entry;
			// If not already done eable instruction and data overlays
			if(!(REGs_CFG11_MPCORE_BOOTCNT[2] & 0x10)) REGs_CFG11_MPCORE_BOOTCNT[2] = 3;
			if(!(REGs_CFG11_MPCORE_BOOTCNT[3] & 0x10)) REGs_CFG11_MPCORE_BOOTCNT[3] = 3;
			// Wait for core 2/3 to jump out of boot11
			while((REGs_CFG11_MPCORE_BOOTCNT[2] & 0x12) != 0x10);
			while((REGs_CFG11_MPCORE_BOOTCNT[3] & 0x12) != 0x10);
			REG_CFG11_BOOTROM_OVERLAY_CNT = 0; // Disable all overlays

			// Set clock back to original one
			if(clkCnt != tmpClkCnt)
			{
				REG_CFG11_MPCORE_CLKCNT = (clkCnt & 7) | 0x8000;
				do
				{
					__wfi();
				} while(!(REG_CFG11_MPCORE_CLKCNT & 0x8000));
			}
		}

		*((vu32*)0x17E01188) = 0x1000000; // REGs_GID_ENA_CLR

		// Wakeup core 2/3 and let them jump to their entrypoint.
		*((vu32*)0x17E01F00) = 0b0100<<16 | 2;
		*((vu32*)0x17E01F00) = 0b1000<<16 | 3;
	}*/

	// Wakeup core 1
	*((vu32*)0x1FFFFFDC) = (u32)_start;  // Core 1 entrypoint
	*((vu32*)0x17E01F00) = 0b10<<16 | 1;
}