Initial commit; kernel source import

This commit is contained in:
Nathan
2025-04-06 23:50:55 -05:00
commit 25c6d769f4
45093 changed files with 18199410 additions and 0 deletions

View File

@@ -0,0 +1,84 @@
#
# Copyright (C) 2007-2010, 2011-2012 Synopsys, Inc. (www.synopsys.com)
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License version 2 as
# published by the Free Software Foundation.
#
menuconfig ARC_PLAT_FPGA_LEGACY
bool "\"Legacy\" ARC FPGA dev Boards"
select ISS_SMP_EXTN if SMP
help
Support for ARC development boards, provided by Synopsys.
These are based on FPGA or ISS. e.g.
- ARCAngel4
- ML509
- MetaWare ISS
if ARC_PLAT_FPGA_LEGACY
config ARC_BOARD_ANGEL4
bool "ARC Angel4"
default y
help
ARC Angel4 FPGA Ref Platform (Xilinx Virtex Based)
config ARC_BOARD_ML509
bool "ML509"
help
ARC ML509 FPGA Ref Platform (Xilinx Virtex-5 Based)
config ISS_SMP_EXTN
bool "ARC SMP Extensions (ISS Models only)"
default n
depends on SMP
select ARC_HAS_COH_RTSC
help
SMP Extensions to ARC700, in a "simulation only" Model, supported in
ARC ISS (Instruction Set Simulator).
The SMP extensions include:
-IDU (Interrupt Distribution Unit)
-XTL (To enable CPU start/stop/set-PC for another CPU)
It doesn't provide coherent Caches and/or Atomic Ops (LLOCK/SCOND)
config ARC_SERIAL_BAUD
int "UART Baud rate"
default "115200"
depends on SERIAL_ARC || SERIAL_ARC_CONSOLE
help
Baud rate for the ARC UART
menuconfig ARC_HAS_BVCI_LAT_UNIT
bool "BVCI Bus Latency Unit"
depends on ARC_BOARD_ML509 || ARC_BOARD_ANGEL4
help
IP to add artificial latency to BVCI Bus Based FPGA builds.
The default latency (even worst case) for FPGA is non-realistic
(~10 SDRAM, ~5 SSRAM).
config BVCI_LAT_UNITS
hex "Latency Unit(s) Bitmap"
default "0x0"
depends on ARC_HAS_BVCI_LAT_UNIT
help
There are multiple Latency Units corresponding to the many
interfaces of the system bus arbiter (both CPU side as well as
the peripheral side).
To add latency to ALL memory transaction, choose Unit 0, otherwise
for finer grainer - interface wise latency, specify a bitmap (1 bit
per unit) of all units. e.g. 1,2,12 will be 0x1003
Unit 0 - System Arb and Mem Controller
Unit 1 - I$ and System Bus
Unit 2 - D$ and System Bus
..
Unit 12 - IDE Disk controller and System Bus
config BVCI_LAT_CYCLES
int "Latency Value in cycles"
range 0 63
default "30"
depends on ARC_HAS_BVCI_LAT_UNIT
endif

View File

@@ -0,0 +1,12 @@
#
# Copyright (C) 2011-2012 Synopsys, Inc. (www.synopsys.com)
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License version 2 as
# published by the Free Software Foundation.
#
KBUILD_CFLAGS += -Iarch/arc/plat-arcfpga/include
obj-y := platform.o irq.o
obj-$(CONFIG_SMP) += smp.o

View File

@@ -0,0 +1,31 @@
/*
* Copyright (C) 2004, 2007-2010, 2011-2012 Synopsys, Inc. (www.synopsys.com)
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* vineetg: Feb 2009
* -For AA4 board, IRQ assignments to peripherals
*/
#ifndef __PLAT_IRQ_H
#define __PLAT_IRQ_H
#define UART0_IRQ 5
#define UART1_IRQ 10
#define UART2_IRQ 11
#define VMAC_IRQ 6
#define IDE_IRQ 13
#define PCI_IRQ 14
#define PS2_IRQ 15
#ifdef CONFIG_SMP
#define IDU_INTERRUPT_0 16
#endif
extern void __init plat_fpga_init_IRQ(void);
#endif

