Linux Input/HID development
 help / color / mirror / Atom feed
* [PATCH 13/15] ARM: at91: remove atmel_tsadcc from sama5_defconfig
From: Alexandre Belloni @ 2014-03-05 17:35 UTC (permalink / raw)
  To: Nicolas Ferre, Jonathan Cameron, Dmitry Torokhov
  Cc: Jean-Christophe Plagniol-Villard,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	linux-iio-u79uwXL29TY76Z2rM5mHXA,
	linux-input-u79uwXL29TY76Z2rM5mHXA, Maxime Ripard,
	Gregory Clement, Alexandre Belloni
In-Reply-To: <1394040940-18246-1-git-send-email-alexandre.belloni-wi1+55ScJUtKEb57/3fJTNBPR1lH4CV8@public.gmane.org>

atmel_tsadcc has been removed, stop selecting it.

Signed-off-by: Alexandre Belloni <alexandre.belloni-wi1+55ScJUtKEb57/3fJTNBPR1lH4CV8@public.gmane.org>
---
 arch/arm/configs/sama5_defconfig | 1 -
 1 file changed, 1 deletion(-)

diff --git a/arch/arm/configs/sama5_defconfig b/arch/arm/configs/sama5_defconfig
index dc3881e07630..869fa18ebeb2 100644
--- a/arch/arm/configs/sama5_defconfig
+++ b/arch/arm/configs/sama5_defconfig
@@ -122,7 +122,6 @@ CONFIG_KEYBOARD_GPIO=y
 # CONFIG_INPUT_MOUSE is not set
 CONFIG_INPUT_TOUCHSCREEN=y
 CONFIG_TOUCHSCREEN_ATMEL_MXT=y
-CONFIG_TOUCHSCREEN_ATMEL_TSADCC=y
 # CONFIG_SERIO is not set
 CONFIG_LEGACY_PTY_COUNT=4
 CONFIG_SERIAL_ATMEL=y
-- 
1.8.3.2

^ permalink raw reply related

* [PATCH 14/15] Input: atmel_tsadcc: remove driver
From: Alexandre Belloni @ 2014-03-05 17:35 UTC (permalink / raw)
  To: Nicolas Ferre, Jonathan Cameron, Dmitry Torokhov
  Cc: Jean-Christophe Plagniol-Villard, linux-kernel, linux-arm-kernel,
	linux-iio, linux-input, Maxime Ripard, Gregory Clement,
	Alexandre Belloni
In-Reply-To: <1394040940-18246-1-git-send-email-alexandre.belloni@free-electrons.com>

The atmel_tsadcc driver is not used anymore, it has been replaced by at91_adc so
remove it.

Signed-off-by: Alexandre Belloni <alexandre.belloni@free-electrons.com>
---
 MAINTAINERS                              |   6 -
 drivers/input/touchscreen/Kconfig        |  12 --
 drivers/input/touchscreen/Makefile       |   1 -
 drivers/input/touchscreen/atmel_tsadcc.c | 358 -------------------------------
 4 files changed, 377 deletions(-)
 delete mode 100644 drivers/input/touchscreen/atmel_tsadcc.c

diff --git a/MAINTAINERS b/MAINTAINERS
index c6d0e93eff62..134dd63dfa17 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -1591,12 +1591,6 @@ S:	Supported
 F:	drivers/misc/atmel_tclib.c
 F:	drivers/clocksource/tcb_clksrc.c
 
-ATMEL TSADCC DRIVER
-M:	Josh Wu <josh.wu@atmel.com>
-L:	linux-input@vger.kernel.org
-S:	Supported
-F:	drivers/input/touchscreen/atmel_tsadcc.c
-
 ATMEL USBA UDC DRIVER
 M:	Nicolas Ferre <nicolas.ferre@atmel.com>
 L:	linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
diff --git a/drivers/input/touchscreen/Kconfig b/drivers/input/touchscreen/Kconfig
index 07e9e82029d1..4090f69e78af 100644
--- a/drivers/input/touchscreen/Kconfig
+++ b/drivers/input/touchscreen/Kconfig
@@ -559,18 +559,6 @@ config TOUCHSCREEN_TI_AM335X_TSC
 	  To compile this driver as a module, choose M here: the
 	  module will be called ti_am335x_tsc.
 
-config TOUCHSCREEN_ATMEL_TSADCC
-	tristate "Atmel Touchscreen Interface"
-	depends on ARCH_AT91
-	help
-	  Say Y here if you have a 4-wire touchscreen connected to the
-          ADC Controller on your Atmel SoC.
-
-	  If unsure, say N.
-
-	  To compile this driver as a module, choose M here: the
-	  module will be called atmel_tsadcc.
-
 config TOUCHSCREEN_UCB1400
 	tristate "Philips UCB1400 touchscreen"
 	depends on AC97_BUS
diff --git a/drivers/input/touchscreen/Makefile b/drivers/input/touchscreen/Makefile
index 62801f213346..f326a8290593 100644
--- a/drivers/input/touchscreen/Makefile
+++ b/drivers/input/touchscreen/Makefile
@@ -13,7 +13,6 @@ obj-$(CONFIG_TOUCHSCREEN_AD7879_I2C)	+= ad7879-i2c.o
 obj-$(CONFIG_TOUCHSCREEN_AD7879_SPI)	+= ad7879-spi.o
 obj-$(CONFIG_TOUCHSCREEN_ADS7846)	+= ads7846.o
 obj-$(CONFIG_TOUCHSCREEN_ATMEL_MXT)	+= atmel_mxt_ts.o
-obj-$(CONFIG_TOUCHSCREEN_ATMEL_TSADCC)	+= atmel_tsadcc.o
 obj-$(CONFIG_TOUCHSCREEN_AUO_PIXCIR)	+= auo-pixcir-ts.o
 obj-$(CONFIG_TOUCHSCREEN_BU21013)	+= bu21013_ts.o
 obj-$(CONFIG_TOUCHSCREEN_CY8CTMG110)	+= cy8ctmg110_ts.o
diff --git a/drivers/input/touchscreen/atmel_tsadcc.c b/drivers/input/touchscreen/atmel_tsadcc.c
deleted file mode 100644
index a7c9d6967d1e..000000000000
--- a/drivers/input/touchscreen/atmel_tsadcc.c
+++ /dev/null
@@ -1,358 +0,0 @@
-/*
- *  Atmel Touch Screen Driver
- *
- *  Copyright (c) 2008 ATMEL
- *  Copyright (c) 2008 Dan Liang
- *  Copyright (c) 2008 TimeSys Corporation
- *  Copyright (c) 2008 Justin Waters
- *
- *  Based on touchscreen code from Atmel Corporation.
- *
- *  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.
- */
-#include <linux/err.h>
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/input.h>
-#include <linux/slab.h>
-#include <linux/interrupt.h>
-#include <linux/clk.h>
-#include <linux/platform_device.h>
-#include <linux/io.h>
-#include <linux/platform_data/atmel.h>
-#include <mach/cpu.h>
-
-/* Register definitions based on AT91SAM9RL64 preliminary draft datasheet */
-
-#define ATMEL_TSADCC_CR		0x00	/* Control register */
-#define   ATMEL_TSADCC_SWRST	(1 << 0)	/* Software Reset*/
-#define	  ATMEL_TSADCC_START	(1 << 1)	/* Start conversion */
-
-#define ATMEL_TSADCC_MR		0x04	/* Mode register */
-#define	  ATMEL_TSADCC_TSAMOD	(3    <<  0)	/* ADC mode */
-#define	    ATMEL_TSADCC_TSAMOD_ADC_ONLY_MODE	(0x0)	/* ADC Mode */
-#define	    ATMEL_TSADCC_TSAMOD_TS_ONLY_MODE	(0x1)	/* Touch Screen Only Mode */
-#define	  ATMEL_TSADCC_LOWRES	(1    <<  4)	/* Resolution selection */
-#define	  ATMEL_TSADCC_SLEEP	(1    <<  5)	/* Sleep mode */
-#define	  ATMEL_TSADCC_PENDET	(1    <<  6)	/* Pen Detect selection */
-#define	  ATMEL_TSADCC_PRES	(1    <<  7)	/* Pressure Measurement Selection */
-#define	  ATMEL_TSADCC_PRESCAL	(0x3f <<  8)	/* Prescalar Rate Selection */
-#define	  ATMEL_TSADCC_EPRESCAL	(0xff <<  8)	/* Prescalar Rate Selection (Extended) */
-#define	  ATMEL_TSADCC_STARTUP	(0x7f << 16)	/* Start Up time */
-#define	  ATMEL_TSADCC_SHTIM	(0xf  << 24)	/* Sample & Hold time */
-#define	  ATMEL_TSADCC_PENDBC	(0xf  << 28)	/* Pen Detect debouncing time */
-
-#define ATMEL_TSADCC_TRGR	0x08	/* Trigger register */
-#define	  ATMEL_TSADCC_TRGMOD	(7      <<  0)	/* Trigger mode */
-#define	    ATMEL_TSADCC_TRGMOD_NONE		(0 << 0)
-#define     ATMEL_TSADCC_TRGMOD_EXT_RISING	(1 << 0)
-#define     ATMEL_TSADCC_TRGMOD_EXT_FALLING	(2 << 0)
-#define     ATMEL_TSADCC_TRGMOD_EXT_ANY		(3 << 0)
-#define     ATMEL_TSADCC_TRGMOD_PENDET		(4 << 0)
-#define     ATMEL_TSADCC_TRGMOD_PERIOD		(5 << 0)
-#define     ATMEL_TSADCC_TRGMOD_CONTINUOUS	(6 << 0)
-#define   ATMEL_TSADCC_TRGPER	(0xffff << 16)	/* Trigger period */
-
-#define ATMEL_TSADCC_TSR	0x0C	/* Touch Screen register */
-#define	  ATMEL_TSADCC_TSFREQ	(0xf <<  0)	/* TS Frequency in Interleaved mode */
-#define	  ATMEL_TSADCC_TSSHTIM	(0xf << 24)	/* Sample & Hold time */
-
-#define ATMEL_TSADCC_CHER	0x10	/* Channel Enable register */
-#define ATMEL_TSADCC_CHDR	0x14	/* Channel Disable register */
-#define ATMEL_TSADCC_CHSR	0x18	/* Channel Status register */
-#define	  ATMEL_TSADCC_CH(n)	(1 << (n))	/* Channel number */
-
-#define ATMEL_TSADCC_SR		0x1C	/* Status register */
-#define	  ATMEL_TSADCC_EOC(n)	(1 << ((n)+0))	/* End of conversion for channel N */
-#define	  ATMEL_TSADCC_OVRE(n)	(1 << ((n)+8))	/* Overrun error for channel N */
-#define	  ATMEL_TSADCC_DRDY	(1 << 16)	/* Data Ready */
-#define	  ATMEL_TSADCC_GOVRE	(1 << 17)	/* General Overrun Error */
-#define	  ATMEL_TSADCC_ENDRX	(1 << 18)	/* End of RX Buffer */
-#define	  ATMEL_TSADCC_RXBUFF	(1 << 19)	/* TX Buffer full */
-#define	  ATMEL_TSADCC_PENCNT	(1 << 20)	/* Pen contact */
-#define	  ATMEL_TSADCC_NOCNT	(1 << 21)	/* No contact */
-
-#define ATMEL_TSADCC_LCDR	0x20	/* Last Converted Data register */
-#define	  ATMEL_TSADCC_DATA	(0x3ff << 0)	/* Channel data */
-
-#define ATMEL_TSADCC_IER	0x24	/* Interrupt Enable register */
-#define ATMEL_TSADCC_IDR	0x28	/* Interrupt Disable register */
-#define ATMEL_TSADCC_IMR	0x2C	/* Interrupt Mask register */
-#define ATMEL_TSADCC_CDR0	0x30	/* Channel Data 0 */
-#define ATMEL_TSADCC_CDR1	0x34	/* Channel Data 1 */
-#define ATMEL_TSADCC_CDR2	0x38	/* Channel Data 2 */
-#define ATMEL_TSADCC_CDR3	0x3C	/* Channel Data 3 */
-#define ATMEL_TSADCC_CDR4	0x40	/* Channel Data 4 */
-#define ATMEL_TSADCC_CDR5	0x44	/* Channel Data 5 */
-
-#define ATMEL_TSADCC_XPOS	0x50
-#define ATMEL_TSADCC_Z1DAT	0x54
-#define ATMEL_TSADCC_Z2DAT	0x58
-
-#define PRESCALER_VAL(x)	((x) >> 8)
-
-#define ADC_DEFAULT_CLOCK	100000
-
-struct atmel_tsadcc {
-	struct input_dev	*input;
-	char			phys[32];
-	struct clk		*clk;
-	int			irq;
-	unsigned int		prev_absx;
-	unsigned int		prev_absy;
-	unsigned char		bufferedmeasure;
-};
-
-static void __iomem		*tsc_base;
-
-#define atmel_tsadcc_read(reg)		__raw_readl(tsc_base + (reg))
-#define atmel_tsadcc_write(reg, val)	__raw_writel((val), tsc_base + (reg))
-
-static irqreturn_t atmel_tsadcc_interrupt(int irq, void *dev)
-{
-	struct atmel_tsadcc	*ts_dev = (struct atmel_tsadcc *)dev;
-	struct input_dev	*input_dev = ts_dev->input;
-
-	unsigned int status;
-	unsigned int reg;
-
-	status = atmel_tsadcc_read(ATMEL_TSADCC_SR);
-	status &= atmel_tsadcc_read(ATMEL_TSADCC_IMR);
-
-	if (status & ATMEL_TSADCC_NOCNT) {
-		/* Contact lost */
-		reg = atmel_tsadcc_read(ATMEL_TSADCC_MR) | ATMEL_TSADCC_PENDBC;
-
-		atmel_tsadcc_write(ATMEL_TSADCC_MR, reg);
-		atmel_tsadcc_write(ATMEL_TSADCC_TRGR, ATMEL_TSADCC_TRGMOD_NONE);
-		atmel_tsadcc_write(ATMEL_TSADCC_IDR,
-				   ATMEL_TSADCC_EOC(3) | ATMEL_TSADCC_NOCNT);
-		atmel_tsadcc_write(ATMEL_TSADCC_IER, ATMEL_TSADCC_PENCNT);
-
-		input_report_key(input_dev, BTN_TOUCH, 0);
-		ts_dev->bufferedmeasure = 0;
-		input_sync(input_dev);
-
-	} else if (status & ATMEL_TSADCC_PENCNT) {
-		/* Pen detected */
-		reg = atmel_tsadcc_read(ATMEL_TSADCC_MR);
-		reg &= ~ATMEL_TSADCC_PENDBC;
-
-		atmel_tsadcc_write(ATMEL_TSADCC_IDR, ATMEL_TSADCC_PENCNT);
-		atmel_tsadcc_write(ATMEL_TSADCC_MR, reg);
-		atmel_tsadcc_write(ATMEL_TSADCC_IER,
-				   ATMEL_TSADCC_EOC(3) | ATMEL_TSADCC_NOCNT);
-		atmel_tsadcc_write(ATMEL_TSADCC_TRGR,
-				   ATMEL_TSADCC_TRGMOD_PERIOD | (0x0FFF << 16));
-
-	} else if (status & ATMEL_TSADCC_EOC(3)) {
-		/* Conversion finished */
-
-		if (ts_dev->bufferedmeasure) {
-			/* Last measurement is always discarded, since it can
-			 * be erroneous.
-			 * Always report previous measurement */
-			input_report_abs(input_dev, ABS_X, ts_dev->prev_absx);
-			input_report_abs(input_dev, ABS_Y, ts_dev->prev_absy);
-			input_report_key(input_dev, BTN_TOUCH, 1);
-			input_sync(input_dev);
-		} else
-			ts_dev->bufferedmeasure = 1;
-
-		/* Now make new measurement */
-		ts_dev->prev_absx = atmel_tsadcc_read(ATMEL_TSADCC_CDR3) << 10;
-		ts_dev->prev_absx /= atmel_tsadcc_read(ATMEL_TSADCC_CDR2);
-
-		ts_dev->prev_absy = atmel_tsadcc_read(ATMEL_TSADCC_CDR1) << 10;
-		ts_dev->prev_absy /= atmel_tsadcc_read(ATMEL_TSADCC_CDR0);
-	}
-
-	return IRQ_HANDLED;
-}
-
-/*
- * The functions for inserting/removing us as a module.
- */
-
-static int atmel_tsadcc_probe(struct platform_device *pdev)
-{
-	struct atmel_tsadcc	*ts_dev;
-	struct input_dev	*input_dev;
-	struct resource		*res;
-	struct at91_tsadcc_data *pdata = dev_get_platdata(&pdev->dev);
-	int		err;
-	unsigned int	prsc;
-	unsigned int	reg;
-
-	if (!pdata)
-		return -EINVAL;
-
-	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-	if (!res) {
-		dev_err(&pdev->dev, "no mmio resource defined.\n");
-		return -ENXIO;
-	}
-
-	/* Allocate memory for device */
-	ts_dev = kzalloc(sizeof(struct atmel_tsadcc), GFP_KERNEL);
-	if (!ts_dev) {
-		dev_err(&pdev->dev, "failed to allocate memory.\n");
-		return -ENOMEM;
-	}
-	platform_set_drvdata(pdev, ts_dev);
-
-	input_dev = input_allocate_device();
-	if (!input_dev) {
-		dev_err(&pdev->dev, "failed to allocate input device.\n");
-		err = -EBUSY;
-		goto err_free_mem;
-	}
-
-	ts_dev->irq = platform_get_irq(pdev, 0);
-	if (ts_dev->irq < 0) {
-		dev_err(&pdev->dev, "no irq ID is designated.\n");
-		err = -ENODEV;
-		goto err_free_dev;
-	}
-
-	if (!request_mem_region(res->start, resource_size(res),
-				"atmel tsadcc regs")) {
-		dev_err(&pdev->dev, "resources is unavailable.\n");
-		err = -EBUSY;
-		goto err_free_dev;
-	}
-
-	tsc_base = ioremap(res->start, resource_size(res));
-	if (!tsc_base) {
-		dev_err(&pdev->dev, "failed to map registers.\n");
-		err = -ENOMEM;
-		goto err_release_mem;
-	}
-
-	err = request_irq(ts_dev->irq, atmel_tsadcc_interrupt, 0,
-			pdev->dev.driver->name, ts_dev);
-	if (err) {
-		dev_err(&pdev->dev, "failed to allocate irq.\n");
-		goto err_unmap_regs;
-	}
-
-	ts_dev->clk = clk_get(&pdev->dev, "tsc_clk");
-	if (IS_ERR(ts_dev->clk)) {
-		dev_err(&pdev->dev, "failed to get ts_clk\n");
-		err = PTR_ERR(ts_dev->clk);
-		goto err_free_irq;
-	}
-
-	ts_dev->input = input_dev;
-	ts_dev->bufferedmeasure = 0;
-
-	snprintf(ts_dev->phys, sizeof(ts_dev->phys),
-		 "%s/input0", dev_name(&pdev->dev));
-
-	input_dev->name = "atmel touch screen controller";
-	input_dev->phys = ts_dev->phys;
-	input_dev->dev.parent = &pdev->dev;
-
-	__set_bit(EV_ABS, input_dev->evbit);
-	input_set_abs_params(input_dev, ABS_X, 0, 0x3FF, 0, 0);
-	input_set_abs_params(input_dev, ABS_Y, 0, 0x3FF, 0, 0);
-
-	input_set_capability(input_dev, EV_KEY, BTN_TOUCH);
-
-	/* clk_enable() always returns 0, no need to check it */
-	clk_enable(ts_dev->clk);
-
-	prsc = clk_get_rate(ts_dev->clk);
-	dev_info(&pdev->dev, "Master clock is set at: %d Hz\n", prsc);
-
-	if (!pdata->adc_clock)
-		pdata->adc_clock = ADC_DEFAULT_CLOCK;
-
-	prsc = (prsc / (2 * pdata->adc_clock)) - 1;
-
-	/* saturate if this value is too high */
-	if (cpu_is_at91sam9rl()) {
-		if (prsc > PRESCALER_VAL(ATMEL_TSADCC_PRESCAL))
-			prsc = PRESCALER_VAL(ATMEL_TSADCC_PRESCAL);
-	} else {
-		if (prsc > PRESCALER_VAL(ATMEL_TSADCC_EPRESCAL))
-			prsc = PRESCALER_VAL(ATMEL_TSADCC_EPRESCAL);
-	}
-
-	dev_info(&pdev->dev, "Prescaler is set at: %d\n", prsc);
-
-	reg = ATMEL_TSADCC_TSAMOD_TS_ONLY_MODE		|
-		((0x00 << 5) & ATMEL_TSADCC_SLEEP)	|	/* Normal Mode */
-		((0x01 << 6) & ATMEL_TSADCC_PENDET)	|	/* Enable Pen Detect */
-		(prsc << 8)				|
-		((0x26 << 16) & ATMEL_TSADCC_STARTUP)	|
-		((pdata->pendet_debounce << 28) & ATMEL_TSADCC_PENDBC);
-
-	atmel_tsadcc_write(ATMEL_TSADCC_CR, ATMEL_TSADCC_SWRST);
-	atmel_tsadcc_write(ATMEL_TSADCC_MR, reg);
-	atmel_tsadcc_write(ATMEL_TSADCC_TRGR, ATMEL_TSADCC_TRGMOD_NONE);
-	atmel_tsadcc_write(ATMEL_TSADCC_TSR,
-		(pdata->ts_sample_hold_time << 24) & ATMEL_TSADCC_TSSHTIM);
-
-	atmel_tsadcc_read(ATMEL_TSADCC_SR);
-	atmel_tsadcc_write(ATMEL_TSADCC_IER, ATMEL_TSADCC_PENCNT);
-
-	/* All went ok, so register to the input system */
-	err = input_register_device(input_dev);
-	if (err)
-		goto err_fail;
-
-	return 0;
-
-err_fail:
-	clk_disable(ts_dev->clk);
-	clk_put(ts_dev->clk);
-err_free_irq:
-	free_irq(ts_dev->irq, ts_dev);
-err_unmap_regs:
-	iounmap(tsc_base);
-err_release_mem:
-	release_mem_region(res->start, resource_size(res));
-err_free_dev:
-	input_free_device(input_dev);
-err_free_mem:
-	kfree(ts_dev);
-	return err;
-}
-
-static int atmel_tsadcc_remove(struct platform_device *pdev)
-{
-	struct atmel_tsadcc *ts_dev = platform_get_drvdata(pdev);
-	struct resource *res;
-
-	free_irq(ts_dev->irq, ts_dev);
-
-	input_unregister_device(ts_dev->input);
-
-	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-	iounmap(tsc_base);
-	release_mem_region(res->start, resource_size(res));
-
-	clk_disable(ts_dev->clk);
-	clk_put(ts_dev->clk);
-
-	kfree(ts_dev);
-
-	return 0;
-}
-
-static struct platform_driver atmel_tsadcc_driver = {
-	.probe		= atmel_tsadcc_probe,
-	.remove		= atmel_tsadcc_remove,
-	.driver		= {
-		.name	= "atmel_tsadcc",
-	},
-};
-module_platform_driver(atmel_tsadcc_driver);
-
-MODULE_LICENSE("GPL");
-MODULE_DESCRIPTION("Atmel TouchScreen Driver");
-MODULE_AUTHOR("Dan Liang <dan.liang@atmel.com>");
-
-- 
1.8.3.2

^ permalink raw reply related

* [PATCH 01/15] ARM: at91: sam9g45: remove unused platform_data
From: Alexandre Belloni @ 2014-03-05 17:35 UTC (permalink / raw)
  To: Nicolas Ferre, Jonathan Cameron, Dmitry Torokhov
  Cc: Jean-Christophe Plagniol-Villard, linux-kernel, linux-arm-kernel,
	linux-iio, linux-input, Maxime Ripard, Gregory Clement,
	Alexandre Belloni
In-Reply-To: <1394040940-18246-1-git-send-email-alexandre.belloni@free-electrons.com>

num_channels and registers are not used anymore since they are defined inside
the at91_adc driver and assigned by matching the id_table.

Also, remove the mach/at91_adc.h include that is not necessary anymore.

Signed-off-by: Alexandre Belloni <alexandre.belloni@free-electrons.com>
---
 arch/arm/mach-at91/at91sam9g45_devices.c | 10 ----------
 1 file changed, 10 deletions(-)

diff --git a/arch/arm/mach-at91/at91sam9g45_devices.c b/arch/arm/mach-at91/at91sam9g45_devices.c
index 88554024eb2d..cd36009c3511 100644
--- a/arch/arm/mach-at91/at91sam9g45_devices.c
+++ b/arch/arm/mach-at91/at91sam9g45_devices.c
@@ -25,7 +25,6 @@
 #include <linux/fb.h>
 #include <video/atmel_lcdc.h>
 
-#include <mach/at91_adc.h>
 #include <mach/at91sam9g45.h>
 #include <mach/at91sam9g45_matrix.h>
 #include <mach/at91_matrix.h>
@@ -1235,13 +1234,6 @@ static struct at91_adc_trigger at91_adc_triggers[] = {
 	},
 };
 
-static struct at91_adc_reg_desc at91_adc_register_g45 = {
-	.channel_base = AT91_ADC_CHR(0),
-	.drdy_mask = AT91_ADC_DRDY,
-	.status_register = AT91_ADC_SR,
-	.trigger_register = 0x08,
-};
-
 void __init at91_add_device_adc(struct at91_adc_data *data)
 {
 	if (!data)
@@ -1267,9 +1259,7 @@ void __init at91_add_device_adc(struct at91_adc_data *data)
 	if (data->use_external_triggers)
 		at91_set_A_periph(AT91_PIN_PD28, 0);
 
-	data->num_channels = 8;
 	data->startup_time = 40;
-	data->registers = &at91_adc_register_g45;
 	data->trigger_number = 4;
 	data->trigger_list = at91_adc_triggers;
 
-- 
1.8.3.2


^ permalink raw reply related

* [PATCH 15/15] ARM: at91/dt: at91-cosino_mega2560 remove useless tsadcc node
From: Alexandre Belloni @ 2014-03-05 17:35 UTC (permalink / raw)
  To: Nicolas Ferre, Jonathan Cameron, Dmitry Torokhov
  Cc: Jean-Christophe Plagniol-Villard, linux-kernel, linux-arm-kernel,
	linux-iio, linux-input, Maxime Ripard, Gregory Clement,
	Alexandre Belloni, Rodolfo Giometti
In-Reply-To: <1394040940-18246-1-git-send-email-alexandre.belloni@free-electrons.com>

The tsadcc node is useless as it doesn't refer to anything and the touchscreen
is handled by the adc0 node.

Signed-off-by: Alexandre Belloni <alexandre.belloni@free-electrons.com>
Cc: Rodolfo Giometti <giometti@linux.it>
---
 arch/arm/boot/dts/at91-cosino_mega2560.dts | 5 -----
 1 file changed, 5 deletions(-)

diff --git a/arch/arm/boot/dts/at91-cosino_mega2560.dts b/arch/arm/boot/dts/at91-cosino_mega2560.dts
index f9415dd11f17..cce621239b72 100644
--- a/arch/arm/boot/dts/at91-cosino_mega2560.dts
+++ b/arch/arm/boot/dts/at91-cosino_mega2560.dts
@@ -33,11 +33,6 @@
 				status = "okay";
 			};
 
-
-			tsadcc: tsadcc@f804c000 {
-				status = "okay";
-			};
-
 			rtc@fffffeb0 {
 				status = "okay";
 			};
-- 
1.8.3.2


^ permalink raw reply related

* Re: [PATCH 04/15] iio: adc: at91_adc: Add support for touchscreens without TSMR
From: Thomas Petazzoni @ 2014-03-05 18:27 UTC (permalink / raw)
  To: Alexandre Belloni
  Cc: Nicolas Ferre, Jonathan Cameron, Dmitry Torokhov, linux-iio,
	linux-kernel, linux-input, Gregory Clement, Maxime Ripard,
	Jean-Christophe Plagniol-Villard, linux-arm-kernel
In-Reply-To: <1394040940-18246-5-git-send-email-alexandre.belloni@free-electrons.com>

Dear Alexandre Belloni,

On Wed,  5 Mar 2014 18:35:29 +0100, Alexandre Belloni wrote:

> -static irqreturn_t at91_adc_interrupt(int irq, void *private)
> +void handle_adc_rl_ts_irq(int irq, struct at91_adc_state *st, u32 status)

I believe this function,

> +void handle_adc_9x5_ts_irq(int irq, struct at91_adc_state *st, u32 status)

and this one should be 'static'.

Thomas
-- 
Thomas Petazzoni, CTO, Free Electrons
Embedded Linux, Kernel and Android engineering
http://free-electrons.com

^ permalink raw reply

* Re: [PATCH 14/15] Input: atmel_tsadcc: remove driver
From: Dmitry Torokhov @ 2014-03-05 18:46 UTC (permalink / raw)
  To: Alexandre Belloni
  Cc: Nicolas Ferre, Jonathan Cameron, Jean-Christophe Plagniol-Villard,
	linux-kernel, linux-arm-kernel, linux-iio, linux-input,
	Maxime Ripard, Gregory Clement
In-Reply-To: <1394040940-18246-15-git-send-email-alexandre.belloni@free-electrons.com>

On Wed, Mar 05, 2014 at 06:35:39PM +0100, Alexandre Belloni wrote:
> The atmel_tsadcc driver is not used anymore, it has been replaced by at91_adc so
> remove it.
> 
> Signed-off-by: Alexandre Belloni <alexandre.belloni@free-electrons.com>

Acked-by: Dmitry Torokhov <dmitry.torokhov@gmail.com>

