Re: [PATCH] ARM: Add hwmon driver for LRADC found on Allwinner A13/A20 SoCs

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Dne sreda, 27. april 2022 ob 23:01:58 CEST je Ruslan Zalata napisal(a):
> Dear Jernej and all.
> 
> I used sendmail instead of "git send-email" and it did the whole this
> wrong - several separate emails were sent. I'm sorry for that, will
> stick to git command next time.
> 
> I read the guide of course and I fed the patch through
> scripts/checkpatch.pl many times in an effort to elaborate all the
> errors and warnings. The only warning left is this:
> 
> WARNING: added, moved or deleted file(s), does MAINTAINERS need
> updating?
> #61:
> new file mode 100644
> 
> total: 0 errors, 1 warnings, 304 lines checked

Did you used --strict? Anyway, you have multiple consecutive empty lines in 
several places. Only one empty line is allowed.

> 
> Since this is my first attempt to submit my code I'm quite confused whom
> should I add as a maintainer for this driver. :)

Usually yourself.

> 
> PS: What's wrong with the subject ?

Too long and ARM is not a proper tag. Check git history of drivers/hwmon 
folder for ideas.

Best regards,
Jernej

> 
> ---
> Regards,
> Ruslan.
> 
> Fabmicro, LLC.
> 
> On 2022-04-28 01:23, Jernej Škrabec wrote:
> > Hi Ruslan!
> > 
> > Dne sreda, 27. april 2022 ob 21:25:12 CEST je Ruslan Zalata napisal(a):
> >> Some Allwinner SoCs like A13, A20 or T2 are equipped with two-channel
> >> low rate (6 bit) ADC that is often used for extra keys. There's a
> >> driver
> >> for that already implementing standard input device, but it has these
> >> limitations: 1) it cannot be used for general ADC data equisition, and
> >> 2) it uses only one LRADC channel of two available.
> >> 
> >> This driver provides basic hwmon interface to both channels of LRADC
> >> on
> >> such Allwinner SoCs.
> >> 
> >> Signed-off-by: Ruslan Zalata <rz@xxxxxxxxxxx>
> > 
> > Before even going to check actual driver, please read
> > https://www.kernel.org/
> > doc/html/latest/process/submitting-patches.html in detail.
> > 
> > Just few basic things to fix first:
> > 1. subject doesn't conform to rules
> > 2. send patch to maintainers and mailing lists (use
> > scripts/get_maintainer.pl)
> > 3. code has style issues (multiple empty lines). Run
> > scripts/checkpatch.pl --
> > strict on your patch before submission and fix all reported issues.
> > 4. you sent same patch two times. If it's same, it should be marked
> > with
> > RESEND, if not, it should be versioned (V2, V3, etc.) with short
> > changelog
> > after --- line (as explained in above link)
> > 5. it's customary to add new entry in MAINTAINERS when adding new
> > driver
> > 
> > Best regards,
> > Jernej
> > 
> >> ---
> >> 
> >>  drivers/hwmon/Kconfig             |  13 ++
> >>  drivers/hwmon/Makefile            |   1 +
> >>  drivers/hwmon/sun4i-lradc-hwmon.c | 278
> >> 
> >> ++++++++++++++++++++++++++++++
> >> 
> >>  3 files changed, 292 insertions(+)
> >>  create mode 100644 drivers/hwmon/sun4i-lradc-hwmon.c
> >> 
> >> diff --git a/drivers/hwmon/Kconfig b/drivers/hwmon/Kconfig
> >> index 68a8a27ab3b..b7732a9e992 100644
> >> --- a/drivers/hwmon/Kconfig
> >> +++ b/drivers/hwmon/Kconfig
> >> @@ -521,6 +521,19 @@ config I8K
> >> 
> >>  	  Say Y if you intend to run userspace programs that use this
> > 
> > interface.
> > 
> >>  	  Say N otherwise.
> >> 
> >> +config SENSORS_SUN4I_LRADC
> >> +	tristate "Allwinner A13/A20 LRADC hwmon"
> >> +	depends on ARCH_SUNXI && (!KEYBOARD_SUN4I_LRADC)
> >> +	help
> >> +	  Say y here to support the LRADC found in Allwinner A13/A20 SoCs.
> >> +	  Both channels are supported.
> >> +
> >> +	  This driver can also be built as module. If so, the module
> >> +	  will be called sun4i-lradc-hwmon.
> >> +
> >> +	  This option is not compatible with KEYBOARD_SUN4I_LRADC, one
> >> +	  of these should be used at a time.
> >> +
> >> 
> >>  config SENSORS_DA9052_ADC
> >>  
> >>  	tristate "Dialog DA9052/DA9053 ADC"
> >>  	depends on PMIC_DA9052
> >> 
> >> diff --git a/drivers/hwmon/Makefile b/drivers/hwmon/Makefile
> >> index 8a03289e2aa..43bed6fff27 100644
> >> --- a/drivers/hwmon/Makefile
> >> +++ b/drivers/hwmon/Makefile
> >> @@ -30,6 +30,7 @@ obj-$(CONFIG_SENSORS_AD7314)	+= ad7314.o
> >> 
> >>  obj-$(CONFIG_SENSORS_AD7414)	+= ad7414.o
> >>  obj-$(CONFIG_SENSORS_AD7418)	+= ad7418.o
> >>  obj-$(CONFIG_SENSORS_ADC128D818) += adc128d818.o
> >> 
> >> +obj-$(CONFIG_SENSORS_SUN4I_LRADC) += sun4i-lradc-hwmon.o
> >> 
> >>  obj-$(CONFIG_SENSORS_ADCXX)	+= adcxx.o
> >>  obj-$(CONFIG_SENSORS_ADM1021)	+= adm1021.o
> >>  obj-$(CONFIG_SENSORS_ADM1025)	+= adm1025.o
> >> 
> >> diff --git a/drivers/hwmon/sun4i-lradc-hwmon.c
> >> b/drivers/hwmon/sun4i-lradc-hwmon.c new file mode 100644
> >> index 00000000000..1947b716dbf
> >> --- /dev/null
> >> +++ b/drivers/hwmon/sun4i-lradc-hwmon.c
> >> @@ -0,0 +1,278 @@
> >> +// SPDX-License-Identifier: GPL-2.0-or-later
> >> +/*
> >> + * Allwinner sun4i (A13/A20) LRADC hwmon driver
> >> + *
> >> + * Copyright (C) 2022 Fabmicro, LLC., Tyumen, Russia.
> >> + * Copyright (C) 2022 Ruslan Zalata <rz@xxxxxxxxxxx>
> >> + */
> >> +
> >> +#include <linux/err.h>
> >> +#include <linux/init.h>
> >> +#include <linux/input.h>
> >> +#include <linux/interrupt.h>
> >> +#include <linux/module.h>
> >> +#include <linux/of_platform.h>
> >> +#include <linux/platform_device.h>
> >> +#include <linux/regulator/consumer.h>
> >> +#include <linux/slab.h>
> >> +#include <linux/hwmon.h>
> >> +#include <linux/hwmon-sysfs.h>
> >> +
> >> +#define LRADC_CTRL		0x00
> >> +#define LRADC_INTC		0x04
> >> +#define LRADC_INTS		0x08
> >> +#define LRADC_DATA0		0x0c
> >> +#define LRADC_DATA1		0x10
> >> +
> >> +/* LRADC_CTRL bits */
> >> +#define FIRST_CONVERT_DLY(x)	((x) << 24) /* 8 bits */
> >> +#define CHAN_SELECT(x)		((x) << 22) /* 2 bits */
> >> +#define CONTINUE_TIME_SEL(x)	((x) << 16) /* 4 bits */
> >> +#define KEY_MODE_SEL(x)		((x) << 12) /* 2 bits */
> >> +#define LEVELA_B_CNT(x)		((x) << 8)  /* 4 bits */
> >> +#define HOLD_KEY_EN(x)		((x) << 7)
> >> +#define HOLD_EN(x)		((x) << 6)
> >> +#define LEVELB_VOL(x)		((x) << 4)  /* 2 bits */
> >> +#define SAMPLE_RATE(x)		((x) << 2)  /* 2 bits */
> >> +#define ENABLE(x)		((x) << 0)
> >> +
> >> +/* LRADC_INTC and LRADC_INTS bits */
> >> +#define CHAN1_KEYUP_IRQ		BIT(12)
> >> +#define CHAN1_ALRDY_HOLD_IRQ	BIT(11)
> >> +#define CHAN1_HOLD_IRQ		BIT(10)
> >> +#define	CHAN1_KEYDOWN_IRQ	BIT(9)
> >> +#define CHAN1_DATA_IRQ		BIT(8)
> >> +#define CHAN0_KEYUP_IRQ		BIT(4)
> >> +#define CHAN0_ALRDY_HOLD_IRQ	BIT(3)
> >> +#define CHAN0_HOLD_IRQ		BIT(2)
> >> +#define	CHAN0_KEYDOWN_IRQ	BIT(1)
> >> +#define CHAN0_DATA_IRQ		BIT(0)
> >> +
> >> +
> >> +struct lradc_variant {
> >> +	u32 bits;
> >> +	u32 resolution;
> >> +	u32 vref;
> >> +};
> >> +
> >> +struct lradc_variant variant_sun4i_a10_lradc = {
> >> +	.bits = 0x3f,
> >> +	.resolution = 63,
> >> +	.vref = 2000000,
> >> +};
> >> +
> >> +struct lradc_variant variant_sun8i_a83t_r_lradc = {
> >> +	.bits = 0x3f,
> >> +	.resolution = 63,
> >> +	.vref = 2000000,
> >> +};
> >> +
> >> +static const struct of_device_id sun4i_lradc_of_match[];
> >> +
> >> +
> >> +struct sun4i_lradc_data {
> >> +	struct device *dev;
> >> +	struct device *hwmon_dev;
> >> +	void __iomem *base;
> >> +	const struct lradc_variant *variant;
> >> +	u32 in[2];
> >> +	u32 in_mvolts[2];
> >> +};
> >> +
> >> +
> >> +static ssize_t lradc_in_mvolts_show(struct device *dev,
> >> +			struct device_attribute *attr, char *buf)
> >> +{
> >> +	struct sun4i_lradc_data *data = dev_get_drvdata(dev);
> >> +	int nr = to_sensor_dev_attr_2(attr)->nr;
> >> +
> >> +	if (IS_ERR(data))
> >> +		return PTR_ERR(data);
> >> +
> >> +	return sprintf(buf, "%d\n", data->in_mvolts[nr]);
> >> +}
> >> +
> >> +static ssize_t lradc_in_show(struct device *dev,
> >> +		struct device_attribute *attr, char *buf)
> >> +{
> >> +	struct sun4i_lradc_data *data = dev_get_drvdata(dev);
> >> +	int nr = to_sensor_dev_attr_2(attr)->nr;
> >> +
> >> +	if (IS_ERR(data))
> >> +		return PTR_ERR(data);
> >> +
> >> +	return sprintf(buf, "%d\n", data->in[nr]);
> >> +}
> >> +
> >> +
> >> +static umode_t lradc_is_visible(struct kobject *kobj,
> >> +		struct attribute *attr, int index)
> >> +{
> >> +	return attr->mode;
> >> +}
> >> +
> >> +
> >> +
> >> +static SENSOR_DEVICE_ATTR_2_RO(in0_input, lradc_in, 0, 0);
> >> +static SENSOR_DEVICE_ATTR_2_RO(in0_input_mvolts, lradc_in_mvolts, 0,
> >> 1);
> >> +
> >> +static SENSOR_DEVICE_ATTR_2_RO(in1_input, lradc_in, 1, 0);
> >> +static SENSOR_DEVICE_ATTR_2_RO(in1_input_mvolts, lradc_in_mvolts, 1,
> >> 1);
> >> +
> >> +static struct attribute *lradc_attrs[] = {
> >> +	&sensor_dev_attr_in0_input.dev_attr.attr,
> >> +	&sensor_dev_attr_in0_input_mvolts.dev_attr.attr,
> >> +	&sensor_dev_attr_in1_input.dev_attr.attr,
> >> +	&sensor_dev_attr_in1_input_mvolts.dev_attr.attr,
> >> +	NULL
> >> +};
> >> +
> >> +static const struct attribute_group lradc_group = {
> >> +	.attrs = lradc_attrs,
> >> +	.is_visible = lradc_is_visible,
> >> +};
> >> +__ATTRIBUTE_GROUPS(lradc);
> >> +
> >> +
> >> +static irqreturn_t sun4i_lradc_irq(int irq, void *dev_id)
> >> +{
> >> +	struct sun4i_lradc_data *lradc = dev_id;
> >> +	u32 ints;
> >> +
> >> +	ints  = readl(lradc->base + LRADC_INTS);
> >> +
> >> +	if (ints & CHAN0_DATA_IRQ) {
> >> +		lradc->in[0] = readl(lradc->base + LRADC_DATA0) &
> >> +			lradc->variant->bits;
> >> +		lradc->in_mvolts[0] = lradc->in[0] * lradc->variant-
> >> vref /
> >> +			lradc->variant->resolution / 1000;
> >> +	}
> >> +
> >> +	if (ints & CHAN1_DATA_IRQ) {
> >> +		lradc->in[1] = readl(lradc->base + LRADC_DATA1) &
> >> +			lradc->variant->bits;
> >> +		lradc->in_mvolts[1] = lradc->in[1] * lradc->variant-
> >> vref /
> >> +			lradc->variant->resolution / 1000;
> >> +	}
> >> +
> >> +	writel(ints, lradc->base + LRADC_INTS);
> >> +
> >> +	return IRQ_HANDLED;
> >> +}
> >> +
> >> +static int sun4i_lradc_open(struct device *dev)
> >> +{
> >> +	struct sun4i_lradc_data *lradc = dev_get_drvdata(dev);
> >> +
> >> +	writel(FIRST_CONVERT_DLY(2) | CHAN_SELECT(3) | LEVELA_B_CNT(1) |
> >> +		HOLD_EN(1) | KEY_MODE_SEL(2) | SAMPLE_RATE(3) |
> > 
> > ENABLE(1),
> > 
> >> +		lradc->base + LRADC_CTRL);
> >> +
> >> +	writel(CHAN0_DATA_IRQ | CHAN1_DATA_IRQ, lradc->base + LRADC_INTC);
> >> +
> >> +	return 0;
> >> +}
> >> +
> >> +static void sun4i_lradc_close(struct device *dev)
> >> +{
> >> +	struct sun4i_lradc_data *lradc = dev_get_drvdata(dev);
> >> +
> >> +	writel(FIRST_CONVERT_DLY(2) | LEVELA_B_CNT(1) | HOLD_EN(1) |
> >> +		SAMPLE_RATE(2), lradc->base + LRADC_CTRL);
> >> +	writel(0, lradc->base + LRADC_INTC);
> >> +}
> >> +
> >> +static int sun4i_lradc_resume(struct platform_device *pdev)
> >> +{
> >> +	struct device *dev = &pdev->dev;
> >> +
> >> +	return sun4i_lradc_open(dev);
> >> +}
> >> +
> >> +static int sun4i_lradc_suspend(struct platform_device *pdev,
> >> pm_message_t
> >> state) +{
> >> +	struct device *dev = &pdev->dev;
> >> +
> >> +	sun4i_lradc_close(dev);
> >> +	return 0;
> >> +}
> >> +
> >> +static int sun4i_lradc_remove(struct platform_device *pdev)
> >> +{
> >> +	struct device *dev = &pdev->dev;
> >> +
> >> +	sun4i_lradc_close(dev);
> >> +	return 0;
> >> +}
> >> +
> >> +static int sun4i_lradc_probe(struct platform_device *pdev)
> >> +{
> >> +	struct sun4i_lradc_data *lradc;
> >> +	struct device *dev = &pdev->dev;
> >> +	int error;
> >> +
> >> +	lradc = devm_kzalloc(dev, sizeof(struct sun4i_lradc_data),
> > 
> > GFP_KERNEL);
> > 
> >> +	if (!lradc)
> >> +		return -ENOMEM;
> >> +
> >> +	dev_set_drvdata(dev, lradc);
> >> +
> >> +	lradc->variant = of_device_get_match_data(&pdev->dev);
> >> +	if (!lradc->variant) {
> >> +		dev_err(&pdev->dev, "Missing '%s' or '%s' variant\n",
> >> +			sun4i_lradc_of_match[0].compatible,
> >> +			sun4i_lradc_of_match[1].compatible);
> >> +		return -EINVAL;
> >> +	}
> >> +
> >> +	lradc->dev = dev;
> >> +	lradc->hwmon_dev = devm_hwmon_device_register_with_groups(dev,
> > 
> > "lradc",
> > 
> >> +
> > 
> > lradc, lradc_groups);
> > 
> >> +	if (IS_ERR(lradc->hwmon_dev)) {
> >> +		error = PTR_ERR(lradc->hwmon_dev);
> >> +		return error;
> >> +	}
> >> +
> >> +	lradc->base = devm_ioremap_resource(dev,
> >> +			platform_get_resource(pdev, IORESOURCE_MEM,
> > 
> > 0));
> > 
> >> +	if (IS_ERR(lradc->base))
> >> +		return PTR_ERR(lradc->base);
> >> +
> >> +	error = devm_request_irq(dev, platform_get_irq(pdev, 0),
> >> +			sun4i_lradc_irq, 0, "sun4i-lradc-hwmon",
> > 
> > lradc);
> > 
> >> +	if (error)
> >> +		return error;
> >> +
> >> +	error = sun4i_lradc_open(dev);
> >> +	if (error)
> >> +		return error;
> >> +
> >> +	return 0;
> >> +}
> >> +
> >> +static const struct of_device_id sun4i_lradc_of_match[] = {
> >> +	{ .compatible = "allwinner,sun4i-a10-lradc-keys", .data =
> >> &variant_sun4i_a10_lradc}, +	{ .compatible =
> >> "allwinner,sun8i-a83t-r-lradc", .data = &variant_sun8i_a83t_r_lradc},
> >> +
> > 
> > {
> > 
> >> /* sentinel */ }
> >> +};
> >> +MODULE_DEVICE_TABLE(of, sun4i_lradc_of_match);
> >> +
> >> +static struct platform_driver sun4i_lradc_driver = {
> >> +	.driver = {
> >> +		.name	= "sun4i-lradc-hwmon",
> >> +		.of_match_table = of_match_ptr(sun4i_lradc_of_match),
> >> +	},
> >> +	.probe	= sun4i_lradc_probe,
> >> +	.remove	= sun4i_lradc_remove,
> >> +	.resume	= sun4i_lradc_resume,
> >> +	.suspend = sun4i_lradc_suspend,
> >> +};
> >> +
> >> +module_platform_driver(sun4i_lradc_driver);
> >> +
> >> +
> >> +
> >> +
> >> +MODULE_DESCRIPTION("Allwinner A13/A20 LRADC hwmon driver");
> >> +MODULE_AUTHOR("Ruslan Zalata <rz@xxxxxxxxxxx>");
> >> +MODULE_LICENSE("GPL");








[Index of Archives]     [LM Sensors]     [Linux Sound]     [ALSA Users]     [ALSA Devel]     [Linux Audio Users]     [Linux Media]     [Kernel]     [Gimp]     [Yosemite News]     [Linux Media]

  Powered by Linux