Files
zOS/common/zpu_soc.c

301 lines
14 KiB
C

////////////////////////////////////////////////////////////////////////////////////////////////////////
//
// Name: zpu_soc.c
// Created: January 2019
// Author(s): Philip Smart
// Description: ZPU System On a Chip utilities.
// A set of utilities specific to interaction with the ZPU SoC hardware.
//
// Credits:
// Copyright: (c) 2019 Philip Smart <philip.smart@net2net.org>
//
// History: January 2019 - Initial script written.
//
/////////////////////////////////////////////////////////////////////////////////////////////////////////
// This source file 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 source file 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/>.
/////////////////////////////////////////////////////////////////////////////////////////////////////////
#ifdef __cplusplus
extern "C" {
#endif
#include <zpu-types.h>
#include "uart.h"
#include "zpu_soc.h"
#include "xprintf.h"
// Global scope variables.
#ifdef USE_BOOT_ROM
SOC_CONFIG cfgSoC;
#else
SOC_CONFIG cfgSoC = { .addrInsnBRAM = INSN_BRAM_ADDR,
.sizeInsnBRAM = INSN_BRAM_SIZE,
.addrBRAM = BRAM_ADDR,
.sizeBRAM = BRAM_SIZE,
.addrRAM = RAM_ADDR,
.sizeRAM = RAM_SIZE,
.addrSDRAM = SDRAM_ADDR,
.sizeSDRAM = SDRAM_SIZE,
.addrWBSDRAM = WB_SDRAM_ADDR,
.sizeWBSDRAM = WB_SDRAM_SIZE,
.resetVector = CPU_RESET_ADDR,
.cpuMemBaseAddr = CPU_MEM_START,
.stackStartAddr = STACK_BRAM_ADDR,
.zpuId = ZPU_ID,
.sysFreq = CLK_FREQ,
.memFreq = CLK_FREQ,
.wbMemFreq = CLK_FREQ,
.implSoCCFG = 0,
.implWB = WB_IMPL,
.implWBSDRAM = WB_SDRAM_IMPL,
.implWBI2C = WB_I2C_IMPL,
.implInsnBRAM = INSN_BRAM_IMPL,
.implBRAM = BRAM_IMPL,
.implRAM = RAM_IMPL,
.implSDRAM = SDRAM_IMPL,
.implIOCTL = IOCTL_IMPL,
.implPS2 = PS2_IMPL,
.implSPI = SPI_IMPL,
.implSD = SD_IMPL,
.sdCardNo = SD_DEVICE_CNT,
.implIntrCtl = INTRCTL_IMPL,
.intrChannels = INTRCTL_CHANNELS,
.implTimer1 = TIMER1_IMPL,
.timer1No = TIMER1_TIMERS_CNT };
#endif
// Method to populate the Configuration structure, initially using in-built values from compile time
// which are overriden with values stored in the SoC if available.
void setupSoCConfig(void)
{
// If the SoC Configuration register is implemented in the SoC, overwrite the compiled constants with those in the chip register.
if( IS_IMPL_SOCCFG )
{
cfgSoC.addrInsnBRAM = SOCCFG(SOCCFG_BRAMINSNADDR);
cfgSoC.sizeInsnBRAM = SOCCFG(SOCCFG_BRAMINSNSIZE);
cfgSoC.addrBRAM = SOCCFG(SOCCFG_BRAMADDR);
cfgSoC.sizeBRAM = SOCCFG(SOCCFG_BRAMSIZE);
cfgSoC.addrRAM = SOCCFG(SOCCFG_RAMADDR);
cfgSoC.sizeRAM = SOCCFG(SOCCFG_RAMSIZE);
cfgSoC.addrSDRAM = SOCCFG(SOCCFG_SDRAMADDR);
cfgSoC.sizeSDRAM = SOCCFG(SOCCFG_SDRAMSIZE);
cfgSoC.addrWBSDRAM = SOCCFG(SOCCFG_WBSDRAMADDR);
cfgSoC.sizeWBSDRAM = SOCCFG(SOCCFG_WBSDRAMSIZE);
cfgSoC.resetVector = SOCCFG(SOCCFG_CPURSTADDR);
cfgSoC.cpuMemBaseAddr = SOCCFG(SOCCFG_CPUMEMSTART);
cfgSoC.stackStartAddr = SOCCFG(SOCCFG_STACKSTART);
cfgSoC.zpuId = SOCCFG(SOCCFG_ZPU_ID);
cfgSoC.sysFreq = SOCCFG(SOCCFG_SYSFREQ);
cfgSoC.memFreq = SOCCFG(SOCCFG_MEMFREQ);
cfgSoC.wbMemFreq = SOCCFG(SOCCFG_WBMEMFREQ);
cfgSoC.implSoCCFG = 1;
cfgSoC.implWB = IS_IMPL_WB != 0;
cfgSoC.implWBSDRAM = IS_IMPL_WB_SDRAM != 0;
cfgSoC.implWBI2C = IS_IMPL_WB_I2C != 0;
cfgSoC.implInsnBRAM = IS_IMPL_INSN_BRAM != 0;
cfgSoC.implBRAM = IS_IMPL_BRAM != 0;
cfgSoC.implRAM = IS_IMPL_RAM != 0;
cfgSoC.implSDRAM = IS_IMPL_SDRAM != 0;
cfgSoC.implIOCTL = IS_IMPL_IOCTL != 0;
cfgSoC.implPS2 = IS_IMPL_PS2 != 0;
cfgSoC.implSPI = IS_IMPL_SPI != 0;
cfgSoC.implSD = IS_IMPL_SD != 0;
cfgSoC.sdCardNo = (uint8_t)(SOCCFG_SD_DEVICES);
cfgSoC.implIntrCtl = IS_IMPL_INTRCTL != 0;
cfgSoC.intrChannels = (uint8_t)(SOCCFG_INTRCTL_CHANNELS);
cfgSoC.implTimer1 = IS_IMPL_TIMER1 != 0;
cfgSoC.timer1No = (uint8_t)(SOCCFG_TIMER1_TIMERS);
#ifndef USE_BOOT_ROM
}
#else
} else
{
// Store builtin constants into structure which will be used when the SoC configuration module isnt implemented.
cfgSoC.addrInsnBRAM = INSN_BRAM_ADDR;
cfgSoC.sizeInsnBRAM = INSN_BRAM_SIZE;
cfgSoC.addrBRAM = BRAM_ADDR;
cfgSoC.sizeBRAM = BRAM_SIZE;
cfgSoC.addrRAM = RAM_ADDR;
cfgSoC.sizeRAM = RAM_SIZE;
cfgSoC.addrSDRAM = SDRAM_ADDR;
cfgSoC.sizeSDRAM = SDRAM_SIZE;
cfgSoC.addrWBSDRAM = WB_SDRAM_ADDR;
cfgSoC.sizeWBSDRAM = WB_SDRAM_SIZE;
cfgSoC.resetVector = CPU_RESET_ADDR;
cfgSoC.cpuMemBaseAddr = CPU_MEM_START;
cfgSoC.stackStartAddr = STACK_BRAM_ADDR;
cfgSoC.zpuId = ZPU_ID;
cfgSoC.sysFreq = CLK_FREQ;
cfgSoC.memFreq = CLK_FREQ;
cfgSoC.wbMemFreq = CLK_FREQ;
cfgSoC.implSoCCFG = 0;
cfgSoC.implWB = WB_IMPL;
cfgSoC.implWBSDRAM = WB_SDRAM_IMPL;
cfgSoC.implWBI2C = WB_I2C_IMPL;
cfgSoC.implInsnBRAM = INSN_BRAM_IMPL;
cfgSoC.implBRAM = BRAM_IMPL ;
cfgSoC.implRAM = RAM_IMPL;
cfgSoC.implSDRAM = SDRAM_IMPL;;
cfgSoC.implIOCTL = IOCTL_IMPL;;
cfgSoC.implPS2 = PS2_IMPL;
cfgSoC.implSPI = SPI_IMPL;
cfgSoC.implSD = IMPL_SD;
cfgSoC.sdCardNo = SD_DEVICE_CNT;
cfgSoC.implIntrCtl = INTRCTL_IMPL;
cfgSoC.intrChannels = INTRCTL_CHANNELS;
cfgSoC.implTimer1 = TIMER1_IMPL;
cfgSoC.timer1No = TIMER1_TIMERS_CNT;
}
#endif
}
// Method to show the current configuration via the primary uart channel.
//
#if !defined(FUNCTIONALITY) || FUNCTIONALITY <= 1
void showSoCConfig(void)
{
#if defined(__ZOS__) || defined(__ZPUTA__)
xputs("SoC Configuration");
if(cfgSoC.implSoCCFG) { xputs(" (from SoC config)"); }
xputs(":\nDevices implemented:\n");
if(cfgSoC.implWBSDRAM) { xprintf(" WB SDRAM (%08X:%08X).\n", cfgSoC.addrWBSDRAM, cfgSoC.addrWBSDRAM + cfgSoC.sizeWBSDRAM); }
if(cfgSoC.implSDRAM) { xprintf(" SDRAM (%08X:%08X).\n", cfgSoC.addrSDRAM, cfgSoC.addrSDRAM + cfgSoC.sizeSDRAM); }
if(cfgSoC.implInsnBRAM) { xprintf(" INSN BRAM (%08X:%08X).\n", cfgSoC.addrInsnBRAM, cfgSoC.addrInsnBRAM + cfgSoC.sizeInsnBRAM); }
if(cfgSoC.implBRAM) { xprintf(" BRAM (%08X:%08X).\n", cfgSoC.addrBRAM, cfgSoC.addrBRAM + cfgSoC.sizeBRAM); }
if(cfgSoC.implRAM) { xprintf(" RAM (%08X:%08X).\n", cfgSoC.addrRAM, cfgSoC.addrRAM + cfgSoC.sizeRAM); }
if(cfgSoC.implSD) { xprintf(" SD CARD (Devices =%02d).\n", (uint8_t)cfgSoC.sdCardNo); }
if(cfgSoC.implTimer1) { xprintf(" TIMER1 (Timers =%02d).\n", (uint8_t)cfgSoC.timer1No); }
if(cfgSoC.implIntrCtl) { xprintf(" INTR CTRL (Channels=%02d).\n", (uint8_t)cfgSoC.intrChannels); }
if(cfgSoC.implWB) { xputs(" WISHBONE BUS\n"); }
if(cfgSoC.implWBI2C) { xputs(" WB I2C\n"); }
if(cfgSoC.implIOCTL) { xputs(" IOCTL\n"); }
if(cfgSoC.implPS2) { xputs(" PS2\n"); }
if(cfgSoC.implSPI) { xputs(" SPI\n"); }
xputs("Addresses:\n");
xprintf(" CPU Reset Vector Address = %08X\n", cfgSoC.resetVector);
xprintf(" CPU Memory Start Address = %08X\n", cfgSoC.cpuMemBaseAddr);
xprintf(" Stack Start Address = %08X\n", cfgSoC.stackStartAddr);
xputs("Misc:\n");
xprintf(" ZPU Id = %04X\n", cfgSoC.zpuId);
xprintf(" System Clock Freq = %d.%04dMHz\n", (cfgSoC.sysFreq / 1000000), cfgSoC.sysFreq - ((cfgSoC.sysFreq / 1000000) * 1000000));
if(cfgSoC.implSDRAM)
xprintf(" SDRAM Clock Freq = %d.%04dMHz\n", (cfgSoC.memFreq / 1000000), cfgSoC.memFreq - ((cfgSoC.memFreq / 1000000) * 1000000));
if(cfgSoC.implWBSDRAM)
xprintf(" Wishbone SDRAM Clock Freq= %d.%04dMHz\n", (cfgSoC.wbMemFreq / 1000000), cfgSoC.wbMemFreq - ((cfgSoC.wbMemFreq / 1000000) * 1000000));
#ifdef DRV_CFC
xprintf(" CFC = %08X\n", DRV_CFC);
#endif
#ifdef DRV_MMC
xprintf(" MMC = %08X\n", DRV_MMC);
#endif
xputs("\n");
#else
puts("SoC Configuration");
if(cfgSoC.implSoCCFG) { puts(" (from SoC config)"); }
puts(":\nDevices implemented:\n");
if(cfgSoC.implWBSDRAM) { puts(" WB SDRAM ("); printdhex(cfgSoC.addrWBSDRAM); puts(":"); printdhex(cfgSoC.addrWBSDRAM + cfgSoC.sizeWBSDRAM); puts(").\n"); }
if(cfgSoC.implSDRAM) { puts(" SDRAM ("); printdhex(cfgSoC.addrSDRAM); puts(":"); printdhex(cfgSoC.addrSDRAM + cfgSoC.sizeSDRAM); puts(").\n"); }
if(cfgSoC.implInsnBRAM) { puts(" INSN BRAM ("); printdhex(cfgSoC.addrInsnBRAM); puts(":"); printdhex(cfgSoC.addrInsnBRAM + cfgSoC.sizeInsnBRAM); puts(").\n"); }
if(cfgSoC.implBRAM) { puts(" BRAM ("); printdhex(cfgSoC.addrBRAM); puts(":"); printdhex(cfgSoC.addrBRAM + cfgSoC.sizeBRAM); puts(").\n"); }
if(cfgSoC.implRAM) { puts(" RAM ("); printdhex(cfgSoC.addrRAM); puts(":"); printdhex(cfgSoC.addrRAM + cfgSoC.sizeRAM); puts(").\n"); }
if(cfgSoC.implSD) { puts(" SD CARD (Devices ="); printhexbyte((uint8_t)cfgSoC.sdCardNo); puts(").\n"); }
if(cfgSoC.implTimer1) { puts(" TIMER1 (Timers ="); printnibble( (uint8_t)cfgSoC.timer1No); puts(").\n"); }
if(cfgSoC.implIntrCtl) { puts(" INTR CTRL (Channels="); printhexbyte((uint8_t)cfgSoC.intrChannels); puts(").\n"); }
if(cfgSoC.implWB) { puts(" WISHBONE BUS\n"); }
if(cfgSoC.implWB) { puts(" WB I2C\n"); }
if(cfgSoC.implIOCTL) { puts(" IOCTL\n"); }
if(cfgSoC.implPS2) { puts(" PS2\n"); }
if(cfgSoC.implSPI) { puts(" SPI\n"); }
puts("Addresses:\n");
puts(" CPU Reset Vector Address = "); printdhex(cfgSoC.resetVector); puts("\n");
puts(" CPU Memory Start Address = "); printdhex(cfgSoC.cpuMemBaseAddr); puts("\n");
puts(" Stack Start Address = "); printdhex(cfgSoC.stackStartAddr); puts("\n");
puts("Misc:\n");
puts(" ZPU Id = "); printhex((uint16_t)cfgSoC.zpuId); puts("\n");
puts(" System Clock Freq = "); printdhex(cfgSoC.sysFreq); puts("\n");
if(cfgSoC.implSDRAM)
puts(" SDRAM Clock Freq = "); printdhex(cfgSoC.memFreq); puts("\n");
if(cfgSoC.implWBSDRAM)
puts(" Wishbone SDRAM Clock Freq= "); printdhex(cfgSoC.wbMemFreq); puts("\n");
#ifdef DRV_CFC
puts(" CFC = "); printdhex(DRV_CFC); puts("\n");
#endif
#ifdef DRV_MMC
puts(" MMC = "); printdhex(DRV_MMC); puts("\n");
#endif
puts("\n");
#endif
}
// Function to print out the ZPU Id in text form.
void printZPUId(uint32_t zpuId)
{
switch((uint8_t)(zpuId >> 8))
{
case ZPU_ID_SMALL:
#if defined __IOCP__
puts("Small");
#else
xputs("Small");
#endif
break;
case ZPU_ID_MEDIUM:
#if defined __IOCP__
puts("Medium");
#else
xputs("Medium");
#endif
break;
case ZPU_ID_FLEX:
#if defined __IOCP__
puts("Flex");
#else
xputs("Flex");
#endif
break;
case ZPU_ID_EVO:
#if defined __IOCP__
puts("EVO");
#else
xputs("EVO");
#endif
break;
case ZPU_ID_EVO_MINIMAL:
#if defined __IOCP__
puts("EVOmin");
#else
xputs("EVOmin");
#endif
break;
default:
#if defined __IOCP__
puts("Unknown");
#else
xputs("Unknown");
#endif
break;
}
}
#endif
#ifdef __cplusplus
}
#endif