Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > linux.kernel > #1408364 > unrolled thread

[PATCH 0/4] pwm: add support for ChromeOS EC PWM

Started byBrian Norris <briannorris@chromium.org>
First post2016-05-28 03:50 +0200
Last post2016-05-30 08:50 +0200
Articles 7 — 3 participants

Back to article view | Back to linux.kernel


Contents

  [PATCH 0/4] pwm: add support for ChromeOS EC PWM Brian Norris <briannorris@chromium.org> - 2016-05-28 03:50 +0200
    [PATCH 1/4] mfd: cros_ec: Add cros_ec_cmd_xfer_status helper Brian Norris <briannorris@chromium.org> - 2016-05-28 03:50 +0200
    [PATCH 4/4] pwm: add ChromeOS EC PWM driver Brian Norris <briannorris@chromium.org> - 2016-05-28 03:50 +0200
      Re: [PATCH 4/4] pwm: add ChromeOS EC PWM driver Gwendal Grignou <gwendal@chromium.org> - 2016-05-29 07:10 +0200
    [PATCH 3/4] doc: dt: pwm: add binding for ChromeOS EC PWM Brian Norris <briannorris@chromium.org> - 2016-05-28 03:50 +0200
      Re: [PATCH 3/4] doc: dt: pwm: add binding for ChromeOS EC PWM Gwendal Grignou <gwendal@chromium.org> - 2016-05-29 07:10 +0200
    Re: [PATCH 0/4] pwm: add support for ChromeOS EC PWM Tomeu Vizoso <tomeu.vizoso@collabora.com> - 2016-05-30 08:50 +0200

#1408364 — [PATCH 0/4] pwm: add support for ChromeOS EC PWM

FromBrian Norris <briannorris@chromium.org>
Date2016-05-28 03:50 +0200
Subject[PATCH 0/4] pwm: add support for ChromeOS EC PWM
Message-ID<rDBy1-2BY-3@gated-at.bofh.it>
Hi,

This series adds support for the new ChromeOS EC PWM API, so we can control,
e.g., the backlight when it's attached to the EC. It uses Boris's latest
"atomic" hooks for the PWM API (i.e., the ->apply() callback), which were
recently merged.

It seems nice to have the cros_ec_cmd_xfer_status() helper, which we have
locally in the ChromeOS kernel, and which has been part of another larger patch
series:

https://lkml.org/lkml/2016/4/12/342

So I've picked it into this series as well. Obviously, I don't care which one
is taken, but AFAICT, Tomeu's USB PD series isn't extremely active right now.

As this touches MFD (sort of), drivers/platform/chrome/, and drivers/pwm/, I'm
not sure who it should all go through: Lee, Thierry, or Olof?

Anyway, please review.

Regards,
Brian

Brian Norris (3):
  mfd: cros_ec: add EC_PWM function definitions
  doc: dt: pwm: add binding for ChromeOS EC PWM
  pwm: add ChromeOS EC PWM driver

Tomeu Vizoso (1):
  mfd: cros_ec: Add cros_ec_cmd_xfer_status helper

 .../devicetree/bindings/pwm/google,cros-ec-pwm.txt |  25 +++
 drivers/platform/chrome/cros_ec_proto.c            |  15 ++
 drivers/pwm/Kconfig                                |   7 +
 drivers/pwm/Makefile                               |   1 +
 drivers/pwm/pwm-cros-ec.c                          | 230 +++++++++++++++++++++
 include/linux/mfd/cros_ec.h                        |  18 ++
 include/linux/mfd/cros_ec_commands.h               |  31 +++
 7 files changed, 327 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/pwm/google,cros-ec-pwm.txt
 create mode 100644 drivers/pwm/pwm-cros-ec.c

-- 
2.8.0.rc3.226.g39d4020

[toc] | [next] | [standalone]


#1408365 — [PATCH 1/4] mfd: cros_ec: Add cros_ec_cmd_xfer_status helper

FromBrian Norris <briannorris@chromium.org>
Date2016-05-28 03:50 +0200
Subject[PATCH 1/4] mfd: cros_ec: Add cros_ec_cmd_xfer_status helper
Message-ID<rDBy1-2BY-1@gated-at.bofh.it>
In reply to#1408364
From: Tomeu Vizoso <tomeu.vizoso@collabora.com>

So that callers of cros_ec_cmd_xfer don't have to repeat boilerplate
code when checking for errors from the EC side.

