OpenRISC updates for 6.20

The main focus for this series has been to improve OpenRISC
 kernel out-of-the-box support for FPGA dev boards.
 
  - Adds device tree configurations for De0 Nano single and
    multicore configurations.
  - Fixes bug in OpenRISC SMP preventing the kernel from running on FPGA
    boards, due to IPIs not being unmasked on secondary CPUs in some
    configurations.
  - Picked up a fix from Brian Masney defining the nop() macro to fix
    build failures on OpenRISC for drivers using the nop() macro.
 -----BEGIN PGP SIGNATURE-----
 
 iQIzBAABCgAdFiEE2cRzVK74bBA6Je/xw7McLV5mJ+QFAmmFyyUACgkQw7McLV5m
 J+R31hAAuT9ZRx/CxqhhMKw4Zgr0tGYYUJ0sPHxqVScIStmX18Ds7a4jyHpYSpuo
 EVW27/IIhfNbC6uphGDA0mRcPEr/7GF3XSCzA/GeiC3hUzAALvqf5gZdxldgcDIq
 g4FZvNNEDaVksUeyWhKMW3cuZUFZtBR2YuAAC4vMYRwQ1SmEozVS5H3+/ek3nQ3Y
 MbKoI9kANC2JRcnp4pzxlC4VSufO4NrFl/9yOUhNtlLxiYPnN7910RWfwGMIOHVD
 TMTU4JJPOaCmVEpIBlQ2y5TeuU+9CTjp0Z/0FbtrP+arhfjEcTwTpACT4ThyGpUb
 xawVfd8BI9iRdGZGw9TRYgo+lz0r8D9i7njVGaDbP6mNjL7QPLAXVUzDwN7fcF1g
 7brvm4PEWSXSYPbaswdf9nkC7Qw/eOltzj5KTNqwiK6+mDCXeA2xXbNkZx/xOmXT
 JJEK+eBSk5vMJiJ5N4sARWFUjwvWbYaeW92e8WQcCBh8NGK9TluuJ/4pAZn2Kg31
 C3SQHjpNFSiBT16kPJsKp2JOoqRn/8SwqdAf2Qou6BKo7Q9N+0y9nvEpyFcmsAI7
 32Nrp7QmtdBxHjxWAnfx6Lc67ycPtcotHKH64/18LX+S36kwa/khxYxR4+/r0Scf
 /ERGbTBEjQjxG52Ne7ivhBNekCc3gKkGO6/8KsYLp18Hu/mdpEQ=
 =e/WD
 -----END PGP SIGNATURE-----

Merge tag 'for-linus' of https://github.com/openrisc/linux

Pull OpenRISC updates from Stafford Horne:
 "The main focus for this series has been to improve OpenRISC kernel
  out-of-the-box support for FPGA dev boards.

   - Add device tree configurations for De0 Nano single and multicore
     configurations

   - Fix bug in OpenRISC SMP preventing the kernel from running on FPGA
     boards, due to IPIs not being unmasked on secondary CPUs in some
     configurations

   - Pick up a fix from Brian Masney defining the nop() macro to fix
     build failures on OpenRISC for drivers using it"

* tag 'for-linus' of https://github.com/openrisc/linux:
  openrisc: define arch-specific version of nop()
  openrisc: dts: Add de0 nano multicore config and devicetree
  openrisc: dts: Split simple smp dts to dts and dtsi
  openrisc: Fix IPIs on simple multicore systems
  openrisc: dts: Add de0 nano config and devicetree
This commit is contained in:
Linus Torvalds 2026-02-12 14:04:43 -08:00
commit a67594c977
13 changed files with 386 additions and 15 deletions

View file

@ -0,0 +1,42 @@
// SPDX-License-Identifier: GPL-2.0
#include <dt-bindings/gpio/gpio.h>
#include <dt-bindings/leds/common.h>
/ {
leds0: leds {
compatible = "gpio-leds";
led-heartbeat {
gpios = <&gpio0 0 GPIO_ACTIVE_HIGH>;
color = <LED_COLOR_ID_GREEN>;
function = LED_FUNCTION_HEARTBEAT;
linux,default-trigger = "heartbeat";
label = "heartbeat";
};
};
memory@0 {
device_type = "memory";
reg = <0x00000000 0x02000000>;
};
/* 8 Green LEDs */
gpio0: gpio@91000000 {
compatible = "opencores,gpio";
reg = <0x91000000 0x1>, <0x91000001 0x1>;
reg-names = "dat", "dirout";
gpio-controller;
#gpio-cells = <2>;
};
/* 4 DIP Switches */
gpio1: gpio@92000000 {
compatible = "opencores,gpio";
reg = <0x92000000 0x1>, <0x92000001 0x1>;
reg-names = "dat", "dirout";
gpio-controller;
#gpio-cells = <2>;
status = "disabled";
};
};

