From 98f02dc8feff29c5b15ef20f350930c22ac19563 Mon Sep 17 00:00:00 2001 From: Filipe Rinaldi Date: Fri, 20 Jun 2014 15:25:38 +0100 Subject: [PATCH] scpi: Add voltage on the DVFS Info command 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 --- drivers/clk/clk-scpi.c | 26 +++++++++++++------------- drivers/cpufreq/scpi-cpufreq.c | 21 +++++++++++---------- drivers/mailbox/scpi_protocol.c | 28 ++++++++++++++-------------- include/linux/scpi_protocol.h | 9 +++++++-- 4 files changed, 45 insertions(+), 39 deletions(-) diff --git a/drivers/clk/clk-scpi.c b/drivers/clk/clk-scpi.c index 501182a..2e80311 100644 --- a/drivers/clk/clk-scpi.c +++ b/drivers/clk/clk-scpi.c @@ -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); } diff --git a/drivers/cpufreq/scpi-cpufreq.c b/drivers/cpufreq/scpi-cpufreq.c index ec1868d..9403ddd 100644 --- a/drivers/cpufreq/scpi-cpufreq.c +++ b/drivers/cpufreq/scpi-cpufreq.c @@ -30,22 +30,23 @@ 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; } } diff --git a/drivers/mailbox/scpi_protocol.c b/drivers/mailbox/scpi_protocol.c index 95d3368..8c2e556 100644 --- a/drivers/mailbox/scpi_protocol.c +++ b/drivers/mailbox/scpi_protocol.c @@ -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); diff --git a/include/linux/scpi_protocol.h b/include/linux/scpi_protocol.h index 66e5eb3..0fdc969 100644 --- a/include/linux/scpi_protocol.h +++ b/include/linux/scpi_protocol.h @@ -17,11 +17,16 @@ */ #include +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); -- 2.7.4