devicetree.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Daniel Lezcano <daniel.lezcano@linaro.org>
To: Lina Iyer <lina.iyer@linaro.org>
Cc: khilman@linaro.org, sboyd@codeaurora.org, galak@codeaurora.org,
	linux-arm-msm@vger.kernel.org, linux-pm@vger.kernel.org,
	linux-arm-kernel@lists.infradead.org, lorenzo.pieralisi@arm.com,
	msivasub@codeaurora.org, devicetree@vger.kernel.org
Subject: Re: [PATCH v13 03/10] qcom: spm: Add Subsystem Power Manager driver
Date: Tue, 02 Dec 2014 10:53:30 +0100	[thread overview]
Message-ID: <547D8C1A.1010204@linaro.org> (raw)
In-Reply-To: <20141201185023.GB499@linaro.org>

On 12/01/2014 07:50 PM, Lina Iyer wrote:
> On Thu, Nov 27 2014 at 01:52 -0700, Daniel Lezcano wrote:
>> On 11/27/2014 06:24 AM, Lina Iyer wrote:
>
>> +    static bool cpuidle_drv_init;
>>
>>        ^^^^^^^^^
>>
>> As already said in a previous comment, please find a way to remove that.
>>
> I will look into it. Stephen and I wanted the cpuidle driver to be
> probed only after any of the SPMs are ready. And possibly, only for that
> cpu, for which the SPM has been probed.
>
> To achieve the SPM -> CPUIDLE Device relation, I havent found a good way
> to do that. Without using CPUIDLE_MULTIPLE_DRIVERS, initializing each
> cpuidle device, separate from the cpuidle driver, requires that I update
> the cpuidle_driver->cpumask after probing each SPM device, to allow for
> only one driver and cpuidle devices only for the probed cpus. Using the
> cpuidle_register_driver(), resets the drv->refcnt in
> __cpuidle_driver_init.
>
> I may need something like this in the else clause of
> CPUIDLE_MULTIPLE_DRIVERS -
>
> static inline struct cpuidle_driver *__cpuidle_get_cpu_driver(int cpu)
> {
>         struct cpuidle_driver *drv = cpuidle_curr_driver;
>
>         if (drv && !cpumask_test_cpu(cpu, drv->cpumask))
>                  drv = NULL;
>
>         return drv;
> }

You don't have to deal with the drv->cpumask and 
CPUIDLE_MULTIPLE_DRIVERS. This field gives the list of the cpus the 
driver will have to potentially handle.

Just register the driver at the first place with the platform device by 
using cpuidle_register_driver(drv), I suggest somewhere else than the 
spm code.

The underlying code will do:

         if (!drv->cpumask)
                 drv->cpumask = (struct cpumask *)cpu_possible_mask;

Until the cpuidle device is not initialized for a specific cpu, the 
cpuidle code will have no effect for this cpu. If you register the 
driver but without registering the cpuidle devices that will result in 
nothing more than a structure initialized but inoperative.

For each SPM being probed:

struct cpuidle_device *dev = &per_cpu(cpuidle_dev, cpu);
dev->cpu = cpu;
cpuidle_register_device(dev);

Note cpuidle_dev is exported via cpuidle.h, so you don't have to 
redeclare a per cpu cpuidle device by your own.

So rephrasing all that:

(1) in cpuidle-qcom register the driver
(2) in the spm code register the device for each spm probe

(1) being called before (2).

If after that in the code you still have a "static bool 
cpuidle_drv_init", then I guess we have a problem in the init sequence 
somewhere else.