View file

@ -0,0 +1,25 @@
// SPDX-License-Identifier: GPL-2.0
#include <dt-bindings/gpio/gpio.h>
#include <dt-bindings/leds/common.h>
/dts-v1/;
#include "simple-smp.dtsi"
#include "de0-nano-common.dtsi"
/ {
model = "Terasic DE0 Nano - Multicore";
};
&cpu0 {
clock-frequency = <50000000>;
};
&cpu1 {
clock-frequency = <50000000>;
};
&serial0 {
clock-frequency = <50000000>;
};

View file

@ -0,0 +1,54 @@
// SPDX-License-Identifier: GPL-2.0
/dts-v1/;
#include "de0-nano-common.dtsi"
/ {
model = "Terasic DE0 Nano";
compatible = "opencores,or1ksim";
#address-cells = <1>;
#size-cells = <1>;
interrupt-parent = <&pic>;
aliases {
uart0 = &serial0;
};
chosen {
stdout-path = "uart0:115200";
};
cpus {
#address-cells = <1>;
#size-cells = <0>;
cpu@0 {
compatible = "opencores,or1200-rtlsvn481";
reg = <0>;
clock-frequency = <50000000>;
};
};
/*
* OR1K PIC is built into CPU and accessed via special purpose
* registers. It is not addressable and, hence, has no 'reg'
* property.
*/
pic: pic {
compatible = "opencores,or1k-pic";
#interrupt-cells = <1>;
interrupt-controller;
};
serial0: serial@90000000 {
compatible = "opencores,uart16550-rtlsvn105", "ns16550a";
reg = <0x90000000 0x100>;
interrupts = <2>;
clock-frequency = <50000000>;
};
};
&gpio1 {
status = "okay";
};

View file

@ -0,0 +1,25 @@
// SPDX-License-Identifier: GPL-2.0
/dts-v1/;
#include "simple-smp.dtsi"
/ {
model = "Simple SMP Board";
};
&cpu0 {
clock-frequency = <20000000>;
};
&cpu1 {
clock-frequency = <20000000>;
};
&enet0 {
status = "okay";
};
&serial0 {
clock-frequency = <20000000>;
};

View file

@ -1,4 +1,3 @@
/dts-v1/;
/ {
compatible = "opencores,or1ksim";
#address-cells = <1>;
@ -22,15 +21,15 @@
cpus {
#address-cells = <1>;
#size-cells = <0>;
cpu@0 {
cpu0: cpu@0 {
compatible = "opencores,or1200-rtlsvn481";
reg = <0>;
clock-frequency = <20000000>;
};
cpu@1 {
cpu1: cpu@1 {
compatible = "opencores,or1200-rtlsvn481";
reg = <1>;
clock-frequency = <20000000>;
};
};
@ -57,7 +56,6 @@
compatible = "opencores,uart16550-rtlsvn105", "ns16550a";
reg = <0x90000000 0x100>;
interrupts = <2>;
clock-frequency = <20000000>;
};
enet0: ethoc@92000000 {
@ -65,5 +63,6 @@
reg = <0x92000000 0x800>;
interrupts = <4>;
big-endian;
status = "disabled";
};
};

View file

@ -0,0 +1,79 @@
CONFIG_SYSVIPC=y
CONFIG_NO_HZ=y
CONFIG_LOG_BUF_SHIFT=14
CONFIG_BLK_DEV_INITRD=y
# CONFIG_RD_GZIP is not set
# CONFIG_RD_LZMA is not set
# CONFIG_RD_LZO is not set
# CONFIG_RD_LZ4 is not set
# CONFIG_RD_ZSTD is not set
CONFIG_EXPERT=y
# CONFIG_EPOLL is not set
# CONFIG_TIMERFD is not set
# CONFIG_EVENTFD is not set
# CONFIG_AIO is not set
CONFIG_BUILTIN_DTB_NAME="de0-nano"
# CONFIG_FPU is not set
CONFIG_HZ_100=y
# CONFIG_BLOCK is not set
CONFIG_SLUB_TINY=y
# CONFIG_COMPAT_BRK is not set
# CONFIG_VM_EVENT_COUNTERS is not set
CONFIG_NET=y
CONFIG_UNIX=y
CONFIG_UNIX_DIAG=y
CONFIG_INET=y
CONFIG_IP_MULTICAST=y
CONFIG_INET_UDP_DIAG=y
CONFIG_INET_RAW_DIAG=y
CONFIG_INET_DIAG_DESTROY=y
# CONFIG_IPV6 is not set
CONFIG_DEVTMPFS=y
CONFIG_DEVTMPFS_MOUNT=y
# CONFIG_PREVENT_FIRMWARE_BUILD is not set
# CONFIG_FW_LOADER is not set
# CONFIG_INPUT is not set
# CONFIG_SERIO is not set
# CONFIG_VT is not set
# CONFIG_LEGACY_PTYS is not set
CONFIG_SERIAL_8250=y
CONFIG_SERIAL_8250_CONSOLE=y
CONFIG_SERIAL_OF_PLATFORM=y
# CONFIG_HW_RANDOM is not set
CONFIG_PPS=y
CONFIG_GPIO_SYSFS=y
# CONFIG_GPIO_SYSFS_LEGACY is not set
CONFIG_GPIO_GENERIC_PLATFORM=y
# CONFIG_HWMON is not set
# CONFIG_USB_SUPPORT is not set
CONFIG_NEW_LEDS=y
CONFIG_LEDS_CLASS=y
CONFIG_LEDS_GPIO=y
CONFIG_LEDS_TRIGGERS=y
CONFIG_LEDS_TRIGGER_TIMER=y
CONFIG_LEDS_TRIGGER_ONESHOT=y
CONFIG_LEDS_TRIGGER_HEARTBEAT=y
CONFIG_LEDS_TRIGGER_CPU=y
CONFIG_LEDS_TRIGGER_ACTIVITY=y
CONFIG_LEDS_TRIGGER_GPIO=y
CONFIG_LEDS_TRIGGER_DEFAULT_ON=y
CONFIG_LEDS_TRIGGER_TRANSIENT=y
CONFIG_LEDS_TRIGGER_PANIC=y
CONFIG_LEDS_TRIGGER_NETDEV=y
CONFIG_LEDS_TRIGGER_PATTERN=y
CONFIG_LEDS_TRIGGER_TTY=y
# CONFIG_VIRTIO_MENU is not set
# CONFIG_VHOST_MENU is not set
# CONFIG_DNOTIFY is not set
CONFIG_TMPFS=y
# CONFIG_XZ_DEC_X86 is not set
# CONFIG_XZ_DEC_POWERPC is not set
# CONFIG_XZ_DEC_ARM is not set
# CONFIG_XZ_DEC_ARMTHUMB is not set
# CONFIG_XZ_DEC_ARM64 is not set
# CONFIG_XZ_DEC_SPARC is not set
# CONFIG_XZ_DEC_RISCV is not set
CONFIG_PRINTK_TIME=y
# CONFIG_DEBUG_MISC is not set
# CONFIG_FTRACE is not set
# CONFIG_RUNTIME_TESTING_MENU is not set

View file

@ -0,0 +1,92 @@
CONFIG_LOCALVERSION="-de0nano-smp"
CONFIG_SYSVIPC=y
CONFIG_POSIX_MQUEUE=y
CONFIG_NO_HZ=y
CONFIG_LOG_BUF_SHIFT=14
CONFIG_BLK_DEV_INITRD=y
# CONFIG_RD_GZIP is not set
# CONFIG_RD_BZIP2 is not set
# CONFIG_RD_LZMA is not set
# CONFIG_RD_XZ is not set
# CONFIG_RD_LZO is not set
# CONFIG_RD_LZ4 is not set
CONFIG_EXPERT=y
# CONFIG_EPOLL is not set
# CONFIG_TIMERFD is not set
# CONFIG_EVENTFD is not set
# CONFIG_AIO is not set
CONFIG_KALLSYMS_ALL=y
CONFIG_DCACHE_WRITETHROUGH=y
CONFIG_BUILTIN_DTB_NAME="de0-nano-multicore"
CONFIG_OPENRISC_HAVE_INST_CMOV=y
CONFIG_SMP=y
CONFIG_HZ_100=y
CONFIG_JUMP_LABEL=y
# CONFIG_BLOCK is not set
CONFIG_SLUB_TINY=y
# CONFIG_COMPAT_BRK is not set
# CONFIG_VM_EVENT_COUNTERS is not set
CONFIG_NET=y
CONFIG_PACKET=y
CONFIG_UNIX=y
CONFIG_UNIX_DIAG=y
CONFIG_INET=y
CONFIG_IP_MULTICAST=y
CONFIG_TCP_CONG_ADVANCED=y
# CONFIG_TCP_CONG_BIC is not set
# CONFIG_TCP_CONG_CUBIC is not set
# CONFIG_TCP_CONG_WESTWOOD is not set
# CONFIG_TCP_CONG_HTCP is not set
# CONFIG_IPV6 is not set
# CONFIG_WIRELESS is not set
CONFIG_DEVTMPFS=y
CONFIG_DEVTMPFS_MOUNT=y
# CONFIG_PREVENT_FIRMWARE_BUILD is not set
# CONFIG_FW_LOADER is not set
CONFIG_NETDEVICES=y
CONFIG_ETHOC=y
CONFIG_MICREL_PHY=y
# CONFIG_WLAN is not set
# CONFIG_INPUT is not set
# CONFIG_SERIO is not set
# CONFIG_VT is not set
# CONFIG_LEGACY_PTYS is not set
CONFIG_SERIAL_8250=y
CONFIG_SERIAL_8250_CONSOLE=y
CONFIG_SERIAL_OF_PLATFORM=y
# CONFIG_HW_RANDOM is not set
CONFIG_GPIO_SYSFS=y
# CONFIG_GPIO_CDEV_V1 is not set
CONFIG_GPIO_GENERIC_PLATFORM=y
# CONFIG_HWMON is not set
# CONFIG_USB_SUPPORT is not set
CONFIG_NEW_LEDS=y
CONFIG_LEDS_CLASS=y
CONFIG_LEDS_GPIO=y
CONFIG_LEDS_TRIGGERS=y
CONFIG_LEDS_TRIGGER_TIMER=y
CONFIG_LEDS_TRIGGER_ONESHOT=y
CONFIG_LEDS_TRIGGER_HEARTBEAT=y
CONFIG_LEDS_TRIGGER_CPU=y
CONFIG_LEDS_TRIGGER_ACTIVITY=y
CONFIG_LEDS_TRIGGER_GPIO=y
CONFIG_LEDS_TRIGGER_DEFAULT_ON=y
CONFIG_LEDS_TRIGGER_TRANSIENT=y
CONFIG_LEDS_TRIGGER_PANIC=y
CONFIG_LEDS_TRIGGER_NETDEV=y
CONFIG_LEDS_TRIGGER_PATTERN=y
CONFIG_LEDS_TRIGGER_TTY=y
# CONFIG_DNOTIFY is not set
CONFIG_TMPFS=y
CONFIG_NFS_FS=y
CONFIG_XZ_DEC=y
CONFIG_PRINTK_TIME=y
CONFIG_DEBUG_INFO_DWARF_TOOLCHAIN_DEFAULT=y
CONFIG_GDB_SCRIPTS=y
CONFIG_VMLINUX_MAP=y
CONFIG_HARDLOCKUP_DETECTOR=y
CONFIG_WQ_WATCHDOG=y
CONFIG_WQ_CPU_INTENSIVE_REPORT=y
CONFIG_STACKTRACE=y
CONFIG_RCU_CPU_STALL_CPUTIME=y
# CONFIG_RCU_TRACE is not set

View file

@ -20,7 +20,7 @@ CONFIG_SLUB=y
CONFIG_SLUB_TINY=y
CONFIG_MODULES=y
# CONFIG_BLOCK is not set
CONFIG_BUILTIN_DTB_NAME="simple_smp"
CONFIG_BUILTIN_DTB_NAME="simple-smp"
CONFIG_SMP=y
CONFIG_HZ_100=y
CONFIG_OPENRISC_HAVE_SHADOW_GPRS=y

View file

@ -4,6 +4,8 @@
#define mb() asm volatile ("l.msync" ::: "memory")
#define nop() asm volatile ("l.nop")
#include <asm-generic/barrier.h>
#endif /* __ASM_BARRIER_H */

View file

@ -20,7 +20,8 @@ extern void smp_init_cpus(void);
extern void arch_send_call_function_single_ipi(int cpu);
extern void arch_send_call_function_ipi_mask(const struct cpumask *mask);
extern void set_smp_cross_call(void (*)(const struct cpumask *, unsigned int));
extern void set_smp_cross_call(void (*)(const struct cpumask *, unsigned int),
unsigned int irq);
extern void handle_IPI(unsigned int ipi_msg);
#endif /* __ASM_OPENRISC_SMP_H */

View file

@ -13,6 +13,7 @@
#include <linux/smp.h>
#include <linux/cpu.h>
#include <linux/interrupt.h>
#include <linux/sched.h>
#include <linux/sched/mm.h>
#include <linux/irq.h>
@ -25,6 +26,7 @@
asmlinkage __init void secondary_start_kernel(void);
static unsigned int ipi_irq __ro_after_init;
static void (*smp_cross_call)(const struct cpumask *, unsigned int);
unsigned long secondary_release = -1;
@ -39,6 +41,14 @@ enum ipi_msg_type {
static DEFINE_SPINLOCK(boot_lock);
static void or1k_ipi_enable(void)
{
if (WARN_ON_ONCE(!ipi_irq))
return;
enable_percpu_irq(ipi_irq, 0);
}
static void boot_secondary(unsigned int cpu, struct task_struct *idle)
{
/*
@ -136,6 +146,7 @@ asmlinkage __init void secondary_start_kernel(void)
complete(&cpu_running);
synchronise_count_slave(cpu);
or1k_ipi_enable();
set_cpu_online(cpu, true);
local_irq_enable();
@ -195,9 +206,18 @@ void smp_send_stop(void)
smp_call_function(stop_this_cpu, NULL, 0);
}
void __init set_smp_cross_call(void (*fn)(const struct cpumask *, unsigned int))
void __init set_smp_cross_call(void (*fn)(const struct cpumask *, unsigned int),
unsigned int irq)
{
if (WARN_ON(ipi_irq))
return;
smp_cross_call = fn;
ipi_irq = irq;
/* Enabled IPIs for boot CPU immediately */
or1k_ipi_enable();
}
void arch_send_call_function_single_ipi(int cpu)

View file

@ -84,6 +84,8 @@ DEFINE_PER_CPU(unsigned long, ops);
static void __iomem *ompic_base;
static DEFINE_PER_CPU_READ_MOSTLY(int, ipi_dummy_dev);
static inline u32 ompic_readreg(void __iomem *base, loff_t offset)
{
return ioread32be(base + offset);
@ -183,12 +185,17 @@ static int __init ompic_of_init(struct device_node *node,
goto out_unmap;
}
ret = request_irq(irq, ompic_ipi_handler, IRQF_PERCPU,
"ompic_ipi", NULL);
if (ret)
goto out_irq_disp;
irq_set_percpu_devid(irq);
ret = request_percpu_irq(irq, ompic_ipi_handler, "ompic_ipi",
&ipi_dummy_dev);
set_smp_cross_call(ompic_raise_softirq);
if (ret) {
pr_err("ompic: failed to request irq %d, error: %d",
irq, ret);
goto out_irq_disp;
}
set_smp_cross_call(ompic_raise_softirq, irq);
return 0;

View file

@ -118,11 +118,36 @@ static void or1k_pic_handle_irq(struct pt_regs *regs)
generic_handle_domain_irq(root_domain, irq);
}
/*
* The OR1K PIC is a cpu-local interrupt controller and does not distinguish or
* use distinct irq number ranges for per-cpu event interrupts (IPI). Since
* information to determine whether a particular irq number should be treated as
* per-cpu is not available at mapping time, we use a wrapper handler function
* which chooses the right handler at runtime based on whether IRQF_PERCPU was
* used when requesting the irq. Borrowed from J-Core AIC.
*/
static void or1k_irq_flow_handler(struct irq_desc *desc)
{
#ifdef CONFIG_SMP
struct irq_data *data = irq_desc_get_irq_data(desc);
struct or1k_pic_dev *pic = data->domain->host_data;
if (irqd_is_per_cpu(data))
handle_percpu_devid_irq(desc);
else
pic->handle(desc);
#endif
}
static int or1k_map(struct irq_domain *d, unsigned int irq, irq_hw_number_t hw)
{
struct or1k_pic_dev *pic = d->host_data;
irq_set_chip_and_handler(irq, &pic->chip, pic->handle);
if (IS_ENABLED(CONFIG_SMP))
irq_set_chip_and_handler(irq, &pic->chip, or1k_irq_flow_handler);
else
irq_set_chip_and_handler(irq, &pic->chip, pic->handle);
irq_set_status_flags(irq, pic->flags);
return 0;