Skip to content

Commit

Permalink
Merge tag 'for-linus' of git://github.com/openrisc/linux
Browse files Browse the repository at this point in the history
Pull OpenRISC updates from Stafford Horne:

 - Update for Litex SoC controller to support wider width registers as
   well as reset.

 - Refactor SMP code to use device tree to define possible cpus.

 - Update build including generating vmlinux.bin

* tag 'for-linus' of git://github.com/openrisc/linux:
  openrisc: Use devicetree to determine present cpus
  drivers/soc/litex: Add restart handler
  openrisc: add arch/openrisc/Kbuild
  drivers/soc/litex: make 'litex_[set|get]_reg()' methods private
  drivers/soc/litex: support 32-bit subregisters, 64-bit CPUs
  drivers/soc/litex: s/LITEX_REG_SIZE/LITEX_SUBREG_ALIGN/g
  drivers/soc/litex: separate MMIO from subregister offset calculation
  drivers/soc/litex: move generic accessors to litex.h
  openrisc: restart: Call common handlers before hanging
  openrisc: Add vmlinux.bin target
  • Loading branch information
torvalds committed Feb 26, 2021
2 parents e7270e4 + 8f722f6 commit a3905af
Show file tree
Hide file tree
Showing 9 changed files with 211 additions and 141 deletions.
3 changes: 3 additions & 0 deletions arch/openrisc/Kbuild
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# SPDX-License-Identifier: GPL-2.0
obj-y += lib/ kernel/ mm/
obj-y += boot/dts/
21 changes: 12 additions & 9 deletions arch/openrisc/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,10 @@ LIBGCC := $(shell $(CC) $(KBUILD_CFLAGS) -print-libgcc-file-name)

KBUILD_CFLAGS += -pipe -ffixed-r10 -D__linux__

all: vmlinux.bin

boot := arch/$(ARCH)/boot

ifeq ($(CONFIG_OPENRISC_HAVE_INST_MUL),y)
KBUILD_CFLAGS += $(call cc-option,-mhard-mul)
else
Expand All @@ -38,14 +42,13 @@ endif

head-y := arch/openrisc/kernel/head.o

core-y += arch/openrisc/lib/ \
arch/openrisc/kernel/ \
arch/openrisc/mm/
core-y += arch/openrisc/
libs-y += $(LIBGCC)

ifneq '$(CONFIG_OPENRISC_BUILTIN_DTB)' '""'
BUILTIN_DTB := y
else
BUILTIN_DTB := n
endif
core-$(BUILTIN_DTB) += arch/openrisc/boot/dts/
PHONY += vmlinux.bin

vmlinux.bin: vmlinux
$(Q)$(MAKE) $(build)=$(boot) $(boot)/$@

archclean:
$(Q)$(MAKE) $(clean)=$(boot)
2 changes: 2 additions & 0 deletions arch/openrisc/boot/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
# SPDX-License-Identifier: GPL-2.0
vmlinux.bin
10 changes: 10 additions & 0 deletions arch/openrisc/boot/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
# SPDX-License-Identifier: GPL-2.0
#
# Makefile for bootable kernel images
#

targets += vmlinux.bin

OBJCOPYFLAGS_vmlinux.bin := -O binary
$(obj)/vmlinux.bin: vmlinux FORCE
$(call if_changed,objcopy)
13 changes: 10 additions & 3 deletions arch/openrisc/kernel/process.c
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@
#include <linux/init_task.h>
#include <linux/mqueue.h>
#include <linux/fs.h>
#include <linux/reboot.h>

#include <linux/uaccess.h>
#include <asm/io.h>
Expand All @@ -49,10 +50,16 @@
*/
struct thread_info *current_thread_info_set[NR_CPUS] = { &init_thread_info, };

void machine_restart(void)
void machine_restart(char *cmd)
{
printk(KERN_INFO "*** MACHINE RESTART ***\n");
__asm__("l.nop 1");
do_kernel_restart(cmd);

/* Give a grace period for failure to restart of 1s */
mdelay(1000);

/* Whoops - the platform was unable to reboot. Tell the user! */
pr_emerg("Reboot failed -- System halted\n");
while (1);
}