Signed-off-by: Tomeu Vizoso <tomeu.vizoso@collabora.com>
Reviewed-by: Benson Leung <bleung@chromium.org>
Signed-off-by: Brian Norris <briannorris@chromium.org>
---
Stolen from:
  https://lkml.org/lkml/2016/4/12/342
  https://patchwork.kernel.org/patch/8810001/

 drivers/platform/chrome/cros_ec_proto.c | 15 +++++++++++++++
 include/linux/mfd/cros_ec.h             | 18 ++++++++++++++++++
 2 files changed, 33 insertions(+)

diff --git a/drivers/platform/chrome/cros_ec_proto.c b/drivers/platform/chrome/cros_ec_proto.c
index 990308ca384f..75eb90d2e4f9 100644
--- a/drivers/platform/chrome/cros_ec_proto.c
+++ b/drivers/platform/chrome/cros_ec_proto.c
@@ -380,3 +380,18 @@ int cros_ec_cmd_xfer(struct cros_ec_device *ec_dev,
 	return ret;
 }
 EXPORT_SYMBOL(cros_ec_cmd_xfer);
+
+int cros_ec_cmd_xfer_status(struct cros_ec_device *ec_dev,
+			    struct cros_ec_command *msg)
+{
+	int ret;
+
+	ret = cros_ec_cmd_xfer(ec_dev, msg);
+	if (ret < 0)
+		dev_err(ec_dev->dev, "Command xfer error (err:%d)\n", ret);
+	else if (msg->result != EC_RES_SUCCESS)
+		return -EECRESULT - msg->result;
+
+	return ret;
+}
+EXPORT_SYMBOL(cros_ec_cmd_xfer_status);
diff --git a/include/linux/mfd/cros_ec.h b/include/linux/mfd/cros_ec.h
index a677c2bd485c..b43153f1aca5 100644
--- a/include/linux/mfd/cros_ec.h
+++ b/include/linux/mfd/cros_ec.h
@@ -40,6 +40,9 @@
 #define EC_MAX_REQUEST_OVERHEAD		1
 #define EC_MAX_RESPONSE_OVERHEAD	2
 
+/* ec_command return value for non-success result from EC */
+#define EECRESULT 1000
+
 /*
  * Command interface between EC and AP, for LPC, I2C and SPI interfaces.
  */
