[source] rbcfg: Implement CPU frequency control

LEDE Commits lede-commits at lists.infradead.org
Sat Oct 7 06:00:39 PDT 2017


jow pushed a commit to source.git, branch master:
https://git.lede-project.org/2be307c99852dc859730b531e9b1cc2f9776234b

commit 2be307c99852dc859730b531e9b1cc2f9776234b
Author: Thibaut VARENE <hacks at slashdirt.org>
AuthorDate: Sat Feb 25 17:34:50 2017 +0100

    rbcfg: Implement CPU frequency control
    
    This patch implements CPU frequency control as found on several
    routerboard devices.
    
    Supported SoCs:
    - QCA953X
    - AR9344
    
    Tested on hAP lite and mAP lite (QCA953x): steps of 50MHz
    Tested on LHG 5 (AR9344): steps of 50MHz
    
    On unsupported hardware, this patch is a NOP: it will not alter the
    new field.
    "rbcfg help" will display an empty "cpu_freq" help listing.
    "rbcfg show" will not show the cpu_freq field.
    "rbcfg set/get cpu_freq" will return an error code.
    
    Signed-off-by: Thibaut VARENE <hacks at slashdirt.org>
    [adjusted subject]
    Signed-off-by: Jo-Philipp Wich <jo at mein.io>
---
 package/boot/rbcfg/Makefile    |   2 +-
 package/boot/rbcfg/src/main.c  | 133 ++++++++++++++++++++++++++++++++++++++++-
 package/boot/rbcfg/src/rbcfg.h |   8 +++
 3 files changed, 139 insertions(+), 4 deletions(-)

diff --git a/package/boot/rbcfg/Makefile b/package/boot/rbcfg/Makefile
index 412f7ab..9d9b975 100644
--- a/package/boot/rbcfg/Makefile
+++ b/package/boot/rbcfg/Makefile
@@ -8,7 +8,7 @@
 include $(TOPDIR)/rules.mk
 
 PKG_NAME:=rbcfg
-PKG_RELEASE:=1
+PKG_RELEASE:=2
 
 PKG_BUILD_DIR := $(BUILD_DIR)/$(PKG_NAME)
 
diff --git a/package/boot/rbcfg/src/main.c b/package/boot/rbcfg/src/main.c
index 9aedcc5..2acbfbd 100644
--- a/package/boot/rbcfg/src/main.c
+++ b/package/boot/rbcfg/src/main.c
@@ -2,6 +2,7 @@
  *  RouterBOOT configuration utility
  *
  *  Copyright (C) 2010 Gabor Juhos <juhosg at openwrt.org>
+ *  Copyright (C) 2017 Thibaut VARENE <varenet at parisc-linux.org>
  *
  *  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
@@ -29,6 +30,7 @@
 #define RB_ERR_INVALID		2
 #define RB_ERR_NOMEM		3
 #define RB_ERR_IO		4
+#define RB_ERR_NOTWANTED	5
 
 #define ARRAY_SIZE(_a)	(sizeof((_a)) / sizeof((_a)[0]))
 
@@ -67,6 +69,11 @@ struct rbcfg_command {
 	int		(*exec)(int argc, const char *argv[]);
 };
 
+struct rbcfg_soc {
+	const char	*needle;
+	const int	type;
+};
+
 static void usage(void);
 
 /* Globals */
@@ -135,12 +142,32 @@ static const struct rbcfg_value rbcfg_cpu_mode[] = {
 		RB_CPU_MODE_REGULAR),
 };
 
+static const struct rbcfg_value rbcfg_cpu_freq_dummy[] = {
+};
+
+static const struct rbcfg_value rbcfg_cpu_freq_qca953x[] = {
+	CFG_U32("-2", "-100MHz", RB_CPU_FREQ_L2),
+	CFG_U32("-1", "- 50MHz", RB_CPU_FREQ_L1),
+	CFG_U32("0", "Factory", RB_CPU_FREQ_N0),
+	CFG_U32("+1", "+ 50MHz", RB_CPU_FREQ_H1),
+	CFG_U32("+2", "+100MHz", RB_CPU_FREQ_H2),
+};
+
+static const struct rbcfg_value rbcfg_cpu_freq_ar9344[] = {
+	CFG_U32("-2", "-100MHz", RB_CPU_FREQ_L2),
+	CFG_U32("-1", "- 50MHz", RB_CPU_FREQ_L1),
+	CFG_U32("0", "Factory", RB_CPU_FREQ_N0),
+	CFG_U32("+1", "+ 50MHz", RB_CPU_FREQ_H1),
+	CFG_U32("+2", "+100MHz", RB_CPU_FREQ_H2),
+	CFG_U32("+3", "+150MHz", RB_CPU_FREQ_H3),
+};
+
 static const struct rbcfg_value rbcfg_booter[] = {
 	CFG_U32("regular", "load regular booter", RB_BOOTER_REGULAR),
 	CFG_U32("backup", "force backup-booter loading", RB_BOOTER_BACKUP),
 };
 
