On Wed 16 Nov 07:17 PST 2016, Avaneesh Kumar Dwivedi wrote:OK
I will have a look once we have agreed on below issues.
On 11/8/2016 12:19 PM, Bjorn Andersson wrote:
On Mon 07 Nov 04:37 PST 2016, Avaneesh Kumar Dwivedi wrote:OK, have broken patches in very small set of function now.
Handling of clock and regulator resources as well as resetIt would be much easier to review this if you didn't do all three
register programing differ according to version of hexagon
dsp hardware. Different version require different resources
and different parameters for same resource. Hence it is
needed that resource handling is generic and independent of
hexagon dsp version.
changes in the same patch, and at the same time changed the function
names. There's large parts of this patch where it's not obvious what the
actual changes are.
but patches has increased from 3 to 9.
sorry for inconvenience caused.
[..]
Just pick the largest number we support right now and then if futuresince i do not know how many resource of a particular type will be needed on+ struct regulator **active_regs;Keeping these as statically sized arrays, potentially with unused
elements at the end removes the need for allocating the storage and the
double pointers.
new version of new class of hexagon that is why i am working with pointers.
have removed many entries from above resource struct, it will lok much
cleaner in next patchset.
versions need more we increment that number.
OK
If it's cleaner, then sureI agree, Have removed them.struct completion start_done;I still don't see the need for these 3 attributes.
struct completion stop_done;
@@ -147,67 +150,245 @@ struct q6v5 {
phys_addr_t mpss_reloc;
void *mpss_region;
size_t mpss_size;
+ struct mutex q6_lock;
+ bool proxy_unvote_reg;
+ bool proxy_unvote_clk;
Agree, have removed check.};If you keep proxy_regs and active_regs as arrays you don't need this
-enum {
- Q6V5_SUPPLY_CX,
- Q6V5_SUPPLY_MX,
- Q6V5_SUPPLY_MSS,
- Q6V5_SUPPLY_PLL,
-};
+static int q6_regulator_init(struct q6v5 *qproc)
+{
+ struct regulator **reg_arr;
+ int i;
+
+ if (qproc->q6_rproc_res->proxy_reg_cnt) {
check.
the way i have reorganized code in next patchset i found using+ reg_arr = devm_kzalloc(qproc->dev,Please keep active_regs and proxy_regs as regulator_bulk_data and
+ sizeof(reg_arr) * qproc->q6_rproc_res->proxy_reg_cnt,
+ GFP_KERNEL);
+
+ for (i = 0; i < qproc->q6_rproc_res->proxy_reg_cnt; i++) {
+ reg_arr[i] = devm_regulator_get(qproc->dev,
+ qproc->q6_rproc_res->proxy_regs[i]);
+ if (IS_ERR(reg_arr[i]))
+ return PTR_ERR(reg_arr[i]);
+ qproc->proxy_regs = reg_arr;
+ }
+ }
+
+ if (qproc->q6_rproc_res->active_reg_cnt) {
+ reg_arr = devm_kzalloc(qproc->dev,
+ sizeof(reg_arr) * qproc->q6_rproc_res->active_reg_cnt,
+ GFP_KERNEL);
+
+ for (i = 0; i < qproc->q6_rproc_res->active_reg_cnt; i++) {
+ reg_arr[i] = devm_regulator_get(qproc->dev,
+ qproc->q6_rproc_res->active_regs[i]);
+
+ if (IS_ERR(reg_arr[i]))
+ return PTR_ERR(reg_arr[i]);
+ qproc->active_regs = reg_arr;
+ }
+ }
continue to use devm_regulator_bulk_get(), it should make this code
cleaner.
devm_regulator_get() more convenient, can i keep using them? as i am reading
string one by one and based on read string filling a regulator struct with
its voltage and load and handle info.
if regulator enabled failed, i am unrolling the programmed load and voltage setting.
The reason for using the bulk operations is that the error path becomesHave modified as per suggestion.+Rather then keeping these properties on int-arrays I strongly prefer
+ return 0;
+}
-static int q6v5_regulator_init(struct q6v5 *qproc)
+static int q6_proxy_regulator_enable(struct q6v5 *qproc)
{
- int ret;
+ int i, j, ret = 0;
+ int **reg_loadnvoltsetflag;
+ int *reg_load;
+ int *reg_voltage;
+
+ reg_loadnvoltsetflag = qproc->q6_rproc_res->proxy_reg_action;
+ reg_load = qproc->q6_rproc_res->proxy_reg_load;
+ reg_voltage = qproc->q6_rproc_res->proxy_reg_voltage;
that you would have a struct { uV, uA } for each regulator.
Sorry for mess, have simplified and cleaned.+I'm sorry, but this is not clean. Please use the fact that we're not
+ for (i = 0; i < qproc->q6_rproc_res->proxy_reg_cnt; i++) {
+ for (j = 0; j <= 1; j++) {
+ if (j == 0 && *(reg_loadnvoltsetflag + i*j + j))
writing assembly code and use the language to your advantage.
As replied above i am going with getting sigle regulator handle one time.+ regulator_set_load(qproc->proxy_regs[i],If you just keep your regulators in a regulator_bulk_data array then you
+ reg_load[i]);
+ if (j == 1 && *(reg_loadnvoltsetflag + i*j + j))
+ regulator_set_voltage(qproc->proxy_regs[i],
+ reg_voltage[i], INT_MAX);
+ }
+ }
- qproc->supply[Q6V5_SUPPLY_CX].supply = "cx";
- qproc->supply[Q6V5_SUPPLY_MX].supply = "mx";
- qproc->supply[Q6V5_SUPPLY_MSS].supply = "mss";
- qproc->supply[Q6V5_SUPPLY_PLL].supply = "pll";
+ for (i = 0; i < qproc->q6_rproc_res->proxy_reg_cnt; i++) {
+ ret = regulator_enable(qproc->proxy_regs[i]);
+ if (ret) {
+ for (; i > 0; --i) {
+ regulator_disable(qproc->proxy_regs[i]);
+ return ret;
+ }
+ }
+ }
can replace this with regulator_bulk_enable(proxy_reg_cnt, proxy_regs);
let me know if i can continue or need to change?
cleaner, however now that I look at this again; in the event of an error
you leave the regulators with voltage and load specified. You need to
unroll this too.
OK, will try to incorporate.
But I would still prefer that you specify the loads & voltages, then
call bulk_enable() and if that fail remove all load and voltage
requests.
OK, may i change enum strings as per HPG?
[..]- ret = devm_regulator_bulk_get(qproc->dev,
- ARRAY_SIZE(qproc->supply), qproc->supply);
- if (ret < 0) {
- dev_err(qproc->dev, "failed to get supplies\n");
- return ret;
Sorry for not seeing this before I answered in the two other places,As replied elsewhere, we need a DT entry to know which version is running,+ if (!strcmp(qproc->q6_rproc_res->q6_version, "v56")) {This would be much better as an enum than a string. But I keep wonder if
this is only for v5.6 of the Hexagon - perhaps should we clamp different
things on the various versions?.
or else many compatible string will be required. for "v56" there are
following version, so as and when we need to support a new version we will
require
a new DT entry which when defined will help to take deviation where
required.
1.10.0
1.3.0
1.4.0
1.5.0
1.6.0
1.8.0
perhaps we should just discuss this to end in one place...
But regarding my specific comment, if you want class based handling then
introduce:
enum {
Q6V5_CLASS5,
Q6V5_CLASS55,
Q5V5_CLASS56
};
Then you don't have to use strcmp() to check which class you have.
I was under impression that clock code will be up streamed by clock team, and they will go by downstream way.
But MSS RESET is a "reset" and far as this driver is concerned it shouldAs i informed MSS RESET REGISTER was never a block control reset or BCR (a+ /*And by using the reset framework for mss_restart this will fall out of
+ * Assert QDSP6 I/O clamp, memory wordline clamp, and compiler
+ * memory clamp as a software workaround to avoid high MX
+ * current during LPASS/MSS restart.
+ */
+
+ val = readl_relaxed(qproc->reg_base + QDSP6SS_PWR_CTL_REG);
+ val |= (Q6SS_CLAMP_IO | QDSP6v56_CLAMP_WL |
+ QDSP6v56_CLAMP_QMC_MEM);
+ writel_relaxed(val, qproc->reg_base + QDSP6SS_PWR_CTL_REG);
+ pil_mss_restart_reg(qproc, 1);
the conditional segment and the else is gone.
term used to define those reset register which control a clock or pll ) so
clock control reset framework can not be used to do reset programming for
MSS
be abstracted by the help of the reset framework. I don't want this
driver to care about the workings of the reset control.
The peripheral resets are part of the GCC block and as such I do not see
the problem with having the driver for the GCC block expose these
resets, even if though it's not a BCR - and this is how we have done it
on 8960, 8974 and 8084 so far.
Sure, will do.
that is why i have adopted IOREMAP based mss reset programming. it is likeI want this driver to consume a reset from a reset-controller, I do not
any other register, may i know if any serious objection on using reset
controller framework only? i will have to add another dummy driver just to
do reset register programming.
let me know please if it is mandatory?
see the technical reason why we cannot just add this to the driver for
the GCC block.
Regards,
Bjorn