Page MenuHomeFreeBSD

D33140.id99468.diff
No OneTemporary

D33140.id99468.diff

Index: sys/dev/cpufreq/cpufreq_dt.c
===================================================================
--- sys/dev/cpufreq/cpufreq_dt.c
+++ sys/dev/cpufreq/cpufreq_dt.c
@@ -73,6 +73,8 @@
bool opp_suspend;
};
+#define CPUFREQ_DT_HAVE_REGULATOR(sc) ((sc)->reg != NULL)
+
struct cpufreq_dt_softc {
device_t dev;
clk_t clk;
@@ -181,24 +183,31 @@
device_printf(dev, "Can't get current clk freq\n");
return (ENXIO);
}
- /* Try to get current valtage by using regulator first. */
- error = regulator_get_voltage(sc->reg, &uvolt);
- if (error != 0) {
- /*
- * Try oppoints table as backup way. However,
- * this is insufficient because the actual processor
- * frequency may not be in the table. PLL frequency
- * granularity can be different that granularity of
- * oppoint table.
- */
- copp = cpufreq_dt_find_opp(sc->dev, freq);
- if (copp == NULL) {
- device_printf(dev,
- "Can't find the current freq in opp\n");
- return (ENOENT);
+
+ /*
+ * Only do the regulator work if it's required.
+ */
+ if (CPUFREQ_DT_HAVE_REGULATOR(sc)) {
+ /* Try to get current valtage by using regulator first. */
+ error = regulator_get_voltage(sc->reg, &uvolt);
+ if (error != 0) {
+ /*
+ * Try oppoints table as backup way. However,
+ * this is insufficient because the actual processor
+ * frequency may not be in the table. PLL frequency
+ * granularity can be different that granularity of
+ * oppoint table.
+ */
+ copp = cpufreq_dt_find_opp(sc->dev, freq);
+ if (copp == NULL) {
+ device_printf(dev,
+ "Can't find the current freq in opp\n");
+ return (ENOENT);
+ }
+ uvolt = copp->uvolt_target;
}
- uvolt = copp->uvolt_target;
- }
+ } else
+ uvolt = 0;
opp = cpufreq_dt_find_opp(sc->dev, set->freq * 1000000);
if (opp == NULL) {
@@ -209,7 +218,7 @@
DPRINTF(sc->dev, "Target freq %ju, , uvolt: %d\n",
opp->freq, opp->uvolt_target);
- if (uvolt < opp->uvolt_target) {
+ if (CPUFREQ_DT_HAVE_REGULATOR(sc) && (uvolt < opp->uvolt_target)) {
DPRINTF(dev, "Changing regulator from %u to %u\n",
uvolt, opp->uvolt_target);
error = regulator_set_voltage(sc->reg,
@@ -226,13 +235,14 @@
if (error != 0) {
DPRINTF(dev, "Failed, backout\n");
/* Restore previous voltage (best effort) */
- error = regulator_set_voltage(sc->reg,
- copp->uvolt_min,
- copp->uvolt_max);
+ if (CPUFREQ_DT_HAVE_REGULATOR(sc))
+ error = regulator_set_voltage(sc->reg,
+ copp->uvolt_min,
+ copp->uvolt_max);
return (ENXIO);
}
- if (uvolt > opp->uvolt_target) {
+ if (CPUFREQ_DT_HAVE_REGULATOR(sc) && (uvolt > opp->uvolt_target)) {
DPRINTF(dev, "Changing regulator from %u to %u\n",
uvolt, opp->uvolt_target);
error = regulator_set_voltage(sc->reg,
@@ -297,9 +307,7 @@
node = ofw_bus_get_node(parent);
/* The cpu@0 node must have the following properties */
- if (!OF_hasprop(node, "clocks") ||
- (!OF_hasprop(node, "cpu-supply") &&
- !OF_hasprop(node, "cpu0-supply")))
+ if (!OF_hasprop(node, "clocks"))
return;
if (!OF_hasprop(node, "operating-points") &&
@@ -321,10 +329,11 @@
node = ofw_bus_get_node(device_get_parent(dev));
- if (!OF_hasprop(node, "clocks") ||
- (!OF_hasprop(node, "cpu-supply") &&
- !OF_hasprop(node, "cpu0-supply")))
-
+ /*
+ * Note - supply isn't required here for probe; we'll check
+ * it out in more detail during attach.
+ */
+ if (!OF_hasprop(node, "clocks"))
return (ENXIO);
if (!OF_hasprop(node, "operating-points") &&
@@ -377,6 +386,10 @@
uint32_t *volts, lat;
int nvolt, i;
+ /*
+ * operating-points-v2 does not require the voltage entries
+ * and a regulator. So, it's OK if they're not there.
+ */
if (OF_getencprop(node, "operating-points-v2", &opp_xref,
sizeof(opp_xref)) == -1) {
device_printf(sc->dev, "Cannot get xref to oppv2 table\n");
@@ -419,24 +432,31 @@
if (OF_hasprop(opp_table, "opp-suspend"))
sc->opp[i].opp_suspend = true;
- nvolt = OF_getencprop_alloc_multi(opp_table, "opp-microvolt",
- sizeof(*volts), (void **)&volts);
- if (nvolt == 1) {
- sc->opp[i].uvolt_target = volts[0];
- sc->opp[i].uvolt_min = volts[0];
- sc->opp[i].uvolt_max = volts[0];
- } else if (nvolt == 3) {
- sc->opp[i].uvolt_target = volts[0];
- sc->opp[i].uvolt_min = volts[1];
- sc->opp[i].uvolt_max = volts[2];
- } else {
- device_printf(sc->dev,
- "Wrong count of opp-microvolt property\n");
+ if (CPUFREQ_DT_HAVE_REGULATOR(sc)) {
+ nvolt = OF_getencprop_alloc_multi(opp_table,
+ "opp-microvolt", sizeof(*volts), (void **)&volts);
+ if (nvolt == 1) {
+ sc->opp[i].uvolt_target = volts[0];
+ sc->opp[i].uvolt_min = volts[0];
+ sc->opp[i].uvolt_max = volts[0];
+ } else if (nvolt == 3) {
+ sc->opp[i].uvolt_target = volts[0];
+ sc->opp[i].uvolt_min = volts[1];
+ sc->opp[i].uvolt_max = volts[2];
+ } else {
+ device_printf(sc->dev,
+ "Wrong count of opp-microvolt property\n");
+ OF_prop_free(volts);
+ free(sc->opp, M_DEVBUF);
+ return (ENXIO);
+ }
OF_prop_free(volts);
- free(sc->opp, M_DEVBUF);
- return (ENXIO);
+ } else {
+ /* No regulator required; don't add anything */
+ sc->opp[i].uvolt_target = 0;
+ sc->opp[i].uvolt_min = 0;
+ sc->opp[i].uvolt_max = 0;
}
- OF_prop_free(volts);
if (bootverbose)
device_printf(sc->dev, "%ju.%03ju Mhz (%u uV)\n",
@@ -463,48 +483,78 @@
sc->dev = dev;
node = ofw_bus_get_node(device_get_parent(dev));
sc->cpu = device_get_unit(device_get_parent(dev));
+ sc->reg = NULL;
DPRINTF(dev, "cpu=%d\n", sc->cpu);
if (sc->cpu >= mp_ncpus) {
device_printf(dev, "Not attaching as cpu is not present\n");
- return (ENXIO);
+ rv = ENXIO;
+ goto error;
}
- if (regulator_get_by_ofw_property(dev, node,
- "cpu-supply", &sc->reg) != 0) {
- if (regulator_get_by_ofw_property(dev, node,
- "cpu0-supply", &sc->reg) != 0) {
- device_printf(dev, "no regulator for %s\n",
- ofw_bus_get_name(device_get_parent(dev)));
- return (ENXIO);
- }
+ /*
+ * Cache if we have the regulator supply but don't error out
+ * quite yet. If it's operating-points-v2 then regulator
+ * and voltage entries are optional.
+ */
+ if (regulator_get_by_ofw_property(dev, node, "cpu-supply",
+ &sc->reg) == 0)
+ device_printf(dev, "Found cpu-supply\n");
+ else if (regulator_get_by_ofw_property(dev, node, "cpu0-supply",
+ &sc->reg) == 0)
+ device_printf(dev, "Found cpu0-supply\n");
+
+ /*
+ * Determine which operating mode we're in. Error out if we expect
+ * a regulator but we're not getting it.
+ */
+ if (OF_hasprop(node, "operating-points"))
+ version = OPP_V1;
+ else if (OF_hasprop(node, "operating-points-v2"))
+ version = OPP_V2;
+ else {
+ device_printf(dev,
+ "didn't find a valid operating-points or v2 node\n");
+ rv = ENXIO;
+ goto error;
+ }
+
+ /*
+ * Now, we only enforce needing a regulator for v1.
+ */
+ if ((version == OPP_V1) && !CPUFREQ_DT_HAVE_REGULATOR(sc)) {
+ device_printf(dev, "no regulator for %s\n",
+ ofw_bus_get_name(device_get_parent(dev)));
+ rv = ENXIO;
+ goto error;
}
if (clk_get_by_ofw_index(dev, node, 0, &sc->clk) != 0) {
device_printf(dev, "no clock for %s\n",
ofw_bus_get_name(device_get_parent(dev)));
- regulator_release(sc->reg);
- return (ENXIO);
+ rv = ENXIO;
+ goto error;
}
- if (OF_hasprop(node, "operating-points")) {
- version = OPP_V1;
+ if (version == OPP_V1) {
rv = cpufreq_dt_oppv1_parse(sc, node);
if (rv != 0) {
device_printf(dev, "Failed to parse opp-v1 table\n");
- return (rv);
+ goto error;
}
OF_getencprop(node, "operating-points", &opp,
sizeof(opp));
- } else {
- version = OPP_V2;
+ } else if (version == OPP_V2) {
rv = cpufreq_dt_oppv2_parse(sc, node);
if (rv != 0) {
device_printf(dev, "Failed to parse opp-v2 table\n");
- return (rv);
+ goto error;
}
OF_getencprop(node, "operating-points-v2", &opp,
sizeof(opp));
+ } else {
+ device_printf(dev, "operating points version is incorrect\n");
+ goto error;
}
/*
@@ -545,6 +595,10 @@
cpufreq_register(dev);
return (0);
+error:
+ if (CPUFREQ_DT_HAVE_REGULATOR(sc))
+ regulator_release(sc->reg);
+ return (rv);
}
static device_method_t cpufreq_dt_methods[] = {

File Metadata

Mime Type
text/plain
Expires
Fri, Jan 24, 6:44 PM (1 h, 6 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
16097038
Default Alt Text
D33140.id99468.diff (8 KB)

Event Timeline