From: Lee Jones <lee.jones@linaro.org>
To: Alistair Francis <alistair@alistair23.me>
Cc: robh+dt@kernel.org, lgirdwood@gmail.com, broonie@kernel.org,
linux-imx@nxp.com, kernel@pengutronix.de,
devicetree@vger.kernel.org, linux-kernel@vger.kernel.org,
alistair23@gmail.com
Subject: Re: [PATCH 2/6] mfd: Initial commit of sy7636a
Date: Thu, 4 Feb 2021 10:31:26 +0000 [thread overview]
Message-ID: <20210204103126.GA2789116@dell> (raw)
In-Reply-To: <20210117042539.1609-2-alistair@alistair23.me>
On Sat, 16 Jan 2021, Alistair Francis wrote:
> Initial support for the Silergy SY7636A Power Management chip
> driver.
Please remove "driver", as this is not support for the driver, it *is*
the driver which supports the chip.
> Signed-off-by: Alistair Francis <alistair@alistair23.me>
> ---
> drivers/mfd/Kconfig | 10 ++
> drivers/mfd/Makefile | 2 +
> drivers/mfd/sy7636a.c | 252 ++++++++++++++++++++++++++++++++++++
> include/linux/mfd/sy7636a.h | 50 +++++++
> 4 files changed, 314 insertions(+)
> create mode 100644 drivers/mfd/sy7636a.c
> create mode 100644 include/linux/mfd/sy7636a.h
>
> diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig
> index bdfce7b15621..c8c62d92433c 100644
> --- a/drivers/mfd/Kconfig
> +++ b/drivers/mfd/Kconfig
> @@ -1360,6 +1360,16 @@ config MFD_SYSCON
> Select this option to enable accessing system control registers
> via regmap.
>
> +config MFD_SY7636A
> + tristate "Silergy SY7636A Power Management chip driver"
Again, please remove the word "driver" here.
> + select MFD_CORE
> + select REGMAP_I2C
> + select REGMAP_IRQ
> + depends on I2C=y
> + help
> + Select this option to enable support for the Silergy SY7636A
> + Power Management chip driver.
And again.
> config MFD_DAVINCI_VOICECODEC
> tristate
> select MFD_CORE
> diff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile
> index 14fdb188af02..1fa1e635f506 100644
> --- a/drivers/mfd/Makefile
> +++ b/drivers/mfd/Makefile
> @@ -265,6 +265,8 @@ obj-$(CONFIG_MFD_ROHM_BD718XX) += rohm-bd718x7.o
> obj-$(CONFIG_MFD_STMFX) += stmfx.o
> obj-$(CONFIG_MFD_KHADAS_MCU) += khadas-mcu.o
>
> +obj-$(CONFIG_MFD_SY7636A) += sy7636a.o
> +
Why does this have to be segregated?
> obj-$(CONFIG_SGI_MFD_IOC3) += ioc3.o
> obj-$(CONFIG_MFD_SIMPLE_MFD_I2C) += simple-mfd-i2c.o
> obj-$(CONFIG_MFD_INTEL_M10_BMC) += intel-m10-bmc.o
> diff --git a/drivers/mfd/sy7636a.c b/drivers/mfd/sy7636a.c
> new file mode 100644
> index 000000000000..39aac965d854
> --- /dev/null
> +++ b/drivers/mfd/sy7636a.c
> @@ -0,0 +1,252 @@
> +// SPDX-License-Identifier: GPL-2.0+
> +/*
> + * MFD driver for SY7636A chip
"Parent driver".
> + * Copyright (C) 2019 reMarkable AS - http://www.remarkable.com/
This is quite out of date. Please update.
> + * Author: Lars Ivar Miljeteig <lars.ivar.miljeteig@remarkable.com>
> + *
> + * This program is free software; you can redistribute it and/or
> + * modify it under the terms of the GNU General Public License as
> + * published by the Free Software Foundation version 2.
> + *
> + * This program is distributed "as is" WITHOUT ANY WARRANTY of any
> + * kind, whether express or implied; without even the implied warranty
> + * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
> + * GNU General Public License for more details.
This test is replaced by the SPDX header above.
> + * Based on the lp87565 driver by Keerthy <j-keerthy@ti.com>
> + */
> +
> +#include <linux/interrupt.h>
> +#include <linux/mfd/core.h>
> +#include <linux/module.h>
> +#include <linux/of_device.h>
> +#include <linux/regmap.h>
> +#include <linux/sysfs.h>
> +
> +#include <linux/mfd/sy7636a.h>
> +
> +static const struct regmap_config sy7636a_regmap_config = {
> + .reg_bits = 8,
> + .val_bits = 8,
> +};
> +
> +static const struct mfd_cell sy7636a_cells[] = {
> + { .name = "sy7636a-regulator", },
> + { .name = "sy7636a-temperature", },
> + { .name = "sy7636a-thermal", },
> +};
> +
> +static const struct of_device_id of_sy7636a_match_table[] = {
> + { .compatible = "silergy,sy7636a", },
> + {}
> +};
> +MODULE_DEVICE_TABLE(of, of_sy7636a_match_table);
Please move this to where it is used i.e. at the bottom of the file.
> +static const char * const states[] = {
> + "no fault event",
> + "UVP at VP rail",
> + "UVP at VN rail",
> + "UVP at VPOS rail",
> + "UVP at VNEG rail",
> + "UVP at VDDH rail",
> + "UVP at VEE rail",
> + "SCP at VP rail",
> + "SCP at VN rail",
> + "SCP at VPOS rail",
> + "SCP at VNEG rail",
> + "SCP at VDDH rail",
> + "SCP at VEE rail",
> + "SCP at V COM rail",
> + "UVLO",
> + "Thermal shutdown",
> +};
> +
> +int get_vcom_voltage_mv(struct regmap *regmap)
> +{
> + int ret;
> + unsigned int val, val_h;
> +
> + ret = regmap_read(regmap, SY7636A_REG_VCOM_ADJUST_CTRL_L, &val);
> + if (ret)
> + return ret;
> +
> + ret = regmap_read(regmap, SY7636A_REG_VCOM_ADJUST_CTRL_H, &val_h);
> + if (ret)
> + return ret;
> +
> + val |= (val_h << 8);
Please define the shifts and masks.
> + return (val & 0x1FF) * 10;
What's 10?
> +}
> +
> +int set_vcom_voltage_mv(struct regmap *regmap, unsigned int vcom)
> +{
> + int ret;
> + unsigned int val;
> +
> + if (vcom < 0 || vcom > 5000)
Please define min/max values.
> + return -EINVAL;
> +
> + val = (unsigned int)(vcom / 10) & 0x1ff;
As above.
> + ret = regmap_write(regmap, SY7636A_REG_VCOM_ADJUST_CTRL_L, val);
> + if (ret)
> + return ret;
> +
> + ret = regmap_write(regmap, SY7636A_REG_VCOM_ADJUST_CTRL_H, val >> 8);
> + if (ret)
> + return ret;
> +
> + return 0;
> +}
Who calls these?
> +static ssize_t state_show(struct device *dev, struct device_attribute *attr,
> + char *buf)
> +{
> + int ret;
> + unsigned int val;
> + struct sy7636a *sy7636a = dev_get_drvdata(dev);
> +
> + ret = regmap_read(sy7636a->regmap, SY7636A_REG_FAULT_FLAG, &val);
> + if (ret) {
> + dev_err(sy7636a->dev, "Failed to read from device\n");
> + return ret;
> + }
> +
> + val = val >> 1;
Why 1?
> + if (val >= ARRAY_SIZE(states)) {
> + dev_err(sy7636a->dev, "Unexpected value read from device: %u\n", val);
> + return -EINVAL;
> + }
> +
> + return snprintf(buf, PAGE_SIZE, "%s\n", states[val]);
> +}
> +static DEVICE_ATTR(state, 0444, state_show, NULL);
You need to document new sysfs entries.
> +static ssize_t power_good_show(struct device *dev, struct device_attribute *attr,
> + char *buf)
> +{
> + int ret;
> + unsigned int val;
> + struct sy7636a *sy7636a = dev_get_drvdata(dev);
> +
> + ret = regmap_read(sy7636a->regmap, SY7636A_REG_FAULT_FLAG, &val);
> + if (ret) {
> + dev_err(sy7636a->dev, "Failed to read from device\n");
> + return ret;
> + }
> +
> + val &= 0x01;
> +
> + return snprintf(buf, PAGE_SIZE, "%s\n", val ? "ON" : "OFF");
Doesn't 0 just mean "no fault event"?
> +}
> +static DEVICE_ATTR(power_good, 0444, power_good_show, NULL);
> +
> +static ssize_t vcom_show(struct device *dev, struct device_attribute *attr,
> + char *buf)
> +{
> + int ret;
> + struct sy7636a *sy7636a = dev_get_drvdata(dev);
> +
> + ret = get_vcom_voltage_mv(sy7636a->regmap);
> + if (ret < 0)
> + return ret;
> +
> + return snprintf(buf, PAGE_SIZE, "%d\n", -ret);
> +}
> +
Remove this line please.
> +static ssize_t vcom_store(struct device *dev,
> + struct device_attribute *attr, const char *buf, size_t count)
> +{
> + int ret;
> + int vcom;
> + struct sy7636a *sy7636a = dev_get_drvdata(dev);
> +
> + ret = kstrtoint(buf, 0, &vcom);
> + if (ret)
> + return ret;
> +
> + if (vcom > 0 || vcom < -5000)
> + return -EINVAL;
> +
> + ret = set_vcom_voltage_mv(sy7636a->regmap, (unsigned int)(-vcom));
> + if (ret)
> + return ret;
> +
> + return count;
> +}
> +static DEVICE_ATTR(vcom, 0644, vcom_show, vcom_store);
> +
> +static struct attribute *sy7636a_sysfs_attrs[] = {
> + &dev_attr_state.attr,
> + &dev_attr_power_good.attr,
> + &dev_attr_vcom.attr,
> + NULL,
> +};
These all look like power options? Do they really belong here?
> +static const struct attribute_group sy7636a_sysfs_attr_group = {
> + .attrs = sy7636a_sysfs_attrs,
> +};
> +
> +static int sy7636a_probe(struct i2c_client *client,
> + const struct i2c_device_id *ids)
> +{
> + struct sy7636a *sy7636a;
> + int ret;
> +
> + sy7636a = devm_kzalloc(&client->dev, sizeof(struct sy7636a), GFP_KERNEL);
sizeof(*sy7636a)
> + if (sy7636a == NULL)
if (!sy7636a)
> + return -ENOMEM;
> +
> + sy7636a->dev = &client->dev;
> +
> + sy7636a->regmap = devm_regmap_init_i2c(client, &sy7636a_regmap_config);
> + if (IS_ERR(sy7636a->regmap)) {
> + ret = PTR_ERR(sy7636a->regmap);
> + dev_err(sy7636a->dev,
> + "Failed to initialize register map: %d\n", ret);
> + return ret;
> + }
> +
> + i2c_set_clientdata(client, sy7636a);
> +
> + ret = sysfs_create_group(&client->dev.kobj, &sy7636a_sysfs_attr_group);
> + if (ret) {
> + dev_err(sy7636a->dev, "Failed to create sysfs attributes\n");
> + return ret;
> + }
> +
> + ret = devm_mfd_add_devices(sy7636a->dev, PLATFORM_DEVID_AUTO,
> + sy7636a_cells, ARRAY_SIZE(sy7636a_cells),
> + NULL, 0, NULL);
> + if (ret) {
> + dev_err(sy7636a->dev, "Failed to add mfd devices\n");
"Failed to add child devices"
> + sysfs_remove_group(&client->dev.kobj, &sy7636a_sysfs_attr_group);
> + return ret;
> + }
> +
> + return 0;
> +}
> +
> +static const struct i2c_device_id sy7636a_id_table[] = {
> + { "sy7636a", 0 },
> + { },
> +};
> +MODULE_DEVICE_TABLE(i2c, sy7636a_id_table);
If you use .probe2, you can omit this table.
> +static struct i2c_driver sy7636a_driver = {
> + .driver = {
> + .name = "sy7636a",
> + .of_match_table = of_sy7636a_match_table,
> + },
> + .probe = sy7636a_probe,
> + .id_table = sy7636a_id_table,
> +};
> +module_i2c_driver(sy7636a_driver);
> +
> +MODULE_AUTHOR("Lars Ivar Miljeteig <lars.ivar.miljeteig@remarkable.com>");
> +MODULE_DESCRIPTION("Silergy SY7636A Multi-Function Device Driver");
s/Multi-Function Device Driver/Power Management Chip/
> +MODULE_LICENSE("GPL v2");
> diff --git a/include/linux/mfd/sy7636a.h b/include/linux/mfd/sy7636a.h
> new file mode 100644
> index 000000000000..642789c4d0a9
> --- /dev/null
> +++ b/include/linux/mfd/sy7636a.h
> @@ -0,0 +1,50 @@
> +/* SPDX-License-Identifier: GPL-2.0-only */
> +/*
> + * Functions to access SY3686A power management chip.
> + *
> + * Copyright (C) 2019 reMarkable AS - http://www.remarkable.com/
> + *
> + * This program is free software; you can redistribute it and/or
> + * modify it under the terms of the GNU General Public License as
> + * published by the Free Software Foundation version 2.
> + *
> + * This program is distributed "as is" WITHOUT ANY WARRANTY of any
> + * kind, whether express or implied; without even the implied warranty
> + * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
> + * GNU General Public License for more details.
> + */
Same issues as mentioned above.
> +#ifndef __LINUX_MFD_SY7636A_H
> +#define __LINUX_MFD_SY7636A_H
Just MFD is fine.
> +#include <linux/i2c.h>
> +#include <linux/regulator/driver.h>
> +#include <linux/regulator/machine.h>
> +#include <linux/regmap.h>
Alphabetical.
> +#define SY7636A_REG_OPERATION_MODE_CRL 0x00
> +#define SY7636A_OPERATION_MODE_CRL_VCOMCTL (1 << 6)
> +#define SY7636A_OPERATION_MODE_CRL_ONOFF (1 << 7)
> +#define SY7636A_REG_VCOM_ADJUST_CTRL_L 0x01
> +#define SY7636A_REG_VCOM_ADJUST_CTRL_H 0x02
> +#define SY7636A_REG_VCOM_ADJUST_CTRL_MASK 0x01ff
> +#define SY7636A_REG_VLDO_VOLTAGE_ADJULST_CTRL 0x03
> +#define SY7636A_REG_POWER_ON_DELAY_TIME 0x06
> +#define SY7636A_REG_FAULT_FLAG 0x07
> +#define SY7636A_FAULT_FLAG_PG (1 << 0)
> +#define SY7636A_REG_TERMISTOR_READOUT 0x08
Tab out the values please.
Use BIT()
> +#define SY7636A_REG_MAX 0x08
> +
> +struct sy7636a {
> + struct device *dev;
> + struct regmap *regmap;
> + unsigned int vcom;
Where is this used?
> + struct gpio_desc *pgood_gpio;
Where is this used?
> + struct mutex reglock;
Where is this used?
> +};
> +
> +int get_vcom_voltage_mv(struct regmap *regmap);
> +int set_vcom_voltage_mv(struct regmap *regmap, unsigned int vcom);
What calls these?
> +#endif /* __LINUX_MFD_SY7636A_H */
--
Lee Jones [李琼斯]
Senior Technical Lead - Developer Services
Linaro.org │ Open source software for Arm SoCs
Follow Linaro: Facebook | Twitter | Blog
next prev parent reply other threads:[~2021-02-04 10:33 UTC|newest]
Thread overview: 19+ messages / expand[flat|nested] mbox.gz Atom feed top
2021-01-17 4:25 [PATCH 1/6] devicetree/bindings: Initial commit of silergy,sy7636a.yaml Alistair Francis
2021-01-17 4:25 ` [PATCH 2/6] mfd: Initial commit of sy7636a Alistair Francis
2021-02-04 10:31 ` Lee Jones [this message]
2021-03-21 2:18 ` Alistair Francis
2021-03-23 9:35 ` Lee Jones
2021-03-25 13:49 ` Alistair Francis
2021-01-17 4:25 ` [PATCH 3/6] devicetree/bindings: Initial commit of silergy,sy7636a-regulator.yaml Alistair Francis
2021-01-18 12:35 ` Mark Brown
2021-01-18 12:42 ` Mark Brown
2021-01-22 5:05 ` Alistair Francis
2021-01-18 15:47 ` Rob Herring
2021-01-17 4:25 ` [PATCH 4/6] regulator: Initial commit of sy7636a Alistair Francis
2021-01-18 12:31 ` Mark Brown
2021-01-22 6:24 ` Alistair Francis
2021-01-22 13:37 ` Mark Brown
2021-01-23 8:34 ` Alistair Francis
2021-01-17 4:25 ` [PATCH 5/6] arch/arm: reMarkable2: Enable silergy,sy7636a Alistair Francis
2021-01-17 4:25 ` [PATCH 6/6] arch/arm: reMarkable2: Enable lcdif Alistair Francis
2021-01-18 15:47 ` [PATCH 1/6] devicetree/bindings: Initial commit of silergy,sy7636a.yaml Rob Herring
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=20210204103126.GA2789116@dell \
--to=lee.jones@linaro.org \
--cc=alistair23@gmail.com \
--cc=alistair@alistair23.me \
--cc=broonie@kernel.org \
--cc=devicetree@vger.kernel.org \
--cc=kernel@pengutronix.de \
--cc=lgirdwood@gmail.com \
--cc=linux-imx@nxp.com \
--cc=linux-kernel@vger.kernel.org \
--cc=robh+dt@kernel.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.