> ---
>  MAINTAINERS                              |   6 -
>  drivers/input/touchscreen/Kconfig        |  12 --
>  drivers/input/touchscreen/Makefile       |   1 -
>  drivers/input/touchscreen/atmel_tsadcc.c | 358 -------------------------------
>  4 files changed, 377 deletions(-)
>  delete mode 100644 drivers/input/touchscreen/atmel_tsadcc.c
> 
> diff --git a/MAINTAINERS b/MAINTAINERS
> index c6d0e93eff62..134dd63dfa17 100644
> --- a/MAINTAINERS
> +++ b/MAINTAINERS
> @@ -1591,12 +1591,6 @@ S:	Supported
>  F:	drivers/misc/atmel_tclib.c
>  F:	drivers/clocksource/tcb_clksrc.c
>  
> -ATMEL TSADCC DRIVER
> -M:	Josh Wu <josh.wu@atmel.com>
> -L:	linux-input@vger.kernel.org
> -S:	Supported
> -F:	drivers/input/touchscreen/atmel_tsadcc.c
> -
>  ATMEL USBA UDC DRIVER
>  M:	Nicolas Ferre <nicolas.ferre@atmel.com>
>  L:	linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
> diff --git a/drivers/input/touchscreen/Kconfig b/drivers/input/touchscreen/Kconfig
> index 07e9e82029d1..4090f69e78af 100644
> --- a/drivers/input/touchscreen/Kconfig
> +++ b/drivers/input/touchscreen/Kconfig
> @@ -559,18 +559,6 @@ config TOUCHSCREEN_TI_AM335X_TSC
>  	  To compile this driver as a module, choose M here: the
>  	  module will be called ti_am335x_tsc.
>  
> -config TOUCHSCREEN_ATMEL_TSADCC
> -	tristate "Atmel Touchscreen Interface"
> -	depends on ARCH_AT91
> -	help
> -	  Say Y here if you have a 4-wire touchscreen connected to the
> -          ADC Controller on your Atmel SoC.
> -
> -	  If unsure, say N.
> -
> -	  To compile this driver as a module, choose M here: the
> -	  module will be called atmel_tsadcc.
> -
>  config TOUCHSCREEN_UCB1400
>  	tristate "Philips UCB1400 touchscreen"
>  	depends on AC97_BUS
> diff --git a/drivers/input/touchscreen/Makefile b/drivers/input/touchscreen/Makefile
> index 62801f213346..f326a8290593 100644
> --- a/drivers/input/touchscreen/Makefile
> +++ b/drivers/input/touchscreen/Makefile
> @@ -13,7 +13,6 @@ obj-$(CONFIG_TOUCHSCREEN_AD7879_I2C)	+= ad7879-i2c.o
>  obj-$(CONFIG_TOUCHSCREEN_AD7879_SPI)	+= ad7879-spi.o
>  obj-$(CONFIG_TOUCHSCREEN_ADS7846)	+= ads7846.o
>  obj-$(CONFIG_TOUCHSCREEN_ATMEL_MXT)	+= atmel_mxt_ts.o
> -obj-$(CONFIG_TOUCHSCREEN_ATMEL_TSADCC)	+= atmel_tsadcc.o
>  obj-$(CONFIG_TOUCHSCREEN_AUO_PIXCIR)	+= auo-pixcir-ts.o
>  obj-$(CONFIG_TOUCHSCREEN_BU21013)	+= bu21013_ts.o
>  obj-$(CONFIG_TOUCHSCREEN_CY8CTMG110)	+= cy8ctmg110_ts.o
> diff --git a/drivers/input/touchscreen/atmel_tsadcc.c b/drivers/input/touchscreen/atmel_tsadcc.c
> deleted file mode 100644
> index a7c9d6967d1e..000000000000
> --- a/drivers/input/touchscreen/atmel_tsadcc.c
> +++ /dev/null
> @@ -1,358 +0,0 @@
> -/*
> - *  Atmel Touch Screen Driver
> - *
> - *  Copyright (c) 2008 ATMEL
> - *  Copyright (c) 2008 Dan Liang
> - *  Copyright (c) 2008 TimeSys Corporation
> - *  Copyright (c) 2008 Justin Waters
> - *
> - *  Based on touchscreen code from Atmel Corporation.
> - *
> - *  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.
> - */
> -#include <linux/err.h>
> -#include <linux/kernel.h>
> -#include <linux/module.h>
> -#include <linux/input.h>
> -#include <linux/slab.h>
> -#include <linux/interrupt.h>
> -#include <linux/clk.h>
> -#include <linux/platform_device.h>
> -#include <linux/io.h>
> -#include <linux/platform_data/atmel.h>
> -#include <mach/cpu.h>
> -
> -/* Register definitions based on AT91SAM9RL64 preliminary draft datasheet */
> -
> -#define ATMEL_TSADCC_CR		0x00	/* Control register */
> -#define   ATMEL_TSADCC_SWRST	(1 << 0)	/* Software Reset*/
> -#define	  ATMEL_TSADCC_START	(1 << 1)	/* Start conversion */
> -
> -#define ATMEL_TSADCC_MR		0x04	/* Mode register */
> -#define	  ATMEL_TSADCC_TSAMOD	(3    <<  0)	/* ADC mode */
> -#define	    ATMEL_TSADCC_TSAMOD_ADC_ONLY_MODE	(0x0)	/* ADC Mode */
> -#define	    ATMEL_TSADCC_TSAMOD_TS_ONLY_MODE	(0x1)	/* Touch Screen Only Mode */
> -#define	  ATMEL_TSADCC_LOWRES	(1    <<  4)	/* Resolution selection */
> -#define	  ATMEL_TSADCC_SLEEP	(1    <<  5)	/* Sleep mode */
> -#define	  ATMEL_TSADCC_PENDET	(1    <<  6)	/* Pen Detect selection */
> -#define	  ATMEL_TSADCC_PRES	(1    <<  7)	/* Pressure Measurement Selection */
> -#define	  ATMEL_TSADCC_PRESCAL	(0x3f <<  8)	/* Prescalar Rate Selection */
> -#define	  ATMEL_TSADCC_EPRESCAL	(0xff <<  8)	/* Prescalar Rate Selection (Extended) */
> -#define	  ATMEL_TSADCC_STARTUP	(0x7f << 16)	/* Start Up time */
> -#define	  ATMEL_TSADCC_SHTIM	(0xf  << 24)	/* Sample & Hold time */
> -#define	  ATMEL_TSADCC_PENDBC	(0xf  << 28)	/* Pen Detect debouncing time */
> -
> -#define ATMEL_TSADCC_TRGR	0x08	/* Trigger register */
> -#define	  ATMEL_TSADCC_TRGMOD	(7      <<  0)	/* Trigger mode */
> -#define	    ATMEL_TSADCC_TRGMOD_NONE		(0 << 0)
> -#define     ATMEL_TSADCC_TRGMOD_EXT_RISING	(1 << 0)
> -#define     ATMEL_TSADCC_TRGMOD_EXT_FALLING	(2 << 0)
> -#define     ATMEL_TSADCC_TRGMOD_EXT_ANY		(3 << 0)
> -#define     ATMEL_TSADCC_TRGMOD_PENDET		(4 << 0)
> -#define     ATMEL_TSADCC_TRGMOD_PERIOD		(5 << 0)
> -#define     ATMEL_TSADCC_TRGMOD_CONTINUOUS	(6 << 0)
> -#define   ATMEL_TSADCC_TRGPER	(0xffff << 16)	/* Trigger period */
> -
> -#define ATMEL_TSADCC_TSR	0x0C	/* Touch Screen register */
> -#define	  ATMEL_TSADCC_TSFREQ	(0xf <<  0)	/* TS Frequency in Interleaved mode */
> -#define	  ATMEL_TSADCC_TSSHTIM	(0xf << 24)	/* Sample & Hold time */
> -
> -#define ATMEL_TSADCC_CHER	0x10	/* Channel Enable register */
> -#define ATMEL_TSADCC_CHDR	0x14	/* Channel Disable register */
> -#define ATMEL_TSADCC_CHSR	0x18	/* Channel Status register */
> -#define	  ATMEL_TSADCC_CH(n)	(1 << (n))	/* Channel number */
> -
> -#define ATMEL_TSADCC_SR		0x1C	/* Status register */
> -#define	  ATMEL_TSADCC_EOC(n)	(1 << ((n)+0))	/* End of conversion for channel N */
> -#define	  ATMEL_TSADCC_OVRE(n)	(1 << ((n)+8))	/* Overrun error for channel N */
> -#define	  ATMEL_TSADCC_DRDY	(1 << 16)	/* Data Ready */
> -#define	  ATMEL_TSADCC_GOVRE	(1 << 17)	/* General Overrun Error */
> -#define	  ATMEL_TSADCC_ENDRX	(1 << 18)	/* End of RX Buffer */
> -#define	  ATMEL_TSADCC_RXBUFF	(1 << 19)	/* TX Buffer full */
> -#define	  ATMEL_TSADCC_PENCNT	(1 << 20)	/* Pen contact */
> -#define	  ATMEL_TSADCC_NOCNT	(1 << 21)	/* No contact */
> -
> -#define ATMEL_TSADCC_LCDR	0x20	/* Last Converted Data register */
> -#define	  ATMEL_TSADCC_DATA	(0x3ff << 0)	/* Channel data */
> -
> -#define ATMEL_TSADCC_IER	0x24	/* Interrupt Enable register */
> -#define ATMEL_TSADCC_IDR	0x28	/* Interrupt Disable register */
> -#define ATMEL_TSADCC_IMR	0x2C	/* Interrupt Mask register */
> -#define ATMEL_TSADCC_CDR0	0x30	/* Channel Data 0 */
> -#define ATMEL_TSADCC_CDR1	0x34	/* Channel Data 1 */
> -#define ATMEL_TSADCC_CDR2	0x38	/* Channel Data 2 */
> -#define ATMEL_TSADCC_CDR3	0x3C	/* Channel Data 3 */
> -#define ATMEL_TSADCC_CDR4	0x40	/* Channel Data 4 */
> -#define ATMEL_TSADCC_CDR5	0x44	/* Channel Data 5 */
> -
> -#define ATMEL_TSADCC_XPOS	0x50
> -#define ATMEL_TSADCC_Z1DAT	0x54
> -#define ATMEL_TSADCC_Z2DAT	0x58
> -
> -#define PRESCALER_VAL(x)	((x) >> 8)
> -
> -#define ADC_DEFAULT_CLOCK	100000
> -
> -struct atmel_tsadcc {
> -	struct input_dev	*input;
> -	char			phys[32];
> -	struct clk		*clk;
> -	int			irq;
> -	unsigned int		prev_absx;
> -	unsigned int		prev_absy;
> -	unsigned char		bufferedmeasure;
> -};
> -
> -static void __iomem		*tsc_base;
> -
> -#define atmel_tsadcc_read(reg)		__raw_readl(tsc_base + (reg))
> -#define atmel_tsadcc_write(reg, val)	__raw_writel((val), tsc_base + (reg))
> -
> -static irqreturn_t atmel_tsadcc_interrupt(int irq, void *dev)
> -{
> -	struct atmel_tsadcc	*ts_dev = (struct atmel_tsadcc *)dev;
> -	struct input_dev	*input_dev = ts_dev->input;
> -
> -	unsigned int status;
> -	unsigned int reg;
> -
> -	status = atmel_tsadcc_read(ATMEL_TSADCC_SR);
> -	status &= atmel_tsadcc_read(ATMEL_TSADCC_IMR);
> -
> -	if (status & ATMEL_TSADCC_NOCNT) {
> -		/* Contact lost */
> -		reg = atmel_tsadcc_read(ATMEL_TSADCC_MR) | ATMEL_TSADCC_PENDBC;
> -
> -		atmel_tsadcc_write(ATMEL_TSADCC_MR, reg);
> -		atmel_tsadcc_write(ATMEL_TSADCC_TRGR, ATMEL_TSADCC_TRGMOD_NONE);
> -		atmel_tsadcc_write(ATMEL_TSADCC_IDR,
> -				   ATMEL_TSADCC_EOC(3) | ATMEL_TSADCC_NOCNT);
> -		atmel_tsadcc_write(ATMEL_TSADCC_IER, ATMEL_TSADCC_PENCNT);
> -
> -		input_report_key(input_dev, BTN_TOUCH, 0);
> -		ts_dev->bufferedmeasure = 0;
> -		input_sync(input_dev);
> -
> -	} else if (status & ATMEL_TSADCC_PENCNT) {
> -		/* Pen detected */
> -		reg = atmel_tsadcc_read(ATMEL_TSADCC_MR);
> -		reg &= ~ATMEL_TSADCC_PENDBC;
> -
> -		atmel_tsadcc_write(ATMEL_TSADCC_IDR, ATMEL_TSADCC_PENCNT);
> -		atmel_tsadcc_write(ATMEL_TSADCC_MR, reg);
> -		atmel_tsadcc_write(ATMEL_TSADCC_IER,
> -				   ATMEL_TSADCC_EOC(3) | ATMEL_TSADCC_NOCNT);
> -		atmel_tsadcc_write(ATMEL_TSADCC_TRGR,
> -				   ATMEL_TSADCC_TRGMOD_PERIOD | (0x0FFF << 16));
> -
> -	} else if (status & ATMEL_TSADCC_EOC(3)) {
> -		/* Conversion finished */
> -
> -		if (ts_dev->bufferedmeasure) {
> -			/* Last measurement is always discarded, since it can
> -			 * be erroneous.
> -			 * Always report previous measurement */
> -			input_report_abs(input_dev, ABS_X, ts_dev->prev_absx);
> -			input_report_abs(input_dev, ABS_Y, ts_dev->prev_absy);
> -			input_report_key(input_dev, BTN_TOUCH, 1);
> -			input_sync(input_dev);
> -		} else
> -			ts_dev->bufferedmeasure = 1;
> -
> -		/* Now make new measurement */
> -		ts_dev->prev_absx = atmel_tsadcc_read(ATMEL_TSADCC_CDR3) << 10;
> -		ts_dev->prev_absx /= atmel_tsadcc_read(ATMEL_TSADCC_CDR2);
> -
> -		ts_dev->prev_absy = atmel_tsadcc_read(ATMEL_TSADCC_CDR1) << 10;
> -		ts_dev->prev_absy /= atmel_tsadcc_read(ATMEL_TSADCC_CDR0);
> -	}
> -
> -	return IRQ_HANDLED;
> -}
> -
> -/*
> - * The functions for inserting/removing us as a module.
> - */
> -
> -static int atmel_tsadcc_probe(struct platform_device *pdev)
> -{
> -	struct atmel_tsadcc	*ts_dev;
> -	struct input_dev	*input_dev;
> -	struct resource		*res;
> -	struct at91_tsadcc_data *pdata = dev_get_platdata(&pdev->dev);
> -	int		err;
> -	unsigned int	prsc;
> -	unsigned int	reg;
> -
> -	if (!pdata)
> -		return -EINVAL;
> -
> -	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> -	if (!res) {
> -		dev_err(&pdev->dev, "no mmio resource defined.\n");
> -		return -ENXIO;
> -	}
> -
> -	/* Allocate memory for device */
> -	ts_dev = kzalloc(sizeof(struct atmel_tsadcc), GFP_KERNEL);
> -	if (!ts_dev) {
> -		dev_err(&pdev->dev, "failed to allocate memory.\n");
> -		return -ENOMEM;
> -	}
> -	platform_set_drvdata(pdev, ts_dev);
> -
> -	input_dev = input_allocate_device();
> -	if (!input_dev) {
> -		dev_err(&pdev->dev, "failed to allocate input device.\n");
> -		err = -EBUSY;
> -		goto err_free_mem;
> -	}
> -
> -	ts_dev->irq = platform_get_irq(pdev, 0);
> -	if (ts_dev->irq < 0) {
> -		dev_err(&pdev->dev, "no irq ID is designated.\n");
> -		err = -ENODEV;
> -		goto err_free_dev;
> -	}
> -
> -	if (!request_mem_region(res->start, resource_size(res),
> -				"atmel tsadcc regs")) {
> -		dev_err(&pdev->dev, "resources is unavailable.\n");
> -		err = -EBUSY;
> -		goto err_free_dev;
> -	}
> -
> -	tsc_base = ioremap(res->start, resource_size(res));
> -	if (!tsc_base) {
> -		dev_err(&pdev->dev, "failed to map registers.\n");
> -		err = -ENOMEM;
> -		goto err_release_mem;
> -	}
> -
> -	err = request_irq(ts_dev->irq, atmel_tsadcc_interrupt, 0,
> -			pdev->dev.driver->name, ts_dev);
> -	if (err) {
> -		dev_err(&pdev->dev, "failed to allocate irq.\n");
> -		goto err_unmap_regs;
> -	}
> -
> -	ts_dev->clk = clk_get(&pdev->dev, "tsc_clk");
> -	if (IS_ERR(ts_dev->clk)) {
> -		dev_err(&pdev->dev, "failed to get ts_clk\n");
> -		err = PTR_ERR(ts_dev->clk);
> -		goto err_free_irq;
> -	}
> -
> -	ts_dev->input = input_dev;
> -	ts_dev->bufferedmeasure = 0;
> -
> -	snprintf(ts_dev->phys, sizeof(ts_dev->phys),
> -		 "%s/input0", dev_name(&pdev->dev));
> -
> -	input_dev->name = "atmel touch screen controller";
> -	input_dev->phys = ts_dev->phys;
> -	input_dev->dev.parent = &pdev->dev;
> -
> -	__set_bit(EV_ABS, input_dev->evbit);
> -	input_set_abs_params(input_dev, ABS_X, 0, 0x3FF, 0, 0);
> -	input_set_abs_params(input_dev, ABS_Y, 0, 0x3FF, 0, 0);
> -
> -	input_set_capability(input_dev, EV_KEY, BTN_TOUCH);
> -
> -	/* clk_enable() always returns 0, no need to check it */
> -	clk_enable(ts_dev->clk);
> -
> -	prsc = clk_get_rate(ts_dev->clk);
> -	dev_info(&pdev->dev, "Master clock is set at: %d Hz\n", prsc);
> -
> -	if (!pdata->adc_clock)
> -		pdata->adc_clock = ADC_DEFAULT_CLOCK;
> -
> -	prsc = (prsc / (2 * pdata->adc_clock)) - 1;
> -
> -	/* saturate if this value is too high */
> -	if (cpu_is_at91sam9rl()) {
> -		if (prsc > PRESCALER_VAL(ATMEL_TSADCC_PRESCAL))
> -			prsc = PRESCALER_VAL(ATMEL_TSADCC_PRESCAL);
> -	} else {
> -		if (prsc > PRESCALER_VAL(ATMEL_TSADCC_EPRESCAL))
> -			prsc = PRESCALER_VAL(ATMEL_TSADCC_EPRESCAL);
> -	}
> -
> -	dev_info(&pdev->dev, "Prescaler is set at: %d\n", prsc);
> -
> -	reg = ATMEL_TSADCC_TSAMOD_TS_ONLY_MODE		|
> -		((0x00 << 5) & ATMEL_TSADCC_SLEEP)	|	/* Normal Mode */
> -		((0x01 << 6) & ATMEL_TSADCC_PENDET)	|	/* Enable Pen Detect */
> -		(prsc << 8)				|
> -		((0x26 << 16) & ATMEL_TSADCC_STARTUP)	|
> -		((pdata->pendet_debounce << 28) & ATMEL_TSADCC_PENDBC);
> -
> -	atmel_tsadcc_write(ATMEL_TSADCC_CR, ATMEL_TSADCC_SWRST);
> -	atmel_tsadcc_write(ATMEL_TSADCC_MR, reg);
> -	atmel_tsadcc_write(ATMEL_TSADCC_TRGR, ATMEL_TSADCC_TRGMOD_NONE);
> -	atmel_tsadcc_write(ATMEL_TSADCC_TSR,
> -		(pdata->ts_sample_hold_time << 24) & ATMEL_TSADCC_TSSHTIM);
> -
> -	atmel_tsadcc_read(ATMEL_TSADCC_SR);
> -	atmel_tsadcc_write(ATMEL_TSADCC_IER, ATMEL_TSADCC_PENCNT);
> -
> -	/* All went ok, so register to the input system */
> -	err = input_register_device(input_dev);
> -	if (err)
> -		goto err_fail;
> -
> -	return 0;
> -
> -err_fail:
> -	clk_disable(ts_dev->clk);
> -	clk_put(ts_dev->clk);
> -err_free_irq:
> -	free_irq(ts_dev->irq, ts_dev);
> -err_unmap_regs:
> -	iounmap(tsc_base);
> -err_release_mem:
> -	release_mem_region(res->start, resource_size(res));
> -err_free_dev:
> -	input_free_device(input_dev);
> -err_free_mem:
> -	kfree(ts_dev);
> -	return err;
> -}
> -
> -static int atmel_tsadcc_remove(struct platform_device *pdev)
> -{
> -	struct atmel_tsadcc *ts_dev = platform_get_drvdata(pdev);
> -	struct resource *res;
> -
> -	free_irq(ts_dev->irq, ts_dev);
> -
> -	input_unregister_device(ts_dev->input);
> -
> -	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> -	iounmap(tsc_base);
> -	release_mem_region(res->start, resource_size(res));
> -
> -	clk_disable(ts_dev->clk);
> -	clk_put(ts_dev->clk);
> -
> -	kfree(ts_dev);
> -
> -	return 0;
> -}
> -
> -static struct platform_driver atmel_tsadcc_driver = {
> -	.probe		= atmel_tsadcc_probe,
> -	.remove		= atmel_tsadcc_remove,
> -	.driver		= {
> -		.name	= "atmel_tsadcc",
> -	},
> -};
> -module_platform_driver(atmel_tsadcc_driver);
> -
> -MODULE_LICENSE("GPL");
> -MODULE_DESCRIPTION("Atmel TouchScreen Driver");
> -MODULE_AUTHOR("Dan Liang <dan.liang@atmel.com>");
> -
> -- 
> 1.8.3.2
> 

-- 
Dmitry

^ permalink raw reply

* Re: [PATCH 04/15] iio: adc: at91_adc: Add support for touchscreens without TSMR
From: Dmitry Torokhov @ 2014-03-05 18:50 UTC (permalink / raw)
  To: Alexandre Belloni
  Cc: Nicolas Ferre, Jonathan Cameron, Jean-Christophe Plagniol-Villard,
	linux-kernel, linux-arm-kernel, linux-iio, linux-input,
	Maxime Ripard, Gregory Clement
In-Reply-To: <1394040940-18246-5-git-send-email-alexandre.belloni@free-electrons.com>

On Wed, Mar 05, 2014 at 06:35:29PM +0100, Alexandre Belloni wrote:
> Old ADCs, as present on the sam9rl and the sam9g45 don't have a TSMR register
> and the touchscreen support should be handled differently.
> 
> Signed-off-by: Alexandre Belloni <alexandre.belloni@free-electrons.com>
> ---
>  arch/arm/mach-at91/include/mach/at91_adc.h |  13 ++
>  drivers/iio/adc/at91_adc.c                 | 199 ++++++++++++++++++++++-------
>  include/linux/platform_data/at91_adc.h     |   8 ++
>  3 files changed, 172 insertions(+), 48 deletions(-)
> 
> diff --git a/arch/arm/mach-at91/include/mach/at91_adc.h b/arch/arm/mach-at91/include/mach/at91_adc.h
> index c287307b9a3b..7d80396346b2 100644
> --- a/arch/arm/mach-at91/include/mach/at91_adc.h
> +++ b/arch/arm/mach-at91/include/mach/at91_adc.h
> @@ -20,6 +20,9 @@
>  #define		AT91_ADC_START		(1 << 1)	/* Start Conversion */
>  
>  #define AT91_ADC_MR		0x04		/* Mode Register */
> +#define		AT91_ADC_TSAMOD		(3 << 0)	/* ADC mode */
> +#define		AT91_ADC_TSAMOD_ADC_ONLY_MODE		(0 << 0)	/* ADC Mode */
> +#define		AT91_ADC_TSAMOD_TS_ONLY_MODE		(1 << 0)	/* Touch Screen Only Mode */
>  #define		AT91_ADC_TRGEN		(1 << 0)	/* Trigger Enable */
>  #define		AT91_ADC_TRGSEL		(7 << 1)	/* Trigger Selection */
>  #define			AT91_ADC_TRGSEL_TC0		(0 << 1)
> @@ -28,6 +31,7 @@
>  #define			AT91_ADC_TRGSEL_EXTERNAL	(6 << 1)
>  #define		AT91_ADC_LOWRES		(1 << 4)	/* Low Resolution */
>  #define		AT91_ADC_SLEEP		(1 << 5)	/* Sleep Mode */
> +#define		AT91_ADC_PENDET		(1 << 6)	/* Pen contact detection enable */
>  #define		AT91_ADC_PRESCAL_9260	(0x3f << 8)	/* Prescalar Rate Selection */
>  #define		AT91_ADC_PRESCAL_9G45	(0xff << 8)
>  #define			AT91_ADC_PRESCAL_(x)	((x) << 8)
> @@ -37,6 +41,12 @@
>  #define			AT91_ADC_STARTUP_(x)	((x) << 16)
>  #define		AT91_ADC_SHTIM		(0xf  << 24)	/* Sample & Hold Time */
>  #define			AT91_ADC_SHTIM_(x)	((x) << 24)
> +#define		AT91_ADC_PENDBC		(0x0f << 28)	/* Pen Debounce time */
> +#define			AT91_ADC_PENDBC_(x)	((x) << 28)
> +
> +#define AT91_ADC_TSR		0x0C
> +#define		AT91_ADC_TSR_SHTIM	(0xf  << 24)	/* Sample & Hold Time */
> +#define			AT91_ADC_TSR_SHTIM_(x)	((x) << 24)
>  
>  #define AT91_ADC_CHER		0x10		/* Channel Enable Register */
>  #define AT91_ADC_CHDR		0x14		/* Channel Disable Register */
> @@ -60,6 +70,8 @@
>  #define AT91_ADC_IER		0x24		/* Interrupt Enable Register */
>  #define AT91_ADC_IDR		0x28		/* Interrupt Disable Register */
>  #define AT91_ADC_IMR		0x2C		/* Interrupt Mask Register */
> +#define		AT91RL_ADC_IER_PEN	(1 << 20)
> +#define		AT91RL_ADC_IER_NOPEN	(1 << 21)
>  #define		AT91_ADC_IER_PEN	(1 << 29)
>  #define		AT91_ADC_IER_NOPEN	(1 << 30)
>  #define		AT91_ADC_IER_XRDY	(1 << 20)
> @@ -102,6 +114,7 @@
>  #define		AT91_ADC_TRGR_TRGPER	(0xffff << 16)
>  #define			AT91_ADC_TRGR_TRGPER_(x)	((x) << 16)
>  #define		AT91_ADC_TRGR_TRGMOD	(0x7 << 0)
> +#define			AT91_ADC_TRGR_NONE		(0 << 0)
>  #define			AT91_ADC_TRGR_MOD_PERIOD_TRIG	(5 << 0)
>  
>  #endif
> diff --git a/drivers/iio/adc/at91_adc.c b/drivers/iio/adc/at91_adc.c
> index 1beae65aef2c..3e92b16e9301 100644
> --- a/drivers/iio/adc/at91_adc.c
> +++ b/drivers/iio/adc/at91_adc.c
> @@ -46,6 +46,10 @@
>  #define TOUCH_SAMPLE_PERIOD_US		2000	/* 2ms */
>  #define TOUCH_PEN_DETECT_DEBOUNCE_US	200
>  
> +#define MAX_RLPOS_BITS         10
> +#define TOUCH_SAMPLE_PERIOD_US_RL      10000   /* 10ms, the SoC can't keep up with 2ms */
> +#define TOUCH_SHTIM                    0xa
> +
>  /**
>   * struct at91_adc_reg_desc - Various informations relative to registers
>   * @channel_base:	Base offset for the channel data registers
> @@ -83,12 +87,6 @@ struct at91_adc_caps {
>  	struct at91_adc_reg_desc registers;
>  };
>  
> -enum atmel_adc_ts_type {
> -	ATMEL_ADC_TOUCHSCREEN_NONE = 0,
> -	ATMEL_ADC_TOUCHSCREEN_4WIRE = 4,
> -	ATMEL_ADC_TOUCHSCREEN_5WIRE = 5,
> -};
> -
>  struct at91_adc_state {
>  	struct clk		*adc_clk;
>  	u16			*buffer;
> @@ -133,6 +131,11 @@ struct at91_adc_state {
>  
>  	u16			ts_sample_period_val;
>  	u32			ts_pressure_threshold;
> +	u16			ts_pendbc;
> +
> +	u8			ts_bufferedmeasure;

bool?

> +	u32			ts_prev_absx;
> +	u32			ts_prev_absy;
>  };
>  
>  static irqreturn_t at91_adc_trigger_handler(int irq, void *p)
> @@ -239,19 +242,68 @@ static int at91_ts_sample(struct at91_adc_state *st)
>  	return 0;
>  }
>  
> -static irqreturn_t at91_adc_interrupt(int irq, void *private)
> +void handle_adc_rl_ts_irq(int irq, struct at91_adc_state *st, u32 status)
> +{
> +	unsigned int reg;
> +
> +	status &= at91_adc_readl(st, AT91_ADC_IMR);
> +	if (status & AT91RL_ADC_IER_PEN) {
> +		/* Disabling pen debounce is required to get a NOPEN irq */
> +		reg = at91_adc_readl(st, AT91_ADC_MR);
> +		reg &= ~AT91_ADC_PENDBC;
> +		at91_adc_writel(st, AT91_ADC_MR, reg);
> +
> +		at91_adc_writel(st, AT91_ADC_IDR, AT91RL_ADC_IER_PEN);
> +		at91_adc_writel(st, AT91_ADC_IER, AT91RL_ADC_IER_NOPEN
> +				| AT91_ADC_EOC(3));
> +		/* Set up period trigger for sampling */
> +		at91_adc_writel(st, st->registers->trigger_register,
> +			AT91_ADC_TRGR_MOD_PERIOD_TRIG |
> +			AT91_ADC_TRGR_TRGPER_(st->ts_sample_period_val));
> +	} else if (status & AT91RL_ADC_IER_NOPEN) {
> +		reg = at91_adc_readl(st, AT91_ADC_MR);
> +		reg |= AT91_ADC_PENDBC_(st->ts_pendbc) & AT91_ADC_PENDBC;
> +		at91_adc_writel(st, AT91_ADC_MR, reg);
> +		at91_adc_writel(st, st->registers->trigger_register,
> +			AT91_ADC_TRGR_NONE);
> +
> +		at91_adc_writel(st, AT91_ADC_IDR, AT91RL_ADC_IER_NOPEN
> +				| AT91_ADC_EOC(3));
> +		at91_adc_writel(st, AT91_ADC_IER, AT91RL_ADC_IER_PEN);
> +		st->ts_bufferedmeasure = 0;

		st->ts_bufferedmeasure = false;

> +		input_report_key(st->ts_input, BTN_TOUCH, 0);
> +		input_sync(st->ts_input);
> +	} else if (status & AT91_ADC_EOC(3)) {
> +		/* Conversion finished */
> +		if (st->ts_bufferedmeasure) {
> +			/* Last measurement is always discarded, since it can
> +			 * be erroneous.
> +			 * Always report previous measurement */

			/*
			 * Multi-line comment.
			 */

> +			input_report_abs(st->ts_input, ABS_X, st->ts_prev_absx);
> +			input_report_abs(st->ts_input, ABS_Y, st->ts_prev_absy);
> +			input_report_key(st->ts_input, BTN_TOUCH, 1);
> +			input_sync(st->ts_input);
> +		} else
> +			st->ts_bufferedmeasure = 1;

		} else {
			st->ts_bufferedmeasure = true;
		}