/*
Expand Down
23 changes: 17 additions & 6 deletions arch/openrisc/kernel/smp.c
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
#include <linux/sched.h>
#include <linux/sched/mm.h>
#include <linux/irq.h>
#include <linux/of.h>
#include <asm/cpuinfo.h>
#include <asm/mmu_context.h>
#include <asm/tlbflush.h>
Expand Down Expand Up @@ -60,22 +61,32 @@ void __init smp_prepare_boot_cpu(void)

void __init smp_init_cpus(void)
{
int i;
struct device_node *cpu;
u32 cpu_id;

for (i = 0; i < NR_CPUS; i++)
set_cpu_possible(i, true);
for_each_of_cpu_node(cpu) {
if (of_property_read_u32(cpu, "reg", &cpu_id)) {
pr_warn("%s missing reg property", cpu->full_name);
continue;
}

if (cpu_id < NR_CPUS)
set_cpu_possible(cpu_id, true);
}
}

void __init smp_prepare_cpus(unsigned int max_cpus)
{
int i;
unsigned int cpu;

/*
* Initialise the present map, which describes the set of CPUs
* actually populated at the present time.
*/
for (i = 0; i < max_cpus; i++)
set_cpu_present(i, true);
for_each_possible_cpu(cpu) {
if (cpu < max_cpus)
set_cpu_present(cpu, true);
}
}

void __init smp_cpus_done(unsigned int max_cpus)
Expand Down
14 changes: 13 additions & 1 deletion drivers/soc/litex/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,21 @@ config LITEX_SOC_CONTROLLER
select LITEX
help
This option enables the SoC Controller Driver which verifies
LiteX CSR access and provides common litex_get_reg/litex_set_reg
LiteX CSR access and provides common litex_[read|write]*
accessors.
All drivers that use functions from litex.h must depend on
LITEX.

config LITEX_SUBREG_SIZE
int "Size of a LiteX CSR subregister, in bytes"
depends on LITEX
range 1 4
default 4
help
LiteX MMIO registers (referred to as Configuration and Status
registers, or CSRs) are spread across adjacent 8- or 32-bit
subregisters, located at 32-bit aligned MMIO addresses. Use
this to select the appropriate size (1 or 4 bytes) matching
your particular LiteX build.

endmenu
116 changes: 42 additions & 74 deletions drivers/soc/litex/litex_soc_ctrl.c
Original file line number Diff line number Diff line change
Expand Up @@ -15,79 +15,11 @@
#include <linux/module.h>
#include <linux/errno.h>
#include <linux/io.h>
#include <linux/reboot.h>

/*
* LiteX SoC Generator, depending on the configuration, can split a single
* logical CSR (Control&Status Register) into a series of consecutive physical
* registers.
*
* For example, in the configuration with 8-bit CSR Bus, 32-bit aligned (the
* default one for 32-bit CPUs) a 32-bit logical CSR will be generated as four
* 32-bit physical registers, each one containing one byte of meaningful data.
*
* For details see: https://github.com/enjoy-digital/litex/wiki/CSR-Bus
*
* The purpose of `litex_set_reg`/`litex_get_reg` is to implement the logic
* of writing to/reading from the LiteX CSR in a single place that can be
* then reused by all LiteX drivers.
*/

/**
* litex_set_reg() - Writes the value to the LiteX CSR (Control&Status Register)
* @reg: Address of the CSR
* @reg_size: The width of the CSR expressed in the number of bytes
* @val: Value to be written to the CSR
*
* In the currently supported LiteX configuration (8-bit CSR Bus, 32-bit aligned),
* a 32-bit LiteX CSR is generated as 4 consecutive 32-bit physical registers,
* each one containing one byte of meaningful data.
*
* This function splits a single possibly multi-byte write into a series of
* single-byte writes with a proper offset.
*/
void litex_set_reg(void __iomem *reg, unsigned long reg_size,
unsigned long val)
{
unsigned long shifted_data, shift, i;

for (i = 0; i < reg_size; ++i) {
shift = ((reg_size - i - 1) * LITEX_SUBREG_SIZE_BIT);
shifted_data = val >> shift;

WRITE_LITEX_SUBREGISTER(shifted_data, reg, i);
}
}
EXPORT_SYMBOL_GPL(litex_set_reg);

