Commit c0d60a8d authored by Jing Li's avatar Jing Li Committed by guzitao
Browse files

sw64: get mclk and external clk from firmware

Sunway inclusion
category: feature
bugzilla: https://gitee.com/openeuler/kernel/issues/IB73UR



--------------------------------

Starting from junzhang, kernel will not directly access Motherboard
Configuration Tables to get mclk and external clk. Instead, kernel get
mclk and external clk from firmware.

This commit will not break backward compatibility.

Signed-off-by: default avatarJing Li <jingli@wxiat.com>
Reviewed-by: default avatarHe Sheng <hesheng@wxiat.com>
Signed-off-by: default avatarGu Zitao <guzitao@wxiat.com>
parent b6fc016c
Loading
Loading
Loading
Loading
+12 −4
Original line number Diff line number Diff line
@@ -38,7 +38,13 @@
#define INITRD_START_OFF	(0x10000UL - 0xA100UL)
#define INITRD_SIZE_OFF		(0x10000UL - 0xA108UL)

/* Motherboard Configuration Tables */
/**
 * Motherboard Configuration Tables
 *
 * Starting from junzhang, we will not directly access Motherboard
 * Configuration Tables in kernel. These macros and related code can
 * be removed when kernel no longer support C3B(xuelang).
 */
#define	MB_CONFIG_START		0x908000
#define	MB_MCLK			(MB_CONFIG_START + 0x1)
#define	MB_EXTCLK		(MB_CONFIG_START + 0x11)
@@ -46,6 +52,8 @@
#ifndef __ASSEMBLY__
#include <asm/bootparam.h>
extern struct boot_params *sunway_boot_params;
extern u64 sunway_mclk_hz;
extern u64 sunway_extclk_hz;
#endif

#endif /* _ASM_SW64_SETUP_H */
+66 −0
Original line number Diff line number Diff line
@@ -19,6 +19,7 @@
#endif
#include <linux/of_fdt.h>
#include <linux/of_platform.h>
#include <linux/libfdt.h>
#include <linux/genalloc.h>
#include <linux/acpi.h>
#include <linux/cpu.h>
@@ -131,6 +132,9 @@ EXPORT_SYMBOL(sunway_boot_magic);
unsigned long sunway_dtb_address;
EXPORT_SYMBOL(sunway_dtb_address);

u64 sunway_mclk_hz;
u64 sunway_extclk_hz;

/*
 * The format of "screen_info" is strange, and due to early
 * i386-setup code. This is just enough to make the console
@@ -549,6 +553,34 @@ static bool __init arch_dtb_verify(void *dt_virt, bool from_firmware)
	return true;
}

static void early_parse_fdt_property(const void *fdt, const char *path,
		const char *prop_name, u64 *property, int size)
{
	int node, prop_len;
	const __be32 *prop;

	if (!path || !prop_name)
		return;

	node = fdt_path_offset(fdt, path);
	if (node < 0) {
		pr_err("Failed to get node [%s]\n", path);
		return;
	}

	prop = fdt_getprop(initial_boot_params, node, prop_name, &prop_len);
	if (!prop) {
		pr_err("Failed to get property [%s]\n", prop_name);
		return;
	}

	if (prop_len != size)
		pr_warn("Expect [%s] %d bytes, but %d bytes\n",
				prop_name, size, prop_len);

	*property = of_read_number(prop, size / 4);
}

static void __init setup_firmware_fdt(void)
{
	void *dt_virt;
@@ -579,6 +611,18 @@ static void __init setup_firmware_fdt(void)
			cpu_relax();
	}

	if (sunway_boot_magic == 0xDEED2024UL) {
		/* Parse MCLK(Hz) from firmware DTB */
		early_parse_fdt_property(dt_virt, "/soc/clocks/mclk",
				"clock-frequency", &sunway_mclk_hz, sizeof(u32));
		pr_info("MCLK: %llu Hz\n", sunway_mclk_hz);

		/* Parse EXTCLK(Hz) from firmware DTB */
		early_parse_fdt_property(dt_virt, "/soc/clocks/extclk",
				"clock-frequency", &sunway_extclk_hz, sizeof(u32));
		pr_info("EXTCLK: %llu Hz\n", sunway_extclk_hz);
	}

	name = of_flat_dt_get_machine_name();
	if (name)
		pr_info("DTB(from firmware): Machine model: %s\n", name);
@@ -1019,6 +1063,28 @@ static int __init debugfs_sw64(void)
	return 0;
}
arch_initcall(debugfs_sw64);

static int __init debugfs_mclk_init(void)
{
	struct dentry *dir = sw64_debugfs_dir;
	static u64 mclk_mhz, mclk_hz;

	if (!dir)
		return -ENODEV;

	if (sunway_boot_magic != 0xDEED2024UL) {
		mclk_mhz = *((unsigned char *)__va(MB_MCLK));
		mclk_hz = mclk_mhz * 1000000;
		debugfs_create_u64("mclk", 0644, dir, &mclk_mhz);
		debugfs_create_u64("mclk_hz", 0644, dir, &mclk_hz);
	} else {
		mclk_hz = sunway_mclk_hz;
		debugfs_create_u64("mclk_hz", 0644, dir, &mclk_hz);
	}

	return 0;
}
late_initcall(debugfs_mclk_init);
#endif

#ifdef CONFIG_OF
+6 −1
Original line number Diff line number Diff line
@@ -47,7 +47,12 @@ early_param("mclk_khz", setup_mclk);

void __init sw64_setup_clocksource(void)
{
	unsigned long mclk_khz = *((unsigned char *)__va(MB_MCLK)) * 1000;
	unsigned long mclk_khz;

	if (sunway_mclk_hz)
		mclk_khz = sunway_mclk_hz / 1000;
	else
		mclk_khz = *((unsigned char *)__va(MB_MCLK)) * 1000;

	if (override_mclk_khz) {
		mclk_khz = override_mclk_khz;