> void cpuidle_update_cpumask(struct cpumask *mask) {
>         struct cpuidle_driver *drv;
>
>         spin_lock(&cpuidle_driver_lock);
>         drv = cpuidle_get_driver();
>      if (drv)
>          drv->cpumask = mask ?: cpu_possible_mask;
>         spin_unlock(&cpuidle_driver_lock);
> }
>
> With that, I could register cpuidle driver the first time when the mask
> changes
> from empty and consequent updates would just update the cpumask. (I am not
> sure, if I missed anything in this change). It just seemed far too
> invasive at
> this time, in lieu of the static bool.
>
>>> +    const struct platform_device_info qcom_cpuidle_info = {
>>> +        .name    = "qcom_cpuidle",
>>> +        .id    = -1,
>>> +        .data = &lpm_ops,
>>> +        .size_data = sizeof(lpm_ops),
>>> +    };
>>> +
>>> +    drv = spm_get_drv(pdev, &cpu);
>>> +    if (!drv || cpu < 0)
>>> +        return -EINVAL;
>>
>> As already said in a previous comment, it is not possible to have "cpu
>> < 0" with "drv != NULL", so except I am missing something the test
>> should be:
>>
>>     if (!drv)
>>         return -EINVAL;
>>
> Sorry, done.
>
>> There is something wrong with the init sequence. Don't you find weird
>> you have to backward search for the cpu belonging to the pdev each
>> time the probe function is called ?
>>
>>
> Well, it was that or the SPM device node pointing to the CPU that it
> references. It seems more common to have an iterator than the doubly
> linked device nodes. I dont have a strong preference either way, just
> chose the way that made device nodes easier.
>
>>> +
>>> +    res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
>>> +    drv->reg_base = devm_ioremap_resource(&pdev->dev, res);
>>> +    if (IS_ERR(drv->reg_base))
>>> +        return PTR_ERR(drv->reg_base);
>>> +
>>> +    match_id = of_match_node(spm_match_table, pdev->dev.of_node);
>>> +    if (!match_id)
>>> +        return -ENODEV;
>>> +
>>> +    drv->reg_data = match_id->data;
>>> +
>>> +    /* Write the SPM sequences first.. */
>>> +    addr = drv->reg_base +
>>> drv->reg_data->reg_offset[SPM_REG_SEQ_ENTRY];
>>> +    __iowrite32_copy(addr, drv->reg_data->seq,
>>> +            ARRAY_SIZE(drv->reg_data->seq) / 4);
>>> +
>>> +    /*
>>> +     * ..and then the control registers.
>>> +     * On some SoC's if the control registers are written first and
>>> if the
>>> +     * CPU was held in reset, the reset signal could trigger the SPM
>>> state
>>> +     * machine, before the sequences are completely written.
>>> +     */
>>> +    spm_register_write(drv, SPM_REG_CFG, drv->reg_data->spm_cfg);
>>> +    spm_register_write(drv, SPM_REG_DLY, drv->reg_data->spm_dly);
>>> +    spm_register_write(drv, SPM_REG_PMIC_DLY, drv->reg_data->pmic_dly);
>>> +
>>> +    spm_register_write(drv, SPM_REG_PMIC_DATA_0,
>>> +                drv->reg_data->pmic_data[0]);
>>> +    spm_register_write(drv, SPM_REG_PMIC_DATA_1,
>>> +                drv->reg_data->pmic_data[1]);
>>> +
>>> +    /*
>>> +     * Ensure all observers see the above register writes before the
>>> +     * cpuidle driver is allowed to use the SPM.
>>> +     */
>>> +    wmb();
>>> +    per_cpu(cpu_spm_drv, cpu) = drv;
>>> +
>>> +    if (!cpuidle_drv_init) {
>>> +        platform_device_register_full(&qcom_cpuidle_info);
>>> +        cpuidle_drv_init = true;
>>> +    }
>>> +
>>> +    return 0;
>>> +}
>>> +
>>> +static struct platform_driver spm_driver = {
>>> +    .probe = spm_dev_probe,
>>> +    .driver = {
>>> +        .name = "saw",
>>> +        .of_match_table = spm_match_table,
>>> +    },
>>> +};
>>> +
>>> +module_platform_driver(spm_driver);
>>> +
>>> +MODULE_LICENSE("GPL v2");
>>> +MODULE_DESCRIPTION("SAW power controller driver");
>>> +MODULE_ALIAS("platform:saw");
>>> diff --git a/include/soc/qcom/pm.h b/include/soc/qcom/pm.h
>>> new file mode 100644
>>> index 0000000..d9a56d7
>>> --- /dev/null
>>> +++ b/include/soc/qcom/pm.h
>>> @@ -0,0 +1,31 @@
>>> +/*
>>> + * Copyright (c) 2009-2014, The Linux Foundation. All rights reserved.
>>> + *
>>> + * This software is licensed under the terms of the GNU General Public
>>> + * License version 2, as published by the Free Software Foundation, and
>>> + * may be copied, distributed, and modified under those terms.
>>> + *
>>> + * This program is distributed in the hope that it will be useful,
>>> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
>>> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
>>> + * GNU General Public License for more details.
>>> + *
>>> + */
>>> +
>>> +#ifndef __QCOM_PM_H
>>> +#define __QCOM_PM_H
>>> +
>>> +enum pm_sleep_mode {
>>> +    PM_SLEEP_MODE_STBY,
>>> +    PM_SLEEP_MODE_RET,
>>> +    PM_SLEEP_MODE_SPC,
>>> +    PM_SLEEP_MODE_PC,
>>> +    PM_SLEEP_MODE_NR,
>>> +};
>>> +
>>> +struct qcom_cpu_pm_ops {
>>> +    int (*standby)(void *data);
>>> +    int (*spc)(void *data);
>>> +};
>>> +
>>> +#endif  /* __QCOM_PM_H */
>>>
>>
>>
>> --
>> <http://www.linaro.org/> Linaro.org │ Open source software for ARM SoCs
>>
>> Follow Linaro:  <http://www.facebook.com/pages/Linaro> Facebook |
>> <http://twitter.com/#!/linaroorg> Twitter |
>> <http://www.linaro.org/linaro-blog/> Blog
>>