View File

@@ -0,0 +1,31 @@
/*
* Copyright (C) 2004, 2007-2010, 2011-2012 Synopsys, Inc. (www.synopsys.com)
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* vineetg: Feb 2009
* -For AA4 board, System Memory Map for Peripherals etc
*/
#ifndef __PLAT_MEMMAP_H
#define __PLAT_MEMMAP_H
#define UART0_BASE 0xC0FC1000
#define UART1_BASE 0xC0FC1100
#define VMAC_REG_BASEADDR 0xC0FC2000
#define IDE_CONTROLLER_BASE 0xC0FC9000
#define AHB_PCI_HOST_BRG_BASE 0xC0FD0000
#define PGU_BASEADDR 0xC0FC8000
#define VLCK_ADDR 0xC0FCF028
#define BVCI_LAT_UNIT_BASE 0xC0FED000
#define PS2_BASE_ADDR 0xC0FCC000
#endif

View File

@@ -0,0 +1,118 @@
/*
* Copyright (C) 2004, 2007-2010, 2011-2012 Synopsys, Inc. (www.synopsys.com)
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* Rajeshwar Ranga: Interrupt Distribution Unit API's
*/
#ifndef __PLAT_ARCFPGA_SMP_H
#define __PLAT_ARCFPGA_SMP_H
#ifdef CONFIG_SMP
#include <linux/types.h>
#include <asm/arcregs.h>
#define ARC_AUX_IDU_REG_CMD 0x2000
#define ARC_AUX_IDU_REG_PARAM 0x2001
#define ARC_AUX_XTL_REG_CMD 0x2002
#define ARC_AUX_XTL_REG_PARAM 0x2003
#define ARC_REG_MP_BCR 0x2021
#define ARC_XTL_CMD_WRITE_PC 0x04
#define ARC_XTL_CMD_CLEAR_HALT 0x02
/*
* Build Configuration Register which identifies the sub-components
*/
struct bcr_mp {
#ifdef CONFIG_CPU_BIG_ENDIAN
unsigned int mp_arch:16, pad:5, sdu:1, idu:1, scu:1, ver:8;
#else
unsigned int ver:8, scu:1, idu:1, sdu:1, pad:5, mp_arch:16;
#endif
};
/* IDU supports 256 common interrupts */
#define NR_IDU_IRQS 256
/*
* The Aux Regs layout is same bit-by-bit in both BE/LE modes.
* However when casted as a bitfield encoded "C" struct, gcc treats it as
* memory, generating different code for BE/LE, requiring strcture adj (see
* include/asm/arcregs.h)
*
* However when manually "carving" the value for a Aux, no special handling
* of BE is needed because of the property discribed above
*/
#define IDU_SET_COMMAND(irq, cmd) \
do { \
uint32_t __val; \
__val = (((irq & 0xFF) << 8) | (cmd & 0xFF)); \
write_aux_reg(ARC_AUX_IDU_REG_CMD, __val); \
} while (0)
#define IDU_SET_PARAM(par) write_aux_reg(ARC_AUX_IDU_REG_PARAM, par)
#define IDU_GET_PARAM() read_aux_reg(ARC_AUX_IDU_REG_PARAM)
/* IDU Commands */
#define IDU_DISABLE 0x00
#define IDU_ENABLE 0x01
#define IDU_IRQ_CLEAR 0x02
#define IDU_IRQ_ASSERT 0x03
#define IDU_IRQ_WMODE 0x04
#define IDU_IRQ_STATUS 0x05
#define IDU_IRQ_ACK 0x06
#define IDU_IRQ_PEND 0x07
#define IDU_IRQ_RMODE 0x08
#define IDU_IRQ_WBITMASK 0x09
#define IDU_IRQ_RBITMASK 0x0A
#define idu_enable() IDU_SET_COMMAND(0, IDU_ENABLE)
#define idu_disable() IDU_SET_COMMAND(0, IDU_DISABLE)
#define idu_irq_assert(irq) IDU_SET_COMMAND((irq), IDU_IRQ_ASSERT)
#define idu_irq_clear(irq) IDU_SET_COMMAND((irq), IDU_IRQ_CLEAR)
/* IDU Interrupt Mode - Destination Encoding */
#define IDU_IRQ_MOD_DISABLE 0x00
#define IDU_IRQ_MOD_ROUND_RECP 0x01
#define IDU_IRQ_MOD_TCPU_FIRSTRECP 0x02
#define IDU_IRQ_MOD_TCPU_ALLRECP 0x03
/* IDU Interrupt Mode - Triggering Mode */
#define IDU_IRQ_MODE_LEVEL_TRIG 0x00
#define IDU_IRQ_MODE_PULSE_TRIG 0x01
#define IDU_IRQ_MODE_PARAM(dest_mode, trig_mode) \
(((trig_mode & 0x01) << 15) | (dest_mode & 0xFF))
struct idu_irq_config {
uint8_t irq;
uint8_t dest_mode;
uint8_t trig_mode;
};
struct idu_irq_status {
uint8_t irq;
bool enabled;
bool status;
bool ack;
bool pend;
uint8_t next_rr;
};
extern void idu_irq_set_tgtcpu(uint8_t irq, uint32_t mask);
extern void idu_irq_set_mode(uint8_t irq, uint8_t dest_mode, uint8_t trig_mode);
extern void iss_model_init_smp(unsigned int cpu);
extern void iss_model_init_early_smp(void);
#endif /* CONFIG_SMP */
#endif