@@ -224,6 +227,21 @@ int cros_ec_cmd_xfer(struct cros_ec_device *ec_dev,
 		     struct cros_ec_command *msg);
 
 /**
+ * cros_ec_cmd_xfer_status - Send a command to the ChromeOS EC
+ *
+ * This function is identical to cros_ec_cmd_xfer, except it returns succes
+ * status only if both the command was transmitted successfully and the EC
+ * replied with success status. It's not necessary to check msg->result when
+ * using this function.
+ *
+ * @ec_dev: EC device
+ * @msg: Message to write
+ * @return: Num. of bytes transferred on success, <0 on failure
+ */
+int cros_ec_cmd_xfer_status(struct cros_ec_device *ec_dev,
+			    struct cros_ec_command *msg);
+
+/**
  * cros_ec_remove - Remove a ChromeOS EC
  *
  * Call this to deregister a ChromeOS EC, then clean up any private data.
-- 
2.8.0.rc3.226.g39d4020

[toc] | [prev] | [next] | [standalone]


#1408366 — [PATCH 4/4] pwm: add ChromeOS EC PWM driver

FromBrian Norris <briannorris@chromium.org>
Date2016-05-28 03:50 +0200
Subject[PATCH 4/4] pwm: add ChromeOS EC PWM driver
Message-ID<rDBy1-2BY-5@gated-at.bofh.it>
In reply to#1408364
Use the new ChromeOS EC EC_CMD_PWM_{GET,SET}_DUTY commands to control
one or more PWMs attached to the Embedded Controller. Because the EC
allows us to modify the duty cycle (as a percentage, where U16_MAX is
100%) but not the period, we assign the period a fixed value of
EC_PWM_MAX_DUTY and reject all attempts to change it.

Signed-off-by: Brian Norris <briannorris@chromium.org>
---
 drivers/pwm/Kconfig       |   7 ++
 drivers/pwm/Makefile      |   1 +
 drivers/pwm/pwm-cros-ec.c | 230 ++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 238 insertions(+)
 create mode 100644 drivers/pwm/pwm-cros-ec.c

diff --git a/drivers/pwm/Kconfig b/drivers/pwm/Kconfig
index c182efc62c7b..4f2b16a50f42 100644
--- a/drivers/pwm/Kconfig
+++ b/drivers/pwm/Kconfig
@@ -137,6 +137,13 @@ config PWM_CRC
 	  Generic PWM framework driver for Crystalcove (CRC) PMIC based PWM
 	  control.
 
+config PWM_CROS_EC
+	tristate "ChromeOS EC PWM driver"
+	depends on MFD_CROS_EC
+	help
+	  PWM driver for exposing a PWM attached to the ChromeOS Embedded
+	  Controller.
+
 config PWM_EP93XX
 	tristate "Cirrus Logic EP93xx PWM support"
 	depends on ARCH_EP93XX
diff --git a/drivers/pwm/Makefile b/drivers/pwm/Makefile
index dd35bc121a18..ffde923cf3df 100644
--- a/drivers/pwm/Makefile
+++ b/drivers/pwm/Makefile
@@ -11,6 +11,7 @@ obj-$(CONFIG_PWM_BFIN)		+= pwm-bfin.o
 obj-$(CONFIG_PWM_BRCMSTB)	+= pwm-brcmstb.o
 obj-$(CONFIG_PWM_CLPS711X)	+= pwm-clps711x.o
 obj-$(CONFIG_PWM_CRC)		+= pwm-crc.o
+obj-$(CONFIG_PWM_CROS_EC)	+= pwm-cros-ec.o
 obj-$(CONFIG_PWM_EP93XX)	+= pwm-ep93xx.o
 obj-$(CONFIG_PWM_FSL_FTM)	+= pwm-fsl-ftm.o
 obj-$(CONFIG_PWM_IMG)		+= pwm-img.o
diff --git a/drivers/pwm/pwm-cros-ec.c b/drivers/pwm/pwm-cros-ec.c
new file mode 100644
index 000000000000..cf65e44fe355
--- /dev/null
+++ b/drivers/pwm/pwm-cros-ec.c
@@ -0,0 +1,230 @@
+/*
+ * Copyright (C) 2016 Google, Inc
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2, as published by
+ * the Free Software Foundation.
+ *
+ * Expose a PWM controlled by the ChromeOS EC to the host processor.
+ */
+
+#include <linux/module.h>
+#include <linux/mfd/cros_ec.h>
+#include <linux/mfd/cros_ec_commands.h>
+#include <linux/platform_device.h>
+#include <linux/pwm.h>
+#include <linux/slab.h>
+
+/**
+ * struct cros_ec_pwm_device - Driver data for EC PWM
+ *
+ * @dev: Device node
+ * @ec: Pointer to EC device
+ * @chip: PWM controller chip
+ */
+struct cros_ec_pwm_device {
+	struct device *dev;
+	struct cros_ec_device *ec;
+	struct pwm_chip chip;
+};
+
+static inline struct cros_ec_pwm_device *pwm_to_cros_ec_pwm(struct pwm_chip *c)
+{
+	return container_of(c, struct cros_ec_pwm_device, chip);
+}
+
+static int cros_ec_pwm_set_duty(struct cros_ec_pwm_device *ec_pwm,
+				   struct pwm_device *pwm,
+				   uint16_t duty)
+{
+	struct cros_ec_device *ec = ec_pwm->ec;
+	struct ec_params_pwm_set_duty *params;
+	struct cros_ec_command *msg;
+	int ret;
+
+	msg = kzalloc(sizeof(*msg) + sizeof(*params), GFP_KERNEL);
+	if (!msg)
+		return -ENOMEM;
+	params = (void *)&msg->data[0];
+
+	msg->version = 0;
+	msg->command = EC_CMD_PWM_SET_DUTY;
+	msg->insize = 0;
+	msg->outsize = sizeof(*params);
+
+	params->duty = duty;
+	params->pwm_type = EC_PWM_TYPE_GENERIC;
+	params->index = pwm->hwpwm;
+
+	ret = cros_ec_cmd_xfer_status(ec, msg);
+	kfree(msg);
+	return ret;
+}
+
+static int cros_ec_pwm_get_duty(struct cros_ec_pwm_device *ec_pwm,
+				struct pwm_device *pwm)
+{
+	struct cros_ec_device *ec = ec_pwm->ec;
+	struct ec_params_pwm_get_duty *params;
+	struct ec_response_pwm_get_duty *resp;
+	struct cros_ec_command *msg;
+	int ret;
+
+	msg = kzalloc(sizeof(*msg) + max(sizeof(*params), sizeof(*resp)),
+			GFP_KERNEL);
+	if (!msg)
+		return -ENOMEM;
+	params = (void *)&msg->data[0];
+	resp = (void *)&msg->data[0];
+
+	msg->version = 0;
+	msg->command = EC_CMD_PWM_GET_DUTY;
+	msg->insize = sizeof(*params);
+	msg->outsize = sizeof(*resp);
+
+	params->pwm_type = EC_PWM_TYPE_GENERIC;
+	params->index = pwm->hwpwm;
+
+	ret = cros_ec_cmd_xfer_status(ec, msg);
+	if (ret < 0)
+		goto out;
+
+	ret = resp->duty;
+
+out:
+	kfree(msg);
+	return ret;
+}
+
+static int cros_ec_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm,
+			     struct pwm_state *state)
+{
+	struct cros_ec_pwm_device *ec_pwm = pwm_to_cros_ec_pwm(chip);
+
+	/* The EC won't let us change the period */
+	if (state->period != EC_PWM_MAX_DUTY)
+		return -EINVAL;
+
+	return cros_ec_pwm_set_duty(ec_pwm, pwm, state->duty_cycle);
+}
+
+static void cros_ec_pwm_get_state(struct pwm_chip *chip, struct pwm_device *pwm,
+				  struct pwm_state *state)
+{
+	struct cros_ec_pwm_device *ec_pwm = pwm_to_cros_ec_pwm(chip);
+	int ret;
+
+	ret = cros_ec_pwm_get_duty(ec_pwm, pwm);
+	if (ret < 0) {
+		dev_err(chip->dev, "error getting initial duty: %d\n", ret);
+		return;
+	}
+
+	state->enabled = (ret > 0);
+	state->period = EC_PWM_MAX_DUTY;
+	state->duty_cycle = ret;
+}
+
+static struct pwm_device *
+cros_ec_pwm_xlate(struct pwm_chip *pc, const struct of_phandle_args *args)
+{
+	struct pwm_device *pwm;
+
+	if (args->args[0] >= pc->npwm)
+		return ERR_PTR(-EINVAL);
+
+	pwm = pwm_request_from_chip(pc, args->args[0], NULL);
+	if (IS_ERR(pwm))
+		return pwm;
+
+	/* The EC won't let us change the period */
+	pwm->args.period = EC_PWM_MAX_DUTY;
+
+	return pwm;
+}
+
+static const struct pwm_ops cros_ec_pwm_ops = {
+	.get_state	= cros_ec_pwm_get_state,
+	.apply		= cros_ec_pwm_apply,
+	.owner		= THIS_MODULE,
+};
+
+static int cros_ec_pwm_probe(struct platform_device *pdev)
+{
+	struct cros_ec_device *ec = dev_get_drvdata(pdev->dev.parent);
+	struct device *dev = &pdev->dev;
+	struct device_node *np = dev->of_node;
+	struct cros_ec_pwm_device *ec_pwm;
+	struct pwm_chip *chip;
+	u32 val;
+	int ret;
+
+	if (!ec) {
+		dev_err(dev, "no parent EC device\n");
+		return -EINVAL;
+	}
+
+	ec_pwm = devm_kzalloc(dev, sizeof(*ec_pwm), GFP_KERNEL);
+	if (!ec_pwm)
+		return -ENOMEM;
+	chip = &ec_pwm->chip;
+	ec_pwm->ec = ec;
+
+	/* PWM chip */
+	chip->dev = dev;
+	chip->ops = &cros_ec_pwm_ops;
+	chip->of_xlate = cros_ec_pwm_xlate;
+	chip->of_pwm_n_cells = 1;
+	chip->base = -1;
+	ret = of_property_read_u32(np, "google,max-pwms", &val);
+	if (ret) {
+		dev_err(dev, "Couldn't read max-pwms property: %d\n", ret);
+		return ret;
+	}
+	/* The index field is only 8 bits */
+	if (val > U8_MAX) {
+		dev_err(dev, "Can't support %u PWMs\n", val);
+		return -EINVAL;
+	}
+	chip->npwm = val;
+
+	ret = pwmchip_add(chip);
+	if (ret < 0) {
+		dev_err(dev, "cannot register PWM: %d\n", ret);
+		return ret;
+	}
+
+	platform_set_drvdata(pdev, ec_pwm);
+
+	return ret;
+}
+
+static int cros_ec_pwm_remove(struct platform_device *dev)
+{
+	struct cros_ec_pwm_device *ec_pwm = platform_get_drvdata(dev);
+	struct pwm_chip *chip = &ec_pwm->chip;
+
+	return pwmchip_remove(chip);
+}
+
+#ifdef CONFIG_OF
+static const struct of_device_id cros_ec_pwm_of_match[] = {
+	{ .compatible = "google,cros-ec-pwm" },
+	{},
+};
+MODULE_DEVICE_TABLE(of, cros_ec_pwm_of_match);
+#endif
+
+static struct platform_driver cros_ec_pwm_driver = {
+	.probe = cros_ec_pwm_probe,
+	.remove = cros_ec_pwm_remove,
+	.driver = {
+		.name = "cros-ec-pwm",
+		.of_match_table = of_match_ptr(cros_ec_pwm_of_match),
+	},
+};
+module_platform_driver(cros_ec_pwm_driver);
+
+MODULE_ALIAS("platform:cros-ec-pwm");
+MODULE_DESCRIPTION("ChromeOS EC PWM driver");
+MODULE_LICENSE("GPL v2");
-- 
2.8.0.rc3.226.g39d4020