/**
* litex_get_reg() - Reads the value of the LiteX CSR (Control&Status Register)
* @reg: Address of the CSR
* @reg_size: The width of the CSR expressed in the number of bytes
*
* Return: Value read from the CSR
*
* In the currently supported LiteX configuration (8-bit CSR Bus, 32-bit aligned),
* a 32-bit LiteX CSR is generated as 4 consecutive 32-bit physical registers,
* each one containing one byte of meaningful data.
*
* This function generates a series of single-byte reads with a proper offset
* and joins their results into a single multi-byte value.
*/
unsigned long litex_get_reg(void __iomem *reg, unsigned long reg_size)
{
unsigned long shifted_data, shift, i;
unsigned long result = 0;

for (i = 0; i < reg_size; ++i) {
shifted_data = READ_LITEX_SUBREGISTER(reg, i);

shift = ((reg_size - i - 1) * LITEX_SUBREG_SIZE_BIT);
result |= (shifted_data << shift);
}

return result;
}
EXPORT_SYMBOL_GPL(litex_get_reg);
/* reset register located at the base address */
#define RESET_REG_OFF 0x00
#define RESET_REG_VALUE 0x00000001

#define SCRATCH_REG_OFF 0x04
#define SCRATCH_REG_VALUE 0x12345678
Expand Down Expand Up @@ -131,15 +63,27 @@ static int litex_check_csr_access(void __iomem *reg_addr)
/* restore original value of the SCRATCH register */
litex_write32(reg_addr + SCRATCH_REG_OFF, SCRATCH_REG_VALUE);

pr_info("LiteX SoC Controller driver initialized");
pr_info("LiteX SoC Controller driver initialized: subreg:%d, align:%d",
LITEX_SUBREG_SIZE, LITEX_SUBREG_ALIGN);

return 0;
}

struct litex_soc_ctrl_device {
void __iomem *base;
struct notifier_block reset_nb;
};

static int litex_reset_handler(struct notifier_block *this, unsigned long mode,
void *cmd)
{
struct litex_soc_ctrl_device *soc_ctrl_dev =
container_of(this, struct litex_soc_ctrl_device, reset_nb);

litex_write32(soc_ctrl_dev->base + RESET_REG_OFF, RESET_REG_VALUE);
return NOTIFY_DONE;
}

#ifdef CONFIG_OF
static const struct of_device_id litex_soc_ctrl_of_match[] = {
{.compatible = "litex,soc-controller"},
Expand All @@ -151,6 +95,7 @@ MODULE_DEVICE_TABLE(of, litex_soc_ctrl_of_match);
static int litex_soc_ctrl_probe(struct platform_device *pdev)
{
struct litex_soc_ctrl_device *soc_ctrl_dev;
int error;

soc_ctrl_dev = devm_kzalloc(&pdev->dev, sizeof(*soc_ctrl_dev), GFP_KERNEL);
if (!soc_ctrl_dev)
Expand All @@ -160,7 +105,29 @@ static int litex_soc_ctrl_probe(struct platform_device *pdev)
if (IS_ERR(soc_ctrl_dev->base))
return PTR_ERR(soc_ctrl_dev->base);

return litex_check_csr_access(soc_ctrl_dev->base);
error = litex_check_csr_access(soc_ctrl_dev->base);
if (error)
return error;

platform_set_drvdata(pdev, soc_ctrl_dev);

soc_ctrl_dev->reset_nb.notifier_call = litex_reset_handler;
soc_ctrl_dev->reset_nb.priority = 128;
error = register_restart_handler(&soc_ctrl_dev->reset_nb);
if (error) {
dev_warn(&pdev->dev, "cannot register restart handler: %d\n",
error);
}

return 0;
}

static int litex_soc_ctrl_remove(struct platform_device *pdev)
{
struct litex_soc_ctrl_device *soc_ctrl_dev = platform_get_drvdata(pdev);

unregister_restart_handler(&soc_ctrl_dev->reset_nb);
return 0;
}

static struct platform_driver litex_soc_ctrl_driver = {
Expand All @@ -169,6 +136,7 @@ static struct platform_driver litex_soc_ctrl_driver = {
.of_match_table = of_match_ptr(litex_soc_ctrl_of_match)
},
.probe = litex_soc_ctrl_probe,
.remove = litex_soc_ctrl_remove,
};

module_platform_driver(litex_soc_ctrl_driver);
Expand Down
Loading

0 comments on commit a3905af

Please sign in to comment.