+#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;
+ }
+ }
+}
+