[toc] | [prev] | [next] | [standalone]


#1408542 — Re: [PATCH 4/4] pwm: add ChromeOS EC PWM driver

FromGwendal Grignou <gwendal@chromium.org>
Date2016-05-29 07:10 +0200
SubjectRe: [PATCH 4/4] pwm: add ChromeOS EC PWM driver
Message-ID<rE197-1Rj-5@gated-at.bofh.it>
In reply to#1408366
On Fri, May 27, 2016 at 6:39 PM, Brian Norris <briannorris@chromium.org> wrote:
> Use the new ChromeOS EC EC_CMD_PWM_{GET,SET}_DUTY commands to control
> one or more PWMs attached to the Embedded Controller. Because the EC
> allows us to modify the duty cycle (as a percentage, where U16_MAX is
> 100%) but not the period, we assign the period a fixed value of
> EC_PWM_MAX_DUTY and reject all attempts to change it.
>
> Signed-off-by: Brian Norris <briannorris@chromium.org>
> ---

> + */
> +struct cros_ec_pwm_device {
> +       struct device *dev;
> +       struct cros_ec_device *ec;
> +       struct pwm_chip chip;
> +};
> +
> +static inline struct cros_ec_pwm_device *pwm_to_cros_ec_pwm(struct pwm_chip *c)
> +{
> +       return container_of(c, struct cros_ec_pwm_device, chip);
> +}
> +
> +static int cros_ec_pwm_set_duty(struct cros_ec_pwm_device *ec_pwm,
> +                                  struct pwm_device *pwm,
> +                                  uint16_t duty)
Given you seprated the pwm stuff from the EC stuff and focusing on
sending a EC command here, the first parameter should be of
cros_ec_device* instead of cros_ec_pwm_device*.
> +{
> +       struct cros_ec_device *ec = ec_pwm->ec;
> +       struct ec_params_pwm_set_duty *params;
> +       struct cros_ec_command *msg;
> +       int ret;
> +
> +       msg = kzalloc(sizeof(*msg) + sizeof(*params), GFP_KERNEL);
Use an ad-hoc data structure on the stack, so you will always be able
to send the command to the EC.
> +       if (!msg)
> +               return -ENOMEM;
> +       params = (void *)&msg->data[0];
> +
> +       msg->version = 0;
> +       msg->command = EC_CMD_PWM_SET_DUTY;
> +       msg->insize = 0;
> +       msg->outsize = sizeof(*params);
> +
> +       params->duty = duty;
> +       params->pwm_type = EC_PWM_TYPE_GENERIC;
> +       params->index = pwm->hwpwm;
> +
> +       ret = cros_ec_cmd_xfer_status(ec, msg);
> +       kfree(msg);
> +       return ret;
> +}
> +
> +static int cros_ec_pwm_get_duty(struct cros_ec_pwm_device *ec_pwm,
> +                               struct pwm_device *pwm)
Idem.
> +{
> +       struct cros_ec_device *ec = ec_pwm->ec;
> +       struct ec_params_pwm_get_duty *params;
> +       struct ec_response_pwm_get_duty *resp;
> +       struct cros_ec_command *msg;
> +       int ret;
> +
> +       msg = kzalloc(sizeof(*msg) + max(sizeof(*params), sizeof(*resp)),
Idem.
> +                       GFP_KERNEL);
> +       if (!msg)
> +               return -ENOMEM;
> +       params = (void *)&msg->data[0];
> +       resp = (void *)&msg->data[0];
> +
> +       msg->version = 0;
> +       msg->command = EC_CMD_PWM_GET_DUTY;
> +       msg->insize = sizeof(*params);
> +       msg->outsize = sizeof(*resp);
> +
> +       params->pwm_type = EC_PWM_TYPE_GENERIC;
> +       params->index = pwm->hwpwm;
> +
> +       ret = cros_ec_cmd_xfer_status(ec, msg);
> +       if (ret < 0)
> +               goto out;
> +
> +       ret = resp->duty;
> +
> +out:
> +       kfree(msg);
> +       return ret;
> +}
> +
> +static int cros_ec_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm,
> +                            struct pwm_state *state)
> +{
> +       struct cros_ec_pwm_device *ec_pwm = pwm_to_cros_ec_pwm(chip);
> +
> +       /* The EC won't let us change the period */
> +       if (state->period != EC_PWM_MAX_DUTY)
> +               return -EINVAL;
> +
> +       return cros_ec_pwm_set_duty(ec_pwm, pwm, state->duty_cycle);
I would use ec_pwm->ec here.
> +}
> +
> +static void cros_ec_pwm_get_state(struct pwm_chip *chip, struct pwm_device *pwm,
> +                                 struct pwm_state *state)
> +{
> +       struct cros_ec_pwm_device *ec_pwm = pwm_to_cros_ec_pwm(chip);
> +       int ret;
> +
> +       ret = cros_ec_pwm_get_duty(ec_pwm, pwm);
> +       if (ret < 0) {
> +               dev_err(chip->dev, "error getting initial duty: %d\n", ret);
> +               return;
> +       }
> +
> +       state->enabled = (ret > 0);
> +       state->period = EC_PWM_MAX_DUTY;
> +       state->duty_cycle = ret;
> +}
> +
> +static struct pwm_device *
> +cros_ec_pwm_xlate(struct pwm_chip *pc, const struct of_phandle_args *args)
> +{
> +       struct pwm_device *pwm;
> +
> +       if (args->args[0] >= pc->npwm)
> +               return ERR_PTR(-EINVAL);
> +
> +       pwm = pwm_request_from_chip(pc, args->args[0], NULL);
> +       if (IS_ERR(pwm))
> +               return pwm;
> +
> +       /* The EC won't let us change the period */
> +       pwm->args.period = EC_PWM_MAX_DUTY;
> +
> +       return pwm;
> +}
> +
> +static const struct pwm_ops cros_ec_pwm_ops = {
> +       .get_state      = cros_ec_pwm_get_state,
> +       .apply          = cros_ec_pwm_apply,
> +       .owner          = THIS_MODULE,
> +};
> +
> +static int cros_ec_pwm_probe(struct platform_device *pdev)
> +{
> +       struct cros_ec_device *ec = dev_get_drvdata(pdev->dev.parent);
> +       struct device *dev = &pdev->dev;
> +       struct device_node *np = dev->of_node;
> +       struct cros_ec_pwm_device *ec_pwm;
> +       struct pwm_chip *chip;
> +       u32 val;
> +       int ret;
> +
> +       if (!ec) {
> +               dev_err(dev, "no parent EC device\n");
> +               return -EINVAL;
> +       }
> +
> +       ec_pwm = devm_kzalloc(dev, sizeof(*ec_pwm), GFP_KERNEL);
> +       if (!ec_pwm)
> +               return -ENOMEM;
> +       chip = &ec_pwm->chip;
> +       ec_pwm->ec = ec;
> +
> +       /* PWM chip */
> +       chip->dev = dev;
> +       chip->ops = &cros_ec_pwm_ops;
> +       chip->of_xlate = cros_ec_pwm_xlate;
> +       chip->of_pwm_n_cells = 1;
> +       chip->base = -1;
> +       ret = of_property_read_u32(np, "google,max-pwms", &val);
> +       if (ret) {
> +               dev_err(dev, "Couldn't read max-pwms property: %d\n", ret);
Does it mean this driver does not work when device tree is not used by
the platform?
The rest of the driver still compiles.
> +               return ret;
> +       }
> +       /* The index field is only 8 bits */
> +       if (val > U8_MAX) {
> +               dev_err(dev, "Can't support %u PWMs\n", val);
> +               return -EINVAL;
> +       }
> +       chip->npwm = val;
> +
> +       ret = pwmchip_add(chip);
> +       if (ret < 0) {
> +               dev_err(dev, "cannot register PWM: %d\n", ret);
> +               return ret;
> +       }
> +
> +       platform_set_drvdata(pdev, ec_pwm);
> +
> +       return ret;
> +}
> +
> +static int cros_ec_pwm_remove(struct platform_device *dev)
> +{
> +       struct cros_ec_pwm_device *ec_pwm = platform_get_drvdata(dev);
> +       struct pwm_chip *chip = &ec_pwm->chip;
> +
> +       return pwmchip_remove(chip);
> +}
> +
> +#ifdef CONFIG_OF
> +static const struct of_device_id cros_ec_pwm_of_match[] = {
> +       { .compatible = "google,cros-ec-pwm" },
> +       {},
> +};
> +MODULE_DEVICE_TABLE(of, cros_ec_pwm_of_match);
> +#endif
> +
> +static struct platform_driver cros_ec_pwm_driver = {
> +       .probe = cros_ec_pwm_probe,
> +       .remove = cros_ec_pwm_remove,
> +       .driver = {
> +               .name = "cros-ec-pwm",
> +               .of_match_table = of_match_ptr(cros_ec_pwm_of_match),
> +       },
> +};
> +module_platform_driver(cros_ec_pwm_driver);
> +
> +MODULE_ALIAS("platform:cros-ec-pwm");
> +MODULE_DESCRIPTION("ChromeOS EC PWM driver");
> +MODULE_LICENSE("GPL v2");
> --
> 2.8.0.rc3.226.g39d4020
>