-- 
  <http://www.linaro.org/> Linaro.org │ Open source software for ARM SoCs

Follow Linaro:  <http://www.facebook.com/pages/Linaro> Facebook |
<http://twitter.com/#!/linaroorg> Twitter |
<http://www.linaro.org/linaro-blog/> Blog

  reply	other threads:[~2014-12-02  9:53 UTC|newest]

Thread overview: 23+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2014-11-27  5:24 [PATCH v13 00/10] cpuidle driver for QCOM SoCs: 8064, 8074, 8084 Lina Iyer
2014-11-27  5:24 ` [PATCH v13 01/10] qcom: scm: Move scm-boot files to drivers/soc/qcom/ and include/soc/qcom Lina Iyer
2014-11-27  5:24 ` [PATCH v13 02/10] qcom: scm: Add SCM warmboot support for quad core SoCs Lina Iyer
2014-11-27  5:24 ` [PATCH v13 03/10] qcom: spm: Add Subsystem Power Manager driver Lina Iyer
2014-11-27  8:44   ` Ivan T. Ivanov
2014-12-01 17:57     ` Lina Iyer
2014-11-27  8:52   ` Daniel Lezcano
2014-12-01 18:50     ` Lina Iyer
2014-12-02  9:53       ` Daniel Lezcano [this message]
2014-12-02 15:35         ` Lina Iyer
2014-12-02 15:47           ` Daniel Lezcano
2014-11-27 15:01   ` Lorenzo Pieralisi
2014-12-01 18:57     ` Lina Iyer
2014-12-02 11:10       ` Catalin Marinas
2014-12-02 15:52         ` Lina Iyer
2014-11-27  5:24 ` [PATCH v13 04/10] arm: dts: qcom: Add power-controller device node for 8074 Krait CPUs Lina Iyer
2014-11-27  5:24 ` [PATCH v13 05/10] arm: dts: qcom: Add power-controller device node for 8084 " Lina Iyer
2014-11-27  5:24 ` [PATCH v13 06/10] arm: dts: qcom: Update power-controller device node for 8064 " Lina Iyer
2014-11-27  5:24 ` [PATCH v13 07/10] qcom: cpuidle: Add cpuidle driver for QCOM cpus Lina Iyer
2014-11-27  5:24 ` [PATCH v13 08/10] arm: dts: qcom: Add idle states device nodes for 8074 Lina Iyer
2014-11-27  5:24 ` [PATCH v13 09/10] arm: dts: qcom: Add idle states device nodes for 8084 Lina Iyer
2014-11-27  5:24 ` [PATCH v13 10/10] arm: dts: qcom: Add idle state device nodes for 8064 Lina Iyer
2014-11-27  8:53 ` [PATCH v13 00/10] cpuidle driver for QCOM SoCs: 8064, 8074, 8084 Daniel Lezcano

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=547D8C1A.1010204@linaro.org \
    --to=daniel.lezcano@linaro.org \
    --cc=devicetree@vger.kernel.org \
    --cc=galak@codeaurora.org \
    --cc=khilman@linaro.org \
    --cc=lina.iyer@linaro.org \
    --cc=linux-arm-kernel@lists.infradead.org \
    --cc=linux-arm-msm@vger.kernel.org \
    --cc=linux-pm@vger.kernel.org \
    --cc=lorenzo.pieralisi@arm.com \
    --cc=msivasub@codeaurora.org \
    --cc=sboyd@codeaurora.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).