diff options
| author | Bin Meng <bmeng.cn@gmail.com> | 2018-12-12 06:12:26 -0800 | 
|---|---|---|
| committer | Andes <uboot@andestech.com> | 2018-12-18 09:56:26 +0800 | 
| commit | 833508c05c1309624cd397dbea2714b723d58c35 (patch) | |
| tree | c1393f9b95f20d38e7c57dd7c14ab2aa7aaa55f9 | |
| parent | 27dc2c130e29093ba88630e8947d189641bda442 (diff) | |
cpu: Add a RISC-V CPU driver
This adds a driver for RISC-V CPU. Note the driver will bind
a RISC-V timer driver if "timebase-frequency" property is
present in the device tree.
Signed-off-by: Bin Meng <bmeng.cn@gmail.com>
Reviewed-by: Lukas Auer <lukas.auer@aisec.fraunhofer.de>
Reviewed-by: Anup Patel <anup@brainfault.org>
| -rw-r--r-- | drivers/cpu/Kconfig | 6 | ||||
| -rw-r--r-- | drivers/cpu/Makefile | 1 | ||||
| -rw-r--r-- | drivers/cpu/riscv_cpu.c | 116 | 
3 files changed, 123 insertions, 0 deletions
| diff --git a/drivers/cpu/Kconfig b/drivers/cpu/Kconfig index d4052005e24..3d5729f6dca 100644 --- a/drivers/cpu/Kconfig +++ b/drivers/cpu/Kconfig @@ -13,3 +13,9 @@ config CPU_MPC83XX  	select CLK_MPC83XX  	help  	  Support CPU cores for SoCs of the MPC83xx series. + +config CPU_RISCV +	bool "Enable RISC-V CPU driver" +	depends on CPU && RISCV +	help +	  Support CPU cores for RISC-V architecture. diff --git a/drivers/cpu/Makefile b/drivers/cpu/Makefile index 858b03755f5..be0300cd4a8 100644 --- a/drivers/cpu/Makefile +++ b/drivers/cpu/Makefile @@ -8,4 +8,5 @@ obj-$(CONFIG_CPU) += cpu-uclass.o  obj-$(CONFIG_ARCH_BMIPS) += bmips_cpu.o  obj-$(CONFIG_CPU_MPC83XX) += mpc83xx_cpu.o +obj-$(CONFIG_CPU_RISCV) += riscv_cpu.o  obj-$(CONFIG_SANDBOX) += cpu_sandbox.o diff --git a/drivers/cpu/riscv_cpu.c b/drivers/cpu/riscv_cpu.c new file mode 100644 index 00000000000..5e15df590e4 --- /dev/null +++ b/drivers/cpu/riscv_cpu.c @@ -0,0 +1,116 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2018, Bin Meng <bmeng.cn@gmail.com> + */ + +#include <common.h> +#include <cpu.h> +#include <dm.h> +#include <errno.h> +#include <dm/device-internal.h> +#include <dm/lists.h> + +static int riscv_cpu_get_desc(struct udevice *dev, char *buf, int size) +{ +	const char *isa; + +	isa = dev_read_string(dev, "riscv,isa"); +	if (size < (strlen(isa) + 1)) +		return -ENOSPC; + +	strcpy(buf, isa); + +	return 0; +} + +static int riscv_cpu_get_info(struct udevice *dev, struct cpu_info *info) +{ +	const char *mmu; + +	dev_read_u32(dev, "clock-frequency", (u32 *)&info->cpu_freq); + +	mmu = dev_read_string(dev, "mmu-type"); +	if (!mmu) +		info->features |= BIT(CPU_FEAT_MMU); + +	return 0; +} + +static int riscv_cpu_get_count(struct udevice *dev) +{ +	ofnode node; +	int num = 0; + +	ofnode_for_each_subnode(node, dev_ofnode(dev->parent)) { +		const char *device_type; + +		device_type = ofnode_read_string(node, "device_type"); +		if (!device_type) +			continue; +		if (strcmp(device_type, "cpu") == 0) +			num++; +	} + +	return num; +} + +static int riscv_cpu_bind(struct udevice *dev) +{ +	struct cpu_platdata *plat = dev_get_parent_platdata(dev); +	struct driver *drv; +	int ret; + +	/* save the hart id */ +	plat->cpu_id = dev_read_addr(dev); + +	/* first examine the property in current cpu node */ +	ret = dev_read_u32(dev, "timebase-frequency", &plat->timebase_freq); +	/* if not found, then look at the parent /cpus node */ +	if (ret) +		dev_read_u32(dev->parent, "timebase-frequency", +			     &plat->timebase_freq); + +	/* +	 * Bind riscv-timer driver on hart 0 +	 * +	 * We only instantiate one timer device which is enough for U-Boot. +	 * Pass the "timebase-frequency" value as the driver data for the +	 * timer device. +	 * +	 * Return value is not checked since it's possible that the timer +	 * driver is not included. +	 */ +	if (!plat->cpu_id && plat->timebase_freq) { +		drv = lists_driver_lookup_name("riscv_timer"); +		if (!drv) { +			debug("Cannot find the timer driver, not included?\n"); +			return 0; +		} + +		device_bind_with_driver_data(dev, drv, "riscv_timer", +					     plat->timebase_freq, ofnode_null(), +					     NULL); +	} + +	return 0; +} + +static const struct cpu_ops riscv_cpu_ops = { +	.get_desc	= riscv_cpu_get_desc, +	.get_info	= riscv_cpu_get_info, +	.get_count	= riscv_cpu_get_count, +}; + +static const struct udevice_id riscv_cpu_ids[] = { +	{ .compatible = "riscv" }, +	{ } +}; + +U_BOOT_DRIVER(riscv_cpu) = { +	.name = "riscv_cpu", +	.id = UCLASS_CPU, +	.of_match = riscv_cpu_ids, +	.bind = riscv_cpu_bind, +	.ops = &riscv_cpu_ops, +	.flags = DM_FLAG_PRE_RELOC, +}; | 