[toc] | [prev] | [next] | [standalone]


#1408367 — [PATCH 3/4] doc: dt: pwm: add binding for ChromeOS EC PWM

FromBrian Norris <briannorris@chromium.org>
Date2016-05-28 03:50 +0200
Subject[PATCH 3/4] doc: dt: pwm: add binding for ChromeOS EC PWM
Message-ID<rDBy1-2BY-7@gated-at.bofh.it>
In reply to#1408364
The ChromeOS Embedded Controller can support controlling its attached
PWMs via its host-command interface. The number of supported PWMs varies
on a per-board basis, so we define a "google,max-pwms" property to
handle this. And because the EC only allows specifying the duty cycle
and not the period, we don't specify the period via pwm-cells, and
instead have only support 1 cell -- to specify the index.

Signed-off-by: Brian Norris <briannorris@chromium.org>
---
 .../devicetree/bindings/pwm/google,cros-ec-pwm.txt | 25 ++++++++++++++++++++++
 1 file changed, 25 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/pwm/google,cros-ec-pwm.txt

diff --git a/Documentation/devicetree/bindings/pwm/google,cros-ec-pwm.txt b/Documentation/devicetree/bindings/pwm/google,cros-ec-pwm.txt
new file mode 100644
index 000000000000..f1c9540fc23f
--- /dev/null
+++ b/Documentation/devicetree/bindings/pwm/google,cros-ec-pwm.txt
@@ -0,0 +1,25 @@
+* PWM controlled by ChromeOS EC
+
+Google's ChromeOS EC PWM is a simple PWM attached to the Embedded Controller
+(EC) and controlled via a host-command interface.
+
+An EC PWM node should be only found as a sub-node of the EC node (see
+Documentation/devicetree/bindings/mfd/cros-ec.txt).
+
+Required properties:
+- compatible: Must contain "google,cros-ec-pwm"
+- #pwm-cells: Should be 1. The cell specifies the PWM index.
+- google,max-pwms: Specifies the number of PWMs supported by the EC.
+
+Example:
+	cros-ec@0 {
+		compatible = "google,cros-ec-spi";
+
+		...
+
+		cros_ec_pwm: ec-pwm {
+			compatible = "google,cros-ec-pwm";
+			#pwm-cells = <1>;
+			google,max-pwms = <4>;
+		};
+	};
-- 
2.8.0.rc3.226.g39d4020

[toc] | [prev] | [next] | [standalone]


#1408541 — Re: [PATCH 3/4] doc: dt: pwm: add binding for ChromeOS EC PWM

FromGwendal Grignou <gwendal@chromium.org>
Date2016-05-29 07:10 +0200
SubjectRe: [PATCH 3/4] doc: dt: pwm: add binding for ChromeOS EC PWM
Message-ID<rE197-1Rj-1@gated-at.bofh.it>
In reply to#1408367
Instead of using device tree, assuming you have firmware control,
another way could be to add a firmware feature:
for instance, there is one EC_FEATURE_PWM_FAN, the fan PWM, one for
the keyboard lightning as well. (see num ec_feature_code)
By adding one more, you let cros_ec_dev load the platform driver for
you, it works even if the machine does not use device tree.

Gwendal.

On Fri, May 27, 2016 at 6:39 PM, Brian Norris <briannorris@chromium.org> wrote:
> The ChromeOS Embedded Controller can support controlling its attached
> PWMs via its host-command interface. The number of supported PWMs varies
> on a per-board basis, so we define a "google,max-pwms" property to
> handle this. And because the EC only allows specifying the duty cycle
> and not the period, we don't specify the period via pwm-cells, and
> instead have only support 1 cell -- to specify the index.
>
> Signed-off-by: Brian Norris <briannorris@chromium.org>
> ---
>  .../devicetree/bindings/pwm/google,cros-ec-pwm.txt | 25 ++++++++++++++++++++++
>  1 file changed, 25 insertions(+)
>  create mode 100644 Documentation/devicetree/bindings/pwm/google,cros-ec-pwm.txt
>
> diff --git a/Documentation/devicetree/bindings/pwm/google,cros-ec-pwm.txt b/Documentation/devicetree/bindings/pwm/google,cros-ec-pwm.txt
> new file mode 100644
> index 000000000000..f1c9540fc23f
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/pwm/google,cros-ec-pwm.txt
> @@ -0,0 +1,25 @@
> +* PWM controlled by ChromeOS EC
> +
> +Google's ChromeOS EC PWM is a simple PWM attached to the Embedded Controller
> +(EC) and controlled via a host-command interface.
> +
> +An EC PWM node should be only found as a sub-node of the EC node (see
> +Documentation/devicetree/bindings/mfd/cros-ec.txt).
> +
> +Required properties:
> +- compatible: Must contain "google,cros-ec-pwm"
> +- #pwm-cells: Should be 1. The cell specifies the PWM index.
> +- google,max-pwms: Specifies the number of PWMs supported by the EC.
> +
> +Example:
> +       cros-ec@0 {
> +               compatible = "google,cros-ec-spi";
> +
> +               ...
> +
> +               cros_ec_pwm: ec-pwm {
> +                       compatible = "google,cros-ec-pwm";
> +                       #pwm-cells = <1>;
> +                       google,max-pwms = <4>;
> +               };
> +       };
> --
> 2.8.0.rc3.226.g39d4020
>

[toc] | [prev] | [next] | [standalone]


#1408800

FromTomeu Vizoso <tomeu.vizoso@collabora.com>
Date2016-05-30 08:50 +0200
Message-ID<rEpbs-B4-21@gated-at.bofh.it>
In reply to#1408364
On 05/28/2016 03:39 AM, Brian Norris wrote:
> Hi,
> 
> This series adds support for the new ChromeOS EC PWM API, so we can control,
> e.g., the backlight when it's attached to the EC. It uses Boris's latest
> "atomic" hooks for the PWM API (i.e., the ->apply() callback), which were
> recently merged.
> 
> It seems nice to have the cros_ec_cmd_xfer_status() helper, which we have
> locally in the ChromeOS kernel, and which has been part of another larger patch
> series:
> 
> https://lkml.org/lkml/2016/4/12/342
> 
> So I've picked it into this series as well. Obviously, I don't care which one
> is taken, but AFAICT, Tomeu's USB PD series isn't extremely active right now.

Hi Brian,

that's on hold during the ongoing discussion about type-c userspace API,
because right now the value of that patchset is on how userspace can
decide from what port to charge (if any), and it was badly abusing a
power supply property for that.

Regards,

Tomeu

> As this touches MFD (sort of), drivers/platform/chrome/, and drivers/pwm/, I'm
> not sure who it should all go through: Lee, Thierry, or Olof?
> 
> Anyway, please review.
> 
> Regards,
> Brian
> 
> Brian Norris (3):
>   mfd: cros_ec: add EC_PWM function definitions
>   doc: dt: pwm: add binding for ChromeOS EC PWM
>   pwm: add ChromeOS EC PWM driver
> 
> Tomeu Vizoso (1):
>   mfd: cros_ec: Add cros_ec_cmd_xfer_status helper
> 
>  .../devicetree/bindings/pwm/google,cros-ec-pwm.txt |  25 +++
>  drivers/platform/chrome/cros_ec_proto.c            |  15 ++
>  drivers/pwm/Kconfig                                |   7 +
>  drivers/pwm/Makefile                               |   1 +
>  drivers/pwm/pwm-cros-ec.c                          | 230 +++++++++++++++++++++
>  include/linux/mfd/cros_ec.h                        |  18 ++
>  include/linux/mfd/cros_ec_commands.h               |  31 +++
>  7 files changed, 327 insertions(+)
>  create mode 100644 Documentation/devicetree/bindings/pwm/google,cros-ec-pwm.txt
>  create mode 100644 drivers/pwm/pwm-cros-ec.c
> 

[toc] | [prev] | [standalone]


Back to top | Article view | linux.kernel


csiph-web