> +
> +		/* Now make new measurement */
> +		st->ts_prev_absx = at91_adc_readl(st, AT91_ADC_CHAN(st, 3))
> +				   << MAX_RLPOS_BITS;
> +		st->ts_prev_absx /= at91_adc_readl(st, AT91_ADC_CHAN(st, 2));
> +
> +		st->ts_prev_absy = at91_adc_readl(st, AT91_ADC_CHAN(st, 1))
> +				   << MAX_RLPOS_BITS;
> +		st->ts_prev_absy /= at91_adc_readl(st, AT91_ADC_CHAN(st, 0));
> +	}
> +}
> +
> +void handle_adc_9x5_ts_irq(int irq, struct at91_adc_state *st, u32 status)
>  {
> -	struct iio_dev *idev = private;
> -	struct at91_adc_state *st = iio_priv(idev);
> -	u32 status = at91_adc_readl(st, st->registers->status_register);
>  	const uint32_t ts_data_irq_mask =
>  		AT91_ADC_IER_XRDY |
>  		AT91_ADC_IER_YRDY |
>  		AT91_ADC_IER_PRDY;
>  
> -	if (status & st->registers->drdy_mask)
> -		handle_adc_eoc_trigger(irq, idev);
> -
>  	if (status & AT91_ADC_IER_PEN) {
>  		at91_adc_writel(st, AT91_ADC_IDR, AT91_ADC_IER_PEN);
>  		at91_adc_writel(st, AT91_ADC_IER, AT91_ADC_IER_NOPEN |
> @@ -283,6 +335,21 @@ static irqreturn_t at91_adc_interrupt(int irq, void *private)
>  			at91_adc_readl(st, AT91_ADC_TSPRESSR);
>  		}
>  	}
> +}
> +
> +static irqreturn_t at91_adc_interrupt(int irq, void *private)
> +{
> +	struct iio_dev *idev = private;
> +	struct at91_adc_state *st = iio_priv(idev);
> +	u32 status = at91_adc_readl(st, st->registers->status_register);
> +
> +	if (status & st->registers->drdy_mask)
> +		handle_adc_eoc_trigger(irq, idev);
> +
> +	if (st->caps->has_tsmr)

Instead of testing maybe you shoudl have 2 separate IRQ handl3er and
instantiate appropriate one depending on device caps?

> +		handle_adc_9x5_ts_irq(irq, st, status);
> +	else
> +		handle_adc_rl_ts_irq(irq, st, status);
>  
>  	return IRQ_HANDLED;
>  }
> @@ -672,6 +739,8 @@ static int at91_adc_probe_dt_ts(struct device_node *node,
>  		return -EINVAL;
>  	}
>  
> +	if (!st->caps->has_tsmr)
> +		return 0;
>  	prop = 0;
>  	of_property_read_u32(node, "atmel,adc-ts-pressure-threshold", &prop);
>  	st->ts_pressure_threshold = prop;
> @@ -795,6 +864,7 @@ static int at91_adc_probe_pdata(struct at91_adc_state *st,
>  	st->trigger_number = pdata->trigger_number;
>  	st->trigger_list = pdata->trigger_list;
>  	st->registers = &st->caps->registers;
> +	st->touchscreen_type = pdata->touchscreen_type;
>  
>  	return 0;
>  }
> @@ -809,7 +879,10 @@ static int atmel_ts_open(struct input_dev *dev)
>  {
>  	struct at91_adc_state *st = input_get_drvdata(dev);
>  
> -	at91_adc_writel(st, AT91_ADC_IER, AT91_ADC_IER_PEN);
> +	if (st->caps->has_tsmr)
> +		at91_adc_writel(st, AT91_ADC_IER, AT91_ADC_IER_PEN);
> +	else
> +		at91_adc_writel(st, AT91_ADC_IER, AT91RL_ADC_IER_PEN);
>  	return 0;
>  }
>  
> @@ -817,45 +890,61 @@ static void atmel_ts_close(struct input_dev *dev)
>  {
>  	struct at91_adc_state *st = input_get_drvdata(dev);
>  
> -	at91_adc_writel(st, AT91_ADC_IDR, AT91_ADC_IER_PEN);
> +	if (st->caps->has_tsmr)
> +		at91_adc_writel(st, AT91_ADC_IDR, AT91_ADC_IER_PEN);
> +	else
> +		at91_adc_writel(st, AT91_ADC_IDR, AT91RL_ADC_IER_PEN);
>  }
>  
>  static int at91_ts_hw_init(struct at91_adc_state *st, u32 adc_clk_khz)
>  {
> -	u32 reg = 0, pendbc;
> +	u32 reg = 0;
>  	int i = 0;
>  
> -	if (st->touchscreen_type == ATMEL_ADC_TOUCHSCREEN_4WIRE)
> -		reg = AT91_ADC_TSMR_TSMODE_4WIRE_PRESS;
> -	else
> -		reg = AT91_ADC_TSMR_TSMODE_5WIRE;
> -
>  	/* a Pen Detect Debounce Time is necessary for the ADC Touch to avoid
>  	 * pen detect noise.
>  	 * The formula is : Pen Detect Debounce Time = (2 ^ pendbc) / ADCClock
>  	 */
> -	pendbc = round_up(TOUCH_PEN_DETECT_DEBOUNCE_US * adc_clk_khz / 1000, 1);
> +	st->ts_pendbc = round_up(TOUCH_PEN_DETECT_DEBOUNCE_US * adc_clk_khz /
> +				 1000, 1);
>  
> -	while (pendbc >> ++i)
> +	while (st->ts_pendbc >> ++i)
>  		;	/* Empty! Find the shift offset */
> -	if (abs(pendbc - (1 << i)) < abs(pendbc - (1 << (i - 1))))
> -		pendbc = i;
> +	if (abs(st->ts_pendbc - (1 << i)) < abs(st->ts_pendbc - (1 << (i - 1))))
> +		st->ts_pendbc = i;
>  	else
> -		pendbc = i - 1;
> +		st->ts_pendbc = i - 1;
>  
> -	if (st->caps->has_tsmr) {
> -		reg |= AT91_ADC_TSMR_TSAV_(st->caps->ts_filter_average)
> -				& AT91_ADC_TSMR_TSAV;
> -		reg |= AT91_ADC_TSMR_PENDBC_(pendbc) & AT91_ADC_TSMR_PENDBC;
> -		reg |= AT91_ADC_TSMR_NOTSDMA;
> -		reg |= AT91_ADC_TSMR_PENDET_ENA;
> -		reg |= 0x03 << 8;	/* TSFREQ, need bigger than TSAV */
> -
> -		at91_adc_writel(st, AT91_ADC_TSMR, reg);
> -	} else {
> -		/* TODO: for 9g45 which has no TSMR */
> +	if (!st->caps->has_tsmr) {
> +		reg = at91_adc_readl(st, AT91_ADC_MR);
> +		reg |= AT91_ADC_TSAMOD_TS_ONLY_MODE | AT91_ADC_PENDET;
> +
> +		reg |= AT91_ADC_PENDBC_(st->ts_pendbc) & AT91_ADC_PENDBC;
> +		at91_adc_writel(st, AT91_ADC_MR, reg);
> +
> +		reg = AT91_ADC_TSR_SHTIM_(TOUCH_SHTIM) & AT91_ADC_TSR_SHTIM;
> +		at91_adc_writel(st, AT91_ADC_TSR, reg);
> +
> +		st->ts_sample_period_val = round_up((TOUCH_SAMPLE_PERIOD_US_RL *
> +						    adc_clk_khz / 1000) - 1, 1);
> +
> +		return 0;
>  	}
>  
> +	if (st->touchscreen_type == ATMEL_ADC_TOUCHSCREEN_4WIRE)
> +		reg = AT91_ADC_TSMR_TSMODE_4WIRE_PRESS;
> +	else
> +		reg = AT91_ADC_TSMR_TSMODE_5WIRE;
> +
> +	reg |= AT91_ADC_TSMR_TSAV_(st->caps->ts_filter_average)
> +	       & AT91_ADC_TSMR_TSAV;
> +	reg |= AT91_ADC_TSMR_PENDBC_(st->ts_pendbc) & AT91_ADC_TSMR_PENDBC;
> +	reg |= AT91_ADC_TSMR_NOTSDMA;
> +	reg |= AT91_ADC_TSMR_PENDET_ENA;
> +	reg |= 0x03 << 8;	/* TSFREQ, needs to be bigger than TSAV */
> +
> +	at91_adc_writel(st, AT91_ADC_TSMR, reg);
> +
>  	/* Change adc internal resistor value for better pen detection,
>  	 * default value is 100 kOhm.
>  	 * 0 = 200 kOhm, 1 = 150 kOhm, 2 = 100 kOhm, 3 = 50 kOhm
> @@ -864,7 +953,7 @@ static int at91_ts_hw_init(struct at91_adc_state *st, u32 adc_clk_khz)
>  	at91_adc_writel(st, AT91_ADC_ACR, st->caps->ts_pen_detect_sensitivity
>  			& AT91_ADC_ACR_PENDETSENS);
>  
> -	/* Sample Peroid Time = (TRGPER + 1) / ADCClock */
> +	/* Sample Period Time = (TRGPER + 1) / ADCClock */
>  	st->ts_sample_period_val = round_up((TOUCH_SAMPLE_PERIOD_US *
>  			adc_clk_khz / 1000) - 1, 1);
>  
> @@ -893,17 +982,37 @@ static int at91_ts_register(struct at91_adc_state *st,
>  	__set_bit(EV_ABS, input->evbit);
>  	__set_bit(EV_KEY, input->evbit);
>  	__set_bit(BTN_TOUCH, input->keybit);
> -	input_set_abs_params(input, ABS_X, 0, (1 << MAX_POS_BITS) - 1, 0, 0);
> -	input_set_abs_params(input, ABS_Y, 0, (1 << MAX_POS_BITS) - 1, 0, 0);
> -	input_set_abs_params(input, ABS_PRESSURE, 0, 0xffffff, 0, 0);
> +	if (st->caps->has_tsmr) {
> +		input_set_abs_params(input, ABS_X, 0, (1 << MAX_POS_BITS) - 1,
> +				     0, 0);
> +		input_set_abs_params(input, ABS_Y, 0, (1 << MAX_POS_BITS) - 1,
> +				     0, 0);
> +		input_set_abs_params(input, ABS_PRESSURE, 0, 0xffffff, 0, 0);
> +	} else {
> +		if (st->touchscreen_type != ATMEL_ADC_TOUCHSCREEN_4WIRE) {
> +			dev_err(&pdev->dev,
> +				"This touchscreen controller only support 4 wires\n");
> +			ret = -EINVAL;
> +			goto err;
> +		}
> +
> +		input_set_abs_params(input, ABS_X, 0, (1 << MAX_RLPOS_BITS) - 1,
> +				     0, 0);
> +		input_set_abs_params(input, ABS_Y, 0, (1 << MAX_RLPOS_BITS) - 1,
> +				     0, 0);
> +	}
>  
>  	st->ts_input = input;
>  	input_set_drvdata(input, st);
>  
>  	ret = input_register_device(input);
>  	if (ret)
> -		input_free_device(st->ts_input);
> +		goto err;
> +
> +	return ret;
>  
> +err:
> +	input_free_device(st->ts_input);
>  	return ret;
>  }
>  
> @@ -1070,12 +1179,6 @@ static int at91_adc_probe(struct platform_device *pdev)
>  			goto error_disable_adc_clk;
>  		}
>  	} else {
> -		if (!st->caps->has_tsmr) {
> -			dev_err(&pdev->dev, "We don't support non-TSMR adc\n");
> -			ret = -ENODEV;
> -			goto error_disable_adc_clk;
> -		}
> -
>  		ret = at91_ts_register(st, pdev);
>  		if (ret)
>  			goto error_disable_adc_clk;
> diff --git a/include/linux/platform_data/at91_adc.h b/include/linux/platform_data/at91_adc.h
> index fcf73879dbfe..7819fc787731 100644
> --- a/include/linux/platform_data/at91_adc.h
> +++ b/include/linux/platform_data/at91_adc.h
> @@ -7,6 +7,12 @@
>  #ifndef _AT91_ADC_H_
>  #define _AT91_ADC_H_
>  
> +enum atmel_adc_ts_type {
> +	ATMEL_ADC_TOUCHSCREEN_NONE = 0,
> +	ATMEL_ADC_TOUCHSCREEN_4WIRE = 4,
> +	ATMEL_ADC_TOUCHSCREEN_5WIRE = 5,
> +};
> +
>  /**
>   * struct at91_adc_trigger - description of triggers
>   * @name:		name of the trigger advertised to the user
> @@ -28,6 +34,7 @@ struct at91_adc_trigger {
>   * @trigger_number:		Number of triggers available in the ADC
>   * @use_external_triggers:	does the board has external triggers availables
>   * @vref:			Reference voltage for the ADC in millivolts
> + * @touchscreen_type:		If a touchscreen is connected, its type (4 or 5 wires)
>   */
>  struct at91_adc_data {
>  	unsigned long			channels_used;
> @@ -36,6 +43,7 @@ struct at91_adc_data {
>  	u8				trigger_number;
>  	bool				use_external_triggers;
>  	u16				vref;
> +	enum atmel_adc_ts_type		touchscreen_type;
>  };
>  
>  extern void __init at91_add_device_adc(struct at91_adc_data *data);
> -- 
> 1.8.3.2
> 

Thanks.

-- 
Dmitry

^ permalink raw reply

* Re: [PATCH v2] mfd: max8997: use regmap to access registers
From: Dmitry Torokhov @ 2014-03-05 18:54 UTC (permalink / raw)
  To: Robert Baldyga
  Cc: sameo, lee.jones, myungjoo.ham, cw00.choi, cooloney, rpurdie,
	dbaryshkov, dwmw2, lgirdwood, broonie, a.zummo, paul.gortmaker,
	linux-kernel, linux-input, linux-leds, rtc-linux, m.szyprowski,
	k.kozlowski
In-Reply-To: <1394031497-16648-1-git-send-email-r.baldyga@samsung.com>

Hi Robert,

On Wed, Mar 05, 2014 at 03:58:17PM +0100, Robert Baldyga wrote:
>  
> -int max8997_write_reg(struct i2c_client *i2c, u8 reg, u8 value)
> +int max8997_write_reg(struct regmap *map, u8 reg, u8 value)

Why don't you make read/write reg to take struct max8997_dev as argument
instead of regmap? regmap seems to be the current implementation du jur,
but that is core's detail, functions do not need to care.

Thanks.

-- 
Dmitry

^ permalink raw reply

* Re: [PATCH] input synaptics-rmi4: rmi_driver.c storage fix
From: Christopher Heiny @ 2014-03-05 19:40 UTC (permalink / raw)
  To: Jiri Kosina
  Cc: Dmitry Torokhov, Linux Input, Andrew Duggan, Vincent Huang,
	Vivian Ly, Daniel Rosenberg, Linus Walleij, Benjamin Tissoires,
	David Herrmann
In-Reply-To: <alpine.LNX.2.00.1403050951090.30402@pobox.suse.cz>

On 03/05/2014 12:51 AM, Jiri Kosina wrote:
> On Tue, 4 Mar 2014, Christopher Heiny wrote:
>
>> Do not use kfree() on storage allocated with devm_kfree(),
>
> I believe you meant devm_kmalloc() here.

I've been trying for an hour to come up with some witty excuse for that 
brain fart, but came up with nothing but "D'oh!  Thanks!"



^ permalink raw reply

* Re: Re: [PATCH 0/7] mfd: AXP20x: Add support for AXP202 and AXP209
From: Hans de Goede @ 2014-03-05 20:02 UTC (permalink / raw)
  To: linux-sunxi-/JYPxA39Uh5TLH3MbocFFw
  Cc: linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	maxime.ripard-wi1+55ScJUtKEb57/3fJTNBPR1lH4CV8,
	emilio-0Z03zUJReD5OxF6Tv1QG9Q, wens-jdAy2FN1RRM,
	sameo-VuQAYsv1563Yd54FQh9/CA, lee.jones-QSEj5FYQhm4dnm+yROfE0A,
	devicetree-u79uwXL29TY76Z2rM5mHXA,
	dmitry.torokhov-Re5JQEeQqe8AvxtiuMwx3w,
	linux-input-u79uwXL29TY76Z2rM5mHXA,
	linux-doc-u79uwXL29TY76Z2rM5mHXA,
	lgirdwood-Re5JQEeQqe8AvxtiuMwx3w, broonie-DgEjT+Ai2ygdnm+yROfE0A
In-Reply-To: <53123507.6020607-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>

Hi,

On 03/01/2014 08:29 PM, Hans de Goede wrote:
> Hi,
> 
> On 03/01/2014 06:17 PM, Carlo Caione wrote:
>> On Sat, Mar 1, 2014 at 5:56 PM, Hans de Goede <hdegoede-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org> wrote:
>>> Hi Carlo,
>>>
>>> Great work, thanks for all the time you're putting into this!
>>
>> Hi Hans :)
>>
>>> I've 2 questions:
>>>
>>> 1) What dependencies does this patch-set have? Obviously it needs the NMI irq
>>> patches for A20, anything else ?  I no longer see any use of a special flag
>>> for ack on unmask, is that no longer needed ?
>>
>> Yes, the only dependency is on the NMI controller patch.
>> After a discussion with Maxime and Thomas I decided to not push for
>> including the special flag for ack on unmask in the irqchip core but
>> to use the unmask callback as in the v3 version of the NMI controller
>> driver (so no flag needed)
>>
>>> 2) No poweroff functionality ? That would be really great to have.
>>
>> Actually in [PATCH 1/7] I support the poweroff using the pm_power_off hook.
> 
> Ah I missed that, cool.
> 
> I'm doing with sunxi hacking for today, but I'll add these to sunxi-devel
> and them give them a test run tomorrow.

So I've added your patches to my sunxi-devel tree and they work as advertised :)

I've also added dt support for the axp209 to the cubietruck dts file, to avoid
things becoming a copy and paste fest I've introduced a new axp209.dtsi file,
as well as did some fixes to the existing sun?i-a*.dtsi files, see my tree here:
https://github.com/jwrdegoede/linux-sunxi/commits/sunxi-devel

If you agree this is a good idea feel free to steal it all for the next
revision of your patch-set :)

Note that I've still left some copy-paste parts inside the per board dts files,
specifically things which may differ per board, ie we know already that A10
boards will have a different interrupt parent for the interrupt.

Thanks for your work on this!

Regards,

Hans

^ permalink raw reply

* Re: Re: [PATCH 0/7] mfd: AXP20x: Add support for AXP202 and AXP209
From: Carlo Caione @ 2014-03-05 20:46 UTC (permalink / raw)
  To: Hans De Goede
  Cc: linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	maxime.ripard-wi1+55ScJUtKEb57/3fJTNBPR1lH4CV8,
	emilio-0Z03zUJReD5OxF6Tv1QG9Q, wens-jdAy2FN1RRM,
	sameo-VuQAYsv1563Yd54FQh9/CA, lee.jones-QSEj5FYQhm4dnm+yROfE0A,
	devicetree-u79uwXL29TY76Z2rM5mHXA,
	dmitry.torokhov-Re5JQEeQqe8AvxtiuMwx3w,
	linux-input-u79uwXL29TY76Z2rM5mHXA,
	linux-doc-u79uwXL29TY76Z2rM5mHXA,
	lgirdwood-Re5JQEeQqe8AvxtiuMwx3w, broonie-DgEjT+Ai2ygdnm+yROfE0A,
	linux-sunxi-/JYPxA39Uh5TLH3MbocFFw
In-Reply-To: <531782DF.6090209-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>

On Wed, Mar 5, 2014 at 9:02 PM, Hans de Goede <hdegoede-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org> wrote:
>
> So I've added your patches to my sunxi-devel tree and they work as advertised :)

Thank you for keeping the tree updated :)

> I've also added dt support for the axp209 to the cubietruck dts file, to avoid
> things becoming a copy and paste fest I've introduced a new axp209.dtsi file,
> as well as did some fixes to the existing sun?i-a*.dtsi files, see my tree here:
> https://github.com/jwrdegoede/linux-sunxi/commits/sunxi-devel

That was also my idea (creating a new axp20x.dtsi) but it has been
turned down by Maxime and Lee

> If you agree this is a good idea feel free to steal it all for the next
> revision of your patch-set :)

I will do for sure, thanks

> Note that I've still left some copy-paste parts inside the per board dts files,
> specifically things which may differ per board, ie we know already that A10
> boards will have a different interrupt parent for the interrupt.

Yep, no prob.

> Thanks for your work on this!

Thank you!

-- 
Carlo Caione

^ permalink raw reply

* Re: [PATCH 2/4] HID: cp2112: remove the last hid_output_raw_report() call
From: Benjamin Tissoires @ 2014-03-05 21:09 UTC (permalink / raw)
  To: David Barksdale
  Cc: Benjamin Tissoires, Jiri Kosina, David Herrmann,
	linux-input@vger.kernel.org, linux-kernel@vger.kernel.org
In-Reply-To: <ba12abe9-5f40-4351-8dc0-76008931fc0d@email.android.com>

On Wed, Mar 5, 2014 at 1:11 PM, David Barksdale <dbarksdale@uplogix.com> wrote:
> Sorry for the delay, hid_hw_output_report() is the correct function.

No worries and thanks for the tests.

This saves me some time!

Sending the v2 right away.

Cheers,
Benjamin

>
>
> On March 4, 2014 8:18:38 AM CST, Benjamin Tissoires
> <benjamin.tissoires@redhat.com> wrote:
>>
>> On Mar 04 2014 or thereabouts, Jiri Kosina wrote:
>>>
>>>  On Fri, 28 Feb 2014, Benjamin Tissoires wrote:
>>>
>>>>
>>>>  I don't have access to the device, so I copied/pasted the code
>>>>  from hidraw.
>>>>
>>>>  Signed-off-by: Benjamin Tissoires <benjamin.tissoires@redhat.com>
>>>>  ---
>>>>   drivers/hid/hid-cp2112.c | 16 +++++++++++++++-
>>>>   1 file changed, 15 insertions(+), 1 deletion(-)
>>>>
>>>>  diff --git a/drivers/hid/hid-cp2112.c b/drivers/hid/hid-cp2112.c
>>>>  index 860db694..c4f87bd 100644
>>>>  --- a/drivers/hid/hid-cp2112.c
>>>>  +++ b/drivers/hid/hid-cp2112.c
>>>>  @@ -290,7 +290,21 @@ static int cp2112_hid_output(struct hid_device
>>>> *hdev, u8 *data, size_t count,
>>>>    if (!buf)
>>>>     return -ENOMEM;
>>>>
>>>>  - ret = hdev->hid_output_raw_report(hdev, buf, count, report_type);
>>>>  + /* Fixme: test which function is actually called for output reports
>>>> */
>>>
>>>
>>>  I don't completely understand this Fixme (oh, and please spell it as
>>>  'FIXME:' so that we are consistent with all the other instances), could
>>>  you please elaborate?
>>
>>
>> Well, sorry:
>> As I said, this part is a copy/paste of what is in hidraw. However, this
>> just reflect that we don't know how the device actually behave, which is
>> not very elegant. I have currently no clues of which function will be
>> actually called for output reports: hid_hw_output_report() or
>> hid_hw_raw_request(). Once we got the confirmation of which function is
>> called, we could make the path more straightforward.
>>
>> I bought one of these (it may help debugging some Synaptics devices),
>> and I'll receive it by the end of the week. So by next week, we should
>> get the actual code path and remove this FIXME.
>>
>> I need to send a v2 of hid-sony in any cases, so I guess you should not
>> pull these 4 patches right away. If you prefer having this in linux-next,
>> the sooner, I can also send the v2 right away, and we will fix this
>> cp2112 driver next week.
>>
>> Cheers,
>> Benjamin
>>
>>>
>>>  Thanks,
>>>
>>>  --
>>>  Jiri Kosina
>>>  SUSE Labs
>
>
> --
> Sent from my Android device with K-9 Mail. Please excuse my brevity.

^ permalink raw reply

* [PATCH v2 0/4] HID: ll transport cleanup: final round
From: Benjamin Tissoires @ 2014-03-05 21:18 UTC (permalink / raw)
  To: Benjamin Tissoires, Jiri Kosina, David Herrmann, David Barksdale,
	Antonio Ospite, linux-input, linux-kernel

Alright, this is the re-spin of the last round of transport cleanup.

Some minor but important modifications are here, but nothing very enthousiastic.

Thanks for the reviews and the tests so far.

Cheers,
Benjamin

Benjamin Tissoires (4):
  HID: cp2112: remove various hid_out_raw_report calls
  HID: cp2112: remove the last hid_output_raw_report() call
  HID: sony: do not rely on hid_output_raw_report
  HID: remove hid_output_raw_report transport implementations

 drivers/hid/hid-cp2112.c      | 19 +++++++++-----
 drivers/hid/hid-sony.c        | 60 ++++++++++---------------------------------
 drivers/hid/hidraw.c          |  3 ++-
 drivers/hid/i2c-hid/i2c-hid.c | 14 ----------
 drivers/hid/uhid.c            |  1 -
 drivers/hid/usbhid/hid-core.c | 19 +++++---------
 include/linux/hid.h           | 21 ++-------------
 net/bluetooth/hidp/core.c     | 14 ----------
 8 files changed, 36 insertions(+), 115 deletions(-)

-- 
1.8.5.3

^ permalink raw reply

* [PATCH v2 2/4] HID: cp2112: remove the last hid_output_raw_report() call
From: Benjamin Tissoires @ 2014-03-05 21:18 UTC (permalink / raw)
  To: Benjamin Tissoires, Jiri Kosina, David Herrmann, David Barksdale,
	Antonio Ospite, linux-input, linux-kernel
In-Reply-To: <1394054334-20438-1-git-send-email-benjamin.tissoires@redhat.com>

tests have shown that output reports use hid_hw_output_report().

Signed-off-by: Benjamin Tissoires <benjamin.tissoires@redhat.com>
---

changes since v1:
- removed FIXME
- actually use the proper calls and do not guess

 drivers/hid/hid-cp2112.c | 7 ++++++-
 1 file changed, 6 insertions(+), 1 deletion(-)

diff --git a/drivers/hid/hid-cp2112.c b/drivers/hid/hid-cp2112.c
index 860db694..a4fff699 100644
--- a/drivers/hid/hid-cp2112.c
+++ b/drivers/hid/hid-cp2112.c
@@ -290,7 +290,12 @@ static int cp2112_hid_output(struct hid_device *hdev, u8 *data, size_t count,
 	if (!buf)
 		return -ENOMEM;
 
-	ret = hdev->hid_output_raw_report(hdev, buf, count, report_type);
+	if (report_type == HID_OUTPUT_REPORT)
+		ret = hid_hw_output_report(hdev, buf, count);
+	else
+		ret = hid_hw_raw_request(hdev, buf[0], buf, count, report_type,
+				HID_REQ_SET_REPORT);
+
 	kfree(buf);
 	return ret;
 }
-- 
1.8.5.3

^ permalink raw reply related

* [PATCH v2 4/4] HID: remove hid_output_raw_report transport implementations
From: Benjamin Tissoires @ 2014-03-05 21:18 UTC (permalink / raw)
  To: Benjamin Tissoires, Jiri Kosina, David Herrmann, David Barksdale,
	Antonio Ospite, linux-input, linux-kernel
In-Reply-To: <1394054334-20438-1-git-send-email-benjamin.tissoires@redhat.com>

Nobody calls hid_output_raw_report anymore, and nobody should.
We can now remove the various implementation in the different
transport drivers and the declarations.

Signed-off-by: Benjamin Tissoires <benjamin.tissoires@redhat.com>
---

no changes since v1 (what did you expected?)

 drivers/hid/i2c-hid/i2c-hid.c | 14 --------------
 drivers/hid/uhid.c            |  1 -
 drivers/hid/usbhid/hid-core.c | 12 ------------
 include/linux/hid.h           | 19 -------------------
 net/bluetooth/hidp/core.c     | 14 --------------
 5 files changed, 60 deletions(-)

diff --git a/drivers/hid/i2c-hid/i2c-hid.c b/drivers/hid/i2c-hid/i2c-hid.c
index cbd44a7..8c52a07 100644
--- a/drivers/hid/i2c-hid/i2c-hid.c
+++ b/drivers/hid/i2c-hid/i2c-hid.c
@@ -596,19 +596,6 @@ static int i2c_hid_output_raw_report(struct hid_device *hid, __u8 *buf,
 	return ret;
 }
 