-static const struct rbcfg_env rbcfg_envs[] = {
+static struct rbcfg_env rbcfg_envs[] = {
 	{
 		.name		= "boot_delay",
 		.id		= RB_ID_BOOT_DELAY,
@@ -178,6 +205,12 @@ static const struct rbcfg_env rbcfg_envs[] = {
 		.values		= rbcfg_cpu_mode,
 		.num_values	= ARRAY_SIZE(rbcfg_cpu_mode),
 	}, {
+		.name		= "cpu_freq",
+		.id		= RB_ID_CPU_FREQ,
+		.type		= RBCFG_ENV_TYPE_U32,
+		.values		= rbcfg_cpu_freq_dummy,
+		.num_values	= ARRAY_SIZE(rbcfg_cpu_freq_dummy),
+	}, {
 		.name		= "uart_speed",
 		.id		= RB_ID_UART_SPEED,
 		.type		= RBCFG_ENV_TYPE_U32,
@@ -240,8 +273,10 @@ rbcfg_find_tag(struct rbcfg_ctx *ctx, uint16_t tag_id, uint16_t *tag_len,
 		buf += 2;
 		buflen -= 2;
 
-		if (id == RB_ID_TERMINATOR)
+		if (id == RB_ID_TERMINATOR) {
+			ret = RB_ERR_NOTWANTED;
 			break;
+		}
 
 		if (buflen < len)
 			break;
@@ -257,7 +292,7 @@ rbcfg_find_tag(struct rbcfg_ctx *ctx, uint16_t tag_id, uint16_t *tag_len,
 		buflen -= len;
 	}
 
-	if (ret)
+	if (RB_ERR_NOTFOUND == ret)
 		fprintf(stderr, "no tag found with id=%u\n", tag_id);
 
 	return ret;
@@ -748,6 +783,96 @@ usage(void)
 	fprintf(stderr, "\n");
 }
 
+#define RBCFG_SOC_UNKNOWN	0
+#define RBCFG_SOC_QCA953X	1
+#define RBCFG_SOC_AR9344	2
+
+static const struct rbcfg_soc rbcfg_socs[] = {
+	{
+		.needle = "QCA953",
+		.type = RBCFG_SOC_QCA953X,
+	}, {
+		.needle = "AR9344",
+		.type = RBCFG_SOC_AR9344,
+	},
+};
+
+#define CPUINFO_BUFSIZE		128	/* lines of interest are < 80 chars */
+
+static int cpuinfo_find_soc(void)
+{
+	FILE *fp;
+	char temp[CPUINFO_BUFSIZE];
+	char *haystack, *needle;
+	int i, found = 0, soc_type = RBCFG_SOC_UNKNOWN;
+
+	fp = fopen("/proc/cpuinfo", "r");
+	if (!fp)
+		goto end;
+
+	/* first, extract the system type line */
+	needle = "system type";
+	while(fgets(temp, CPUINFO_BUFSIZE, fp)) {
+		if (!strncmp(temp, needle, strlen(needle))) {
+			found = 1;
+			break;
+		}
+	}
+
+	fclose(fp);
+
+	/* failsafe in case cpuinfo format changes */
+	if (!found)
+		goto end;
+
+	/* skip the field header */
+	haystack = strchr(temp, ':');
+
+	/* then, try to identify known SoC, stop at first match */
+	for (i = 0; i < ARRAY_SIZE(rbcfg_socs); i++) {
+		if ((strstr(haystack, rbcfg_socs[i].needle))) {
+			soc_type = rbcfg_socs[i].type;
+			break;
+		}
+	}
+
+end:
+	return soc_type;
+}
+
+static void fixup_rbcfg_envs(void)
+{
+	int i, num_val, soc_type;
+	const struct rbcfg_value * env_value;
+
+	/* detect SoC */
+	soc_type = cpuinfo_find_soc();
+
+	/* update rbcfg_envs */
+	switch (soc_type) {
+		case RBCFG_SOC_QCA953X:
+			env_value = rbcfg_cpu_freq_qca953x;
+			num_val = ARRAY_SIZE(rbcfg_cpu_freq_qca953x);
+			break;
+		case RBCFG_SOC_AR9344:
+			env_value = rbcfg_cpu_freq_ar9344;
+			num_val = ARRAY_SIZE(rbcfg_cpu_freq_ar9344);
+			break;
+	}
+
+	for (i = 0; i < ARRAY_SIZE(rbcfg_envs); i++) {
+		if (RB_ID_CPU_FREQ == rbcfg_envs[i].id) {
+			if (RBCFG_SOC_UNKNOWN == soc_type)
+				rbcfg_envs[i].id = RB_ID_TERMINATOR;
+			else {
+				rbcfg_envs[i].values = env_value;
+				rbcfg_envs[i].num_values = num_val;
+			}
+			break;
+		}
+	}
+}
+
 int main(int argc, const char *argv[])
 {
 	const struct rbcfg_command *cmd = NULL;
@@ -756,6 +881,8 @@ int main(int argc, const char *argv[])
 
 	rbcfg_name = (char *) argv[0];
 
+	fixup_rbcfg_envs();
+
 	if (argc < 2) {
 		usage();
 		return EXIT_FAILURE;
diff --git a/package/boot/rbcfg/src/rbcfg.h b/package/boot/rbcfg/src/rbcfg.h
index 864bc82..88acc13 100644
--- a/package/boot/rbcfg/src/rbcfg.h
+++ b/package/boot/rbcfg/src/rbcfg.h
@@ -32,6 +32,7 @@
 #define RB_ID_BOOT_PROTOCOL	9
 #define RB_ID_SOFT_10		10
 #define RB_ID_SOFT_11		11
+#define RB_ID_CPU_FREQ		12
 #define RB_ID_BOOTER		13
 
 #define RB_UART_SPEED_115200	0
@@ -71,6 +72,13 @@
 #define RB_BOOT_PROTOCOL_BOOTP	0
 #define RB_BOOT_PROTOCOL_DHCP	1
 
+#define RB_CPU_FREQ_L2		(0 << 3)
+#define RB_CPU_FREQ_L1		(1 << 3)
+#define RB_CPU_FREQ_N0		(2 << 3)
+#define RB_CPU_FREQ_H1		(3 << 3)
+#define RB_CPU_FREQ_H2		(4 << 3)
+#define RB_CPU_FREQ_H3		(5 << 3)
+
 #define RB_BOOTER_REGULAR	0
 #define RB_BOOTER_BACKUP	1
 



More information about the lede-commits mailing list