scpi: Add voltage on the DVFS Info command
authorFilipe Rinaldi <filipe.rinaldi@arm.com>
Fri, 20 Jun 2014 14:25:38 +0000 (15:25 +0100)
committerLiviu Dudau <Liviu.Dudau@arm.com>
Thu, 11 Sep 2014 09:08:41 +0000 (10:08 +0100)
Newer versions of SCP added voltage as one of the parameters in the
DVFS Info command. This patch reads the voltage which can be used by
CPUFreq and Devfreq.

Signed-off-by: Filipe Rinaldi <filipe.rinaldi@arm.com>
drivers/clk/clk-scpi.c
drivers/cpufreq/scpi-cpufreq.c
drivers/mailbox/scpi_protocol.c
include/linux/scpi_protocol.h

index 501182a..2e80311 100644 (file)
@@ -72,11 +72,11 @@ static struct clk_ops scpi_clk_ops = {
 static int __scpi_dvfs_round_rate(struct scpi_clk *clk, unsigned long rate)
 {
        int idx, max_opp = clk->opps->count;
-       u32 *freqs = clk->opps->freqs;
+       struct scpi_opp_entry *opp = clk->opps->opp;
        u32 fmin = 0, fmax = ~0, ftmp;
 
-       for (idx = 0; idx < max_opp; idx++, freqs++) {
-               ftmp = *freqs;
+       for (idx = 0; idx < max_opp; idx++, opp++) {
+               ftmp = opp->freq_hz;
                if (ftmp >= (u32)rate) {
                        if (ftmp <= fmax)
                                fmax = ftmp;
@@ -96,12 +96,12 @@ static unsigned long scpi_dvfs_recalc_rate(struct clk_hw *hw,
 {
        struct scpi_clk *clk = to_scpi_clk(hw);
        int idx = scpi_dvfs_get_idx(clk->id);
-       u32 *freqs = clk->opps->freqs;
+       struct scpi_opp_entry *opp = clk->opps->opp;
 
        if (idx < 0)
                return 0;
        else
-               return *(freqs + idx);
+               return opp[idx].freq_hz;
 }
 
 static long scpi_dvfs_round_rate(struct clk_hw *hw, unsigned long rate,
@@ -114,10 +114,10 @@ static long scpi_dvfs_round_rate(struct clk_hw *hw, unsigned long rate,
 static int __scpi_find_dvfs_index(struct scpi_clk *clk, unsigned long rate)
 {
        int idx, max_opp = clk->opps->count;
-       u32 *freqs = clk->opps->freqs;
+       struct scpi_opp_entry *opp = clk->opps->opp;
 
-       for (idx = 0; idx < max_opp; idx++, freqs++)
-               if (*freqs == (u32)rate)
+       for (idx = 0; idx < max_opp; idx++, opp++)
+               if (opp->freq_hz == (u32)rate)
                        break;
        return (idx == max_opp) ? -EINVAL : idx;
 }
@@ -145,7 +145,7 @@ scpi_dvfs_ops_init(struct device *dev, struct device_node *np,
                   struct scpi_clk *sclk)
 {
        struct clk_init_data init;
-       struct scpi_opp *opp;
+       struct scpi_opp *opps;
 
        init.name = sclk->name;
        init.flags = CLK_IS_ROOT;
@@ -153,11 +153,11 @@ scpi_dvfs_ops_init(struct device *dev, struct device_node *np,
        init.ops = &scpi_dvfs_ops;
        sclk->hw.init = &init;
 
-       opp = scpi_dvfs_get_opps(sclk->id);
-       if (IS_ERR(opp))
-               return (struct clk *)opp;
+       opps = scpi_dvfs_get_opps(sclk->id);
+       if (IS_ERR(opps))
+               return (struct clk *)opps;
 
-       sclk->opps = opp;
+       sclk->opps = opps;
 
        return devm_clk_register(dev, &sclk->hw);
 }
index ec1868d..9403ddd 100644 (file)
 static int scpi_init_opp_table(struct device *cpu_dev)
 {
        u8 domain = topology_physical_package_id(cpu_dev->id);
-       struct scpi_opp *opp;
+       struct scpi_opp *opps;
        int idx, ret = 0, max_opp;
-       u32 *freqs;
+       struct scpi_opp_entry *opp;
 
        if ((dev_pm_opp_get_opp_count(cpu_dev)) > 0)
                return 0;
-       opp = scpi_dvfs_get_opps(domain);
-       if (IS_ERR(opp))
-               return PTR_ERR(opp);
+       opps = scpi_dvfs_get_opps(domain);
+       if (IS_ERR(opps))
+               return PTR_ERR(opps);
 
-       freqs = opp->freqs;
-       max_opp = opp->count;
-       for (idx = 0; idx < max_opp; idx++, freqs++) {
-               ret = dev_pm_opp_add(cpu_dev, *freqs, 900000000 /* TODO */);
+       opp = opps->opp;
+       max_opp = opps->count;
+       for (idx = 0; idx < max_opp; idx++, opp++) {
+               ret = dev_pm_opp_add(cpu_dev, opp->freq_hz, opp->volt_mv*1000);
                if (ret) {
-                       dev_warn(cpu_dev, "failed to add opp %u\n", *freqs);
+                       dev_warn(cpu_dev, "failed to add opp %uHz %umV\n",
+                                       opp->freq_hz, opp->volt_mv);
                        return ret;
                }
        }
index 95d3368..8c2e556 100644 (file)
@@ -271,10 +271,10 @@ struct scpi_opp *scpi_dvfs_get_opps(u8 domain)
        struct __packed {
                u32 status;
                u32 header;
-               u32 freqs[MAX_DVFS_OPPS];
+               struct scpi_opp_entry opp[MAX_DVFS_OPPS];
        } buf;
-       struct scpi_opp *opp;
-       size_t freqs_sz;
+       struct scpi_opp *opps;
+       size_t opps_sz;
        int count, ret;
 
        if (domain >= MAX_DVFS_DOMAINS)
@@ -289,25 +289,25 @@ struct scpi_opp *scpi_dvfs_get_opps(u8 domain)
        if (ret)
                return ERR_PTR(ret);
 
-       opp = kmalloc(sizeof(*opp), GFP_KERNEL);
-       if (!opp)
+       opps = kmalloc(sizeof(*opps), GFP_KERNEL);
+       if (!opps)
                return ERR_PTR(-ENOMEM);
 
        count = DVFS_OPP_COUNT(buf.header);
-       freqs_sz = count * sizeof(*(opp->freqs));
+       opps_sz = count * sizeof(*(opps->opp));
 
-       opp->count = count;
-       opp->latency = DVFS_LATENCY(buf.header);
-       opp->freqs = kmalloc(freqs_sz, GFP_KERNEL);
-       if (!opp->freqs) {
-               kfree(opp);
+       opps->count = count;
+       opps->latency = DVFS_LATENCY(buf.header);
+       opps->opp = kmalloc(opps_sz, GFP_KERNEL);
+       if (!opps->opp) {
+               kfree(opps);
                return ERR_PTR(-ENOMEM);
        }
 
-       memcpy(opp->freqs, &buf.freqs[0], freqs_sz);
-       scpi_opps[domain] = opp;
+       memcpy(opps->opp, &buf.opp[0], opps_sz);
+       scpi_opps[domain] = opps;
 
-       return opp;
+       return opps;
 }
 EXPORT_SYMBOL_GPL(scpi_dvfs_get_opps);
 
index 66e5eb3..0fdc969 100644 (file)
  */
 #include <linux/types.h>
 
+struct scpi_opp_entry {
+       u32 freq_hz;
+       u32 volt_mv;
+} __packed;
+
 struct scpi_opp {
-       u32 *freqs;
+       struct scpi_opp_entry *opp;
        u32 latency; /* in usecs */
        int count;
-};
+} __packed;
 
 unsigned long scpi_clk_get_val(u16 clk_id);
 int scpi_clk_set_val(u16 clk_id, unsigned long rate);