-static int __i2c_hid_output_raw_report(struct hid_device *hid, __u8 *buf,
-		size_t count, unsigned char report_type)
-{
-	struct i2c_client *client = hid->driver_data;
-	struct i2c_hid *ihid = i2c_get_clientdata(client);
-	bool data = true; /* SET_REPORT */
-
-	if (report_type == HID_OUTPUT_REPORT)
-		data = le16_to_cpu(ihid->hdesc.wMaxOutputLength) == 0;
-
-	return i2c_hid_output_raw_report(hid, buf, count, report_type, data);
-}
-
 static int i2c_hid_output_report(struct hid_device *hid, __u8 *buf,
 		size_t count)
 {
@@ -1037,7 +1024,6 @@ static int i2c_hid_probe(struct i2c_client *client,
 
 	hid->driver_data = client;
 	hid->ll_driver = &i2c_hid_ll_driver;
-	hid->hid_output_raw_report = __i2c_hid_output_raw_report;
 	hid->dev.parent = &client->dev;
 	ACPI_COMPANION_SET(&hid->dev, ACPI_COMPANION(&client->dev));
 	hid->bus = BUS_I2C;
diff --git a/drivers/hid/uhid.c b/drivers/hid/uhid.c
index 60acee4..7ed79be 100644
--- a/drivers/hid/uhid.c
+++ b/drivers/hid/uhid.c
@@ -400,7 +400,6 @@ static int uhid_dev_create(struct uhid_device *uhid,
 	hid->uniq[63] = 0;
 
 	hid->ll_driver = &uhid_hid_driver;
-	hid->hid_output_raw_report = uhid_hid_output_raw;
 	hid->bus = ev->u.create.bus;
 	hid->vendor = ev->u.create.vendor;
 	hid->product = ev->u.create.product;
diff --git a/drivers/hid/usbhid/hid-core.c b/drivers/hid/usbhid/hid-core.c
index 3bc7cad..7b88f4c 100644
--- a/drivers/hid/usbhid/hid-core.c
+++ b/drivers/hid/usbhid/hid-core.c
@@ -950,17 +950,6 @@ static int usbhid_output_report(struct hid_device *hid, __u8 *buf, size_t count)
 	return ret;
 }
 
-static int usbhid_output_raw_report(struct hid_device *hid, __u8 *buf,
-		size_t count, unsigned char report_type)
-{
-	struct usbhid_device *usbhid = hid->driver_data;
-
-	if (usbhid->urbout && report_type != HID_FEATURE_REPORT)
-		return usbhid_output_report(hid, buf, count);
-
-	return usbhid_set_raw_report(hid, buf[0], buf, count, report_type);
-}
-
 static void usbhid_restart_queues(struct usbhid_device *usbhid)
 {
 	if (usbhid->urbout && !test_bit(HID_OUT_RUNNING, &usbhid->iofl))
@@ -1294,7 +1283,6 @@ static int usbhid_probe(struct usb_interface *intf, const struct usb_device_id *
 
 	usb_set_intfdata(intf, hid);
 	hid->ll_driver = &usb_hid_driver;
-	hid->hid_output_raw_report = usbhid_output_raw_report;
 	hid->ff_init = hid_pidff_init;
 #ifdef CONFIG_USB_HIDDEV
 	hid->hiddev_connect = hiddev_connect;
diff --git a/include/linux/hid.h b/include/linux/hid.h
index 2cd7174..720e3a1 100644
--- a/include/linux/hid.h
+++ b/include/linux/hid.h
@@ -513,9 +513,6 @@ struct hid_device {							/* device report descriptor */
 				  struct hid_usage *, __s32);
 	void (*hiddev_report_event) (struct hid_device *, struct hid_report *);
 
-	/* handler for raw output data, used by hidraw */
-	int (*hid_output_raw_report) (struct hid_device *, __u8 *, size_t, unsigned char);
-
 	/* debugging support via debugfs */
 	unsigned short debug;
 	struct dentry *debug_dir;
@@ -1023,22 +1020,6 @@ static inline int hid_hw_output_report(struct hid_device *hdev, __u8 *buf,
 }
 
 /**
- * hid_output_raw_report - send an output or a feature report to the device
- *
- * @hdev: hid device
- * @buf: raw data to transfer
- * @len: length of buf
- * @report_type: HID_FEATURE_REPORT or HID_OUTPUT_REPORT
- *
- * @return: count of data transfered, negative if error
- */
-static inline int hid_output_raw_report(struct hid_device *hdev, __u8 *buf,
-					size_t len, unsigned char report_type)
-{
-	return hdev->hid_output_raw_report(hdev, buf, len, report_type);
-}
-
-/**
  * hid_hw_idle - send idle request to device
  *
  * @hdev: hid device
diff --git a/net/bluetooth/hidp/core.c b/net/bluetooth/hidp/core.c
index 98e4840..514ddb5 100644
--- a/net/bluetooth/hidp/core.c
+++ b/net/bluetooth/hidp/core.c
@@ -382,18 +382,6 @@ static int hidp_output_report(struct hid_device *hid, __u8 *data, size_t count)
 				      data, count);
 }
 
-static int hidp_output_raw_report(struct hid_device *hid, unsigned char *data,
-		size_t count, unsigned char report_type)
-{
-	if (report_type == HID_OUTPUT_REPORT) {
-		return hidp_output_report(hid, data, count);
-	} else if (report_type != HID_FEATURE_REPORT) {
-		return -EINVAL;
-	}
-
-	return hidp_set_raw_report(hid, data[0], data, count, report_type);
-}
-
 static int hidp_raw_request(struct hid_device *hid, unsigned char reportnum,
 			    __u8 *buf, size_t len, unsigned char rtype,
 			    int reqtype)
@@ -776,8 +764,6 @@ static int hidp_setup_hid(struct hidp_session *session,
 	hid->dev.parent = &session->conn->hcon->dev;
 	hid->ll_driver = &hidp_hid_driver;
 
-	hid->hid_output_raw_report = hidp_output_raw_report;
-
 	/* True if device is blacklisted in drivers/hid/hid-core.c */
 	if (hid_ignore(hid)) {
 		hid_destroy_device(session->hid);
-- 
1.8.5.3

^ permalink raw reply related

* [PATCH v2 1/4] HID: cp2112: remove various hid_out_raw_report calls
From: Benjamin Tissoires @ 2014-03-05 21:18 UTC (permalink / raw)
  To: Benjamin Tissoires, Jiri Kosina, David Herrmann, David Barksdale,
	Antonio Ospite, linux-input, linux-kernel
In-Reply-To: <1394054334-20438-1-git-send-email-benjamin.tissoires@redhat.com>

hid_out_raw_report is going to be obsoleted as it is not part of the
unified HID low level transport documentation
(Documentation/hid/hid-transport.txt)

  hid_output_raw_report(hdev, buf, sizeof(buf), HID_FEATURE_REPORT);
is strictly equivalent to:
  hid_hw_raw_request(hdev, buf[0], buf, sizeof(buf),
		HID_FEATURE_REPORT, HID_REQ_SET_REPORT);

So use the new api.

Signed-off-by: Benjamin Tissoires <benjamin.tissoires@redhat.com>
---

no changes since v1

 drivers/hid/hid-cp2112.c | 12 ++++++------
 1 file changed, 6 insertions(+), 6 deletions(-)

diff --git a/drivers/hid/hid-cp2112.c b/drivers/hid/hid-cp2112.c
index 1025982..860db694 100644
--- a/drivers/hid/hid-cp2112.c
+++ b/drivers/hid/hid-cp2112.c
@@ -185,8 +185,8 @@ static int cp2112_gpio_direction_input(struct gpio_chip *chip, unsigned offset)
 	buf[1] &= ~(1 << offset);
 	buf[2] = gpio_push_pull;
 
-	ret = hdev->hid_output_raw_report(hdev, buf, sizeof(buf),
-					  HID_FEATURE_REPORT);
+	ret = hid_hw_raw_request(hdev, buf[0], buf, sizeof(buf),
+				 HID_FEATURE_REPORT, HID_REQ_SET_REPORT);
 	if (ret < 0) {
 		hid_err(hdev, "error setting GPIO config: %d\n", ret);
 		return ret;
@@ -207,8 +207,8 @@ static void cp2112_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
 	buf[1] = value ? 0xff : 0;
 	buf[2] = 1 << offset;
 
-	ret = hdev->hid_output_raw_report(hdev, buf, sizeof(buf),
-					  HID_FEATURE_REPORT);
+	ret = hid_hw_raw_request(hdev, buf[0], buf, sizeof(buf),
+				 HID_FEATURE_REPORT, HID_REQ_SET_REPORT);
 	if (ret < 0)
 		hid_err(hdev, "error setting GPIO values: %d\n", ret);
 }
@@ -253,8 +253,8 @@ static int cp2112_gpio_direction_output(struct gpio_chip *chip,
 	buf[1] |= 1 << offset;
 	buf[2] = gpio_push_pull;
 
-	ret = hdev->hid_output_raw_report(hdev, buf, sizeof(buf),
-					  HID_FEATURE_REPORT);
+	ret = hid_hw_raw_request(hdev, buf[0], buf, sizeof(buf),
+				 HID_FEATURE_REPORT, HID_REQ_SET_REPORT);
 	if (ret < 0) {
 		hid_err(hdev, "error setting GPIO config: %d\n", ret);
 		return ret;
-- 
1.8.5.3


^ permalink raw reply related

* [PATCH v2 3/4] HID: sony: do not rely on hid_output_raw_report
From: Benjamin Tissoires @ 2014-03-05 21:18 UTC (permalink / raw)
  To: Benjamin Tissoires, Jiri Kosina, David Herrmann, David Barksdale,
	Antonio Ospite, linux-input, linux-kernel
In-Reply-To: <1394054334-20438-1-git-send-email-benjamin.tissoires@redhat.com>

hid_out_raw_report is going to be obsoleted as it is not part of the
unified HID low level transport documentation
(Documentation/hid/hid-transport.txt)

To do so, we need to introduce two new quirks:
* HID_QUIRK_NO_OUTPUT_REPORTS_ON_INTR_EP: this quirks prevents the
  transport driver to use the interrupt channel to send output report
  (and thus force to use HID_REQ_SET_REPORT command)
* HID_QUIRK_SKIP_OUTPUT_REPORT_ID: this one forces usbhid to not
  include the report ID in the buffer it sends to the device through
  HID_REQ_SET_REPORT in case of an output report

This also fixes a regression introduced in commit 3a75b24949a8
(HID: hidraw: replace hid_output_raw_report() calls by appropriates ones).
The hidraw API was not able to communicate with the PS3 SixAxis
controllers in USB mode.

Signed-off-by: Benjamin Tissoires <benjamin.tissoires@redhat.com>
---

changes since v1:
- removed usb.h include
- renamed HID_QUIRK_NO_OUTPUT_REPORTS_ON_INTR_EP
- fix typo

 drivers/hid/hid-sony.c        | 60 ++++++++++---------------------------------
 drivers/hid/hidraw.c          |  3 ++-
 drivers/hid/usbhid/hid-core.c |  7 ++++-
 include/linux/hid.h           |  2 ++
 4 files changed, 24 insertions(+), 48 deletions(-)

diff --git a/drivers/hid/hid-sony.c b/drivers/hid/hid-sony.c
index b5fe65e..4884bb5 100644
--- a/drivers/hid/hid-sony.c
+++ b/drivers/hid/hid-sony.c
@@ -29,7 +29,6 @@
 #include <linux/hid.h>
 #include <linux/module.h>
 #include <linux/slab.h>
-#include <linux/usb.h>
 #include <linux/leds.h>
 #include <linux/power_supply.h>
 #include <linux/spinlock.h>
@@ -1007,45 +1006,6 @@ static int sony_mapping(struct hid_device *hdev, struct hid_input *hi,
 }
 
 /*
- * The Sony Sixaxis does not handle HID Output Reports on the Interrupt EP
- * like it should according to usbhid/hid-core.c::usbhid_output_raw_report()
- * so we need to override that forcing HID Output Reports on the Control EP.
- *
- * There is also another issue about HID Output Reports via USB, the Sixaxis
- * does not want the report_id as part of the data packet, so we have to
- * discard buf[0] when sending the actual control message, even for numbered
- * reports, humpf!
- */
-static int sixaxis_usb_output_raw_report(struct hid_device *hid, __u8 *buf,
-		size_t count, unsigned char report_type)
-{
-	struct usb_interface *intf = to_usb_interface(hid->dev.parent);
-	struct usb_device *dev = interface_to_usbdev(intf);
-	struct usb_host_interface *interface = intf->cur_altsetting;
-	int report_id = buf[0];
-	int ret;
-
-	if (report_type == HID_OUTPUT_REPORT) {
-		/* Don't send the Report ID */
-		buf++;
-		count--;
-	}
-
-	ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
-		HID_REQ_SET_REPORT,
-		USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE,
-		((report_type + 1) << 8) | report_id,
-		interface->desc.bInterfaceNumber, buf, count,
-		USB_CTRL_SET_TIMEOUT);
-
-	/* Count also the Report ID, in case of an Output report. */
-	if (ret > 0 && report_type == HID_OUTPUT_REPORT)
-		ret++;
-
-	return ret;
-}
-
-/*
  * Sending HID_REQ_GET_REPORT changes the operation mode of the ps3 controller
  * to "operational".  Without this, the ps3 controller will not report any
  * events.
@@ -1305,11 +1265,8 @@ static void sixaxis_state_worker(struct work_struct *work)
 	buf[10] |= sc->led_state[2] << 3;
 	buf[10] |= sc->led_state[3] << 4;
 
-	if (sc->quirks & SIXAXIS_CONTROLLER_USB)
-		hid_output_raw_report(sc->hdev, buf, sizeof(buf), HID_OUTPUT_REPORT);
-	else
-		hid_hw_raw_request(sc->hdev, 0x01, buf, sizeof(buf),
-				HID_OUTPUT_REPORT, HID_REQ_SET_REPORT);
+	hid_hw_raw_request(sc->hdev, 0x01, buf, sizeof(buf), HID_OUTPUT_REPORT,
+			HID_REQ_SET_REPORT);
 }
 
 static void dualshock4_state_worker(struct work_struct *work)
@@ -1659,7 +1616,18 @@ static int sony_probe(struct hid_device *hdev, const struct hid_device_id *id)
 	}
 
 	if (sc->quirks & SIXAXIS_CONTROLLER_USB) {
-		hdev->hid_output_raw_report = sixaxis_usb_output_raw_report;
+		/*
+		 * The Sony Sixaxis does not handle HID Output Reports on the
+		 * Interrupt EP like it could, so we need to force HID Output
+		 * Reports to use HID_REQ_SET_REPORT on the Control EP.
+		 *
+		 * There is also another issue about HID Output Reports via USB,
+		 * the Sixaxis does not want the report_id as part of the data
+		 * packet, so we have to discard buf[0] when sending the actual
+		 * control message, even for numbered reports, humpf!
+		 */
+		hdev->quirks |= HID_QUIRK_NO_OUTPUT_REPORTS_ON_INTR_EP;
+		hdev->quirks |= HID_QUIRK_SKIP_OUTPUT_REPORT_ID;
 		ret = sixaxis_set_operational_usb(hdev);
 		sc->worker_initialized = 1;
 		INIT_WORK(&sc->state_worker, sixaxis_state_worker);
diff --git a/drivers/hid/hidraw.c b/drivers/hid/hidraw.c
index 2cc484c..ffa648c 100644
--- a/drivers/hid/hidraw.c
+++ b/drivers/hid/hidraw.c
@@ -149,7 +149,8 @@ static ssize_t hidraw_send_report(struct file *file, const char __user *buffer,
 		goto out_free;
 	}
 
-	if (report_type == HID_OUTPUT_REPORT) {
+	if ((report_type == HID_OUTPUT_REPORT) &&
+	    !(dev->quirks & HID_QUIRK_NO_OUTPUT_REPORTS_ON_INTR_EP)) {
 		ret = hid_hw_output_report(dev, buf, count);
 		/*
 		 * compatibility with old implementation of USB-HID and I2C-HID:
diff --git a/drivers/hid/usbhid/hid-core.c b/drivers/hid/usbhid/hid-core.c
index 0d1d875..3bc7cad 100644
--- a/drivers/hid/usbhid/hid-core.c
+++ b/drivers/hid/usbhid/hid-core.c
@@ -894,7 +894,12 @@ static int usbhid_set_raw_report(struct hid_device *hid, unsigned int reportnum,
 	int ret, skipped_report_id = 0;
 
 	/* Byte 0 is the report number. Report data starts at byte 1.*/
-	buf[0] = reportnum;
+	if ((rtype == HID_OUTPUT_REPORT) &&
+	    (hid->quirks & HID_QUIRK_SKIP_OUTPUT_REPORT_ID))
+		buf[0] = 0;
+	else
+		buf[0] = reportnum;
+
 	if (buf[0] == 0x0) {
 		/* Don't send the Report ID */
 		buf++;
diff --git a/include/linux/hid.h b/include/linux/hid.h
index e224516..2cd7174 100644
--- a/include/linux/hid.h
+++ b/include/linux/hid.h
@@ -290,6 +290,8 @@ struct hid_item {
 #define HID_QUIRK_NO_EMPTY_INPUT		0x00000100
 #define HID_QUIRK_NO_INIT_INPUT_REPORTS		0x00000200
 #define HID_QUIRK_SKIP_OUTPUT_REPORTS		0x00010000
+#define HID_QUIRK_SKIP_OUTPUT_REPORT_ID		0x00020000
+#define HID_QUIRK_NO_OUTPUT_REPORTS_ON_INTR_EP	0x00040000
 #define HID_QUIRK_FULLSPEED_INTERVAL		0x10000000
 #define HID_QUIRK_NO_INIT_REPORTS		0x20000000
 #define HID_QUIRK_NO_IGNORE			0x40000000
-- 
1.8.5.3


^ permalink raw reply related

* [PATCH v1.01] input synaptics-rmi4: rmi_driver.c storage fix
From: Christopher Heiny @ 2014-03-06  1:11 UTC (permalink / raw)
  To: Dmitry Torokhov
  Cc: Linux Input, Christopher Heiny, Andrew Duggan, Vincent Huang,
	Vivian Ly, Daniel Rosenberg, Linus Walleij, Benjamin Tissoires,
	David Herrmann, Jiri Kosina

Do not use kfree() on storage allocated with devm_kzalloc(),
eliminating kernel panics on device removal.

I'm not sure how this eluded all the patching that's been going on over
the past few weeks, but somehow it did.  v1.01 - fix brain hiccup in
the commit message.

Reported-by: Courtney Cavin <courtney.cavin@sonymobile.com>
Reported-by: Dmitry Torokhov <dmitry.torokhov@gmail.com>
Reported-by: Andrew Duggan <aduggan@synaptics.com>
Signed-off-by: Christopher Heiny <cheiny@synaptics.com>
Cc: Dmitry Torokhov <dmitry.torokhov@gmail.com>
Cc: Benjamin Tissoires <benjamin.tissoires@redhat.com>
Cc: Linux Walleij <linus.walleij@linaro.org>
Cc: David Herrmann <dh.herrmann@gmail.com>
Cc: Jiri Kosina <jkosina@suse.cz>

---

 drivers/input/rmi4/rmi_driver.c | 2 --
 1 file changed, 2 deletions(-)

diff --git a/drivers/input/rmi4/rmi_driver.c b/drivers/input/rmi4/rmi_driver.c
index 4406a7f..3552ffb 100644
--- a/drivers/input/rmi4/rmi_driver.c
+++ b/drivers/input/rmi4/rmi_driver.c
@@ -743,7 +743,6 @@ static int rmi_driver_remove(struct device *dev)
 		gpio_free(pdata->attn_gpio);
 
 	kfree(data->irq_status);
-	kfree(data);
 
 	return 0;
 }
@@ -942,7 +941,6 @@ err_destroy_functions:
 err_free_mem:
 	if (data->gpio_held)
 		gpio_free(pdata->attn_gpio);
-	kfree(data);
 	return retval < 0 ? retval : 0;
 }
 

^ permalink raw reply related

* Re: [PATCH v2] mfd: max8997: use regmap to access registers
From: Chanwoo Choi @ 2014-03-06  2:44 UTC (permalink / raw)
  To: Robert Baldyga
  Cc: sameo, lee.jones, myungjoo.ham, dmitry.torokhov, cooloney,
	rpurdie, dbaryshkov, dwmw2, lgirdwood, broonie, a.zummo,
	paul.gortmaker, linux-kernel, linux-input, linux-leds, rtc-linux,
	m.szyprowski, k.kozlowski
In-Reply-To: <1394031497-16648-1-git-send-email-r.baldyga@samsung.com>

This patch has build error as following: 
I added some comment in max8997_irq_init()
At least, you should test kernel build.

drivers/mfd/max8997-irq.c: In function ‘max8997_irq_init’:
drivers/mfd/max8997-irq.c:333:3: error: ‘i2c’ undeclared (first use in this function)
drivers/mfd/max8997-irq.c:333:3: note: each undeclared identifier is reported only once for each function it appears in
make[2]: *** [drivers/mfd/max8997-irq.o] Error 1
make[1]: *** [drivers/mfd] Error 2
make[1]: *** Waiting for unfinished jobs....


Thansk,
Chanwoo CHoi

On 03/05/2014 11:58 PM, Robert Baldyga wrote:
> This patch modifies max8997 driver and each associated function driver,
> to use regmap instead of operating directly on i2c bus. It will allow to
> simplify IRQ handling using regmap-irq.
> 
> Signed-off-by: Robert Baldyga <r.baldyga@samsung.com>
> ---
> 
> Changelog:
> 
> v2:
> - check devm_regmap_init_i2c() return value
> - use proper register maps for muic and haptic registers in functions
>   max8997_freeze() and max8997_restore()
> - fix style problems
> 
> v1: http://www.spinics.net/lists/kernel/msg1700375.html
> 
>  drivers/extcon/extcon-max8997.c     |   17 ++---
>  drivers/input/misc/max8997_haptic.c |   33 ++++-----
>  drivers/leds/leds-max8997.c         |   12 ++--
>  drivers/mfd/max8997-irq.c           |   31 ++++----
>  drivers/mfd/max8997.c               |  133 ++++++++++++++++++++++-------------
>  drivers/power/max8997_charger.c     |   28 ++++----
>  drivers/regulator/max8997.c         |   80 ++++++++++-----------
>  drivers/rtc/rtc-max8997.c           |   51 ++++++++------
>  include/linux/mfd/max8997-private.h |   19 +++--
>  9 files changed, 227 insertions(+), 177 deletions(-)
> 
> diff --git a/drivers/extcon/extcon-max8997.c b/drivers/extcon/extcon-max8997.c
> index 6a00464..9abc614 100644
> --- a/drivers/extcon/extcon-max8997.c
> +++ b/drivers/extcon/extcon-max8997.c
> @@ -116,7 +116,7 @@ enum max8997_muic_charger_type {
>  
>  struct max8997_muic_info {
>  	struct device *dev;
> -	struct i2c_client *muic;
> +	struct max8997_dev *max8997;
>  	struct extcon_dev *edev;
>  	int prev_cable_type;
>  	int prev_chg_type;
> @@ -190,7 +190,7 @@ static int max8997_muic_set_debounce_time(struct max8997_muic_info *info,
>  	case ADC_DEBOUNCE_TIME_10MS:
>  	case ADC_DEBOUNCE_TIME_25MS:
>  	case ADC_DEBOUNCE_TIME_38_62MS:
> -		ret = max8997_update_reg(info->muic,
> +		ret = max8997_update_reg(info->max8997->regmap_muic,
>  					  MAX8997_MUIC_REG_CONTROL3,
>  					  time << CONTROL3_ADCDBSET_SHIFT,
>  					  CONTROL3_ADCDBSET_MASK);
> @@ -228,7 +228,7 @@ static int max8997_muic_set_path(struct max8997_muic_info *info,
>  	else
>  		ctrl1 = CONTROL1_SW_OPEN;
>  
> -	ret = max8997_update_reg(info->muic,
> +	ret = max8997_update_reg(info->max8997->regmap_muic,
>  			MAX8997_MUIC_REG_CONTROL1, ctrl1, COMP_SW_MASK);
>  	if (ret < 0) {
>  		dev_err(info->dev, "failed to update MUIC register\n");
> @@ -240,7 +240,7 @@ static int max8997_muic_set_path(struct max8997_muic_info *info,
>  	else
>  		ctrl2 |= CONTROL2_LOWPWR_MASK;	/* LowPwr=1, CPEn=0 */
>  
> -	ret = max8997_update_reg(info->muic,
> +	ret = max8997_update_reg(info->max8997->regmap_muic,
>  			MAX8997_MUIC_REG_CONTROL2, ctrl2,
>  			CONTROL2_LOWPWR_MASK | CONTROL2_CPEN_MASK);
>  	if (ret < 0) {
> @@ -543,7 +543,8 @@ static void max8997_muic_irq_work(struct work_struct *work)
>  		if (info->irq == muic_irqs[i].virq)
>  			irq_type = muic_irqs[i].irq;
>  
> -	ret = max8997_bulk_read(info->muic, MAX8997_MUIC_REG_STATUS1,
> +	ret = max8997_bulk_read(info->max8997->regmap_muic,
> +				MAX8997_MUIC_REG_STATUS1,
>  				2, info->status);
>  	if (ret) {
>  		dev_err(info->dev, "failed to read muic register\n");
> @@ -605,7 +606,7 @@ static int max8997_muic_detect_dev(struct max8997_muic_info *info)
>  	mutex_lock(&info->mutex);
>  
>  	/* Read STATUSx register to detect accessory */
> -	ret = max8997_bulk_read(info->muic,
> +	ret = max8997_bulk_read(info->max8997->regmap_muic,
>  			MAX8997_MUIC_REG_STATUS1, 2, info->status);
>  	if (ret) {
>  		dev_err(info->dev, "failed to read MUIC register\n");
> @@ -667,7 +668,7 @@ static int max8997_muic_probe(struct platform_device *pdev)
>  	}
>  
>  	info->dev = &pdev->dev;
> -	info->muic = max8997->muic;
> +	info->max8997 = max8997;
>  
>  	platform_set_drvdata(pdev, info);
>  	mutex_init(&info->mutex);
> @@ -721,7 +722,7 @@ static int max8997_muic_probe(struct platform_device *pdev)
>  
>  		/* Initialize registers according to platform data */
>  		for (i = 0; i < muic_pdata->num_init_data; i++) {
> -			max8997_write_reg(info->muic,
> +			max8997_write_reg(info->max8997->regmap_muic,
>  					muic_pdata->init_data[i].addr,
>  					muic_pdata->init_data[i].data);
>  		}
> diff --git a/drivers/input/misc/max8997_haptic.c b/drivers/input/misc/max8997_haptic.c
> index 1fea548..bce1f0f 100644
> --- a/drivers/input/misc/max8997_haptic.c
> +++ b/drivers/input/misc/max8997_haptic.c
> @@ -45,7 +45,7 @@
>  
>  struct max8997_haptic {
>  	struct device *dev;
> -	struct i2c_client *client;
> +	struct max8997_dev *max8997;
>  	struct input_dev *input_dev;
>  	struct regulator *regulator;
>  
> @@ -86,19 +86,19 @@ static int max8997_haptic_set_duty_cycle(struct max8997_haptic *chip)
>  		}
>  		switch (chip->internal_mode_pattern) {
>  		case 0:
> -			max8997_write_reg(chip->client,
> +			max8997_write_reg(chip->max8997->regmap_haptic,
>  				MAX8997_HAPTIC_REG_SIGPWMDC1, duty_index);
>  			break;
>  		case 1:
> -			max8997_write_reg(chip->client,
> +			max8997_write_reg(chip->max8997->regmap_haptic,
>  				MAX8997_HAPTIC_REG_SIGPWMDC2, duty_index);
>  			break;
>  		case 2:
> -			max8997_write_reg(chip->client,
> +			max8997_write_reg(chip->max8997->regmap_haptic,
>  				MAX8997_HAPTIC_REG_SIGPWMDC3, duty_index);
>  			break;
>  		case 3:
> -			max8997_write_reg(chip->client,
> +			max8997_write_reg(chip->max8997->regmap_haptic,
>  				MAX8997_HAPTIC_REG_SIGPWMDC4, duty_index);
>  			break;
>  		default:
> @@ -115,50 +115,51 @@ static void max8997_haptic_configure(struct max8997_haptic *chip)
>  	value = chip->type << MAX8997_MOTOR_TYPE_SHIFT |
>  		chip->enabled << MAX8997_ENABLE_SHIFT |
>  		chip->mode << MAX8997_MODE_SHIFT | chip->pwm_divisor;
> -	max8997_write_reg(chip->client, MAX8997_HAPTIC_REG_CONF2, value);
> +	max8997_write_reg(chip->max8997->regmap_haptic,
> +		MAX8997_HAPTIC_REG_CONF2, value);
>  
>  	if (chip->mode == MAX8997_INTERNAL_MODE && chip->enabled) {
>  		value = chip->internal_mode_pattern << MAX8997_CYCLE_SHIFT |
>  			chip->internal_mode_pattern << MAX8997_SIG_PERIOD_SHIFT |
>  			chip->internal_mode_pattern << MAX8997_SIG_DUTY_SHIFT |
>  			chip->internal_mode_pattern << MAX8997_PWM_DUTY_SHIFT;
> -		max8997_write_reg(chip->client,
> +		max8997_write_reg(chip->max8997->regmap_haptic,
>  			MAX8997_HAPTIC_REG_DRVCONF, value);
>  
>  		switch (chip->internal_mode_pattern) {
>  		case 0:
>  			value = chip->pattern_cycle << 4;
> -			max8997_write_reg(chip->client,
> +			max8997_write_reg(chip->max8997->regmap_haptic,
>  				MAX8997_HAPTIC_REG_CYCLECONF1, value);
>  			value = chip->pattern_signal_period;
> -			max8997_write_reg(chip->client,
> +			max8997_write_reg(chip->max8997->regmap_haptic,
>  				MAX8997_HAPTIC_REG_SIGCONF1, value);
>  			break;
>  
>  		case 1:
>  			value = chip->pattern_cycle;
> -			max8997_write_reg(chip->client,
> +			max8997_write_reg(chip->max8997->regmap_haptic,
>  				MAX8997_HAPTIC_REG_CYCLECONF1, value);
>  			value = chip->pattern_signal_period;
> -			max8997_write_reg(chip->client,
> +			max8997_write_reg(chip->max8997->regmap_haptic,
>  				MAX8997_HAPTIC_REG_SIGCONF2, value);
>  			break;
>  
>  		case 2:
>  			value = chip->pattern_cycle << 4;
> -			max8997_write_reg(chip->client,
> +			max8997_write_reg(chip->max8997->regmap_haptic,
>  				MAX8997_HAPTIC_REG_CYCLECONF2, value);
>  			value = chip->pattern_signal_period;
> -			max8997_write_reg(chip->client,
> +			max8997_write_reg(chip->max8997->regmap_haptic,
>  				MAX8997_HAPTIC_REG_SIGCONF3, value);
>  			break;
>  
>  		case 3:
>  			value = chip->pattern_cycle;
> -			max8997_write_reg(chip->client,
> +			max8997_write_reg(chip->max8997->regmap_haptic,
>  				MAX8997_HAPTIC_REG_CYCLECONF2, value);
>  			value = chip->pattern_signal_period;
> -			max8997_write_reg(chip->client,
> +			max8997_write_reg(chip->max8997->regmap_haptic,
>  				MAX8997_HAPTIC_REG_SIGCONF4, value);
>  			break;
>  
> @@ -267,7 +268,7 @@ static int max8997_haptic_probe(struct platform_device *pdev)
>  	INIT_WORK(&chip->work, max8997_haptic_play_effect_work);
>  	mutex_init(&chip->mutex);
>  
> -	chip->client = iodev->haptic;
> +	chip->max8997 = iodev;
>  	chip->dev = &pdev->dev;
>  	chip->input_dev = input_dev;
>  	chip->pwm_period = haptic_pdata->pwm_period;
> diff --git a/drivers/leds/leds-max8997.c b/drivers/leds/leds-max8997.c
> index f449a8b..a6b8696 100644
> --- a/drivers/leds/leds-max8997.c
> +++ b/drivers/leds/leds-max8997.c
> @@ -53,7 +53,6 @@ static void max8997_led_set_mode(struct max8997_led *led,
>  			enum max8997_led_mode mode)
>  {
>  	int ret;
> -	struct i2c_client *client = led->iodev->i2c;
>  	u8 mask = 0, val;
>  
>  	switch (mode) {
> @@ -89,8 +88,8 @@ static void max8997_led_set_mode(struct max8997_led *led,
>  	}
>  
>  	if (mask) {
> -		ret = max8997_update_reg(client, MAX8997_REG_LEN_CNTL, val,
> -					 mask);
> +		ret = max8997_update_reg(led->iodev->regmap,
> +					MAX8997_REG_LEN_CNTL, val, mask);
>  		if (ret)
>  			dev_err(led->iodev->dev,
>  				"failed to update register(%d)\n", ret);
> @@ -102,7 +101,6 @@ static void max8997_led_set_mode(struct max8997_led *led,
>  static void max8997_led_enable(struct max8997_led *led, bool enable)
>  {
>  	int ret;
> -	struct i2c_client *client = led->iodev->i2c;
>  	u8 val = 0, mask = MAX8997_LED_BOOST_ENABLE_MASK;
>  
>  	if (led->enabled == enable)
> @@ -110,7 +108,8 @@ static void max8997_led_enable(struct max8997_led *led, bool enable)
>  
>  	val = enable ? MAX8997_LED_BOOST_ENABLE_MASK : 0;
>  
> -	ret = max8997_update_reg(client, MAX8997_REG_BOOST_CNTL, val, mask);
> +	ret = max8997_update_reg(led->iodev->regmap,
> +				MAX8997_REG_BOOST_CNTL, val, mask);
>  	if (ret)
>  		dev_err(led->iodev->dev,
>  			"failed to update register(%d)\n", ret);
> @@ -122,7 +121,6 @@ static void max8997_led_set_current(struct max8997_led *led,
>  				enum led_brightness value)
>  {
>  	int ret;
> -	struct i2c_client *client = led->iodev->i2c;
>  	u8 val = 0, mask = 0, reg = 0;
>  
>  	switch (led->led_mode) {
> @@ -143,7 +141,7 @@ static void max8997_led_set_current(struct max8997_led *led,
>  	}
>  
>  	if (mask) {
> -		ret = max8997_update_reg(client, reg, val, mask);
> +		ret = max8997_update_reg(led->iodev->regmap, reg, val, mask);
>  		if (ret)
>  			dev_err(led->iodev->dev,
>  				"failed to update register(%d)\n", ret);
> diff --git a/drivers/mfd/max8997-irq.c b/drivers/mfd/max8997-irq.c
> index 43fa614..05d3b87 100644
> --- a/drivers/mfd/max8997-irq.c
> +++ b/drivers/mfd/max8997-irq.c
> @@ -124,15 +124,20 @@ static void max8997_irq_sync_unlock(struct irq_data *data)
>  	int i;
>  
>  	for (i = 0; i < MAX8997_IRQ_GROUP_NR; i++) {
> +		struct regmap *map;
>  		u8 mask_reg = max8997_mask_reg[i];
> -		struct i2c_client *i2c = get_i2c(max8997, i);
> +
> +		if (i >= MUIC_INT1 && i <= MUIC_INT3)
> +			map = max8997->regmap_muic;
> +		else
> +			map = max8997->regmap;
>  
>  		if (mask_reg == MAX8997_REG_INVALID ||
> -				IS_ERR_OR_NULL(i2c))
> +				IS_ERR_OR_NULL(map))
>  			continue;
>  		max8997->irq_masks_cache[i] = max8997->irq_masks_cur[i];
>  
> -		max8997_write_reg(i2c, max8997_mask_reg[i],
> +		max8997_write_reg(map, max8997_mask_reg[i],
>  				max8997->irq_masks_cur[i]);
>  	}
>  
> @@ -185,7 +190,7 @@ static irqreturn_t max8997_irq_thread(int irq, void *data)
>  	int ret;
>  	int i, cur_irq;
>  
> -	ret = max8997_read_reg(max8997->i2c, MAX8997_REG_INTSRC, &irq_src);
> +	ret = max8997_read_reg(max8997->regmap, MAX8997_REG_INTSRC, &irq_src);
>  	if (ret < 0) {
>  		dev_err(max8997->dev, "Failed to read interrupt source: %d\n",
>  				ret);
> @@ -194,7 +199,7 @@ static irqreturn_t max8997_irq_thread(int irq, void *data)
>  
>  	if (irq_src & MAX8997_IRQSRC_PMIC) {
>  		/* PMIC INT1 ~ INT4 */
> -		max8997_bulk_read(max8997->i2c, MAX8997_REG_INT1, 4,
> +		max8997_bulk_read(max8997->regmap, MAX8997_REG_INT1, 4,
>  				&irq_reg[PMIC_INT1]);
>  	}
>  	if (irq_src & MAX8997_IRQSRC_FUELGAUGE) {
> @@ -215,8 +220,8 @@ static irqreturn_t max8997_irq_thread(int irq, void *data)
>  	}
>  	if (irq_src & MAX8997_IRQSRC_MUIC) {
>  		/* MUIC INT1 ~ INT3 */
> -		max8997_bulk_read(max8997->muic, MAX8997_MUIC_REG_INT1, 3,
> -				&irq_reg[MUIC_INT1]);
> +		max8997_bulk_read(max8997->regmap_muic,
> +				MAX8997_MUIC_REG_INT1, 3, &irq_reg[MUIC_INT1]);
>  	}
>  	if (irq_src & MAX8997_IRQSRC_GPIO) {
>  		/* GPIO Interrupt */
> @@ -225,7 +230,7 @@ static irqreturn_t max8997_irq_thread(int irq, void *data)
>  		irq_reg[GPIO_LOW] = 0;
>  		irq_reg[GPIO_HI] = 0;
>  
> -		max8997_bulk_read(max8997->i2c, MAX8997_REG_GPIOCNTL1,
> +		max8997_bulk_read(max8997->regmap, MAX8997_REG_GPIOCNTL1,
>  				MAX8997_NUM_GPIO, gpio_info);
>  		for (i = 0; i < MAX8997_NUM_GPIO; i++) {
>  			bool interrupt = false;
> @@ -260,7 +265,7 @@ static irqreturn_t max8997_irq_thread(int irq, void *data)
>  	}
>  	if (irq_src & MAX8997_IRQSRC_FLASH) {
>  		/* Flash Status Interrupt */
> -		ret = max8997_read_reg(max8997->i2c, MAX8997_REG_FLASHSTATUS,
> +		ret = max8997_read_reg(max8997->regmap, MAX8997_REG_FLASHSTATUS,
>  				&irq_reg[FLASH_STATUS]);
>  	}
>  
> @@ -323,22 +328,20 @@ int max8997_irq_init(struct max8997_dev *max8997)
>  
>  	/* Mask individual interrupt sources */
>  	for (i = 0; i < MAX8997_IRQ_GROUP_NR; i++) {
> -		struct i2c_client *i2c;
> -

If you delete i2c instance, this patch happen build error.

>  		max8997->irq_masks_cur[i] = 0xff;
>  		max8997->irq_masks_cache[i] = 0xff;
>  		i2c = get_i2c(max8997, i);

This line need 'i2c' instance.

>  
> -		if (IS_ERR_OR_NULL(i2c))
> +		if (IS_ERR_OR_NULL(max8997->regmap))
>  			continue;
>  		if (max8997_mask_reg[i] == MAX8997_REG_INVALID)
>  			continue;
>  
> -		max8997_write_reg(i2c, max8997_mask_reg[i], 0xff);
> +		max8997_write_reg(max8997->regmap, max8997_mask_reg[i], 0xff);
>  	}
>  
>  	for (i = 0; i < MAX8997_NUM_GPIO; i++) {
> -		max8997->gpio_status[i] = (max8997_read_reg(max8997->i2c,
> +		max8997->gpio_status[i] = (max8997_read_reg(max8997->regmap,
>  						MAX8997_REG_GPIOCNTL1 + i,
>  						&val)
>  					& MAX8997_GPIO_DATA_MASK) ?
> diff --git a/drivers/mfd/max8997.c b/drivers/mfd/max8997.c
> index be88a3b..590e368 100644
> --- a/drivers/mfd/max8997.c
> +++ b/drivers/mfd/max8997.c
> @@ -33,6 +33,7 @@
>  #include <linux/mfd/core.h>
>  #include <linux/mfd/max8997.h>
>  #include <linux/mfd/max8997-private.h>
> +#include <linux/regmap.h>
>  
>  #define I2C_ADDR_PMIC	(0xCC >> 1)
>  #define I2C_ADDR_MUIC	(0x4A >> 1)
> @@ -57,82 +58,82 @@ static struct of_device_id max8997_pmic_dt_match[] = {
>  };
>  #endif
>  
> -int max8997_read_reg(struct i2c_client *i2c, u8 reg, u8 *dest)
> +int max8997_read_reg(struct regmap *map, u8 reg, u8 *dest)
>  {
> -	struct max8997_dev *max8997 = i2c_get_clientdata(i2c);
> +	unsigned int val;
>  	int ret;
>  
> -	mutex_lock(&max8997->iolock);
> -	ret = i2c_smbus_read_byte_data(i2c, reg);
> -	mutex_unlock(&max8997->iolock);
> -	if (ret < 0)
> -		return ret;
> +	ret = regmap_read(map, reg, &val);
> +	*dest = val;
>  
> -	ret &= 0xff;
> -	*dest = ret;
> -	return 0;
> +	return ret;
>  }
>  EXPORT_SYMBOL_GPL(max8997_read_reg);
>  
> -int max8997_bulk_read(struct i2c_client *i2c, u8 reg, int count, u8 *buf)
> +int max8997_bulk_read(struct regmap *map, u8 reg, int count, u8 *buf)
>  {
> -	struct max8997_dev *max8997 = i2c_get_clientdata(i2c);
>  	int ret;
>  
> -	mutex_lock(&max8997->iolock);
> -	ret = i2c_smbus_read_i2c_block_data(i2c, reg, count, buf);
> -	mutex_unlock(&max8997->iolock);
> -	if (ret < 0)
> -		return ret;
> +	ret = regmap_bulk_read(map, reg, buf, count);
>  
> -	return 0;
> +	return ret;
>  }
>  EXPORT_SYMBOL_GPL(max8997_bulk_read);
>  
> -int max8997_write_reg(struct i2c_client *i2c, u8 reg, u8 value)
> +int max8997_write_reg(struct regmap *map, u8 reg, u8 value)
>  {
> -	struct max8997_dev *max8997 = i2c_get_clientdata(i2c);
>  	int ret;
>  
> -	mutex_lock(&max8997->iolock);
> -	ret = i2c_smbus_write_byte_data(i2c, reg, value);
> -	mutex_unlock(&max8997->iolock);
> +	ret = regmap_write(map, reg, value);
> +
>  	return ret;
>  }
>  EXPORT_SYMBOL_GPL(max8997_write_reg);
>  
> -int max8997_bulk_write(struct i2c_client *i2c, u8 reg, int count, u8 *buf)
> +int max8997_bulk_write(struct regmap *map, u8 reg, int count, u8 *buf)
>  {
> -	struct max8997_dev *max8997 = i2c_get_clientdata(i2c);
>  	int ret;
>  
> -	mutex_lock(&max8997->iolock);
> -	ret = i2c_smbus_write_i2c_block_data(i2c, reg, count, buf);
> -	mutex_unlock(&max8997->iolock);
> -	if (ret < 0)
> -		return ret;
> +	ret = regmap_bulk_write(map, reg, buf, count);
>  
> -	return 0;
> +	return ret;
>  }
>  EXPORT_SYMBOL_GPL(max8997_bulk_write);
>  
> -int max8997_update_reg(struct i2c_client *i2c, u8 reg, u8 val, u8 mask)
> +int max8997_update_reg(struct regmap *map, u8 reg, u8 val, u8 mask)
>  {
> -	struct max8997_dev *max8997 = i2c_get_clientdata(i2c);
>  	int ret;
>  
> -	mutex_lock(&max8997->iolock);
> -	ret = i2c_smbus_read_byte_data(i2c, reg);
> -	if (ret >= 0) {
> -		u8 old_val = ret & 0xff;
> -		u8 new_val = (val & mask) | (old_val & (~mask));
> -		ret = i2c_smbus_write_byte_data(i2c, reg, new_val);
> -	}
> -	mutex_unlock(&max8997->iolock);
> +	ret = regmap_update_bits(map, reg, mask, val);
> +
>  	return ret;
>  }
>  EXPORT_SYMBOL_GPL(max8997_update_reg);
>  
> +static const struct regmap_config max8997_regmap_config = {
> +	.reg_bits = 8,
> +	.val_bits = 8,
> +	.max_register = MAX8997_REG_PMIC_END,
> +};
> +
> +static const struct regmap_config max8997_regmap_rtc_config = {
> +	.reg_bits = 8,
> +	.val_bits = 8,
> +	.max_register = MAX8997_RTC_REG_END,
> +};
> +
> +static const struct regmap_config max8997_regmap_haptic_config = {
> +	.reg_bits = 8,
> +	.val_bits = 8,
> +	.max_register = MAX8997_HAPTIC_REG_END,
> +};
> +
> +static const struct regmap_config max8997_regmap_muic_config = {
> +	.reg_bits = 8,
> +	.val_bits = 8,
> +	.max_register = MAX8997_MUIC_REG_END,
> +};
> +
>  /*
>   * Only the common platform data elements for max8997 are parsed here from the
>   * device tree. Other sub-modules of max8997 such as pmic, rtc and others have
> @@ -202,6 +203,14 @@ static int max8997_i2c_probe(struct i2c_client *i2c,
>  	if (!pdata)
>  		return ret;
>  
> +	max8997->regmap = devm_regmap_init_i2c(i2c, &max8997_regmap_config);
> +	if (IS_ERR(max8997->regmap)) {
> +		ret = PTR_ERR(max8997->regmap);
> +		dev_err(max8997->dev, "failed to allocate register map: %d\n",
> +				ret);
> +		return ret;
> +	}
> +
>  	max8997->pdata = pdata;
>  	max8997->ono = pdata->ono;
>  
> @@ -209,11 +218,40 @@ static int max8997_i2c_probe(struct i2c_client *i2c,
>  
>  	max8997->rtc = i2c_new_dummy(i2c->adapter, I2C_ADDR_RTC);
>  	i2c_set_clientdata(max8997->rtc, max8997);
> +
>  	max8997->haptic = i2c_new_dummy(i2c->adapter, I2C_ADDR_HAPTIC);
>  	i2c_set_clientdata(max8997->haptic, max8997);
> +
>  	max8997->muic = i2c_new_dummy(i2c->adapter, I2C_ADDR_MUIC);
>  	i2c_set_clientdata(max8997->muic, max8997);
>  
> +	max8997->regmap_rtc = devm_regmap_init_i2c(max8997->rtc,
> +					&max8997_regmap_rtc_config);
> +	if (IS_ERR(max8997->regmap_rtc)) {
> +		ret = PTR_ERR(max8997->regmap_rtc);
> +		dev_err(max8997->dev,
> +				"failed to allocate register map: %d\n", ret);
> +		goto err_regmap;
> +	}
> +
> +	max8997->regmap_haptic = devm_regmap_init_i2c(max8997->haptic,
> +					&max8997_regmap_haptic_config);
> +	if (IS_ERR(max8997->regmap_haptic)) {
> +		ret = PTR_ERR(max8997->regmap_haptic);
> +		dev_err(max8997->dev,
> +				"failed to allocate register map: %d\n", ret);
> +		goto err_regmap;
> +	}
> +
> +	max8997->regmap_muic = devm_regmap_init_i2c(max8997->muic,
> +					&max8997_regmap_muic_config);
> +	if (IS_ERR(max8997->regmap_muic)) {
> +		ret = PTR_ERR(max8997->regmap_muic);
> +		dev_err(max8997->dev,
> +				"failed to allocate register map: %d\n", ret);
> +		goto err_regmap;
> +	}
> +
>  	pm_runtime_set_active(max8997->dev);
>  
>  	max8997_irq_init(max8997);
> @@ -238,6 +276,7 @@ static int max8997_i2c_probe(struct i2c_client *i2c,
>  
>  err_mfd:
>  	mfd_remove_devices(max8997->dev);
> +err_regmap:
>  	i2c_unregister_device(max8997->muic);
>  	i2c_unregister_device(max8997->haptic);
>  	i2c_unregister_device(max8997->rtc);
> @@ -423,15 +462,15 @@ static int max8997_freeze(struct device *dev)
>  	int i;
>  
>  	for (i = 0; i < ARRAY_SIZE(max8997_dumpaddr_pmic); i++)
> -		max8997_read_reg(i2c, max8997_dumpaddr_pmic[i],
> +		max8997_read_reg(max8997->regmap, max8997_dumpaddr_pmic[i],
>  				&max8997->reg_dump[i]);
>  
>  	for (i = 0; i < ARRAY_SIZE(max8997_dumpaddr_muic); i++)
> -		max8997_read_reg(i2c, max8997_dumpaddr_muic[i],
> +		max8997_read_reg(max8997->regmap_muic, max8997_dumpaddr_muic[i],
>  				&max8997->reg_dump[i + MAX8997_REG_PMIC_END]);
>  
>  	for (i = 0; i < ARRAY_SIZE(max8997_dumpaddr_haptic); i++)
> -		max8997_read_reg(i2c, max8997_dumpaddr_haptic[i],
> +		max8997_read_reg(max8997->regmap_haptic, max8997_dumpaddr_haptic[i],
>  				&max8997->reg_dump[i + MAX8997_REG_PMIC_END +
>  				MAX8997_MUIC_REG_END]);
>  
> @@ -445,15 +484,15 @@ static int max8997_restore(struct device *dev)
>  	int i;
>  
>  	for (i = 0; i < ARRAY_SIZE(max8997_dumpaddr_pmic); i++)
> -		max8997_write_reg(i2c, max8997_dumpaddr_pmic[i],
> +		max8997_write_reg(max8997->regmap, max8997_dumpaddr_pmic[i],
>  				max8997->reg_dump[i]);
>  
>  	for (i = 0; i < ARRAY_SIZE(max8997_dumpaddr_muic); i++)
> -		max8997_write_reg(i2c, max8997_dumpaddr_muic[i],
> +		max8997_write_reg(max8997->regmap_muic, max8997_dumpaddr_muic[i],
>  				max8997->reg_dump[i + MAX8997_REG_PMIC_END]);
>  
>  	for (i = 0; i < ARRAY_SIZE(max8997_dumpaddr_haptic); i++)
> -		max8997_write_reg(i2c, max8997_dumpaddr_haptic[i],
> +		max8997_write_reg(max8997->regmap_haptic, max8997_dumpaddr_haptic[i],
>  				max8997->reg_dump[i + MAX8997_REG_PMIC_END +
>  				MAX8997_MUIC_REG_END]);
>  
> diff --git a/drivers/power/max8997_charger.c b/drivers/power/max8997_charger.c
> index 4bdedfe..027e9bf 100644
> --- a/drivers/power/max8997_charger.c
> +++ b/drivers/power/max8997_charger.c
> @@ -46,14 +46,14 @@ static int max8997_battery_get_property(struct power_supply *psy,
>  {
>  	struct charger_data *charger = container_of(psy,
>  			struct charger_data, battery);
> -	struct i2c_client *i2c = charger->iodev->i2c;
>  	int ret;
>  	u8 reg;
>  
>  	switch (psp) {
>  	case POWER_SUPPLY_PROP_STATUS:
>  		val->intval = 0;
> -		ret = max8997_read_reg(i2c, MAX8997_REG_STATUS4, &reg);
> +		ret = max8997_read_reg(charger->iodev->regmap,
> +				MAX8997_REG_STATUS4, &reg);
>  		if (ret)
>  			return ret;
>  		if ((reg & (1 << 0)) == 0x1)
> @@ -62,7 +62,8 @@ static int max8997_battery_get_property(struct power_supply *psy,
>  		break;
>  	case POWER_SUPPLY_PROP_PRESENT:
>  		val->intval = 0;
> -		ret = max8997_read_reg(i2c, MAX8997_REG_STATUS4, &reg);
> +		ret = max8997_read_reg(charger->iodev->regmap,
> +				MAX8997_REG_STATUS4, &reg);
>  		if (ret)
>  			return ret;
>  		if ((reg & (1 << 2)) == 0x0)
> @@ -71,7 +72,8 @@ static int max8997_battery_get_property(struct power_supply *psy,
>  		break;
>  	case POWER_SUPPLY_PROP_ONLINE:
>  		val->intval = 0;
> -		ret = max8997_read_reg(i2c, MAX8997_REG_STATUS4, &reg);
> +		ret = max8997_read_reg(charger->iodev->regmap,
> +				MAX8997_REG_STATUS4, &reg);
>  		if (ret)
>  			return ret;
>  		/* DCINOK */
> @@ -103,7 +105,7 @@ static int max8997_battery_probe(struct platform_device *pdev)
>  		if (val > 0xf)
>  			val = 0xf;
>  
> -		ret = max8997_update_reg(iodev->i2c,
> +		ret = max8997_update_reg(iodev->regmap,
>  				MAX8997_REG_MBCCTRL5, val, 0xf);
>  		if (ret < 0) {
>  			dev_err(&pdev->dev, "Cannot use i2c bus.\n");
> @@ -113,20 +115,20 @@ static int max8997_battery_probe(struct platform_device *pdev)
>  
>  	switch (pdata->timeout) {
>  	case 5:
> -		ret = max8997_update_reg(iodev->i2c, MAX8997_REG_MBCCTRL1,
> -				0x2 << 4, 0x7 << 4);
> +		ret = max8997_update_reg(iodev->regmap,
> +				MAX8997_REG_MBCCTRL1, 0x2 << 4, 0x7 << 4);
>  		break;
>  	case 6:
> -		ret = max8997_update_reg(iodev->i2c, MAX8997_REG_MBCCTRL1,
> -				0x3 << 4, 0x7 << 4);
> +		ret = max8997_update_reg(iodev->regmap,
> +				MAX8997_REG_MBCCTRL1, 0x3 << 4, 0x7 << 4);
>  		break;
>  	case 7:
> -		ret = max8997_update_reg(iodev->i2c, MAX8997_REG_MBCCTRL1,
> -				0x4 << 4, 0x7 << 4);
> +		ret = max8997_update_reg(iodev->regmap,
> +				MAX8997_REG_MBCCTRL1, 0x4 << 4, 0x7 << 4);
>  		break;
>  	case 0:
> -		ret = max8997_update_reg(iodev->i2c, MAX8997_REG_MBCCTRL1,
> -				0x7 << 4, 0x7 << 4);
> +		ret = max8997_update_reg(iodev->regmap,
> +				MAX8997_REG_MBCCTRL1, 0x7 << 4, 0x7 << 4);
>  		break;
>  	default:
>  		dev_err(&pdev->dev, "incorrect timeout value (%d)\n",
> diff --git a/drivers/regulator/max8997.c b/drivers/regulator/max8997.c
> index 2d618fc..470435e 100644
> --- a/drivers/regulator/max8997.c
> +++ b/drivers/regulator/max8997.c
> @@ -258,7 +258,6 @@ static int max8997_get_enable_register(struct regulator_dev *rdev,
>  static int max8997_reg_is_enabled(struct regulator_dev *rdev)
>  {
>  	struct max8997_data *max8997 = rdev_get_drvdata(rdev);
> -	struct i2c_client *i2c = max8997->iodev->i2c;
>  	int ret, reg, mask, pattern;
>  	u8 val;
>  
> @@ -266,7 +265,7 @@ static int max8997_reg_is_enabled(struct regulator_dev *rdev)
>  	if (ret)
>  		return ret;
>  
> -	ret = max8997_read_reg(i2c, reg, &val);
> +	ret = max8997_read_reg(max8997->iodev->regmap, reg, &val);
>  	if (ret)
>  		return ret;
>  
> @@ -276,27 +275,25 @@ static int max8997_reg_is_enabled(struct regulator_dev *rdev)
>  static int max8997_reg_enable(struct regulator_dev *rdev)
>  {
>  	struct max8997_data *max8997 = rdev_get_drvdata(rdev);
> -	struct i2c_client *i2c = max8997->iodev->i2c;
>  	int ret, reg, mask, pattern;
>  
>  	ret = max8997_get_enable_register(rdev, &reg, &mask, &pattern);
>  	if (ret)
>  		return ret;
>  
> -	return max8997_update_reg(i2c, reg, pattern, mask);
> +	return max8997_update_reg(max8997->iodev->regmap, reg, pattern, mask);
>  }
>  
>  static int max8997_reg_disable(struct regulator_dev *rdev)
>  {
>  	struct max8997_data *max8997 = rdev_get_drvdata(rdev);
> -	struct i2c_client *i2c = max8997->iodev->i2c;
>  	int ret, reg, mask, pattern;
>  
>  	ret = max8997_get_enable_register(rdev, &reg, &mask, &pattern);
>  	if (ret)
>  		return ret;
>  
> -	return max8997_update_reg(i2c, reg, ~pattern, mask);
> +	return max8997_update_reg(max8997->iodev->regmap, reg, ~pattern, mask);
>  }
>  
>  static int max8997_get_voltage_register(struct regulator_dev *rdev,
> @@ -368,7 +365,6 @@ static int max8997_get_voltage_register(struct regulator_dev *rdev,
>  static int max8997_get_voltage_sel(struct regulator_dev *rdev)
>  {
>  	struct max8997_data *max8997 = rdev_get_drvdata(rdev);
> -	struct i2c_client *i2c = max8997->iodev->i2c;
>  	int reg, shift, mask, ret;
>  	u8 val;
>  
> @@ -376,7 +372,7 @@ static int max8997_get_voltage_sel(struct regulator_dev *rdev)
>  	if (ret)
>  		return ret;
>  
> -	ret = max8997_read_reg(i2c, reg, &val);
> +	ret = max8997_read_reg(max8997->iodev->regmap, reg, &val);
>  	if (ret)
>  		return ret;
>  
> @@ -413,7 +409,6 @@ static int max8997_set_voltage_charger_cv(struct regulator_dev *rdev,
>  		int min_uV, int max_uV, unsigned *selector)
>  {
>  	struct max8997_data *max8997 = rdev_get_drvdata(rdev);
> -	struct i2c_client *i2c = max8997->iodev->i2c;
>  	int rid = rdev_get_id(rdev);
>  	int lb, ub;
>  	int reg, shift = 0, mask, ret = 0;
> @@ -455,7 +450,8 @@ static int max8997_set_voltage_charger_cv(struct regulator_dev *rdev,
>  
>  	*selector = val;
>  
> -	ret = max8997_update_reg(i2c, reg, val << shift, mask);
> +	ret = max8997_update_reg(max8997->iodev->regmap,
> +				reg, val << shift, mask);
>  
>  	return ret;
>  }
> @@ -468,7 +464,6 @@ static int max8997_set_voltage_ldobuck(struct regulator_dev *rdev,
>  		int min_uV, int max_uV, unsigned *selector)
>  {
>  	struct max8997_data *max8997 = rdev_get_drvdata(rdev);
> -	struct i2c_client *i2c = max8997->iodev->i2c;
>  	const struct voltage_map_desc *desc;
>  	int rid = rdev_get_id(rdev);
>  	int i, reg, shift, mask, ret;
> @@ -500,7 +495,8 @@ static int max8997_set_voltage_ldobuck(struct regulator_dev *rdev,
>  	if (ret)
>  		return ret;
>  
> -	ret = max8997_update_reg(i2c, reg, i << shift, mask << shift);
> +	ret = max8997_update_reg(max8997->iodev->regmap,
> +				reg, i << shift, mask << shift);
>  	*selector = i;
>  
>  	return ret;
> @@ -710,7 +706,6 @@ static int max8997_set_voltage_safeout_sel(struct regulator_dev *rdev,
>  					   unsigned selector)
>  {
>  	struct max8997_data *max8997 = rdev_get_drvdata(rdev);
> -	struct i2c_client *i2c = max8997->iodev->i2c;
>  	int rid = rdev_get_id(rdev);
>  	int reg, shift = 0, mask, ret;
>  
> @@ -721,13 +716,13 @@ static int max8997_set_voltage_safeout_sel(struct regulator_dev *rdev,
>  	if (ret)
>  		return ret;
>  
> -	return max8997_update_reg(i2c, reg, selector << shift, mask << shift);
> +	return max8997_update_reg(max8997->iodev->regmap,
> +				reg, selector << shift, mask << shift);
>  }
>  
>  static int max8997_reg_disable_suspend(struct regulator_dev *rdev)
>  {
>  	struct max8997_data *max8997 = rdev_get_drvdata(rdev);
> -	struct i2c_client *i2c = max8997->iodev->i2c;
>  	int ret, reg, mask, pattern;
>  	int rid = rdev_get_id(rdev);
>  
> @@ -735,20 +730,22 @@ static int max8997_reg_disable_suspend(struct regulator_dev *rdev)
>  	if (ret)
>  		return ret;
>  
> -	max8997_read_reg(i2c, reg, &max8997->saved_states[rid]);
> +	max8997_read_reg(max8997->iodev->regmap,
> +			reg, &max8997->saved_states[rid]);
>  
>  	if (rid == MAX8997_LDO1 ||
>  			rid == MAX8997_LDO10 ||
>  			rid == MAX8997_LDO21) {
>  		dev_dbg(&rdev->dev, "Conditional Power-Off for %s\n",
>  				rdev->desc->name);
> -		return max8997_update_reg(i2c, reg, 0x40, mask);
> +		return max8997_update_reg(max8997->iodev->regmap,
> +				reg, 0x40, mask);
>  	}
>  
>  	dev_dbg(&rdev->dev, "Full Power-Off for %s (%xh -> %xh)\n",
>  			rdev->desc->name, max8997->saved_states[rid] & mask,
>  			(~pattern) & mask);
> -	return max8997_update_reg(i2c, reg, ~pattern, mask);
> +	return max8997_update_reg(max8997->iodev->regmap, reg, ~pattern, mask);
>  }
>  
>  static struct regulator_ops max8997_ldo_ops = {
> @@ -1032,7 +1029,6 @@ static int max8997_pmic_probe(struct platform_device *pdev)
>  	struct regulator_config config = { };
>  	struct regulator_dev **rdev;
>  	struct max8997_data *max8997;
> -	struct i2c_client *i2c;
>  	int i, ret, size, nr_dvs;
>  	u8 max_buck1 = 0, max_buck2 = 0, max_buck5 = 0;
>  
> @@ -1062,7 +1058,6 @@ static int max8997_pmic_probe(struct platform_device *pdev)
>  	max8997->iodev = iodev;
>  	max8997->num_regulators = pdata->num_regulators;
>  	platform_set_drvdata(pdev, max8997);
> -	i2c = max8997->iodev->i2c;
>  
>  	max8997->buck125_gpioindex = pdata->buck125_default_idx;
>  	max8997->buck1_gpiodvs = pdata->buck1_gpiodvs;
> @@ -1112,25 +1107,25 @@ static int max8997_pmic_probe(struct platform_device *pdev)
>  
>  	/* For the safety, set max voltage before setting up */
>  	for (i = 0; i < 8; i++) {
> -		max8997_update_reg(i2c, MAX8997_REG_BUCK1DVS1 + i,
> -				max_buck1, 0x3f);
> -		max8997_update_reg(i2c, MAX8997_REG_BUCK2DVS1 + i,
> -				max_buck2, 0x3f);
> -		max8997_update_reg(i2c, MAX8997_REG_BUCK5DVS1 + i,
> -				max_buck5, 0x3f);
> +		max8997_update_reg(max8997->iodev->regmap,
> +				MAX8997_REG_BUCK1DVS1 + i, max_buck1, 0x3f);
> +		max8997_update_reg(max8997->iodev->regmap,
> +				MAX8997_REG_BUCK2DVS1 + i, max_buck2, 0x3f);
> +		max8997_update_reg(max8997->iodev->regmap,
> +				MAX8997_REG_BUCK5DVS1 + i, max_buck5, 0x3f);
>  	}
>  
>  	/* Initialize all the DVS related BUCK registers */
>  	for (i = 0; i < nr_dvs; i++) {
> -		max8997_update_reg(i2c, MAX8997_REG_BUCK1DVS1 + i,
> -				max8997->buck1_vol[i],
> -				0x3f);
> -		max8997_update_reg(i2c, MAX8997_REG_BUCK2DVS1 + i,
> -				max8997->buck2_vol[i],
> -				0x3f);
> -		max8997_update_reg(i2c, MAX8997_REG_BUCK5DVS1 + i,
> -				max8997->buck5_vol[i],
> -				0x3f);
> +		max8997_update_reg(max8997->iodev->regmap,
> +				MAX8997_REG_BUCK1DVS1 + i,
> +				max8997->buck1_vol[i], 0x3f);
> +		max8997_update_reg(max8997->iodev->regmap,
> +				MAX8997_REG_BUCK2DVS1 + i,
> +				max8997->buck2_vol[i], 0x3f);
> +		max8997_update_reg(max8997->iodev->regmap,
> +				MAX8997_REG_BUCK5DVS1 + i,
> +				max8997->buck5_vol[i], 0x3f);
>  	}
>  
>  	/*
> @@ -1174,16 +1169,17 @@ static int max8997_pmic_probe(struct platform_device *pdev)
>  	}
>  
>  	/* DVS-GPIO disabled */
> -	max8997_update_reg(i2c, MAX8997_REG_BUCK1CTRL, (pdata->buck1_gpiodvs) ?
> -			(1 << 1) : (0 << 1), 1 << 1);
> -	max8997_update_reg(i2c, MAX8997_REG_BUCK2CTRL, (pdata->buck2_gpiodvs) ?
> -			(1 << 1) : (0 << 1), 1 << 1);
> -	max8997_update_reg(i2c, MAX8997_REG_BUCK5CTRL, (pdata->buck5_gpiodvs) ?
> -			(1 << 1) : (0 << 1), 1 << 1);
> +	max8997_update_reg(max8997->iodev->regmap, MAX8997_REG_BUCK1CTRL,
> +			(pdata->buck1_gpiodvs) ? (1 << 1) : (0 << 1), 1 << 1);
> +	max8997_update_reg(max8997->iodev->regmap, MAX8997_REG_BUCK2CTRL,
> +			(pdata->buck2_gpiodvs) ? (1 << 1) : (0 << 1), 1 << 1);
> +	max8997_update_reg(max8997->iodev->regmap, MAX8997_REG_BUCK5CTRL,
> +			(pdata->buck5_gpiodvs) ? (1 << 1) : (0 << 1), 1 << 1);
>  
>  	/* Misc Settings */
>  	max8997->ramp_delay = 10; /* set 10mV/us, which is the default */
> -	max8997_write_reg(i2c, MAX8997_REG_BUCKRAMP, (0xf << 4) | 0x9);
> +	max8997_write_reg(max8997->iodev->regmap,
> +			MAX8997_REG_BUCKRAMP, (0xf << 4) | 0x9);
>  
>  	for (i = 0; i < pdata->num_regulators; i++) {
>  		const struct voltage_map_desc *desc;
> diff --git a/drivers/rtc/rtc-max8997.c b/drivers/rtc/rtc-max8997.c
> index 0777c01..218535c 100644
> --- a/drivers/rtc/rtc-max8997.c
> +++ b/drivers/rtc/rtc-max8997.c
> @@ -68,7 +68,6 @@ enum {
>  struct max8997_rtc_info {
>  	struct device		*dev;
>  	struct max8997_dev	*max8997;
> -	struct i2c_client	*rtc;
>  	struct rtc_device	*rtc_dev;
>  	struct mutex		lock;
>  	int virq;
> @@ -118,8 +117,8 @@ static inline int max8997_rtc_set_update_reg(struct max8997_rtc_info *info)
>  {
>  	int ret;
>  
> -	ret = max8997_write_reg(info->rtc, MAX8997_RTC_UPDATE1,
> -						RTC_UDR_MASK);
> +	ret = max8997_write_reg(info->max8997->regmap_rtc,
> +				MAX8997_RTC_UPDATE1, RTC_UDR_MASK);
>  	if (ret < 0)
>  		dev_err(info->dev, "%s: fail to write update reg(%d)\n",
>  				__func__, ret);
> @@ -140,7 +139,8 @@ static int max8997_rtc_read_time(struct device *dev, struct rtc_time *tm)
>  	int ret;
>  
>  	mutex_lock(&info->lock);
> -	ret = max8997_bulk_read(info->rtc, MAX8997_RTC_SEC, RTC_NR_TIME, data);
> +	ret = max8997_bulk_read(info->max8997->regmap_rtc,
> +				MAX8997_RTC_SEC, RTC_NR_TIME, data);
>  	mutex_unlock(&info->lock);
>  
>  	if (ret < 0) {
> @@ -166,7 +166,8 @@ static int max8997_rtc_set_time(struct device *dev, struct rtc_time *tm)
>  
>  	mutex_lock(&info->lock);
>  
> -	ret = max8997_bulk_write(info->rtc, MAX8997_RTC_SEC, RTC_NR_TIME, data);
> +	ret = max8997_bulk_write(info->max8997->regmap_rtc,
> +				MAX8997_RTC_SEC, RTC_NR_TIME, data);
>  	if (ret < 0) {
>  		dev_err(info->dev, "%s: fail to write time reg(%d)\n", __func__,
>  				ret);
> @@ -188,8 +189,8 @@ static int max8997_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm)
>  
>  	mutex_lock(&info->lock);
>  
> -	ret = max8997_bulk_read(info->rtc, MAX8997_RTC_ALARM1_SEC, RTC_NR_TIME,
> -			data);
> +	ret = max8997_bulk_read(info->max8997->regmap_rtc,
> +				MAX8997_RTC_ALARM1_SEC, RTC_NR_TIME, data);
>  	if (ret < 0) {
>  		dev_err(info->dev, "%s:%d fail to read alarm reg(%d)\n",
>  				__func__, __LINE__, ret);
> @@ -207,7 +208,8 @@ static int max8997_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm)
>  	}
>  
>  	alrm->pending = 0;
> -	ret = max8997_read_reg(info->max8997->i2c, MAX8997_REG_STATUS1, &val);
> +	ret = max8997_read_reg(info->max8997->regmap_rtc,
> +			       MAX8997_REG_STATUS1, &val);
>  	if (ret < 0) {
>  		dev_err(info->dev, "%s:%d fail to read status1 reg(%d)\n",
>  				__func__, __LINE__, ret);
> @@ -230,8 +232,8 @@ static int max8997_rtc_stop_alarm(struct max8997_rtc_info *info)
>  	if (!mutex_is_locked(&info->lock))
>  		dev_warn(info->dev, "%s: should have mutex locked\n", __func__);
>  
> -	ret = max8997_bulk_read(info->rtc, MAX8997_RTC_ALARM1_SEC, RTC_NR_TIME,
> -				data);
> +	ret = max8997_bulk_read(info->max8997->regmap_rtc,
> +				MAX8997_RTC_ALARM1_SEC, RTC_NR_TIME, data);
>  	if (ret < 0) {
>  		dev_err(info->dev, "%s: fail to read alarm reg(%d)\n",
>  				__func__, ret);
> @@ -241,8 +243,8 @@ static int max8997_rtc_stop_alarm(struct max8997_rtc_info *info)
>  	for (i = 0; i < RTC_NR_TIME; i++)
>  		data[i] &= ~ALARM_ENABLE_MASK;
>  
> -	ret = max8997_bulk_write(info->rtc, MAX8997_RTC_ALARM1_SEC, RTC_NR_TIME,
> -				 data);
> +	ret = max8997_bulk_write(info->max8997->regmap_rtc,
> +				 MAX8997_RTC_ALARM1_SEC, RTC_NR_TIME, data);
>  	if (ret < 0) {
>  		dev_err(info->dev, "%s: fail to write alarm reg(%d)\n",
>  				__func__, ret);
> @@ -262,8 +264,8 @@ static int max8997_rtc_start_alarm(struct max8997_rtc_info *info)
>  	if (!mutex_is_locked(&info->lock))
>  		dev_warn(info->dev, "%s: should have mutex locked\n", __func__);
>  
> -	ret = max8997_bulk_read(info->rtc, MAX8997_RTC_ALARM1_SEC, RTC_NR_TIME,
> -				data);
> +	ret = max8997_bulk_read(info->max8997->regmap_rtc,
> +				MAX8997_RTC_ALARM1_SEC, RTC_NR_TIME, data);
>  	if (ret < 0) {
>  		dev_err(info->dev, "%s: fail to read alarm reg(%d)\n",
>  				__func__, ret);
> @@ -281,8 +283,8 @@ static int max8997_rtc_start_alarm(struct max8997_rtc_info *info)
>  	if (data[RTC_DATE] & 0x1f)
>  		data[RTC_DATE] |= (1 << ALARM_ENABLE_SHIFT);
>  
> -	ret = max8997_bulk_write(info->rtc, MAX8997_RTC_ALARM1_SEC, RTC_NR_TIME,
> -				 data);
> +	ret = max8997_bulk_write(info->max8997->regmap_rtc,
> +				 MAX8997_RTC_ALARM1_SEC, RTC_NR_TIME, data);
>  	if (ret < 0) {
>  		dev_err(info->dev, "%s: fail to write alarm reg(%d)\n",
>  				__func__, ret);
> @@ -313,8 +315,8 @@ static int max8997_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm)
>  	if (ret < 0)
>  		goto out;
>  
> -	ret = max8997_bulk_write(info->rtc, MAX8997_RTC_ALARM1_SEC, RTC_NR_TIME,
> -				data);
> +	ret = max8997_bulk_write(info->max8997->regmap_rtc,
> +				 MAX8997_RTC_ALARM1_SEC, RTC_NR_TIME, data);
>  	if (ret < 0) {
>  		dev_err(info->dev, "%s: fail to write alarm reg(%d)\n",
>  				__func__, ret);
> @@ -385,7 +387,8 @@ static void max8997_rtc_enable_wtsr(struct max8997_rtc_info *info, bool enable)
>  	dev_info(info->dev, "%s: %s WTSR\n", __func__,
>  			enable ? "enable" : "disable");
>  
> -	ret = max8997_update_reg(info->rtc, MAX8997_RTC_WTSR_SMPL, val, mask);
> +	ret = max8997_update_reg(info->max8997->regmap_rtc,
> +				 MAX8997_RTC_WTSR_SMPL, val, mask);
>  	if (ret < 0) {
>  		dev_err(info->dev, "%s: fail to update WTSR reg(%d)\n",
>  				__func__, ret);
> @@ -413,7 +416,8 @@ static void max8997_rtc_enable_smpl(struct max8997_rtc_info *info, bool enable)
>  	dev_info(info->dev, "%s: %s SMPL\n", __func__,
>  			enable ? "enable" : "disable");
>  
> -	ret = max8997_update_reg(info->rtc, MAX8997_RTC_WTSR_SMPL, val, mask);
> +	ret = max8997_update_reg(info->max8997->regmap_rtc,
> +				 MAX8997_RTC_WTSR_SMPL, val, mask);
>  	if (ret < 0) {
>  		dev_err(info->dev, "%s: fail to update SMPL reg(%d)\n",
>  				__func__, ret);
> @@ -423,7 +427,8 @@ static void max8997_rtc_enable_smpl(struct max8997_rtc_info *info, bool enable)
>  	max8997_rtc_set_update_reg(info);
>  
>  	val = 0;
> -	max8997_read_reg(info->rtc, MAX8997_RTC_WTSR_SMPL, &val);
> +	max8997_read_reg(info->max8997->regmap_rtc,
> +			 MAX8997_RTC_WTSR_SMPL, &val);
>  	pr_info("%s: WTSR_SMPL(0x%02x)\n", __func__, val);
>  }
>  
> @@ -438,7 +443,8 @@ static int max8997_rtc_init_reg(struct max8997_rtc_info *info)
>  
>  	info->rtc_24hr_mode = 1;
>  
> -	ret = max8997_bulk_write(info->rtc, MAX8997_RTC_CTRLMASK, 2, data);
> +	ret = max8997_bulk_write(info->max8997->regmap_rtc,
> +				 MAX8997_RTC_CTRLMASK, 2, data);
>  	if (ret < 0) {
>  		dev_err(info->dev, "%s: fail to write controlm reg(%d)\n",
>  				__func__, ret);
> @@ -463,7 +469,6 @@ static int max8997_rtc_probe(struct platform_device *pdev)
>  	mutex_init(&info->lock);
>  	info->dev = &pdev->dev;
>  	info->max8997 = max8997;
> -	info->rtc = max8997->rtc;
>  
>  	platform_set_drvdata(pdev, info);
>  
> diff --git a/include/linux/mfd/max8997-private.h b/include/linux/mfd/max8997-private.h
> index ad1ae7f..184e40a 100644
> --- a/include/linux/mfd/max8997-private.h
> +++ b/include/linux/mfd/max8997-private.h
> @@ -309,6 +309,8 @@ enum max8997_rtc_reg {
>  	MAX8997_RTC_ALARM2_MONTH	= 0x22,
>  	MAX8997_RTC_ALARM2_YEAR		= 0x23,
>  	MAX8997_RTC_ALARM2_DAY_OF_MONTH	= 0x24,
> +
> +	MAX8997_RTC_REG_END		= 0x25,
>  };
>  
>  enum max8997_irq_source {
> @@ -390,6 +392,11 @@ struct max8997_dev {
>  	int type;
>  	struct platform_device *battery; /* battery control (not fuel gauge) */
>  
> +	struct regmap *regmap;
> +	struct regmap *regmap_rtc;
> +	struct regmap *regmap_haptic;
> +	struct regmap *regmap_muic;
> +
>  	int irq;
>  	int ono;
>  	struct irq_domain *irq_domain;
> @@ -413,13 +420,11 @@ extern int max8997_irq_init(struct max8997_dev *max8997);
>  extern void max8997_irq_exit(struct max8997_dev *max8997);
>  extern int max8997_irq_resume(struct max8997_dev *max8997);
>  
> -extern int max8997_read_reg(struct i2c_client *i2c, u8 reg, u8 *dest);
> -extern int max8997_bulk_read(struct i2c_client *i2c, u8 reg, int count,
> -				u8 *buf);
> -extern int max8997_write_reg(struct i2c_client *i2c, u8 reg, u8 value);
> -extern int max8997_bulk_write(struct i2c_client *i2c, u8 reg, int count,
> -				u8 *buf);
> -extern int max8997_update_reg(struct i2c_client *i2c, u8 reg, u8 val, u8 mask);
> +extern int max8997_read_reg(struct regmap *map, u8 reg, u8 *dest);
> +extern int max8997_bulk_read(struct regmap *map, u8 reg, int count, u8 *buf);
> +extern int max8997_write_reg(struct regmap *map, u8 reg, u8 value);
> +extern int max8997_bulk_write(struct regmap *map, u8 reg, int count, u8 *buf);
> +extern int max8997_update_reg(struct regmap *map, u8 reg, u8 val, u8 mask);
>  
>  #define MAX8997_GPIO_INT_BOTH	(0x3 << 4)
>  #define MAX8997_GPIO_INT_RISE	(0x2 << 4)
> 

^ permalink raw reply

* Re: [PATCH v2] mfd: max8997: use regmap to access registers
From: Mark Brown @ 2014-03-06  4:31 UTC (permalink / raw)
  To: Dmitry Torokhov
  Cc: Robert Baldyga, sameo, lee.jones, myungjoo.ham, cw00.choi,
	cooloney, rpurdie, dbaryshkov, dwmw2, lgirdwood, a.zummo,
	paul.gortmaker, linux-kernel, linux-input, linux-leds, rtc-linux,
	m.szyprowski, k.kozlowski
In-Reply-To: <20140305185439.GC5453@core.coreip.homeip.net>

[-- Attachment #1: Type: text/plain, Size: 561 bytes --]

On Wed, Mar 05, 2014 at 10:54:39AM -0800, Dmitry Torokhov wrote:
> On Wed, Mar 05, 2014 at 03:58:17PM +0100, Robert Baldyga wrote:

> > -int max8997_write_reg(struct i2c_client *i2c, u8 reg, u8 value)
> > +int max8997_write_reg(struct regmap *map, u8 reg, u8 value)

> Why don't you make read/write reg to take struct max8997_dev as argument
> instead of regmap? regmap seems to be the current implementation du jur,
> but that is core's detail, functions do not need to care.

Indeed, and had this been done originally this refactoring would be much
smoother.

[-- Attachment #2: Digital signature --]
[-- Type: application/pgp-signature, Size: 836 bytes --]

^ permalink raw reply

* Re: [PATCH v2] mfd: max8997: use regmap to access registers
From: Robert Baldyga @ 2014-03-06  6:42 UTC (permalink / raw)
  To: Dmitry Torokhov
  Cc: sameo, lee.jones, myungjoo.ham, cw00.choi, cooloney, rpurdie,
	dbaryshkov, dwmw2, lgirdwood, broonie, a.zummo, paul.gortmaker,
	linux-kernel, linux-input, linux-leds, rtc-linux, m.szyprowski,
	k.kozlowski
In-Reply-To: <20140305185439.GC5453@core.coreip.homeip.net>

Hi,

On 03/05/2014 07:54 PM, Dmitry Torokhov wrote:
> Hi Robert,
> 
> On Wed, Mar 05, 2014 at 03:58:17PM +0100, Robert Baldyga wrote:
>>  
>> -int max8997_write_reg(struct i2c_client *i2c, u8 reg, u8 value)
>> +int max8997_write_reg(struct regmap *map, u8 reg, u8 value)
> 
> Why don't you make read/write reg to take struct max8997_dev as argument
> instead of regmap? regmap seems to be the current implementation du jur,
> but that is core's detail, functions do not need to care.
> 
> Thanks.
> 

It's because there are few regmaps in max8997_dev, and read/write reg
functions has no way to check which regmap should be used. I think it
would be clearer if I remove this functions and use regmap_read and
regmap_write instead, because there is no particular purpose for them.

Best regards
Robert Baldyga
Samsung R&D Institute Poland

^ permalink raw reply

* Re: [PATCH v2] mfd: max8997: use regmap to access registers
From: Robert Baldyga @ 2014-03-06  6:46 UTC (permalink / raw)
  To: Chanwoo Choi
  Cc: sameo, lee.jones, myungjoo.ham, dmitry.torokhov, cooloney,
	rpurdie, dbaryshkov, dwmw2, lgirdwood, broonie, a.zummo,
	paul.gortmaker, linux-kernel, linux-input, linux-leds, rtc-linux,
	m.szyprowski, k.kozlowski
In-Reply-To: <5317E0F0.60808@samsung.com>

Hi,

On 03/06/2014 03:44 AM, Chanwoo Choi wrote:
> This patch has build error as following: 
> I added some comment in max8997_irq_init()
> At least, you should test kernel build.
> 
> drivers/mfd/max8997-irq.c: In function ‘max8997_irq_init’:
> drivers/mfd/max8997-irq.c:333:3: error: ‘i2c’ undeclared (first use in this function)
> drivers/mfd/max8997-irq.c:333:3: note: each undeclared identifier is reported only once for each function it appears in
> make[2]: *** [drivers/mfd/max8997-irq.o] Error 1
> make[1]: *** [drivers/mfd] Error 2
> make[1]: *** Waiting for unfinished jobs....
> 

I have missed to remove reference to unused variable. I will fix it.

Thanks!
Robert Baldyga
Samsung R&D Institute Poland

> 
> On 03/05/2014 11:58 PM, Robert Baldyga wrote:
>> This patch modifies max8997 driver and each associated function driver,
>> to use regmap instead of operating directly on i2c bus. It will allow to
>> simplify IRQ handling using regmap-irq.
>>
>> Signed-off-by: Robert Baldyga <r.baldyga@samsung.com>
>> ---
>>
>> Changelog:
>>
>> v2:
>> - check devm_regmap_init_i2c() return value
>> - use proper register maps for muic and haptic registers in functions
>>   max8997_freeze() and max8997_restore()
>> - fix style problems
>>
>> v1: http://www.spinics.net/lists/kernel/msg1700375.html
>>
>>  drivers/extcon/extcon-max8997.c     |   17 ++---
>>  drivers/input/misc/max8997_haptic.c |   33 ++++-----
>>  drivers/leds/leds-max8997.c         |   12 ++--
>>  drivers/mfd/max8997-irq.c           |   31 ++++----
>>  drivers/mfd/max8997.c               |  133 ++++++++++++++++++++++-------------
>>  drivers/power/max8997_charger.c     |   28 ++++----
>>  drivers/regulator/max8997.c         |   80 ++++++++++-----------
>>  drivers/rtc/rtc-max8997.c           |   51 ++++++++------
>>  include/linux/mfd/max8997-private.h |   19 +++--
>>  9 files changed, 227 insertions(+), 177 deletions(-)
>>
>> diff --git a/drivers/extcon/extcon-max8997.c b/drivers/extcon/extcon-max8997.c
>> index 6a00464..9abc614 100644
>> --- a/drivers/extcon/extcon-max8997.c
>> +++ b/drivers/extcon/extcon-max8997.c
>> @@ -116,7 +116,7 @@ enum max8997_muic_charger_type {
>>  
>>  struct max8997_muic_info {
>>  	struct device *dev;
>> -	struct i2c_client *muic;
>> +	struct max8997_dev *max8997;
>>  	struct extcon_dev *edev;
>>  	int prev_cable_type;
>>  	int prev_chg_type;
>> @@ -190,7 +190,7 @@ static int max8997_muic_set_debounce_time(struct max8997_muic_info *info,
>>  	case ADC_DEBOUNCE_TIME_10MS:
>>  	case ADC_DEBOUNCE_TIME_25MS:
>>  	case ADC_DEBOUNCE_TIME_38_62MS:
>> -		ret = max8997_update_reg(info->muic,
>> +		ret = max8997_update_reg(info->max8997->regmap_muic,
>>  					  MAX8997_MUIC_REG_CONTROL3,
>>  					  time << CONTROL3_ADCDBSET_SHIFT,
>>  					  CONTROL3_ADCDBSET_MASK);
>> @@ -228,7 +228,7 @@ static int max8997_muic_set_path(struct max8997_muic_info *info,
>>  	else
>>  		ctrl1 = CONTROL1_SW_OPEN;
>>  
>> -	ret = max8997_update_reg(info->muic,
>> +	ret = max8997_update_reg(info->max8997->regmap_muic,
>>  			MAX8997_MUIC_REG_CONTROL1, ctrl1, COMP_SW_MASK);
>>  	if (ret < 0) {
>>  		dev_err(info->dev, "failed to update MUIC register\n");
>> @@ -240,7 +240,7 @@ static int max8997_muic_set_path(struct max8997_muic_info *info,
>>  	else
>>  		ctrl2 |= CONTROL2_LOWPWR_MASK;	/* LowPwr=1, CPEn=0 */
>>  
>> -	ret = max8997_update_reg(info->muic,
>> +	ret = max8997_update_reg(info->max8997->regmap_muic,
>>  			MAX8997_MUIC_REG_CONTROL2, ctrl2,
>>  			CONTROL2_LOWPWR_MASK | CONTROL2_CPEN_MASK);
>>  	if (ret < 0) {
>> @@ -543,7 +543,8 @@ static void max8997_muic_irq_work(struct work_struct *work)
>>  		if (info->irq == muic_irqs[i].virq)
>>  			irq_type = muic_irqs[i].irq;
>>  
>> -	ret = max8997_bulk_read(info->muic, MAX8997_MUIC_REG_STATUS1,
>> +	ret = max8997_bulk_read(info->max8997->regmap_muic,
>> +				MAX8997_MUIC_REG_STATUS1,
>>  				2, info->status);
>>  	if (ret) {
>>  		dev_err(info->dev, "failed to read muic register\n");
>> @@ -605,7 +606,7 @@ static int max8997_muic_detect_dev(struct max8997_muic_info *info)
>>  	mutex_lock(&info->mutex);
>>  
>>  	/* Read STATUSx register to detect accessory */
>> -	ret = max8997_bulk_read(info->muic,
>> +	ret = max8997_bulk_read(info->max8997->regmap_muic,
>>  			MAX8997_MUIC_REG_STATUS1, 2, info->status);
>>  	if (ret) {
>>  		dev_err(info->dev, "failed to read MUIC register\n");
>> @@ -667,7 +668,7 @@ static int max8997_muic_probe(struct platform_device *pdev)
>>  	}
>>  
>>  	info->dev = &pdev->dev;
>> -	info->muic = max8997->muic;
>> +	info->max8997 = max8997;
>>  
>>  	platform_set_drvdata(pdev, info);
>>  	mutex_init(&info->mutex);
>> @@ -721,7 +722,7 @@ static int max8997_muic_probe(struct platform_device *pdev)
>>  
>>  		/* Initialize registers according to platform data */
>>  		for (i = 0; i < muic_pdata->num_init_data; i++) {
>> -			max8997_write_reg(info->muic,
>> +			max8997_write_reg(info->max8997->regmap_muic,
>>  					muic_pdata->init_data[i].addr,
>>  					muic_pdata->init_data[i].data);
>>  		}
>> diff --git a/drivers/input/misc/max8997_haptic.c b/drivers/input/misc/max8997_haptic.c
>> index 1fea548..bce1f0f 100644
>> --- a/drivers/input/misc/max8997_haptic.c
>> +++ b/drivers/input/misc/max8997_haptic.c
>> @@ -45,7 +45,7 @@
>>  
>>  struct max8997_haptic {
>>  	struct device *dev;
>> -	struct i2c_client *client;
>> +	struct max8997_dev *max8997;
>>  	struct input_dev *input_dev;
>>  	struct regulator *regulator;
>>  
>> @@ -86,19 +86,19 @@ static int max8997_haptic_set_duty_cycle(struct max8997_haptic *chip)
>>  		}
>>  		switch (chip->internal_mode_pattern) {
>>  		case 0:
>> -			max8997_write_reg(chip->client,
>> +			max8997_write_reg(chip->max8997->regmap_haptic,
>>  				MAX8997_HAPTIC_REG_SIGPWMDC1, duty_index);
>>  			break;
>>  		case 1:
>> -			max8997_write_reg(chip->client,
>> +			max8997_write_reg(chip->max8997->regmap_haptic,
>>  				MAX8997_HAPTIC_REG_SIGPWMDC2, duty_index);
>>  			break;
>>  		case 2:
>> -			max8997_write_reg(chip->client,
>> +			max8997_write_reg(chip->max8997->regmap_haptic,
>>  				MAX8997_HAPTIC_REG_SIGPWMDC3, duty_index);
>>  			break;
>>  		case 3:
>> -			max8997_write_reg(chip->client,
>> +			max8997_write_reg(chip->max8997->regmap_haptic,
>>  				MAX8997_HAPTIC_REG_SIGPWMDC4, duty_index);
>>  			break;
>>  		default:
>> @@ -115,50 +115,51 @@ static void max8997_haptic_configure(struct max8997_haptic *chip)
>>  	value = chip->type << MAX8997_MOTOR_TYPE_SHIFT |
>>  		chip->enabled << MAX8997_ENABLE_SHIFT |
>>  		chip->mode << MAX8997_MODE_SHIFT | chip->pwm_divisor;
>> -	max8997_write_reg(chip->client, MAX8997_HAPTIC_REG_CONF2, value);
>> +	max8997_write_reg(chip->max8997->regmap_haptic,
>> +		MAX8997_HAPTIC_REG_CONF2, value);
>>  
>>  	if (chip->mode == MAX8997_INTERNAL_MODE && chip->enabled) {
>>  		value = chip->internal_mode_pattern << MAX8997_CYCLE_SHIFT |
>>  			chip->internal_mode_pattern << MAX8997_SIG_PERIOD_SHIFT |
>>  			chip->internal_mode_pattern << MAX8997_SIG_DUTY_SHIFT |
>>  			chip->internal_mode_pattern << MAX8997_PWM_DUTY_SHIFT;
>> -		max8997_write_reg(chip->client,
>> +		max8997_write_reg(chip->max8997->regmap_haptic,
>>  			MAX8997_HAPTIC_REG_DRVCONF, value);
>>  
>>  		switch (chip->internal_mode_pattern) {
>>  		case 0:
>>  			value = chip->pattern_cycle << 4;
>> -			max8997_write_reg(chip->client,
>> +			max8997_write_reg(chip->max8997->regmap_haptic,
>>  				MAX8997_HAPTIC_REG_CYCLECONF1, value);
>>  			value = chip->pattern_signal_period;
>> -			max8997_write_reg(chip->client,
>> +			max8997_write_reg(chip->max8997->regmap_haptic,
>>  				MAX8997_HAPTIC_REG_SIGCONF1, value);
>>  			break;
>>  
>>  		case 1:
>>  			value = chip->pattern_cycle;
>> -			max8997_write_reg(chip->client,
>> +			max8997_write_reg(chip->max8997->regmap_haptic,
>>  				MAX8997_HAPTIC_REG_CYCLECONF1, value);
>>  			value = chip->pattern_signal_period;
>> -			max8997_write_reg(chip->client,
>> +			max8997_write_reg(chip->max8997->regmap_haptic,
>>  				MAX8997_HAPTIC_REG_SIGCONF2, value);
>>  			break;
>>  
>>  		case 2:
>>  			value = chip->pattern_cycle << 4;
>> -			max8997_write_reg(chip->client,
>> +			max8997_write_reg(chip->max8997->regmap_haptic,
>>  				MAX8997_HAPTIC_REG_CYCLECONF2, value);
>>  			value = chip->pattern_signal_period;
>> -			max8997_write_reg(chip->client,
>> +			max8997_write_reg(chip->max8997->regmap_haptic,
>>  				MAX8997_HAPTIC_REG_SIGCONF3, value);
>>  			break;
>>  
>>  		case 3:
>>  			value = chip->pattern_cycle;
>> -			max8997_write_reg(chip->client,
>> +			max8997_write_reg(chip->max8997->regmap_haptic,
>>  				MAX8997_HAPTIC_REG_CYCLECONF2, value);
>>  			value = chip->pattern_signal_period;
>> -			max8997_write_reg(chip->client,
>> +			max8997_write_reg(chip->max8997->regmap_haptic,
>>  				MAX8997_HAPTIC_REG_SIGCONF4, value);
>>  			break;
>>  
>> @@ -267,7 +268,7 @@ static int max8997_haptic_probe(struct platform_device *pdev)
>>  	INIT_WORK(&chip->work, max8997_haptic_play_effect_work);
>>  	mutex_init(&chip->mutex);
>>  
>> -	chip->client = iodev->haptic;
>> +	chip->max8997 = iodev;
>>  	chip->dev = &pdev->dev;
>>  	chip->input_dev = input_dev;
>>  	chip->pwm_period = haptic_pdata->pwm_period;
>> diff --git a/drivers/leds/leds-max8997.c b/drivers/leds/leds-max8997.c
>> index f449a8b..a6b8696 100644
>> --- a/drivers/leds/leds-max8997.c
>> +++ b/drivers/leds/leds-max8997.c
>> @@ -53,7 +53,6 @@ static void max8997_led_set_mode(struct max8997_led *led,
>>  			enum max8997_led_mode mode)
>>  {
>>  	int ret;
>> -	struct i2c_client *client = led->iodev->i2c;
>>  	u8 mask = 0, val;
>>  
>>  	switch (mode) {
>> @@ -89,8 +88,8 @@ static void max8997_led_set_mode(struct max8997_led *led,
>>  	}
>>  
>>  	if (mask) {
>> -		ret = max8997_update_reg(client, MAX8997_REG_LEN_CNTL, val,
>> -					 mask);
>> +		ret = max8997_update_reg(led->iodev->regmap,
>> +					MAX8997_REG_LEN_CNTL, val, mask);
>>  		if (ret)
>>  			dev_err(led->iodev->dev,
>>  				"failed to update register(%d)\n", ret);
>> @@ -102,7 +101,6 @@ static void max8997_led_set_mode(struct max8997_led *led,
>>  static void max8997_led_enable(struct max8997_led *led, bool enable)
>>  {
>>  	int ret;
>> -	struct i2c_client *client = led->iodev->i2c;
>>  	u8 val = 0, mask = MAX8997_LED_BOOST_ENABLE_MASK;
>>  
>>  	if (led->enabled == enable)
>> @@ -110,7 +108,8 @@ static void max8997_led_enable(struct max8997_led *led, bool enable)
>>  
>>  	val = enable ? MAX8997_LED_BOOST_ENABLE_MASK : 0;
>>  
>> -	ret = max8997_update_reg(client, MAX8997_REG_BOOST_CNTL, val, mask);
>> +	ret = max8997_update_reg(led->iodev->regmap,
>> +				MAX8997_REG_BOOST_CNTL, val, mask);
>>  	if (ret)
>>  		dev_err(led->iodev->dev,
>>  			"failed to update register(%d)\n", ret);
>> @@ -122,7 +121,6 @@ static void max8997_led_set_current(struct max8997_led *led,
>>  				enum led_brightness value)
>>  {
>>  	int ret;
>> -	struct i2c_client *client = led->iodev->i2c;
>>  	u8 val = 0, mask = 0, reg = 0;
>>  
>>  	switch (led->led_mode) {
>> @@ -143,7 +141,7 @@ static void max8997_led_set_current(struct max8997_led *led,
>>  	}
>>  
>>  	if (mask) {
>> -		ret = max8997_update_reg(client, reg, val, mask);
>> +		ret = max8997_update_reg(led->iodev->regmap, reg, val, mask);
>>  		if (ret)
>>  			dev_err(led->iodev->dev,
>>  				"failed to update register(%d)\n", ret);
>> diff --git a/drivers/mfd/max8997-irq.c b/drivers/mfd/max8997-irq.c
>> index 43fa614..05d3b87 100644
>> --- a/drivers/mfd/max8997-irq.c
>> +++ b/drivers/mfd/max8997-irq.c
>> @@ -124,15 +124,20 @@ static void max8997_irq_sync_unlock(struct irq_data *data)
>>  	int i;
>>  
>>  	for (i = 0; i < MAX8997_IRQ_GROUP_NR; i++) {
>> +		struct regmap *map;
>>  		u8 mask_reg = max8997_mask_reg[i];
>> -		struct i2c_client *i2c = get_i2c(max8997, i);
>> +
>> +		if (i >= MUIC_INT1 && i <= MUIC_INT3)
>> +			map = max8997->regmap_muic;
>> +		else
>> +			map = max8997->regmap;
>>  
>>  		if (mask_reg == MAX8997_REG_INVALID ||
>> -				IS_ERR_OR_NULL(i2c))
>> +				IS_ERR_OR_NULL(map))
>>  			continue;
>>  		max8997->irq_masks_cache[i] = max8997->irq_masks_cur[i];
>>  
>> -		max8997_write_reg(i2c, max8997_mask_reg[i],
>> +		max8997_write_reg(map, max8997_mask_reg[i],
>>  				max8997->irq_masks_cur[i]);
>>  	}
>>  
>> @@ -185,7 +190,7 @@ static irqreturn_t max8997_irq_thread(int irq, void *data)
>>  	int ret;
>>  	int i, cur_irq;
>>  
>> -	ret = max8997_read_reg(max8997->i2c, MAX8997_REG_INTSRC, &irq_src);
>> +	ret = max8997_read_reg(max8997->regmap, MAX8997_REG_INTSRC, &irq_src);
>>  	if (ret < 0) {
>>  		dev_err(max8997->dev, "Failed to read interrupt source: %d\n",
>>  				ret);
>> @@ -194,7 +199,7 @@ static irqreturn_t max8997_irq_thread(int irq, void *data)
>>  
>>  	if (irq_src & MAX8997_IRQSRC_PMIC) {
>>  		/* PMIC INT1 ~ INT4 */
>> -		max8997_bulk_read(max8997->i2c, MAX8997_REG_INT1, 4,
>> +		max8997_bulk_read(max8997->regmap, MAX8997_REG_INT1, 4,
>>  				&irq_reg[PMIC_INT1]);
>>  	}
>>  	if (irq_src & MAX8997_IRQSRC_FUELGAUGE) {
>> @@ -215,8 +220,8 @@ static irqreturn_t max8997_irq_thread(int irq, void *data)
>>  	}
>>  	if (irq_src & MAX8997_IRQSRC_MUIC) {
>>  		/* MUIC INT1 ~ INT3 */
>> -		max8997_bulk_read(max8997->muic, MAX8997_MUIC_REG_INT1, 3,
>> -				&irq_reg[MUIC_INT1]);
>> +		max8997_bulk_read(max8997->regmap_muic,
>> +				MAX8997_MUIC_REG_INT1, 3, &irq_reg[MUIC_INT1]);
>>  	}
>>  	if (irq_src & MAX8997_IRQSRC_GPIO) {
>>  		/* GPIO Interrupt */
>> @@ -225,7 +230,7 @@ static irqreturn_t max8997_irq_thread(int irq, void *data)
>>  		irq_reg[GPIO_LOW] = 0;
>>  		irq_reg[GPIO_HI] = 0;
>>  
>> -		max8997_bulk_read(max8997->i2c, MAX8997_REG_GPIOCNTL1,
>> +		max8997_bulk_read(max8997->regmap, MAX8997_REG_GPIOCNTL1,
>>  				MAX8997_NUM_GPIO, gpio_info);
>>  		for (i = 0; i < MAX8997_NUM_GPIO; i++) {
>>  			bool interrupt = false;
>> @@ -260,7 +265,7 @@ static irqreturn_t max8997_irq_thread(int irq, void *data)
>>  	}
>>  	if (irq_src & MAX8997_IRQSRC_FLASH) {
>>  		/* Flash Status Interrupt */
>> -		ret = max8997_read_reg(max8997->i2c, MAX8997_REG_FLASHSTATUS,
>> +		ret = max8997_read_reg(max8997->regmap, MAX8997_REG_FLASHSTATUS,
>>  				&irq_reg[FLASH_STATUS]);
>>  	}
>>  
>> @@ -323,22 +328,20 @@ int max8997_irq_init(struct max8997_dev *max8997)
>>  
>>  	/* Mask individual interrupt sources */
>>  	for (i = 0; i < MAX8997_IRQ_GROUP_NR; i++) {
>> -		struct i2c_client *i2c;
>> -
> 
> If you delete i2c instance, this patch happen build error.
> 
>>  		max8997->irq_masks_cur[i] = 0xff;
>>  		max8997->irq_masks_cache[i] = 0xff;
>>  		i2c = get_i2c(max8997, i);
> 
> This line need 'i2c' instance.
> 
>>  
>> -		if (IS_ERR_OR_NULL(i2c))
>> +		if (IS_ERR_OR_NULL(max8997->regmap))
>>  			continue;
>>  		if (max8997_mask_reg[i] == MAX8997_REG_INVALID)
>>  			continue;
>>  
>> -		max8997_write_reg(i2c, max8997_mask_reg[i], 0xff);
>> +		max8997_write_reg(max8997->regmap, max8997_mask_reg[i], 0xff);
>>  	}
>>  
>>  	for (i = 0; i < MAX8997_NUM_GPIO; i++) {
>> -		max8997->gpio_status[i] = (max8997_read_reg(max8997->i2c,
>> +		max8997->gpio_status[i] = (max8997_read_reg(max8997->regmap,
>>  						MAX8997_REG_GPIOCNTL1 + i,
>>  						&val)
>>  					& MAX8997_GPIO_DATA_MASK) ?
>> diff --git a/drivers/mfd/max8997.c b/drivers/mfd/max8997.c
>> index be88a3b..590e368 100644
>> --- a/drivers/mfd/max8997.c
>> +++ b/drivers/mfd/max8997.c
>> @@ -33,6 +33,7 @@
>>  #include <linux/mfd/core.h>
>>  #include <linux/mfd/max8997.h>
>>  #include <linux/mfd/max8997-private.h>
>> +#include <linux/regmap.h>
>>  
>>  #define I2C_ADDR_PMIC	(0xCC >> 1)
>>  #define I2C_ADDR_MUIC	(0x4A >> 1)
>> @@ -57,82 +58,82 @@ static struct of_device_id max8997_pmic_dt_match[] = {
>>  };
>>  #endif
>>  
>> -int max8997_read_reg(struct i2c_client *i2c, u8 reg, u8 *dest)
>> +int max8997_read_reg(struct regmap *map, u8 reg, u8 *dest)
>>  {
>> -	struct max8997_dev *max8997 = i2c_get_clientdata(i2c);
>> +	unsigned int val;
>>  	int ret;
>>  
>> -	mutex_lock(&max8997->iolock);
>> -	ret = i2c_smbus_read_byte_data(i2c, reg);
>> -	mutex_unlock(&max8997->iolock);
>> -	if (ret < 0)
>> -		return ret;
>> +	ret = regmap_read(map, reg, &val);
>> +	*dest = val;
>>  
>> -	ret &= 0xff;
>> -	*dest = ret;
>> -	return 0;
>> +	return ret;
>>  }
>>  EXPORT_SYMBOL_GPL(max8997_read_reg);
>>  
>> -int max8997_bulk_read(struct i2c_client *i2c, u8 reg, int count, u8 *buf)
>> +int max8997_bulk_read(struct regmap *map, u8 reg, int count, u8 *buf)
>>  {
>> -	struct max8997_dev *max8997 = i2c_get_clientdata(i2c);
>>  	int ret;
>>  
>> -	mutex_lock(&max8997->iolock);
>> -	ret = i2c_smbus_read_i2c_block_data(i2c, reg, count, buf);
>> -	mutex_unlock(&max8997->iolock);
>> -	if (ret < 0)
>> -		return ret;
>> +	ret = regmap_bulk_read(map, reg, buf, count);
>>  
>> -	return 0;
>> +	return ret;
>>  }
>>  EXPORT_SYMBOL_GPL(max8997_bulk_read);
>>  
>> -int max8997_write_reg(struct i2c_client *i2c, u8 reg, u8 value)
>> +int max8997_write_reg(struct regmap *map, u8 reg, u8 value)
>>  {
>> -	struct max8997_dev *max8997 = i2c_get_clientdata(i2c);
>>  	int ret;
>>  
>> -	mutex_lock(&max8997->iolock);
>> -	ret = i2c_smbus_write_byte_data(i2c, reg, value);
>> -	mutex_unlock(&max8997->iolock);
>> +	ret = regmap_write(map, reg, value);
>> +
>>  	return ret;
>>  }
>>  EXPORT_SYMBOL_GPL(max8997_write_reg);
>>  
>> -int max8997_bulk_write(struct i2c_client *i2c, u8 reg, int count, u8 *buf)
>> +int max8997_bulk_write(struct regmap *map, u8 reg, int count, u8 *buf)
>>  {
>> -	struct max8997_dev *max8997 = i2c_get_clientdata(i2c);
>>  	int ret;
>>  
>> -	mutex_lock(&max8997->iolock);
>> -	ret = i2c_smbus_write_i2c_block_data(i2c, reg, count, buf);
>> -	mutex_unlock(&max8997->iolock);
>> -	if (ret < 0)
>> -		return ret;
>> +	ret = regmap_bulk_write(map, reg, buf, count);
>>  
>> -	return 0;
>> +	return ret;
>>  }
>>  EXPORT_SYMBOL_GPL(max8997_bulk_write);
>>  
>> -int max8997_update_reg(struct i2c_client *i2c, u8 reg, u8 val, u8 mask)
>> +int max8997_update_reg(struct regmap *map, u8 reg, u8 val, u8 mask)
>>  {
>> -	struct max8997_dev *max8997 = i2c_get_clientdata(i2c);
>>  	int ret;
>>  
>> -	mutex_lock(&max8997->iolock);
>> -	ret = i2c_smbus_read_byte_data(i2c, reg);
>> -	if (ret >= 0) {
>> -		u8 old_val = ret & 0xff;
>> -		u8 new_val = (val & mask) | (old_val & (~mask));
>> -		ret = i2c_smbus_write_byte_data(i2c, reg, new_val);
>> -	}
>> -	mutex_unlock(&max8997->iolock);
>> +	ret = regmap_update_bits(map, reg, mask, val);
>> +
>>  	return ret;
>>  }
>>  EXPORT_SYMBOL_GPL(max8997_update_reg);
>>  
>> +static const struct regmap_config max8997_regmap_config = {
>> +	.reg_bits = 8,
>> +	.val_bits = 8,
>> +	.max_register = MAX8997_REG_PMIC_END,
>> +};
>> +
>> +static const struct regmap_config max8997_regmap_rtc_config = {
>> +	.reg_bits = 8,
>> +	.val_bits = 8,
>> +	.max_register = MAX8997_RTC_REG_END,
>> +};
>> +
>> +static const struct regmap_config max8997_regmap_haptic_config = {
>> +	.reg_bits = 8,
>> +	.val_bits = 8,
>> +	.max_register = MAX8997_HAPTIC_REG_END,
>> +};
>> +
>> +static const struct regmap_config max8997_regmap_muic_config = {
>> +	.reg_bits = 8,
>> +	.val_bits = 8,
>> +	.max_register = MAX8997_MUIC_REG_END,
>> +};
>> +
>>  /*
>>   * Only the common platform data elements for max8997 are parsed here from the
>>   * device tree. Other sub-modules of max8997 such as pmic, rtc and others have
>> @@ -202,6 +203,14 @@ static int max8997_i2c_probe(struct i2c_client *i2c,
>>  	if (!pdata)
>>  		return ret;
>>  
>> +	max8997->regmap = devm_regmap_init_i2c(i2c, &max8997_regmap_config);
>> +	if (IS_ERR(max8997->regmap)) {
>> +		ret = PTR_ERR(max8997->regmap);
>> +		dev_err(max8997->dev, "failed to allocate register map: %d\n",
>> +				ret);
>> +		return ret;
>> +	}
>> +
>>  	max8997->pdata = pdata;
>>  	max8997->ono = pdata->ono;
>>  
>> @@ -209,11 +218,40 @@ static int max8997_i2c_probe(struct i2c_client *i2c,
>>  
>>  	max8997->rtc = i2c_new_dummy(i2c->adapter, I2C_ADDR_RTC);
>>  	i2c_set_clientdata(max8997->rtc, max8997);
>> +
>>  	max8997->haptic = i2c_new_dummy(i2c->adapter, I2C_ADDR_HAPTIC);
>>  	i2c_set_clientdata(max8997->haptic, max8997);
>> +
>>  	max8997->muic = i2c_new_dummy(i2c->adapter, I2C_ADDR_MUIC);
>>  	i2c_set_clientdata(max8997->muic, max8997);
>>  
>> +	max8997->regmap_rtc = devm_regmap_init_i2c(max8997->rtc,
>> +					&max8997_regmap_rtc_config);
>> +	if (IS_ERR(max8997->regmap_rtc)) {
>> +		ret = PTR_ERR(max8997->regmap_rtc);
>> +		dev_err(max8997->dev,
>> +				"failed to allocate register map: %d\n", ret);
>> +		goto err_regmap;
>> +	}
>> +
>> +	max8997->regmap_haptic = devm_regmap_init_i2c(max8997->haptic,
>> +					&max8997_regmap_haptic_config);
>> +	if (IS_ERR(max8997->regmap_haptic)) {
>> +		ret = PTR_ERR(max8997->regmap_haptic);
>> +		dev_err(max8997->dev,
>> +				"failed to allocate register map: %d\n", ret);
>> +		goto err_regmap;
>> +	}
>> +
>> +	max8997->regmap_muic = devm_regmap_init_i2c(max8997->muic,
>> +					&max8997_regmap_muic_config);
>> +	if (IS_ERR(max8997->regmap_muic)) {
>> +		ret = PTR_ERR(max8997->regmap_muic);
>> +		dev_err(max8997->dev,
>> +				"failed to allocate register map: %d\n", ret);
>> +		goto err_regmap;
>> +	}
>> +
>>  	pm_runtime_set_active(max8997->dev);
>>  
>>  	max8997_irq_init(max8997);
>> @@ -238,6 +276,7 @@ static int max8997_i2c_probe(struct i2c_client *i2c,
>>  
>>  err_mfd:
>>  	mfd_remove_devices(max8997->dev);
>> +err_regmap:
>>  	i2c_unregister_device(max8997->muic);
>>  	i2c_unregister_device(max8997->haptic);
>>  	i2c_unregister_device(max8997->rtc);
>> @@ -423,15 +462,15 @@ static int max8997_freeze(struct device *dev)
>>  	int i;
>>  
>>  	for (i = 0; i < ARRAY_SIZE(max8997_dumpaddr_pmic); i++)
>> -		max8997_read_reg(i2c, max8997_dumpaddr_pmic[i],
>> +		max8997_read_reg(max8997->regmap, max8997_dumpaddr_pmic[i],
>>  				&max8997->reg_dump[i]);
>>  
>>  	for (i = 0; i < ARRAY_SIZE(max8997_dumpaddr_muic); i++)
>> -		max8997_read_reg(i2c, max8997_dumpaddr_muic[i],
>> +		max8997_read_reg(max8997->regmap_muic, max8997_dumpaddr_muic[i],
>>  				&max8997->reg_dump[i + MAX8997_REG_PMIC_END]);
>>  
>>  	for (i = 0; i < ARRAY_SIZE(max8997_dumpaddr_haptic); i++)
>> -		max8997_read_reg(i2c, max8997_dumpaddr_haptic[i],
>> +		max8997_read_reg(max8997->regmap_haptic, max8997_dumpaddr_haptic[i],
>>  				&max8997->reg_dump[i + MAX8997_REG_PMIC_END +
>>  				MAX8997_MUIC_REG_END]);
>>  
>> @@ -445,15 +484,15 @@ static int max8997_restore(struct device *dev)
>>  	int i;
>>  
>>  	for (i = 0; i < ARRAY_SIZE(max8997_dumpaddr_pmic); i++)
>> -		max8997_write_reg(i2c, max8997_dumpaddr_pmic[i],
>> +		max8997_write_reg(max8997->regmap, max8997_dumpaddr_pmic[i],
>>  				max8997->reg_dump[i]);
>>  
>>  	for (i = 0; i < ARRAY_SIZE(max8997_dumpaddr_muic); i++)
>> -		max8997_write_reg(i2c, max8997_dumpaddr_muic[i],
>> +		max8997_write_reg(max8997->regmap_muic, max8997_dumpaddr_muic[i],
>>  				max8997->reg_dump[i + MAX8997_REG_PMIC_END]);
>>  
>>  	for (i = 0; i < ARRAY_SIZE(max8997_dumpaddr_haptic); i++)
>> -		max8997_write_reg(i2c, max8997_dumpaddr_haptic[i],
>> +		max8997_write_reg(max8997->regmap_haptic, max8997_dumpaddr_haptic[i],
>>  				max8997->reg_dump[i + MAX8997_REG_PMIC_END +
>>  				MAX8997_MUIC_REG_END]);
>>  
>> diff --git a/drivers/power/max8997_charger.c b/drivers/power/max8997_charger.c
>> index 4bdedfe..027e9bf 100644
>> --- a/drivers/power/max8997_charger.c
>> +++ b/drivers/power/max8997_charger.c
>> @@ -46,14 +46,14 @@ static int max8997_battery_get_property(struct power_supply *psy,
>>  {
>>  	struct charger_data *charger = container_of(psy,
>>  			struct charger_data, battery);
>> -	struct i2c_client *i2c = charger->iodev->i2c;
>>  	int ret;
>>  	u8 reg;
>>  
>>  	switch (psp) {
>>  	case POWER_SUPPLY_PROP_STATUS:
>>  		val->intval = 0;
>> -		ret = max8997_read_reg(i2c, MAX8997_REG_STATUS4, &reg);
>> +		ret = max8997_read_reg(charger->iodev->regmap,
>> +				MAX8997_REG_STATUS4, &reg);
>>  		if (ret)
>>  			return ret;
>>  		if ((reg & (1 << 0)) == 0x1)
>> @@ -62,7 +62,8 @@ static int max8997_battery_get_property(struct power_supply *psy,
>>  		break;
>>  	case POWER_SUPPLY_PROP_PRESENT:
>>  		val->intval = 0;
>> -		ret = max8997_read_reg(i2c, MAX8997_REG_STATUS4, &reg);
>> +		ret = max8997_read_reg(charger->iodev->regmap,
>> +				MAX8997_REG_STATUS4, &reg);
>>  		if (ret)
>>  			return ret;
>>  		if ((reg & (1 << 2)) == 0x0)
>> @@ -71,7 +72,8 @@ static int max8997_battery_get_property(struct power_supply *psy,
>>  		break;
>>  	case POWER_SUPPLY_PROP_ONLINE:
>>  		val->intval = 0;
>> -		ret = max8997_read_reg(i2c, MAX8997_REG_STATUS4, &reg);
>> +		ret = max8997_read_reg(charger->iodev->regmap,
>> +				MAX8997_REG_STATUS4, &reg);
>>  		if (ret)
>>  			return ret;
>>  		/* DCINOK */
>> @@ -103,7 +105,7 @@ static int max8997_battery_probe(struct platform_device *pdev)
>>  		if (val > 0xf)
>>  			val = 0xf;
>>  
>> -		ret = max8997_update_reg(iodev->i2c,
>> +		ret = max8997_update_reg(iodev->regmap,
>>  				MAX8997_REG_MBCCTRL5, val, 0xf);
>>  		if (ret < 0) {
>>  			dev_err(&pdev->dev, "Cannot use i2c bus.\n");
>> @@ -113,20 +115,20 @@ static int max8997_battery_probe(struct platform_device *pdev)
>>  
>>  	switch (pdata->timeout) {
>>  	case 5:
>> -		ret = max8997_update_reg(iodev->i2c, MAX8997_REG_MBCCTRL1,
>> -				0x2 << 4, 0x7 << 4);
>> +		ret = max8997_update_reg(iodev->regmap,
>> +				MAX8997_REG_MBCCTRL1, 0x2 << 4, 0x7 << 4);
>>  		break;
>>  	case 6:
>> -		ret = max8997_update_reg(iodev->i2c, MAX8997_REG_MBCCTRL1,
>> -				0x3 << 4, 0x7 << 4);
>> +		ret = max8997_update_reg(iodev->regmap,
>> +				MAX8997_REG_MBCCTRL1, 0x3 << 4, 0x7 << 4);
>>  		break;
>>  	case 7:
>> -		ret = max8997_update_reg(iodev->i2c, MAX8997_REG_MBCCTRL1,
>> -				0x4 << 4, 0x7 << 4);
>> +		ret = max8997_update_reg(iodev->regmap,
>> +				MAX8997_REG_MBCCTRL1, 0x4 << 4, 0x7 << 4);
>>  		break;
>>  	case 0:
>> -		ret = max8997_update_reg(iodev->i2c, MAX8997_REG_MBCCTRL1,
>> -				0x7 << 4, 0x7 << 4);
>> +		ret = max8997_update_reg(iodev->regmap,
>> +				MAX8997_REG_MBCCTRL1, 0x7 << 4, 0x7 << 4);
>>  		break;
>>  	default:
>>  		dev_err(&pdev->dev, "incorrect timeout value (%d)\n",
>> diff --git a/drivers/regulator/max8997.c b/drivers/regulator/max8997.c
>> index 2d618fc..470435e 100644
>> --- a/drivers/regulator/max8997.c
>> +++ b/drivers/regulator/max8997.c
>> @@ -258,7 +258,6 @@ static int max8997_get_enable_register(struct regulator_dev *rdev,
>>  static int max8997_reg_is_enabled(struct regulator_dev *rdev)
>>  {
>>  	struct max8997_data *max8997 = rdev_get_drvdata(rdev);
>> -	struct i2c_client *i2c = max8997->iodev->i2c;
>>  	int ret, reg, mask, pattern;
>>  	u8 val;
>>  
>> @@ -266,7 +265,7 @@ static int max8997_reg_is_enabled(struct regulator_dev *rdev)
>>  	if (ret)
>>  		return ret;
>>  
>> -	ret = max8997_read_reg(i2c, reg, &val);
>> +	ret = max8997_read_reg(max8997->iodev->regmap, reg, &val);
>>  	if (ret)
>>  		return ret;
>>  
>> @@ -276,27 +275,25 @@ static int max8997_reg_is_enabled(struct regulator_dev *rdev)
>>  static int max8997_reg_enable(struct regulator_dev *rdev)
>>  {
>>  	struct max8997_data *max8997 = rdev_get_drvdata(rdev);
>> -	struct i2c_client *i2c = max8997->iodev->i2c;
>>  	int ret, reg, mask, pattern;
>>  
>>  	ret = max8997_get_enable_register(rdev, &reg, &mask, &pattern);
>>  	if (ret)
>>  		return ret;
>>  
>> -	return max8997_update_reg(i2c, reg, pattern, mask);
>> +	return max8997_update_reg(max8997->iodev->regmap, reg, pattern, mask);
>>  }
>>  
>>  static int max8997_reg_disable(struct regulator_dev *rdev)
>>  {
>>  	struct max8997_data *max8997 = rdev_get_drvdata(rdev);
>> -	struct i2c_client *i2c = max8997->iodev->i2c;
>>  	int ret, reg, mask, pattern;
>>  
>>  	ret = max8997_get_enable_register(rdev, &reg, &mask, &pattern);
>>  	if (ret)
>>  		return ret;
>>  
>> -	return max8997_update_reg(i2c, reg, ~pattern, mask);
>> +	return max8997_update_reg(max8997->iodev->regmap, reg, ~pattern, mask);
>>  }
>>  
>>  static int max8997_get_voltage_register(struct regulator_dev *rdev,
>> @@ -368,7 +365,6 @@ static int max8997_get_voltage_register(struct regulator_dev *rdev,
>>  static int max8997_get_voltage_sel(struct regulator_dev *rdev)
>>  {
>>  	struct max8997_data *max8997 = rdev_get_drvdata(rdev);
>> -	struct i2c_client *i2c = max8997->iodev->i2c;
>>  	int reg, shift, mask, ret;
>>  	u8 val;
>>  
>> @@ -376,7 +372,7 @@ static int max8997_get_voltage_sel(struct regulator_dev *rdev)
>>  	if (ret)
>>  		return ret;
>>  
>> -	ret = max8997_read_reg(i2c, reg, &val);
>> +	ret = max8997_read_reg(max8997->iodev->regmap, reg, &val);
>>  	if (ret)
>>  		return ret;
>>  
>> @@ -413,7 +409,6 @@ static int max8997_set_voltage_charger_cv(struct regulator_dev *rdev,
>>  		int min_uV, int max_uV, unsigned *selector)
>>  {
>>  	struct max8997_data *max8997 = rdev_get_drvdata(rdev);
>> -	struct i2c_client *i2c = max8997->iodev->i2c;
>>  	int rid = rdev_get_id(rdev);
>>  	int lb, ub;
>>  	int reg, shift = 0, mask, ret = 0;
>> @@ -455,7 +450,8 @@ static int max8997_set_voltage_charger_cv(struct regulator_dev *rdev,
>>  
>>  	*selector = val;
>>  
>> -	ret = max8997_update_reg(i2c, reg, val << shift, mask);
>> +	ret = max8997_update_reg(max8997->iodev->regmap,
>> +				reg, val << shift, mask);
>>  
>>  	return ret;
>>  }
>> @@ -468,7 +464,6 @@ static int max8997_set_voltage_ldobuck(struct regulator_dev *rdev,
>>  		int min_uV, int max_uV, unsigned *selector)
>>  {
>>  	struct max8997_data *max8997 = rdev_get_drvdata(rdev);
>> -	struct i2c_client *i2c = max8997->iodev->i2c;
>>  	const struct voltage_map_desc *desc;
>>  	int rid = rdev_get_id(rdev);
>>  	int i, reg, shift, mask, ret;
>> @@ -500,7 +495,8 @@ static int max8997_set_voltage_ldobuck(struct regulator_dev *rdev,
>>  	if (ret)
>>  		return ret;
>>  
>> -	ret = max8997_update_reg(i2c, reg, i << shift, mask << shift);
>> +	ret = max8997_update_reg(max8997->iodev->regmap,
>> +				reg, i << shift, mask << shift);
>>  	*selector = i;
>>  
>>  	return ret;
>> @@ -710,7 +706,6 @@ static int max8997_set_voltage_safeout_sel(struct regulator_dev *rdev,
>>  					   unsigned selector)
>>  {
>>  	struct max8997_data *max8997 = rdev_get_drvdata(rdev);
>> -	struct i2c_client *i2c = max8997->iodev->i2c;
>>  	int rid = rdev_get_id(rdev);
>>  	int reg, shift = 0, mask, ret;
>>  
>> @@ -721,13 +716,13 @@ static int max8997_set_voltage_safeout_sel(struct regulator_dev *rdev,
>>  	if (ret)
>>  		return ret;
>>  
>> -	return max8997_update_reg(i2c, reg, selector << shift, mask << shift);
>> +	return max8997_update_reg(max8997->iodev->regmap,
>> +				reg, selector << shift, mask << shift);
>>  }
>>  
>>  static int max8997_reg_disable_suspend(struct regulator_dev *rdev)
>>  {
>>  	struct max8997_data *max8997 = rdev_get_drvdata(rdev);
>> -	struct i2c_client *i2c = max8997->iodev->i2c;
>>  	int ret, reg, mask, pattern;
>>  	int rid = rdev_get_id(rdev);
>>  
>> @@ -735,20 +730,22 @@ static int max8997_reg_disable_suspend(struct regulator_dev *rdev)
>>  	if (ret)
>>  		return ret;
>>  
>> -	max8997_read_reg(i2c, reg, &max8997->saved_states[rid]);
>> +	max8997_read_reg(max8997->iodev->regmap,
>> +			reg, &max8997->saved_states[rid]);
>>  
>>  	if (rid == MAX8997_LDO1 ||
>>  			rid == MAX8997_LDO10 ||
>>  			rid == MAX8997_LDO21) {
>>  		dev_dbg(&rdev->dev, "Conditional Power-Off for %s\n",
>>  				rdev->desc->name);
>> -		return max8997_update_reg(i2c, reg, 0x40, mask);
>> +		return max8997_update_reg(max8997->iodev->regmap,
>> +				reg, 0x40, mask);
>>  	}
>>  
>>  	dev_dbg(&rdev->dev, "Full Power-Off for %s (%xh -> %xh)\n",
>>  			rdev->desc->name, max8997->saved_states[rid] & mask,
>>  			(~pattern) & mask);
>> -	return max8997_update_reg(i2c, reg, ~pattern, mask);
>> +	return max8997_update_reg(max8997->iodev->regmap, reg, ~pattern, mask);
>>  }
>>  
>>  static struct regulator_ops max8997_ldo_ops = {
>> @@ -1032,7 +1029,6 @@ static int max8997_pmic_probe(struct platform_device *pdev)
>>  	struct regulator_config config = { };
>>  	struct regulator_dev **rdev;
>>  	struct max8997_data *max8997;
>> -	struct i2c_client *i2c;
>>  	int i, ret, size, nr_dvs;
>>  	u8 max_buck1 = 0, max_buck2 = 0, max_buck5 = 0;
>>  
>> @@ -1062,7 +1058,6 @@ static int max8997_pmic_probe(struct platform_device *pdev)
>>  	max8997->iodev = iodev;
>>  	max8997->num_regulators = pdata->num_regulators;
>>  	platform_set_drvdata(pdev, max8997);
>> -	i2c = max8997->iodev->i2c;
>>  
>>  	max8997->buck125_gpioindex = pdata->buck125_default_idx;
>>  	max8997->buck1_gpiodvs = pdata->buck1_gpiodvs;
>> @@ -1112,25 +1107,25 @@ static int max8997_pmic_probe(struct platform_device *pdev)
>>  
>>  	/* For the safety, set max voltage before setting up */
>>  	for (i = 0; i < 8; i++) {
>> -		max8997_update_reg(i2c, MAX8997_REG_BUCK1DVS1 + i,
>> -				max_buck1, 0x3f);
>> -		max8997_update_reg(i2c, MAX8997_REG_BUCK2DVS1 + i,
>> -				max_buck2, 0x3f);
>> -		max8997_update_reg(i2c, MAX8997_REG_BUCK5DVS1 + i,
>> -				max_buck5, 0x3f);
>> +		max8997_update_reg(max8997->iodev->regmap,
>> +				MAX8997_REG_BUCK1DVS1 + i, max_buck1, 0x3f);
>> +		max8997_update_reg(max8997->iodev->regmap,
>> +				MAX8997_REG_BUCK2DVS1 + i, max_buck2, 0x3f);
>> +		max8997_update_reg(max8997->iodev->regmap,
>> +				MAX8997_REG_BUCK5DVS1 + i, max_buck5, 0x3f);
>>  	}
>>  
>>  	/* Initialize all the DVS related BUCK registers */
>>  	for (i = 0; i < nr_dvs; i++) {
>> -		max8997_update_reg(i2c, MAX8997_REG_BUCK1DVS1 + i,
>> -				max8997->buck1_vol[i],
>> -				0x3f);
>> -		max8997_update_reg(i2c, MAX8997_REG_BUCK2DVS1 + i,
>> -				max8997->buck2_vol[i],
>> -				0x3f);
>> -		max8997_update_reg(i2c, MAX8997_REG_BUCK5DVS1 + i,
>> -				max8997->buck5_vol[i],
>> -				0x3f);
>> +		max8997_update_reg(max8997->iodev->regmap,
>> +				MAX8997_REG_BUCK1DVS1 + i,
>> +				max8997->buck1_vol[i], 0x3f);
>> +		max8997_update_reg(max8997->iodev->regmap,
>> +				MAX8997_REG_BUCK2DVS1 + i,
>> +				max8997->buck2_vol[i], 0x3f);
>> +		max8997_update_reg(max8997->iodev->regmap,
>> +				MAX8997_REG_BUCK5DVS1 + i,
>> +				max8997->buck5_vol[i], 0x3f);
>>  	}
>>  
>>  	/*
>> @@ -1174,16 +1169,17 @@ static int max8997_pmic_probe(struct platform_device *pdev)
>>  	}
>>  
>>  	/* DVS-GPIO disabled */
>> -	max8997_update_reg(i2c, MAX8997_REG_BUCK1CTRL, (pdata->buck1_gpiodvs) ?
>> -			(1 << 1) : (0 << 1), 1 << 1);
>> -	max8997_update_reg(i2c, MAX8997_REG_BUCK2CTRL, (pdata->buck2_gpiodvs) ?
>> -			(1 << 1) : (0 << 1), 1 << 1);
>> -	max8997_update_reg(i2c, MAX8997_REG_BUCK5CTRL, (pdata->buck5_gpiodvs) ?
>> -			(1 << 1) : (0 << 1), 1 << 1);
>> +	max8997_update_reg(max8997->iodev->regmap, MAX8997_REG_BUCK1CTRL,
>> +			(pdata->buck1_gpiodvs) ? (1 << 1) : (0 << 1), 1 << 1);
>> +	max8997_update_reg(max8997->iodev->regmap, MAX8997_REG_BUCK2CTRL,
>> +			(pdata->buck2_gpiodvs) ? (1 << 1) : (0 << 1), 1 << 1);
>> +	max8997_update_reg(max8997->iodev->regmap, MAX8997_REG_BUCK5CTRL,
>> +			(pdata->buck5_gpiodvs) ? (1 << 1) : (0 << 1), 1 << 1);
>>  
>>  	/* Misc Settings */
>>  	max8997->ramp_delay = 10; /* set 10mV/us, which is the default */
>> -	max8997_write_reg(i2c, MAX8997_REG_BUCKRAMP, (0xf << 4) | 0x9);
>> +	max8997_write_reg(max8997->iodev->regmap,
>> +			MAX8997_REG_BUCKRAMP, (0xf << 4) | 0x9);
>>  
>>  	for (i = 0; i < pdata->num_regulators; i++) {
>>  		const struct voltage_map_desc *desc;
>> diff --git a/drivers/rtc/rtc-max8997.c b/drivers/rtc/rtc-max8997.c
>> index 0777c01..218535c 100644
>> --- a/drivers/rtc/rtc-max8997.c
>> +++ b/drivers/rtc/rtc-max8997.c
>> @@ -68,7 +68,6 @@ enum {
>>  struct max8997_rtc_info {
>>  	struct device		*dev;
>>  	struct max8997_dev	*max8997;
>> -	struct i2c_client	*rtc;
>>  	struct rtc_device	*rtc_dev;
>>  	struct mutex		lock;
>>  	int virq;
>> @@ -118,8 +117,8 @@ static inline int max8997_rtc_set_update_reg(struct max8997_rtc_info *info)
>>  {
>>  	int ret;
>>  
>> -	ret = max8997_write_reg(info->rtc, MAX8997_RTC_UPDATE1,
>> -						RTC_UDR_MASK);
>> +	ret = max8997_write_reg(info->max8997->regmap_rtc,
>> +				MAX8997_RTC_UPDATE1, RTC_UDR_MASK);
>>  	if (ret < 0)
>>  		dev_err(info->dev, "%s: fail to write update reg(%d)\n",
>>  				__func__, ret);
>> @@ -140,7 +139,8 @@ static int max8997_rtc_read_time(struct device *dev, struct rtc_time *tm)
>>  	int ret;
>>  
>>  	mutex_lock(&info->lock);
>> -	ret = max8997_bulk_read(info->rtc, MAX8997_RTC_SEC, RTC_NR_TIME, data);
>> +	ret = max8997_bulk_read(info->max8997->regmap_rtc,
>> +				MAX8997_RTC_SEC, RTC_NR_TIME, data);
>>  	mutex_unlock(&info->lock);
>>  
>>  	if (ret < 0) {
>> @@ -166,7 +166,8 @@ static int max8997_rtc_set_time(struct device *dev, struct rtc_time *tm)
>>  
>>  	mutex_lock(&info->lock);
>>  
>> -	ret = max8997_bulk_write(info->rtc, MAX8997_RTC_SEC, RTC_NR_TIME, data);
>> +	ret = max8997_bulk_write(info->max8997->regmap_rtc,
>> +				MAX8997_RTC_SEC, RTC_NR_TIME, data);
>>  	if (ret < 0) {
>>  		dev_err(info->dev, "%s: fail to write time reg(%d)\n", __func__,
>>  				ret);
>> @@ -188,8 +189,8 @@ static int max8997_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm)
>>  
>>  	mutex_lock(&info->lock);
>>  
>> -	ret = max8997_bulk_read(info->rtc, MAX8997_RTC_ALARM1_SEC, RTC_NR_TIME,
>> -			data);
>> +	ret = max8997_bulk_read(info->max8997->regmap_rtc,
>> +				MAX8997_RTC_ALARM1_SEC, RTC_NR_TIME, data);
>>  	if (ret < 0) {
>>  		dev_err(info->dev, "%s:%d fail to read alarm reg(%d)\n",
>>  				__func__, __LINE__, ret);
>> @@ -207,7 +208,8 @@ static int max8997_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm)
>>  	}
>>  
>>  	alrm->pending = 0;
>> -	ret = max8997_read_reg(info->max8997->i2c, MAX8997_REG_STATUS1, &val);
>> +	ret = max8997_read_reg(info->max8997->regmap_rtc,
>> +			       MAX8997_REG_STATUS1, &val);
>>  	if (ret < 0) {
>>  		dev_err(info->dev, "%s:%d fail to read status1 reg(%d)\n",
>>  				__func__, __LINE__, ret);
>> @@ -230,8 +232,8 @@ static int max8997_rtc_stop_alarm(struct max8997_rtc_info *info)
>>  	if (!mutex_is_locked(&info->lock))
>>  		dev_warn(info->dev, "%s: should have mutex locked\n", __func__);
>>  
>> -	ret = max8997_bulk_read(info->rtc, MAX8997_RTC_ALARM1_SEC, RTC_NR_TIME,
>> -				data);
>> +	ret = max8997_bulk_read(info->max8997->regmap_rtc,
>> +				MAX8997_RTC_ALARM1_SEC, RTC_NR_TIME, data);
>>  	if (ret < 0) {
>>  		dev_err(info->dev, "%s: fail to read alarm reg(%d)\n",
>>  				__func__, ret);
>> @@ -241,8 +243,8 @@ static int max8997_rtc_stop_alarm(struct max8997_rtc_info *info)
>>  	for (i = 0; i < RTC_NR_TIME; i++)
>>  		data[i] &= ~ALARM_ENABLE_MASK;
>>  
>> -	ret = max8997_bulk_write(info->rtc, MAX8997_RTC_ALARM1_SEC, RTC_NR_TIME,
>> -				 data);
>> +	ret = max8997_bulk_write(info->max8997->regmap_rtc,
>> +				 MAX8997_RTC_ALARM1_SEC, RTC_NR_TIME, data);
>>  	if (ret < 0) {
>>  		dev_err(info->dev, "%s: fail to write alarm reg(%d)\n",
>>  				__func__, ret);
>> @@ -262,8 +264,8 @@ static int max8997_rtc_start_alarm(struct max8997_rtc_info *info)
>>  	if (!mutex_is_locked(&info->lock))
>>  		dev_warn(info->dev, "%s: should have mutex locked\n", __func__);
>>  
>> -	ret = max8997_bulk_read(info->rtc, MAX8997_RTC_ALARM1_SEC, RTC_NR_TIME,
>> -				data);
>> +	ret = max8997_bulk_read(info->max8997->regmap_rtc,
>> +				MAX8997_RTC_ALARM1_SEC, RTC_NR_TIME, data);
>>  	if (ret < 0) {
>>  		dev_err(info->dev, "%s: fail to read alarm reg(%d)\n",
>>  				__func__, ret);
>> @@ -281,8 +283,8 @@ static int max8997_rtc_start_alarm(struct max8997_rtc_info *info)
>>  	if (data[RTC_DATE] & 0x1f)
>>  		data[RTC_DATE] |= (1 << ALARM_ENABLE_SHIFT);
>>  
>> -	ret = max8997_bulk_write(info->rtc, MAX8997_RTC_ALARM1_SEC, RTC_NR_TIME,
>> -				 data);
>> +	ret = max8997_bulk_write(info->max8997->regmap_rtc,
>> +				 MAX8997_RTC_ALARM1_SEC, RTC_NR_TIME, data);
>>  	if (ret < 0) {
>>  		dev_err(info->dev, "%s: fail to write alarm reg(%d)\n",
>>  				__func__, ret);
>> @@ -313,8 +315,8 @@ static int max8997_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm)
>>  	if (ret < 0)
>>  		goto out;
>>  
>> -	ret = max8997_bulk_write(info->rtc, MAX8997_RTC_ALARM1_SEC, RTC_NR_TIME,
>> -				data);
>> +	ret = max8997_bulk_write(info->max8997->regmap_rtc,
>> +				 MAX8997_RTC_ALARM1_SEC, RTC_NR_TIME, data);
>>  	if (ret < 0) {
>>  		dev_err(info->dev, "%s: fail to write alarm reg(%d)\n",
>>  				__func__, ret);
>> @@ -385,7 +387,8 @@ static void max8997_rtc_enable_wtsr(struct max8997_rtc_info *info, bool enable)
>>  	dev_info(info->dev, "%s: %s WTSR\n", __func__,
>>  			enable ? "enable" : "disable");
>>  
>> -	ret = max8997_update_reg(info->rtc, MAX8997_RTC_WTSR_SMPL, val, mask);
>> +	ret = max8997_update_reg(info->max8997->regmap_rtc,
>> +				 MAX8997_RTC_WTSR_SMPL, val, mask);
>>  	if (ret < 0) {
>>  		dev_err(info->dev, "%s: fail to update WTSR reg(%d)\n",
>>  				__func__, ret);
>> @@ -413,7 +416,8 @@ static void max8997_rtc_enable_smpl(struct max8997_rtc_info *info, bool enable)
>>  	dev_info(info->dev, "%s: %s SMPL\n", __func__,
>>  			enable ? "enable" : "disable");
>>  
>> -	ret = max8997_update_reg(info->rtc, MAX8997_RTC_WTSR_SMPL, val, mask);
>> +	ret = max8997_update_reg(info->max8997->regmap_rtc,
>> +				 MAX8997_RTC_WTSR_SMPL, val, mask);
>>  	if (ret < 0) {
>>  		dev_err(info->dev, "%s: fail to update SMPL reg(%d)\n",
>>  				__func__, ret);
>> @@ -423,7 +427,8 @@ static void max8997_rtc_enable_smpl(struct max8997_rtc_info *info, bool enable)
>>  	max8997_rtc_set_update_reg(info);
>>  
>>  	val = 0;
>> -	max8997_read_reg(info->rtc, MAX8997_RTC_WTSR_SMPL, &val);
>> +	max8997_read_reg(info->max8997->regmap_rtc,
>> +			 MAX8997_RTC_WTSR_SMPL, &val);
>>  	pr_info("%s: WTSR_SMPL(0x%02x)\n", __func__, val);
>>  }
>>  
>> @@ -438,7 +443,8 @@ static int max8997_rtc_init_reg(struct max8997_rtc_info *info)
>>  
>>  	info->rtc_24hr_mode = 1;
>>  
>> -	ret = max8997_bulk_write(info->rtc, MAX8997_RTC_CTRLMASK, 2, data);
>> +	ret = max8997_bulk_write(info->max8997->regmap_rtc,
>> +				 MAX8997_RTC_CTRLMASK, 2, data);
>>  	if (ret < 0) {
>>  		dev_err(info->dev, "%s: fail to write controlm reg(%d)\n",
>>  				__func__, ret);
>> @@ -463,7 +469,6 @@ static int max8997_rtc_probe(struct platform_device *pdev)
>>  	mutex_init(&info->lock);
>>  	info->dev = &pdev->dev;
>>  	info->max8997 = max8997;
>> -	info->rtc = max8997->rtc;
>>  
>>  	platform_set_drvdata(pdev, info);
>>  
>> diff --git a/include/linux/mfd/max8997-private.h b/include/linux/mfd/max8997-private.h
>> index ad1ae7f..184e40a 100644
>> --- a/include/linux/mfd/max8997-private.h
>> +++ b/include/linux/mfd/max8997-private.h
>> @@ -309,6 +309,8 @@ enum max8997_rtc_reg {
>>  	MAX8997_RTC_ALARM2_MONTH	= 0x22,
>>  	MAX8997_RTC_ALARM2_YEAR		= 0x23,
>>  	MAX8997_RTC_ALARM2_DAY_OF_MONTH	= 0x24,
>> +
>> +	MAX8997_RTC_REG_END		= 0x25,
>>  };
>>  
>>  enum max8997_irq_source {
>> @@ -390,6 +392,11 @@ struct max8997_dev {
>>  	int type;
>>  	struct platform_device *battery; /* battery control (not fuel gauge) */
>>  
>> +	struct regmap *regmap;
>> +	struct regmap *regmap_rtc;
>> +	struct regmap *regmap_haptic;
>> +	struct regmap *regmap_muic;
>> +
>>  	int irq;
>>  	int ono;
>>  	struct irq_domain *irq_domain;
>> @@ -413,13 +420,11 @@ extern int max8997_irq_init(struct max8997_dev *max8997);
>>  extern void max8997_irq_exit(struct max8997_dev *max8997);
>>  extern int max8997_irq_resume(struct max8997_dev *max8997);
>>  
>> -extern int max8997_read_reg(struct i2c_client *i2c, u8 reg, u8 *dest);
>> -extern int max8997_bulk_read(struct i2c_client *i2c, u8 reg, int count,
>> -				u8 *buf);
>> -extern int max8997_write_reg(struct i2c_client *i2c, u8 reg, u8 value);
>> -extern int max8997_bulk_write(struct i2c_client *i2c, u8 reg, int count,
>> -				u8 *buf);
>> -extern int max8997_update_reg(struct i2c_client *i2c, u8 reg, u8 val, u8 mask);
>> +extern int max8997_read_reg(struct regmap *map, u8 reg, u8 *dest);
>> +extern int max8997_bulk_read(struct regmap *map, u8 reg, int count, u8 *buf);
>> +extern int max8997_write_reg(struct regmap *map, u8 reg, u8 value);
>> +extern int max8997_bulk_write(struct regmap *map, u8 reg, int count, u8 *buf);
>> +extern int max8997_update_reg(struct regmap *map, u8 reg, u8 val, u8 mask);
>>  
>>  #define MAX8997_GPIO_INT_BOTH	(0x3 << 4)
>>  #define MAX8997_GPIO_INT_RISE	(0x2 << 4)
>>
> 
> 

^ permalink raw reply

* Re: Re: [PATCH 0/7] mfd: AXP20x: Add support for AXP202 and AXP209
From: Hans de Goede @ 2014-03-06 10:07 UTC (permalink / raw)
  To: Carlo Caione
  Cc: linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	maxime.ripard-wi1+55ScJUtKEb57/3fJTNBPR1lH4CV8,
	emilio-0Z03zUJReD5OxF6Tv1QG9Q, wens-jdAy2FN1RRM,
	sameo-VuQAYsv1563Yd54FQh9/CA, lee.jones-QSEj5FYQhm4dnm+yROfE0A,
	devicetree-u79uwXL29TY76Z2rM5mHXA,
	dmitry.torokhov-Re5JQEeQqe8AvxtiuMwx3w,
	linux-input-u79uwXL29TY76Z2rM5mHXA,
	linux-doc-u79uwXL29TY76Z2rM5mHXA,
	lgirdwood-Re5JQEeQqe8AvxtiuMwx3w, broonie-DgEjT+Ai2ygdnm+yROfE0A,
	linux-sunxi-/JYPxA39Uh5TLH3MbocFFw
In-Reply-To: <CAOQ7t2bx1u73kxQVa3AeQ-hZ9nP3GSukEdXk-jRNwbT0vUH4+A-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>

Hi,

On 03/05/2014 09:46 PM, Carlo Caione wrote:
> On Wed, Mar 5, 2014 at 9:02 PM, Hans de Goede <hdegoede-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org> wrote:
>>
>> So I've added your patches to my sunxi-devel tree and they work as advertised :)
> 
> Thank you for keeping the tree updated :)
> 
>> I've also added dt support for the axp209 to the cubietruck dts file, to avoid
>> things becoming a copy and paste fest I've introduced a new axp209.dtsi file,
>> as well as did some fixes to the existing sun?i-a*.dtsi files, see my tree here:
>> https://github.com/jwrdegoede/linux-sunxi/commits/sunxi-devel
> 
> That was also my idea (creating a new axp20x.dtsi) but it has been
> turned down by Maxime and Lee

Hmm, do you have a pointer to the mailinglist discussion about this ?

Regards,

Hans

^ permalink raw reply

* Re: Re: [PATCH 0/7] mfd: AXP20x: Add support for AXP202 and AXP209
From: Carlo Caione @ 2014-03-06 10:10 UTC (permalink / raw)
  To: Hans de Goede
  Cc: linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r, Maxime Ripard,
	emilio-0Z03zUJReD5OxF6Tv1QG9Q, wens Tsai,
	sameo-VuQAYsv1563Yd54FQh9/CA, Lee Jones,
	devicetree-u79uwXL29TY76Z2rM5mHXA, Dmitry Torokhov,
	linux-input-u79uwXL29TY76Z2rM5mHXA,
	linux-doc-u79uwXL29TY76Z2rM5mHXA, Liam Girdwood,
	broonie-DgEjT+Ai2ygdnm+yROfE0A,
	linux-sunxi-/JYPxA39Uh5TLH3MbocFFw
In-Reply-To: <531848E5.4050704-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>

On Thu, Mar 6, 2014 at 11:07 AM, Hans de Goede <hdegoede-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org> wrote:
> Hi,
>
> On 03/05/2014 09:46 PM, Carlo Caione wrote:
>> On Wed, Mar 5, 2014 at 9:02 PM, Hans de Goede <hdegoede-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org> wrote:
>>>
>>> So I've added your patches to my sunxi-devel tree and they work as advertised :)
>>
>> Thank you for keeping the tree updated :)
>>
>>> I've also added dt support for the axp209 to the cubietruck dts file, to avoid
>>> things becoming a copy and paste fest I've introduced a new axp209.dtsi file,
>>> as well as did some fixes to the existing sun?i-a*.dtsi files, see my tree here:
>>> https://github.com/jwrdegoede/linux-sunxi/commits/sunxi-devel
>>
>> That was also my idea (creating a new axp20x.dtsi) but it has been
>> turned down by Maxime and Lee
>
> Hmm, do you have a pointer to the mailinglist discussion about this ?

Sure, http://www.spinics.net/lists/arm-kernel/msg306497.html

Best,

-- 
Carlo Caione

^ permalink raw reply

* Re: Re: [PATCH 0/7] mfd: AXP20x: Add support for AXP202 and AXP209
From: Hans de Goede @ 2014-03-06 11:05 UTC (permalink / raw)
  To: linux-sunxi-/JYPxA39Uh5TLH3MbocFFw
  Cc: linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r, Maxime Ripard,
	emilio-0Z03zUJReD5OxF6Tv1QG9Q, wens Tsai,
	sameo-VuQAYsv1563Yd54FQh9/CA, Lee Jones,
	devicetree-u79uwXL29TY76Z2rM5mHXA, Dmitry Torokhov,
	linux-input-u79uwXL29TY76Z2rM5mHXA,
	linux-doc-u79uwXL29TY76Z2rM5mHXA, Liam Girdwood,
	broonie-DgEjT+Ai2ygdnm+yROfE0A
In-Reply-To: <CAOQ7t2aVchEe0Mtbp8KV4ZTzE_0C0BeO15S7aF4nJx6PaBno=w@mail.gmail.com>

Hi,

On 03/06/2014 11:10 AM, Carlo Caione wrote:
> On Thu, Mar 6, 2014 at 11:07 AM, Hans de Goede <hdegoede-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org> wrote:
>> Hi,
>>
>> On 03/05/2014 09:46 PM, Carlo Caione wrote:
>>> On Wed, Mar 5, 2014 at 9:02 PM, Hans de Goede <hdegoede-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org> wrote:
>>>>
>>>> So I've added your patches to my sunxi-devel tree and they work as advertised :)
>>>
>>> Thank you for keeping the tree updated :)
>>>
>>>> I've also added dt support for the axp209 to the cubietruck dts file, to avoid
>>>> things becoming a copy and paste fest I've introduced a new axp209.dtsi file,
>>>> as well as did some fixes to the existing sun?i-a*.dtsi files, see my tree here:
>>>> https://github.com/jwrdegoede/linux-sunxi/commits/sunxi-devel
>>>
>>> That was also my idea (creating a new axp20x.dtsi) but it has been
>>> turned down by Maxime and Lee
>>
>> Hmm, do you have a pointer to the mailinglist discussion about this ?
> 
> Sure, http://www.spinics.net/lists/arm-kernel/msg306497.html

Ah, yes but that is before you added all the regulators, which are a fixed part
of the chip. Once you get long dts bits like that having a dtsi file makes a lot
of sense IMHO. Note that the part of the dts this was discussing is actually the part
I did not put in the dtis, since it can vary per board :)

Regards,

Hans

^ permalink raw reply


This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox