All of lore.kernel.org
 help / color / mirror / Atom feed
From: Hans de Goede <hdegoede@redhat.com>
To: linux-arm-kernel@lists.infradead.org
Subject: Re: [PATCH RFC v2 2/2] simplefb: Claim and enable regulators
Date: Wed, 21 Oct 2015 08:09:11 +0000	[thread overview]
Message-ID: <56274827.3000708@redhat.com> (raw)
In-Reply-To: <CAGb2v643sDnNv5DPYocu-50UB3q-itpwGdw8hZ3YN=V+nEBkMg@mail.gmail.com>

Hi,

On 21-10-15 10:04, Chen-Yu Tsai wrote:
> Hi,
>
> On Wed, Oct 21, 2015 at 3:54 PM, Hans de Goede <hdegoede@redhat.com> wrote:
>> Hi,
>>
>>
>> On 21-10-15 07:59, Chen-Yu Tsai wrote:
>>>
>>> This claims and enables regulators listed in the simple framebuffer dt
>>> node. This is needed so that regulators powering the display pipeline
>>> and external hardware, described in the device node and known by the
>>> kernel code, will remain properly enabled.
>>>
>>> Signed-off-by: Chen-Yu Tsai <wens@csie.org>
>>> ---
>>>    drivers/video/fbdev/simplefb.c | 122
>>> ++++++++++++++++++++++++++++++++++++++++-
>>>    1 file changed, 121 insertions(+), 1 deletion(-)
>>>
>>> diff --git a/drivers/video/fbdev/simplefb.c
>>> b/drivers/video/fbdev/simplefb.c
>>> index 52c5c7e63b52..c4ee10d83a70 100644
>>> --- a/drivers/video/fbdev/simplefb.c
>>> +++ b/drivers/video/fbdev/simplefb.c
>>> @@ -28,7 +28,10 @@
>>>    #include <linux/platform_device.h>
>>>    #include <linux/clk.h>
>>>    #include <linux/clk-provider.h>
>>> +#include <linux/of.h>
>>>    #include <linux/of_platform.h>
>>> +#include <linux/parser.h>
>>> +#include <linux/regulator/consumer.h>
>>>
>>>    static struct fb_fix_screeninfo simplefb_fix = {
>>>          .id             = "simple",
>>> @@ -174,6 +177,10 @@ struct simplefb_par {
>>>          int clk_count;
>>>          struct clk **clks;
>>>    #endif
>>> +#if defined CONFIG_OF && defined CONFIG_REGULATOR
>>> +       u32 regulator_count;
>>> +       struct regulator **regulators;
>>> +#endif
>>>    };
>>>
>>>    #if defined CONFIG_OF && defined CONFIG_COMMON_CLK
>>> @@ -269,6 +276,112 @@ static int simplefb_clocks_init(struct simplefb_par
>>> *par,
>>>    static void simplefb_clocks_destroy(struct simplefb_par *par) { }
>>>    #endif
>>>
>>> +#if defined CONFIG_OF && defined CONFIG_REGULATOR
>>> +
>>> +#define SUPPLY_SUFFIX "-supply"
>>> +
>>> +/*
>>> + * Regulator handling code.
>>> + *
>>> + * Here we handle the num-supplies and vin*-supply properties of our
>>> + * "simple-framebuffer" dt node. This is necessary so that we can make
>>> sure
>>> + * that any regulators needed by the display hardware that the bootloader
>>> + * set up for us (and for which it provided a simplefb dt node), stay up,
>>> + * for the life of the simplefb driver.
>>> + *
>>> + * When the driver unloads, we cleanly disable, and then release the
>>> + * regulators.
>>> + *
>>> + * We only complain about errors here, no action is taken as the most
>>> likely
>>> + * error can only happen due to a mismatch between the bootloader which
>>> set
>>> + * up simplefb, and the regulator definitions in the device tree. Chances
>>> are
>>> + * that there are no adverse effects, and if there are, a clean teardown
>>> of
>>> + * the fb probe will not help us much either. So just complain and carry
>>> on,
>>> + * and hope that the user actually gets a working fb at the end of
>>> things.
>>> + */
>>> +static int simplefb_regulators_init(struct simplefb_par *par,
>>> +       struct platform_device *pdev)
>>> +{
>>> +       struct device_node *np = pdev->dev.of_node;
>>> +       struct property *prop;
>>> +       struct regulator *regulator;
>>> +       const char *p;
>>> +       int count = 0, i = 0, ret;
>>> +
>>> +       if (dev_get_platdata(&pdev->dev) || !np)
>>> +               return 0;
>>> +
>>> +       /* Count the number of regulator supplies */
>>> +       for_each_property_of_node(np, prop) {
>>> +               p = strstr(prop->name, SUPPLY_SUFFIX);
>>> +               if (p && p != prop->name)
>>> +                       count++;
>>> +       }
>>> +
>>> +       if (!count)
>>> +               return 0;
>>> +
>>> +       par->regulators = devm_kcalloc(&pdev->dev, count,
>>> +                                      sizeof(struct regulator *),
>>> GFP_KERNEL);
>>> +       if (!par->regulators)
>>> +               return -ENOMEM;
>>> +
>>> +       /* Get all the regulators */
>>> +       for_each_property_of_node(np, prop) {
>>> +               char name[32]; /* 32 is max size of property name */
>>> +
>>> +               p = strstr(prop->name, SUPPLY_SUFFIX);
>>> +               if (p && p != prop->name)
>>> +                       continue;
>>> +
>>> +               strlcpy(name, prop->name,
>>> +                       strlen(prop->name) - sizeof(SUPPLY_SUFFIX) + 1);
>>> +               regulator = devm_regulator_get_optional(&pdev->dev, name);
>>> +               if (IS_ERR(regulator)) {
>>> +                       if (PTR_ERR(regulator) = -EPROBE_DEFER)
>>> +                               return -EPROBE_DEFER;
>>> +                       dev_err(&pdev->dev, "regulator %s not found:
>>> %ld\n",
>>> +                               name, PTR_ERR(regulator));
>>> +                       continue;
>>> +               }
>>> +               par->regulators[i++] = regulator;
>>
>>
>> So you only fill slots when the regulator_get has succeeded
>>
>>> +       }
>>> +       par->regulator_count = i;
>>
>>
>> and regulator_count now is the amount of successfully gotten regulators
>> (which may be different from count).
>>
>>> +
>>> +       /* Enable all the regulators */
>>> +       for (i = 0; i < par->regulator_count; i++) {
>>> +               if (par->regulators[i]) {
>>
>>
>> That means that this "if" is not necessary, it will always be true.
>
> Right. This is leftover code from the first version. I'll remove it.
>
>>> +                       ret = regulator_enable(par->regulators[i]);
>>> +                       if (ret) {
>>> +                               dev_err(&pdev->dev,
>>> +                                       "failed to enable regulator %d:
>>> %d\n",
>>> +                                       i, ret);
>>> +                               devm_regulator_put(par->regulators[i]);
>>> +                               par->regulators[i] = NULL;
>
> Note here.
>
>>> +                       }
>>> +               }
>>> +       }
>>> +
>>> +       return 0;
>>> +}
>>> +
>>> +static void simplefb_regulators_destroy(struct simplefb_par *par)
>>> +{
>>> +       int i;
>>> +
>>> +       if (!par->regulators)
>>> +               return;
>>> +
>>> +       for (i = 0; i < par->regulator_count; i++)
>>> +               if (par->regulators[i])
>>
>>
>> And idem for this if.
>
> This is still needed, since if we fail to enable any regulator, we just
> ignore it, call regulator_put() on it, and forget about it (set the entry
> to NULL). See the noted place above.

Ah right, ok lets keep that in then :)

Regards,

Hans

WARNING: multiple messages have this Message-ID (diff)
From: hdegoede@redhat.com (Hans de Goede)
To: linux-arm-kernel@lists.infradead.org
Subject: [PATCH RFC v2 2/2] simplefb: Claim and enable regulators
Date: Wed, 21 Oct 2015 10:09:11 +0200	[thread overview]
Message-ID: <56274827.3000708@redhat.com> (raw)
In-Reply-To: <CAGb2v643sDnNv5DPYocu-50UB3q-itpwGdw8hZ3YN=V+nEBkMg@mail.gmail.com>

Hi,

On 21-10-15 10:04, Chen-Yu Tsai wrote:
> Hi,
>
> On Wed, Oct 21, 2015 at 3:54 PM, Hans de Goede <hdegoede@redhat.com> wrote:
>> Hi,
>>
>>
>> On 21-10-15 07:59, Chen-Yu Tsai wrote:
>>>
>>> This claims and enables regulators listed in the simple framebuffer dt
>>> node. This is needed so that regulators powering the display pipeline
>>> and external hardware, described in the device node and known by the
>>> kernel code, will remain properly enabled.
>>>
>>> Signed-off-by: Chen-Yu Tsai <wens@csie.org>
>>> ---
>>>    drivers/video/fbdev/simplefb.c | 122
>>> ++++++++++++++++++++++++++++++++++++++++-
>>>    1 file changed, 121 insertions(+), 1 deletion(-)
>>>
>>> diff --git a/drivers/video/fbdev/simplefb.c
>>> b/drivers/video/fbdev/simplefb.c
>>> index 52c5c7e63b52..c4ee10d83a70 100644
>>> --- a/drivers/video/fbdev/simplefb.c
>>> +++ b/drivers/video/fbdev/simplefb.c
>>> @@ -28,7 +28,10 @@
>>>    #include <linux/platform_device.h>
>>>    #include <linux/clk.h>
>>>    #include <linux/clk-provider.h>
>>> +#include <linux/of.h>
>>>    #include <linux/of_platform.h>
>>> +#include <linux/parser.h>
>>> +#include <linux/regulator/consumer.h>
>>>
>>>    static struct fb_fix_screeninfo simplefb_fix = {
>>>          .id             = "simple",
>>> @@ -174,6 +177,10 @@ struct simplefb_par {
>>>          int clk_count;
>>>          struct clk **clks;
>>>    #endif
>>> +#if defined CONFIG_OF && defined CONFIG_REGULATOR
>>> +       u32 regulator_count;
>>> +       struct regulator **regulators;
>>> +#endif
>>>    };
>>>
>>>    #if defined CONFIG_OF && defined CONFIG_COMMON_CLK
>>> @@ -269,6 +276,112 @@ static int simplefb_clocks_init(struct simplefb_par
>>> *par,
>>>    static void simplefb_clocks_destroy(struct simplefb_par *par) { }
>>>    #endif
>>>
>>> +#if defined CONFIG_OF && defined CONFIG_REGULATOR
>>> +
>>> +#define SUPPLY_SUFFIX "-supply"
>>> +
>>> +/*
>>> + * Regulator handling code.
>>> + *
>>> + * Here we handle the num-supplies and vin*-supply properties of our
>>> + * "simple-framebuffer" dt node. This is necessary so that we can make
>>> sure
>>> + * that any regulators needed by the display hardware that the bootloader
>>> + * set up for us (and for which it provided a simplefb dt node), stay up,
>>> + * for the life of the simplefb driver.
>>> + *
>>> + * When the driver unloads, we cleanly disable, and then release the
>>> + * regulators.
>>> + *
>>> + * We only complain about errors here, no action is taken as the most
>>> likely
>>> + * error can only happen due to a mismatch between the bootloader which
>>> set
>>> + * up simplefb, and the regulator definitions in the device tree. Chances
>>> are
>>> + * that there are no adverse effects, and if there are, a clean teardown
>>> of
>>> + * the fb probe will not help us much either. So just complain and carry
>>> on,
>>> + * and hope that the user actually gets a working fb at the end of
>>> things.
>>> + */
>>> +static int simplefb_regulators_init(struct simplefb_par *par,
>>> +       struct platform_device *pdev)
>>> +{
>>> +       struct device_node *np = pdev->dev.of_node;
>>> +       struct property *prop;
>>> +       struct regulator *regulator;
>>> +       const char *p;
>>> +       int count = 0, i = 0, ret;
>>> +
>>> +       if (dev_get_platdata(&pdev->dev) || !np)
>>> +               return 0;
>>> +
>>> +       /* Count the number of regulator supplies */
>>> +       for_each_property_of_node(np, prop) {
>>> +               p = strstr(prop->name, SUPPLY_SUFFIX);
>>> +               if (p && p != prop->name)
>>> +                       count++;
>>> +       }
>>> +
>>> +       if (!count)
>>> +               return 0;
>>> +
>>> +       par->regulators = devm_kcalloc(&pdev->dev, count,
>>> +                                      sizeof(struct regulator *),
>>> GFP_KERNEL);
>>> +       if (!par->regulators)
>>> +               return -ENOMEM;
>>> +
>>> +       /* Get all the regulators */
>>> +       for_each_property_of_node(np, prop) {
>>> +               char name[32]; /* 32 is max size of property name */
>>> +
>>> +               p = strstr(prop->name, SUPPLY_SUFFIX);
>>> +               if (p && p != prop->name)
>>> +                       continue;
>>> +
>>> +               strlcpy(name, prop->name,
>>> +                       strlen(prop->name) - sizeof(SUPPLY_SUFFIX) + 1);
>>> +               regulator = devm_regulator_get_optional(&pdev->dev, name);
>>> +               if (IS_ERR(regulator)) {
>>> +                       if (PTR_ERR(regulator) == -EPROBE_DEFER)
>>> +                               return -EPROBE_DEFER;
>>> +                       dev_err(&pdev->dev, "regulator %s not found:
>>> %ld\n",
>>> +                               name, PTR_ERR(regulator));
>>> +                       continue;
>>> +               }
>>> +               par->regulators[i++] = regulator;
>>
>>
>> So you only fill slots when the regulator_get has succeeded
>>
>>> +       }
>>> +       par->regulator_count = i;
>>
>>
>> and regulator_count now is the amount of successfully gotten regulators
>> (which may be different from count).
>>
>>> +
>>> +       /* Enable all the regulators */
>>> +       for (i = 0; i < par->regulator_count; i++) {
>>> +               if (par->regulators[i]) {
>>
>>
>> That means that this "if" is not necessary, it will always be true.
>
> Right. This is leftover code from the first version. I'll remove it.
>
>>> +                       ret = regulator_enable(par->regulators[i]);
>>> +                       if (ret) {
>>> +                               dev_err(&pdev->dev,
>>> +                                       "failed to enable regulator %d:
>>> %d\n",
>>> +                                       i, ret);
>>> +                               devm_regulator_put(par->regulators[i]);
>>> +                               par->regulators[i] = NULL;
>
> Note here.
>
>>> +                       }
>>> +               }
>>> +       }
>>> +
>>> +       return 0;
>>> +}
>>> +
>>> +static void simplefb_regulators_destroy(struct simplefb_par *par)
>>> +{
>>> +       int i;
>>> +
>>> +       if (!par->regulators)
>>> +               return;
>>> +
>>> +       for (i = 0; i < par->regulator_count; i++)
>>> +               if (par->regulators[i])
>>
>>
>> And idem for this if.
>
> This is still needed, since if we fail to enable any regulator, we just
> ignore it, call regulator_put() on it, and forget about it (set the entry
> to NULL). See the noted place above.

Ah right, ok lets keep that in then :)

Regards,

Hans

WARNING: multiple messages have this Message-ID (diff)
From: Hans de Goede <hdegoede@redhat.com>
To: Chen-Yu Tsai <wens@csie.org>
Cc: Mark Rutland <mark.rutland@arm.com>,
	devicetree <devicetree@vger.kernel.org>,
	"linux-fbdev@vger.kernel.org" <linux-fbdev@vger.kernel.org>,
	Pawel Moll <pawel.moll@arm.com>,
	Ian Campbell <ijc+devicetree@hellion.org.uk>,
	Mark Brown <broonie@kernel.org>,
	linux-kernel <linux-kernel@vger.kernel.org>,
	Rob Herring <robh+dt@kernel.org>,
	Tomi Valkeinen <tomi.valkeinen@ti.com>,
	Kumar Gala <galak@codeaurora.org>,
	Jean-Christophe Plagniol-Villard <plagnioj@jcrosoft.com>,
	linux-arm-kernel <linux-arm-kernel@lists.infradead.org>
Subject: Re: [PATCH RFC v2 2/2] simplefb: Claim and enable regulators
Date: Wed, 21 Oct 2015 10:09:11 +0200	[thread overview]
Message-ID: <56274827.3000708@redhat.com> (raw)
In-Reply-To: <CAGb2v643sDnNv5DPYocu-50UB3q-itpwGdw8hZ3YN=V+nEBkMg@mail.gmail.com>

Hi,

On 21-10-15 10:04, Chen-Yu Tsai wrote:
> Hi,
>
> On Wed, Oct 21, 2015 at 3:54 PM, Hans de Goede <hdegoede@redhat.com> wrote:
>> Hi,
>>
>>
>> On 21-10-15 07:59, Chen-Yu Tsai wrote:
>>>
>>> This claims and enables regulators listed in the simple framebuffer dt
>>> node. This is needed so that regulators powering the display pipeline
>>> and external hardware, described in the device node and known by the
>>> kernel code, will remain properly enabled.
>>>
>>> Signed-off-by: Chen-Yu Tsai <wens@csie.org>
>>> ---
>>>    drivers/video/fbdev/simplefb.c | 122
>>> ++++++++++++++++++++++++++++++++++++++++-
>>>    1 file changed, 121 insertions(+), 1 deletion(-)
>>>
>>> diff --git a/drivers/video/fbdev/simplefb.c
>>> b/drivers/video/fbdev/simplefb.c
>>> index 52c5c7e63b52..c4ee10d83a70 100644
>>> --- a/drivers/video/fbdev/simplefb.c
>>> +++ b/drivers/video/fbdev/simplefb.c
>>> @@ -28,7 +28,10 @@
>>>    #include <linux/platform_device.h>
>>>    #include <linux/clk.h>
>>>    #include <linux/clk-provider.h>
>>> +#include <linux/of.h>
>>>    #include <linux/of_platform.h>
>>> +#include <linux/parser.h>
>>> +#include <linux/regulator/consumer.h>
>>>
>>>    static struct fb_fix_screeninfo simplefb_fix = {
>>>          .id             = "simple",
>>> @@ -174,6 +177,10 @@ struct simplefb_par {
>>>          int clk_count;
>>>          struct clk **clks;
>>>    #endif
>>> +#if defined CONFIG_OF && defined CONFIG_REGULATOR
>>> +       u32 regulator_count;
>>> +       struct regulator **regulators;
>>> +#endif
>>>    };
>>>
>>>    #if defined CONFIG_OF && defined CONFIG_COMMON_CLK
>>> @@ -269,6 +276,112 @@ static int simplefb_clocks_init(struct simplefb_par
>>> *par,
>>>    static void simplefb_clocks_destroy(struct simplefb_par *par) { }
>>>    #endif
>>>
>>> +#if defined CONFIG_OF && defined CONFIG_REGULATOR
>>> +
>>> +#define SUPPLY_SUFFIX "-supply"
>>> +
>>> +/*
>>> + * Regulator handling code.
>>> + *
>>> + * Here we handle the num-supplies and vin*-supply properties of our
>>> + * "simple-framebuffer" dt node. This is necessary so that we can make
>>> sure
>>> + * that any regulators needed by the display hardware that the bootloader
>>> + * set up for us (and for which it provided a simplefb dt node), stay up,
>>> + * for the life of the simplefb driver.
>>> + *
>>> + * When the driver unloads, we cleanly disable, and then release the
>>> + * regulators.
>>> + *
>>> + * We only complain about errors here, no action is taken as the most
>>> likely
>>> + * error can only happen due to a mismatch between the bootloader which
>>> set
>>> + * up simplefb, and the regulator definitions in the device tree. Chances
>>> are
>>> + * that there are no adverse effects, and if there are, a clean teardown
>>> of
>>> + * the fb probe will not help us much either. So just complain and carry
>>> on,
>>> + * and hope that the user actually gets a working fb at the end of
>>> things.
>>> + */
>>> +static int simplefb_regulators_init(struct simplefb_par *par,
>>> +       struct platform_device *pdev)
>>> +{
>>> +       struct device_node *np = pdev->dev.of_node;
>>> +       struct property *prop;
>>> +       struct regulator *regulator;
>>> +       const char *p;
>>> +       int count = 0, i = 0, ret;
>>> +
>>> +       if (dev_get_platdata(&pdev->dev) || !np)
>>> +               return 0;
>>> +
>>> +       /* Count the number of regulator supplies */
>>> +       for_each_property_of_node(np, prop) {
>>> +               p = strstr(prop->name, SUPPLY_SUFFIX);
>>> +               if (p && p != prop->name)
>>> +                       count++;
>>> +       }
>>> +
>>> +       if (!count)
>>> +               return 0;
>>> +
>>> +       par->regulators = devm_kcalloc(&pdev->dev, count,
>>> +                                      sizeof(struct regulator *),
>>> GFP_KERNEL);
>>> +       if (!par->regulators)
>>> +               return -ENOMEM;
>>> +
>>> +       /* Get all the regulators */
>>> +       for_each_property_of_node(np, prop) {
>>> +               char name[32]; /* 32 is max size of property name */
>>> +
>>> +               p = strstr(prop->name, SUPPLY_SUFFIX);
>>> +               if (p && p != prop->name)
>>> +                       continue;
>>> +
>>> +               strlcpy(name, prop->name,
>>> +                       strlen(prop->name) - sizeof(SUPPLY_SUFFIX) + 1);
>>> +               regulator = devm_regulator_get_optional(&pdev->dev, name);
>>> +               if (IS_ERR(regulator)) {
>>> +                       if (PTR_ERR(regulator) == -EPROBE_DEFER)
>>> +                               return -EPROBE_DEFER;
>>> +                       dev_err(&pdev->dev, "regulator %s not found:
>>> %ld\n",
>>> +                               name, PTR_ERR(regulator));
>>> +                       continue;
>>> +               }
>>> +               par->regulators[i++] = regulator;
>>
>>
>> So you only fill slots when the regulator_get has succeeded
>>
>>> +       }
>>> +       par->regulator_count = i;
>>
>>
>> and regulator_count now is the amount of successfully gotten regulators
>> (which may be different from count).
>>
>>> +
>>> +       /* Enable all the regulators */
>>> +       for (i = 0; i < par->regulator_count; i++) {
>>> +               if (par->regulators[i]) {
>>
>>
>> That means that this "if" is not necessary, it will always be true.
>
> Right. This is leftover code from the first version. I'll remove it.
>
>>> +                       ret = regulator_enable(par->regulators[i]);
>>> +                       if (ret) {
>>> +                               dev_err(&pdev->dev,
>>> +                                       "failed to enable regulator %d:
>>> %d\n",
>>> +                                       i, ret);
>>> +                               devm_regulator_put(par->regulators[i]);
>>> +                               par->regulators[i] = NULL;
>
> Note here.
>
>>> +                       }
>>> +               }
>>> +       }
>>> +
>>> +       return 0;
>>> +}
>>> +
>>> +static void simplefb_regulators_destroy(struct simplefb_par *par)
>>> +{
>>> +       int i;
>>> +
>>> +       if (!par->regulators)
>>> +               return;
>>> +
>>> +       for (i = 0; i < par->regulator_count; i++)
>>> +               if (par->regulators[i])
>>
>>
>> And idem for this if.
>
> This is still needed, since if we fail to enable any regulator, we just
> ignore it, call regulator_put() on it, and forget about it (set the entry
> to NULL). See the noted place above.

Ah right, ok lets keep that in then :)

Regards,

Hans

WARNING: multiple messages have this Message-ID (diff)
From: Hans de Goede <hdegoede@redhat.com>
To: Chen-Yu Tsai <wens@csie.org>
Cc: Jean-Christophe Plagniol-Villard <plagnioj@jcrosoft.com>,
	Tomi Valkeinen <tomi.valkeinen@ti.com>,
	Rob Herring <robh+dt@kernel.org>, Pawel Moll <pawel.moll@arm.com>,
	Mark Rutland <mark.rutland@arm.com>,
	Ian Campbell <ijc+devicetree@hellion.org.uk>,
	Kumar Gala <galak@codeaurora.org>,
	"linux-fbdev@vger.kernel.org" <linux-fbdev@vger.kernel.org>,
	devicetree <devicetree@vger.kernel.org>,
	linux-kernel <linux-kernel@vger.kernel.org>,
	linux-arm-kernel <linux-arm-kernel@lists.infradead.org>,
	Mark Brown <broonie@kernel.org>
Subject: Re: [PATCH RFC v2 2/2] simplefb: Claim and enable regulators
Date: Wed, 21 Oct 2015 10:09:11 +0200	[thread overview]
Message-ID: <56274827.3000708@redhat.com> (raw)
In-Reply-To: <CAGb2v643sDnNv5DPYocu-50UB3q-itpwGdw8hZ3YN=V+nEBkMg@mail.gmail.com>

Hi,

On 21-10-15 10:04, Chen-Yu Tsai wrote:
> Hi,
>
> On Wed, Oct 21, 2015 at 3:54 PM, Hans de Goede <hdegoede@redhat.com> wrote:
>> Hi,
>>
>>
>> On 21-10-15 07:59, Chen-Yu Tsai wrote:
>>>
>>> This claims and enables regulators listed in the simple framebuffer dt
>>> node. This is needed so that regulators powering the display pipeline
>>> and external hardware, described in the device node and known by the
>>> kernel code, will remain properly enabled.
>>>
>>> Signed-off-by: Chen-Yu Tsai <wens@csie.org>
>>> ---
>>>    drivers/video/fbdev/simplefb.c | 122
>>> ++++++++++++++++++++++++++++++++++++++++-
>>>    1 file changed, 121 insertions(+), 1 deletion(-)
>>>
>>> diff --git a/drivers/video/fbdev/simplefb.c
>>> b/drivers/video/fbdev/simplefb.c
>>> index 52c5c7e63b52..c4ee10d83a70 100644
>>> --- a/drivers/video/fbdev/simplefb.c
>>> +++ b/drivers/video/fbdev/simplefb.c
>>> @@ -28,7 +28,10 @@
>>>    #include <linux/platform_device.h>
>>>    #include <linux/clk.h>
>>>    #include <linux/clk-provider.h>
>>> +#include <linux/of.h>
>>>    #include <linux/of_platform.h>
>>> +#include <linux/parser.h>
>>> +#include <linux/regulator/consumer.h>
>>>
>>>    static struct fb_fix_screeninfo simplefb_fix = {
>>>          .id             = "simple",
>>> @@ -174,6 +177,10 @@ struct simplefb_par {
>>>          int clk_count;
>>>          struct clk **clks;
>>>    #endif
>>> +#if defined CONFIG_OF && defined CONFIG_REGULATOR
>>> +       u32 regulator_count;
>>> +       struct regulator **regulators;
>>> +#endif
>>>    };
>>>
>>>    #if defined CONFIG_OF && defined CONFIG_COMMON_CLK
>>> @@ -269,6 +276,112 @@ static int simplefb_clocks_init(struct simplefb_par
>>> *par,
>>>    static void simplefb_clocks_destroy(struct simplefb_par *par) { }
>>>    #endif
>>>
>>> +#if defined CONFIG_OF && defined CONFIG_REGULATOR
>>> +
>>> +#define SUPPLY_SUFFIX "-supply"
>>> +
>>> +/*
>>> + * Regulator handling code.
>>> + *
>>> + * Here we handle the num-supplies and vin*-supply properties of our
>>> + * "simple-framebuffer" dt node. This is necessary so that we can make
>>> sure
>>> + * that any regulators needed by the display hardware that the bootloader
>>> + * set up for us (and for which it provided a simplefb dt node), stay up,
>>> + * for the life of the simplefb driver.
>>> + *
>>> + * When the driver unloads, we cleanly disable, and then release the
>>> + * regulators.
>>> + *
>>> + * We only complain about errors here, no action is taken as the most
>>> likely
>>> + * error can only happen due to a mismatch between the bootloader which
>>> set
>>> + * up simplefb, and the regulator definitions in the device tree. Chances
>>> are
>>> + * that there are no adverse effects, and if there are, a clean teardown
>>> of
>>> + * the fb probe will not help us much either. So just complain and carry
>>> on,
>>> + * and hope that the user actually gets a working fb at the end of
>>> things.
>>> + */
>>> +static int simplefb_regulators_init(struct simplefb_par *par,
>>> +       struct platform_device *pdev)
>>> +{
>>> +       struct device_node *np = pdev->dev.of_node;
>>> +       struct property *prop;
>>> +       struct regulator *regulator;
>>> +       const char *p;
>>> +       int count = 0, i = 0, ret;
>>> +
>>> +       if (dev_get_platdata(&pdev->dev) || !np)
>>> +               return 0;
>>> +
>>> +       /* Count the number of regulator supplies */
>>> +       for_each_property_of_node(np, prop) {
>>> +               p = strstr(prop->name, SUPPLY_SUFFIX);
>>> +               if (p && p != prop->name)
>>> +                       count++;
>>> +       }
>>> +
>>> +       if (!count)
>>> +               return 0;
>>> +
>>> +       par->regulators = devm_kcalloc(&pdev->dev, count,
>>> +                                      sizeof(struct regulator *),
>>> GFP_KERNEL);
>>> +       if (!par->regulators)
>>> +               return -ENOMEM;
>>> +
>>> +       /* Get all the regulators */
>>> +       for_each_property_of_node(np, prop) {
>>> +               char name[32]; /* 32 is max size of property name */
>>> +
>>> +               p = strstr(prop->name, SUPPLY_SUFFIX);
>>> +               if (p && p != prop->name)
>>> +                       continue;
>>> +
>>> +               strlcpy(name, prop->name,
>>> +                       strlen(prop->name) - sizeof(SUPPLY_SUFFIX) + 1);
>>> +               regulator = devm_regulator_get_optional(&pdev->dev, name);
>>> +               if (IS_ERR(regulator)) {
>>> +                       if (PTR_ERR(regulator) == -EPROBE_DEFER)
>>> +                               return -EPROBE_DEFER;
>>> +                       dev_err(&pdev->dev, "regulator %s not found:
>>> %ld\n",
>>> +                               name, PTR_ERR(regulator));
>>> +                       continue;
>>> +               }
>>> +               par->regulators[i++] = regulator;
>>
>>
>> So you only fill slots when the regulator_get has succeeded
>>
>>> +       }
>>> +       par->regulator_count = i;
>>
>>
>> and regulator_count now is the amount of successfully gotten regulators
>> (which may be different from count).
>>
>>> +
>>> +       /* Enable all the regulators */
>>> +       for (i = 0; i < par->regulator_count; i++) {
>>> +               if (par->regulators[i]) {
>>
>>
>> That means that this "if" is not necessary, it will always be true.
>
> Right. This is leftover code from the first version. I'll remove it.
>
>>> +                       ret = regulator_enable(par->regulators[i]);
>>> +                       if (ret) {
>>> +                               dev_err(&pdev->dev,
>>> +                                       "failed to enable regulator %d:
>>> %d\n",
>>> +                                       i, ret);
>>> +                               devm_regulator_put(par->regulators[i]);
>>> +                               par->regulators[i] = NULL;
>
> Note here.
>
>>> +                       }
>>> +               }
>>> +       }
>>> +
>>> +       return 0;
>>> +}
>>> +
>>> +static void simplefb_regulators_destroy(struct simplefb_par *par)
>>> +{
>>> +       int i;
>>> +
>>> +       if (!par->regulators)
>>> +               return;
>>> +
>>> +       for (i = 0; i < par->regulator_count; i++)
>>> +               if (par->regulators[i])
>>
>>
>> And idem for this if.
>
> This is still needed, since if we fail to enable any regulator, we just
> ignore it, call regulator_put() on it, and forget about it (set the entry
> to NULL). See the noted place above.

Ah right, ok lets keep that in then :)

Regards,

Hans

  reply	other threads:[~2015-10-21  8:09 UTC|newest]

Thread overview: 28+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2015-10-21  5:58 [PATCH RFC v2 0/2] simplefb: Add regulator handling support Chen-Yu Tsai
2015-10-21  5:58 ` Chen-Yu Tsai
2015-10-21  5:58 ` Chen-Yu Tsai
2015-10-21  5:59 ` [PATCH RFC v2 1/2] dt-bindings: simplefb: Support a list of regulator supply properties Chen-Yu Tsai
2015-10-21  5:59   ` Chen-Yu Tsai
2015-10-21  5:59   ` Chen-Yu Tsai
2015-10-21  5:59   ` Chen-Yu Tsai
2015-10-21  7:50   ` Hans de Goede
2015-10-21  7:50     ` Hans de Goede
2015-10-21  7:50     ` Hans de Goede
2015-10-21  7:50     ` Hans de Goede
2015-10-21  5:59 ` [PATCH RFC v2 2/2] simplefb: Claim and enable regulators Chen-Yu Tsai
2015-10-21  5:59   ` Chen-Yu Tsai
2015-10-21  5:59   ` Chen-Yu Tsai
2015-10-21  7:54   ` Hans de Goede
2015-10-21  7:54     ` Hans de Goede
2015-10-21  7:54     ` Hans de Goede
2015-10-21  8:04     ` Chen-Yu Tsai
2015-10-21  8:04       ` Chen-Yu Tsai
2015-10-21  8:04       ` Chen-Yu Tsai
2015-10-21  8:09       ` Hans de Goede [this message]
2015-10-21  8:09         ` Hans de Goede
2015-10-21  8:09         ` Hans de Goede
2015-10-21  8:09         ` Hans de Goede
2015-10-22 16:53 ` [PATCH RFC v2 0/2] simplefb: Add regulator handling support Mark Brown
2015-10-22 16:53   ` Mark Brown
2015-10-22 16:53   ` Mark Brown
2015-10-22 16:53   ` Mark Brown

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=56274827.3000708@redhat.com \
    --to=hdegoede@redhat.com \
    --cc=linux-arm-kernel@lists.infradead.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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.