All of lore.kernel.org
 help / color / mirror / Atom feed
From: Stephen Boyd <sboyd@codeaurora.org>
To: Bjorn Andersson <bjorn.andersson@sonymobile.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>, Bryan Wu <cooloney@gmail.com>,
	Richard Purdie <rpurdie@rpsys.net>,
	Grant Likely <grant.likely@linaro.org>
Cc: Courtney Cavin <courtney.cavin@sonymobile.com>,
	devicetree@vger.kernel.org, linux-kernel@vger.kernel.org,
	linux-leds@vger.kernel.org, linux-arm-msm@vger.kernel.org
Subject: Re: [PATCH 2/2] leds: add Qualcomm PM8941 WLED driver
Date: Tue, 16 Dec 2014 17:15:22 -0800	[thread overview]
Message-ID: <5490D92A.3070107@codeaurora.org> (raw)
In-Reply-To: <1418084551-28946-2-git-send-email-bjorn.andersson@sonymobile.com>

On 12/08/2014 04:22 PM, Bjorn Andersson wrote:
> diff --git a/drivers/leds/leds-pm8941-wled.c b/drivers/leds/leds-pm8941-wled.c
> new file mode 100644
> index 0000000..aa06d0b
> --- /dev/null
> +++ b/drivers/leds/leds-pm8941-wled.c
> @@ -0,0 +1,466 @@
> +/* Copyright (c) 2013, Sony Mobile Communications, AB.
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License version 2 and
> + * only version 2 as published by the Free Software Foundation.
> + *
> + * 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.
> + */
> +
> +#include <linux/leds.h>
> +#include <linux/module.h>
> +#include <linux/of.h>
> +#include <linux/of_device.h>
> +#include <linux/regmap.h>

Missing <linux/kernel.h> for container_of() macro.

> +
> +enum pm8941_wled_reg {
> +	PM8941_WLED_REG_VAL_BASE		= 0x40,
> +#define PM8941_WLED_REG_VAL_MAX			0xFFF
> +
> +	PM8941_WLED_REG_MOD_EN			= 0x46,
> +#define PM8941_WLED_REG_MOD_EN_BIT		BIT(7)
> +#define PM8941_WLED_REG_MOD_EN_MASK		BIT(7)
> +
> +	PM8941_WLED_REG_SYNC			= 0x47,
> +#define PM8941_WLED_REG_SYNC_MASK		0x07
> +#define PM8941_WLED_REG_SYNC_LED1		BIT(0)
> +#define PM8941_WLED_REG_SYNC_LED2		BIT(1)
> +#define PM8941_WLED_REG_SYNC_LED3		BIT(2)
> +#define PM8941_WLED_REG_SYNC_ALL		0x07
> +#define PM8941_WLED_REG_SYNC_CLEAR		0x00
> +
> +	PM8941_WLED_REG_FREQ			= 0x4c,
> +#define PM8941_WLED_REG_FREQ_MASK		0x0f
> +
> +	PM8941_WLED_REG_OVP			= 0x4d,
> +#define PM8941_WLED_REG_OVP_MASK		0x03
> +
> +	PM8941_WLED_REG_BOOST			= 0x4e,
> +#define PM8941_WLED_REG_BOOST_MASK		0x07
> +
> +	PM8941_WLED_REG_SINK			= 0x4f,
> +#define PM8941_WLED_REG_SINK_MASK		0xe0
> +#define PM8941_WLED_REG_SINK_SHFT		0x05
> +
> +/* Per-'string' registers below */
> +#define PM8941_WLED_REG_STR_OFFSET		0x10
> +
> +	PM8941_WLED_REG_STR_MOD_EN_BASE		= 0x60,
> +#define PM8941_WLED_REG_STR_MOD_EN		BIT(7)
> +#define PM8941_WLED_REG_STR_MOD_MASK		BIT(7)
> +
> +	PM8941_WLED_REG_STR_SCALE_BASE		= 0x62,
> +#define PM8941_WLED_REG_STR_SCALE_MASK		0x1f
> +
> +	PM8941_WLED_REG_STR_MOD_SRC_BASE	= 0x63,
> +#define PM8941_WLED_REG_STR_MOD_SRC_MASK	0x01
> +#define PM8941_WLED_REG_STR_MOD_SRC_INT		0x00
> +#define PM8941_WLED_REG_STR_MOD_SRC_EXT		0x01
> +
> +	PM8941_WLED_REG_STR_CABC_BASE		= 0x66,
> +#define PM8941_WLED_REG_STR_CABC_MASK		BIT(7)
> +#define PM8941_WLED_REG_STR_CABC_EN		BIT(7)
> +};

I don't see any value in this enum. It's never used in a switch
statement so why not just have #defines for the register offsets. It
would make reading this a lot easier too.


> +
> +static int pm8941_wled_set(struct led_classdev *cdev,
> +			   enum led_brightness value)
> +{
> +	struct pm8941_wled_context *ctx;
> +	struct pm8941_wled *wled;
> +	u8 ctrl = 0;
> +	u16 val;
> +	int rc;
> +	int i;
> +
> +	wled = container_of(cdev, struct pm8941_wled, cdev);
> +	ctx = container_of(wled, struct pm8941_wled_context, wled);
> +
> +	if (value != 0)
> +		ctrl = PM8941_WLED_REG_MOD_EN_BIT;
> +
> +	val = (value * PM8941_WLED_REG_VAL_MAX) / LED_FULL;

Unnecessary parens here.

> +
> +	rc = regmap_update_bits(ctx->regmap,
>
> +
> +static int pm8941_wled_configure(struct pm8941_wled *wled, struct device *dev)
> +{
[...]
> +
> +	if (dev->of_node == NULL) {
> +		dev_err(dev, "no OF node!\n");
> +		return -EINVAL;
> +	}

Seems like an unnecessary check. Everything's DT so far.

> +
> +	rc = of_property_read_u32(dev->of_node, "reg", &val);
> +	if (rc || val > 0xffff) {
> +		dev_err(dev, "invalid IO resources\n");
> +		return rc ? rc : -EINVAL;
> +	}
> +	wled->addr = val;
> +
> +	rc = of_property_read_string(dev->of_node, "label", &wled->cdev.name);
> +	if (rc)
> +		wled->cdev.name = dev->of_node->name;
> +
> +	wled->cdev.default_trigger = of_get_property(dev->of_node,
> +			"linux,default-trigger", NULL);
> +
> +	*cfg = pm8941_wled_config_defaults;
> +	for (i = 0; i < ARRAY_SIZE(u32_opts); ++i) {
> +		u32 sel, c;
> +		int j, rj;
> +
> +		rc = of_property_read_u32(dev->of_node, u32_opts[i].name, &val);
> +		if (rc) {
> +			if (rc != -EINVAL) {
> +				dev_err(dev, "error reading '%s'\n",
> +						u32_opts[i].name);
> +				return rc;
> +			}
> +			continue;
> +		}
> +
> +		sel = UINT_MAX;
> +		rj = -1;
> +		c = pm8941_wled_values(u32_opts[i].cfg, 0);
> +		for (j = 0; c != UINT_MAX; ++j) {
> +			if (c <= val && (sel == UINT_MAX || c >= sel)) {
> +				sel = c;
> +				rj = j;
> +			}
> +			c = pm8941_wled_values(u32_opts[i].cfg, j + 1);
> +		}
> +		if (sel == UINT_MAX) {
> +			dev_err(dev, "invalid value for '%s'\n",
> +					u32_opts[i].name);
> +			return rc;
> +		}
> +		if (sel != val) {
> +			dev_warn(dev, "rounding '%s' down to %u\n",
> +					u32_opts[i].name, sel);
> +		}

Do we really want to do all this complicated rounding and checking?
Can't we just assume the DT is correct?

> +		dev_dbg(dev, "'%s' = %u\n", u32_opts[i].name, sel);
> +		*u32_opts[i].val_ptr = rj;
> +	};
> +
> +	for (i = 0; i < ARRAY_SIZE(bool_opts); ++i) {
> +		if (of_property_read_bool(dev->of_node, bool_opts[i].name))
> +			*bool_opts[i].val_ptr = true;
> +	}
> +
> +	cfg->num_strings = cfg->num_strings + 1;
> +
> +	return 0;
> +}
> +
> +static int pm8941_wled_probe(struct platform_device *pdev)
> +{
> +	struct pm8941_wled_context *ctx;
> +	struct regmap *regmap;
> +	int rc;
> +
> +	regmap = dev_get_regmap(pdev->dev.parent, NULL);
> +	if (!regmap) {
> +		dev_err(&pdev->dev, "Unable to get regmap\n");
> +		return -EINVAL;
> +	}
> +
> +	ctx = devm_kzalloc(&pdev->dev, sizeof(*ctx), GFP_KERNEL);
> +	if (ctx == NULL)

Nitpick only because it doesn't match the !regmap style above. Please
use the !ctx style here as well.

> +		return -ENOMEM;
> +
> +	ctx->regmap = regmap;
> +
> +	rc = pm8941_wled_configure(&ctx->wled, &pdev->dev);
> +	if (rc)
> +		return rc;
> +
> +	rc = pm8941_wled_setup(&ctx->wled);
> +	if (rc)
> +		return rc;
> +
> +	ctx->wled.cdev.brightness_set = pm8941_wled_set_brightness;
> +
> +	rc = led_classdev_register(&pdev->dev, &ctx->wled.cdev);
> +	if (rc)
> +		return rc;
> +
> +	platform_set_drvdata(pdev, ctx);
> +	dev_info(&pdev->dev, "registered led \"%s\"\n", ctx->wled.cdev.name);

Please don't spam the log with "I'm alive!" messages.

> +
> +	return 0;
> +};
> +
> +static int pm8941_wled_remove(struct platform_device *pdev)
> +{
> +	struct pm8941_wled_context *ctx;
> +
> +	ctx = platform_get_drvdata(pdev);
> +	led_classdev_unregister(&ctx->wled.cdev);
> +
> +	return 0;
> +}
> +
> +static const struct of_device_id pm8941_wled_match_table[] = {
> +	{ .compatible = "qcom,pm8941-wled" },
> +	{}
> +};

MODULE_DEVICE_TABLE?

> +
> +static struct platform_driver pm8941_wled_driver = {
> +	.probe	= pm8941_wled_probe,
> +	.remove = pm8941_wled_remove,
> +	.driver	= {
> +		.name		= "pm8941-wled",
> +		.owner		= THIS_MODULE,
> +		.of_match_table	= pm8941_wled_match_table,
> +	},
> +};
> +
> +module_platform_driver(pm8941_wled_driver);
> +
> +MODULE_DESCRIPTION("pm8941 wled driver");
> +MODULE_LICENSE("GPL v2");
> +MODULE_ALIAS("platform: pm8941-wled");

-- 
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum,
a Linux Foundation Collaborative Project

  parent reply	other threads:[~2014-12-17  1:15 UTC|newest]

Thread overview: 13+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2014-12-09  0:22 [PATCH 1/2] leds: add DT binding for Qualcomm PM8941 WLED block Bjorn Andersson
2014-12-09  0:22 ` Bjorn Andersson
2014-12-09  0:22 ` [PATCH 2/2] leds: add Qualcomm PM8941 WLED driver Bjorn Andersson
2014-12-09  0:22   ` Bjorn Andersson
2014-12-17  0:54   ` Bryan Wu
2014-12-18 23:43     ` Bjorn
2014-12-19  8:15       ` Ivan T. Ivanov
2014-12-17  1:15   ` Stephen Boyd [this message]
2014-12-18 23:57     ` Bjorn
2014-12-10  1:19 ` [PATCH 1/2] leds: add DT binding for Qualcomm PM8941 WLED block Bryan Wu
2014-12-17  0:54   ` Bryan Wu
2014-12-17  1:15 ` Stephen Boyd
2014-12-18 23:36   ` Bjorn

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=5490D92A.3070107@codeaurora.org \
    --to=sboyd@codeaurora.org \
    --cc=bjorn.andersson@sonymobile.com \
    --cc=cooloney@gmail.com \
    --cc=courtney.cavin@sonymobile.com \
    --cc=devicetree@vger.kernel.org \
    --cc=galak@codeaurora.org \
    --cc=grant.likely@linaro.org \
    --cc=ijc+devicetree@hellion.org.uk \
    --cc=linux-arm-msm@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-leds@vger.kernel.org \
    --cc=mark.rutland@arm.com \
    --cc=pawel.moll@arm.com \
    --cc=robh+dt@kernel.org \
    --cc=rpurdie@rpsys.net \
    /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.