View File

@@ -0,0 +1,25 @@
/*
* ARC FPGA Platform IRQ hookups
*
* Copyright (C) 2012 Synopsys, Inc. (www.synopsys.com)
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
#include <linux/interrupt.h>
#include <plat/irq.h>
void __init plat_fpga_init_IRQ(void)
{
/*
* SMP Hack because UART IRQ hardwired to cpu0 (boot-cpu) but if the
* request_irq() comes from any other CPU, the low level IRQ unamsking
* essential for getting Interrupts won't be enabled on cpu0, locking
* up the UART state machine.
*/
#ifdef CONFIG_SMP
arch_unmask_irq(UART0_IRQ);
#endif
}

View File

@@ -0,0 +1,238 @@
/*
* ARC FPGA Platform support code
*
* Copyright (C) 2012 Synopsys, Inc. (www.synopsys.com)
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
#include <linux/types.h>
#include <linux/init.h>
#include <linux/device.h>
#include <linux/platform_device.h>
#include <linux/io.h>
#include <linux/console.h>
#include <linux/of_platform.h>
#include <asm/setup.h>
#include <asm/clk.h>
#include <asm/mach_desc.h>
#include <plat/memmap.h>
#include <plat/smp.h>
#include <plat/irq.h>
/*-----------------------BVCI Latency Unit -----------------------------*/
#ifdef CONFIG_ARC_HAS_BVCI_LAT_UNIT
int lat_cycles = CONFIG_BVCI_LAT_CYCLES;
/* BVCI Bus Profiler: Latency Unit */
static void __init setup_bvci_lat_unit(void)
{
#define MAX_BVCI_UNITS 12
unsigned int i;
unsigned int *base = (unsigned int *)BVCI_LAT_UNIT_BASE;
const unsigned long units_req = CONFIG_BVCI_LAT_UNITS;
const unsigned int REG_UNIT = 21;
const unsigned int REG_VAL = 22;
/*
* There are multiple Latency Units corresponding to the many
* interfaces of the system bus arbiter (both CPU side as well as
* the peripheral side).
*
* Unit 0 - System Arb and Mem Controller - adds latency to all
* memory trasactions
* Unit 1 - I$ and System Bus
* Unit 2 - D$ and System Bus
* ..
* Unit 12 - IDE Disk controller and System Bus
*
* The programmers model requires writing to lat_unit reg first
* and then the latency value (cycles) to lat_value reg
*/
if (CONFIG_BVCI_LAT_UNITS == 0) {
writel(0, base + REG_UNIT);
writel(lat_cycles, base + REG_VAL);
pr_info("BVCI Latency for all Memory Transactions %d cycles\n",
lat_cycles);
} else {
for_each_set_bit(i, &units_req, MAX_BVCI_UNITS) {
writel(i + 1, base + REG_UNIT); /* loop is 0 based */
writel(lat_cycles, base + REG_VAL);
pr_info("BVCI Latency for Unit[%d] = %d cycles\n",
(i + 1), lat_cycles);
}
}
}
#else
static void __init setup_bvci_lat_unit(void)
{
}
#endif
/*----------------------- Platform Devices -----------------------------*/
static unsigned long arc_uart_info[] = {
0, /* uart->is_emulated (runtime @running_on_hw) */
0, /* uart->port.uartclk */
0, /* uart->baud */
0
};
#if defined(CONFIG_SERIAL_ARC_CONSOLE)
/*
* static platform data - but only for early serial
* TBD: derive this from a special DT node
*/
static struct resource arc_uart0_res[] = {
{
.start = UART0_BASE,
.end = UART0_BASE + 0xFF,
.flags = IORESOURCE_MEM,
},
{
.start = UART0_IRQ,
.end = UART0_IRQ,
.flags = IORESOURCE_IRQ,
},
};
static struct platform_device arc_uart0_dev = {
.name = "arc-uart",
.id = 0,
.num_resources = ARRAY_SIZE(arc_uart0_res),
.resource = arc_uart0_res,
.dev = {
.platform_data = &arc_uart_info,
},
};
static struct platform_device *fpga_early_devs[] __initdata = {
&arc_uart0_dev,
};
#endif
static void arc_fpga_serial_init(void)
{
/* To let driver workaround ISS bug: baudh Reg can't be set to 0 */
arc_uart_info[0] = !running_on_hw;
arc_uart_info[1] = arc_get_core_freq();
arc_uart_info[2] = CONFIG_ARC_SERIAL_BAUD;
#if defined(CONFIG_SERIAL_ARC_CONSOLE)
early_platform_add_devices(fpga_early_devs,
ARRAY_SIZE(fpga_early_devs));
/*
* ARC console driver registers itself as an early platform driver
* of class "earlyprintk".
* Install it here, followed by probe of devices.
* The installation here doesn't require earlyprintk in command line
* To do so however, replace the lines below with
* parse_early_param();
* early_platform_driver_probe("earlyprintk", 1, 1);
* ^^
*/
early_platform_driver_register_all("earlyprintk");
early_platform_driver_probe("earlyprintk", 1, 0);
/*
* This is to make sure that arc uart would be preferred console
* despite one/more of following:
* -command line lacked "console=ttyARC0" or
* -CONFIG_VT_CONSOLE was enabled (for no reason whatsoever)
* Note that this needs to be done after above early console is reg,
* otherwise the early console never gets a chance to run.
*/
add_preferred_console("ttyARC", 0, "115200");
#endif
}
static void __init plat_fpga_early_init(void)
{
pr_info("[plat-arcfpga]: registering early dev resources\n");
setup_bvci_lat_unit();
arc_fpga_serial_init();
#ifdef CONFIG_SMP
iss_model_init_early_smp();
#endif
}
static struct of_dev_auxdata plat_auxdata_lookup[] __initdata = {
#if defined(CONFIG_SERIAL_ARC) || defined(CONFIG_SERIAL_ARC_MODULE)
OF_DEV_AUXDATA("snps,arc-uart", UART0_BASE, "arc-uart", arc_uart_info),
#endif
{}
};
static void __init plat_fpga_populate_dev(void)
{
pr_info("[plat-arcfpga]: registering device resources\n");
/*
* Traverses flattened DeviceTree - registering platform devices
* complete with their resources
*/
of_platform_populate(NULL, of_default_bus_match_table,
plat_auxdata_lookup, NULL);
}
/*----------------------- Machine Descriptions ------------------------------
*
* Machine description is simply a set of platform/board specific callbacks
* This is not directly related to DeviceTree based dynamic device creation,
* however as part of early device tree scan, we also select the right
* callback set, by matching the DT compatible name.
*/
static const char *aa4_compat[] __initdata = {
"snps,arc-angel4",
NULL,
};
MACHINE_START(ANGEL4, "angel4")
.dt_compat = aa4_compat,
.init_early = plat_fpga_early_init,
.init_machine = plat_fpga_populate_dev,
.init_irq = plat_fpga_init_IRQ,
#ifdef CONFIG_SMP
.init_smp = iss_model_init_smp,
#endif
MACHINE_END
static const char *ml509_compat[] __initdata = {
"snps,arc-ml509",
NULL,
};
MACHINE_START(ML509, "ml509")
.dt_compat = ml509_compat,
.init_early = plat_fpga_early_init,
.init_machine = plat_fpga_populate_dev,
.init_irq = plat_fpga_init_IRQ,
#ifdef CONFIG_SMP
.init_smp = iss_model_init_smp,
#endif
MACHINE_END
static const char *nsimosci_compat[] __initdata = {
"snps,nsimosci",
NULL,
};
MACHINE_START(NSIMOSCI, "nsimosci")
.dt_compat = nsimosci_compat,
.init_early = NULL,
.init_machine = plat_fpga_populate_dev,
.init_irq = NULL,
MACHINE_END

171
arch/arc/plat-arcfpga/smp.c Normal file
View File

@@ -0,0 +1,171 @@
/*
* ARC700 Simulation-only Extensions for SMP
*
* Copyright (C) 2004, 2007-2010, 2011-2012 Synopsys, Inc. (www.synopsys.com)
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* Vineet Gupta - 2012 : split off arch common and plat specific SMP
* Rajeshwar Ranga - 2007 : Interrupt Distribution Unit API's
*/
#include <linux/smp.h>
#include <linux/irq.h>
#include <plat/irq.h>
#include <plat/smp.h>
static char smp_cpuinfo_buf[128];
/*
*-------------------------------------------------------------------
* Platform specific callbacks expected by arch SMP code
*-------------------------------------------------------------------
*/
/*
* Master kick starting another CPU
*/
static void iss_model_smp_wakeup_cpu(int cpu, unsigned long pc)
{
/* setup the start PC */
write_aux_reg(ARC_AUX_XTL_REG_PARAM, pc);
/* Trigger WRITE_PC cmd for this cpu */
write_aux_reg(ARC_AUX_XTL_REG_CMD,
(ARC_XTL_CMD_WRITE_PC | (cpu << 8)));
/* Take the cpu out of Halt */
write_aux_reg(ARC_AUX_XTL_REG_CMD,
(ARC_XTL_CMD_CLEAR_HALT | (cpu << 8)));
}
/*
* Any SMP specific init any CPU does when it comes up.
* Here we setup the CPU to enable Inter-Processor-Interrupts
* Called for each CPU
* -Master : init_IRQ()
* -Other(s) : start_kernel_secondary()
*/
void iss_model_init_smp(unsigned int cpu)
{
/* Check if CPU is configured for more than 16 interrupts */
if (NR_IRQS <= 16 || get_hw_config_num_irq() <= 16)
panic("[arcfpga] IRQ system can't support IDU IPI\n");
idu_disable();
/****************************************************************
* IDU provides a set of Common IRQs, each of which can be dynamically
* attached to (1|many|all) CPUs.
* The Common IRQs [0-15] are mapped as CPU pvt [16-31]
*
* Here we use a simple 1:1 mapping:
* A CPU 'x' is wired to Common IRQ 'x'.
* So an IDU ASSERT on IRQ 'x' will trigger Interupt on CPU 'x', which
* makes up for our simple IPI plumbing.
*
* TBD: Have a dedicated multicast IRQ for sending IPIs to all CPUs
* w/o having to do one-at-a-time
******************************************************************/
/*
* Claim an IRQ which would trigger IPI on this CPU.
* In IDU parlance it involves setting up a cpu bitmask for the IRQ
* The bitmap here contains only 1 CPU (self).
*/
idu_irq_set_tgtcpu(cpu, 0x1 << cpu);
/* Set the IRQ destination to use the bitmask above */
idu_irq_set_mode(cpu, 7, /* XXX: IDU_IRQ_MOD_TCPU_ALLRECP: ISS bug */
IDU_IRQ_MODE_PULSE_TRIG);
idu_enable();
/* Attach the arch-common IPI ISR to our IDU IRQ */
smp_ipi_irq_setup(cpu, IDU_INTERRUPT_0 + cpu);
}
static void iss_model_ipi_send(void *arg)
{
struct cpumask *callmap = arg;
unsigned int cpu;
for_each_cpu(cpu, callmap)
idu_irq_assert(cpu);
}
static void iss_model_ipi_clear(int cpu, int irq)
{
idu_irq_clear(IDU_INTERRUPT_0 + cpu);
}
void iss_model_init_early_smp(void)
{
#define IS_AVAIL1(var, str) ((var) ? str : "")
struct bcr_mp mp;
READ_BCR(ARC_REG_MP_BCR, mp);
sprintf(smp_cpuinfo_buf, "Extn [ISS-SMP]: v%d, arch(%d) %s %s %s\n",
mp.ver, mp.mp_arch, IS_AVAIL1(mp.scu, "SCU"),
IS_AVAIL1(mp.idu, "IDU"), IS_AVAIL1(mp.sdu, "SDU"));
plat_smp_ops.info = smp_cpuinfo_buf;
plat_smp_ops.cpu_kick = iss_model_smp_wakeup_cpu;
plat_smp_ops.ipi_send = iss_model_ipi_send;
plat_smp_ops.ipi_clear = iss_model_ipi_clear;
}
/*
*-------------------------------------------------------------------
* Low level Platform IPI Providers
*-------------------------------------------------------------------
*/
/* Set the Mode for the Common IRQ */
void idu_irq_set_mode(uint8_t irq, uint8_t dest_mode, uint8_t trig_mode)
{
uint32_t par = IDU_IRQ_MODE_PARAM(dest_mode, trig_mode);
IDU_SET_PARAM(par);
IDU_SET_COMMAND(irq, IDU_IRQ_WMODE);
}
/* Set the target cpu Bitmask for Common IRQ */
void idu_irq_set_tgtcpu(uint8_t irq, uint32_t mask)
{
IDU_SET_PARAM(mask);
IDU_SET_COMMAND(irq, IDU_IRQ_WBITMASK);
}
/* Get the Interrupt Acknowledged status for IRQ (as CPU Bitmask) */
bool idu_irq_get_ack(uint8_t irq)
{
uint32_t val;
IDU_SET_COMMAND(irq, IDU_IRQ_ACK);
val = IDU_GET_PARAM();
return val & (1 << irq);
}
/*
* Get the Interrupt Pending status for IRQ (as CPU Bitmask)
* -Pending means CPU has not yet noticed the IRQ (e.g. disabled)
* -After Interrupt has been taken, the IPI expcitily needs to be
* cleared, to be acknowledged.
*/
bool idu_irq_get_pend(uint8_t irq)
{
uint32_t val;
IDU_SET_COMMAND(irq, IDU_IRQ_PEND);
val = IDU_GET_PARAM();
return val & (1 << irq);
}