All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 0/5] mfd: twl: improvements and new regulator driver
@ 2016-11-26 18:13 ` Nicolae Rosia
  0 siblings, 0 replies; 38+ messages in thread
From: Nicolae Rosia @ 2016-11-26 18:13 UTC (permalink / raw)
  To: Lee Jones, Mark Brown, Rob Herring, Mark Rutland, Tony Lindgren
  Cc: Liam Girdwood, Paul Gortmaker, Graeme Gregory, Baruch Siach,
	linux-omap, linux-arm-kernel, linux-kernel, devicetree,
	Nicolae Rosia

Hello,

The current TWL MFD driver has a number of problems which are
very well described by Russell King [0].
This series attemps to fix this by making the driver's private
structure available to child nodes.
A regulator driver for TWL6032 which makes use of the private
drvdata is introduced.
A driver for TWL6032 PMIC already exists in mainline,
twl-regulator, but it has the following drawbacks:
* has no mainline users
* it does not follow the recommended regulators binding since
it uses a compatible string for every regulator;
* it is broken
** the features flag is not set, hence the TWL6032
support is broken since it depends on TWL6032_SUBCLASS flag;
** even with that fixed, bit manipulations are wrong

If this receives positive feedback, I could convert all TWL drivers
to use drvdata, then get rid of the exported symbols.

[0] https://www.spinics.net/lists/linux-omap/msg133387.html

Nicolae Rosia (5):
  mfd: twl-core: make driver DT only
  mfd: twl: remove useless header
  mfd: twl: move structure definitions to a public header
  regulator: Add support for TI TWL6032
  mfd: twl: use mfd_add_devices for TWL6032 regulator

 .../bindings/regulator/twl6032-regulator.txt       | 109 ++++
 drivers/mfd/Kconfig                                |   1 +
 drivers/mfd/twl-core.c                             | 444 ++--------------
 drivers/mfd/twl-core.h                             |  10 -
 drivers/mfd/twl4030-irq.c                          |   2 -
 drivers/mfd/twl6030-irq.c                          |   2 -
 drivers/regulator/Kconfig                          |   7 +
 drivers/regulator/Makefile                         |   1 +
 drivers/regulator/twl6032-regulator.c              | 582 +++++++++++++++++++++
 include/linux/mfd/twl-core.h                       |  35 ++
 10 files changed, 768 insertions(+), 425 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/regulator/twl6032-regulator.txt
 delete mode 100644 drivers/mfd/twl-core.h
 create mode 100644 drivers/regulator/twl6032-regulator.c
 create mode 100644 include/linux/mfd/twl-core.h

-- 
2.9.3

^ permalink raw reply	[flat|nested] 38+ messages in thread

* [PATCH 0/5] mfd: twl: improvements and new regulator driver
@ 2016-11-26 18:13 ` Nicolae Rosia
  0 siblings, 0 replies; 38+ messages in thread
From: Nicolae Rosia @ 2016-11-26 18:13 UTC (permalink / raw)
  To: Lee Jones, Mark Brown, Rob Herring, Mark Rutland, Tony Lindgren
  Cc: Liam Girdwood, Paul Gortmaker, Graeme Gregory, Baruch Siach,
	linux-omap-u79uwXL29TY76Z2rM5mHXA,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	devicetree-u79uwXL29TY76Z2rM5mHXA, Nicolae Rosia

Hello,

The current TWL MFD driver has a number of problems which are
very well described by Russell King [0].
This series attemps to fix this by making the driver's private
structure available to child nodes.
A regulator driver for TWL6032 which makes use of the private
drvdata is introduced.
A driver for TWL6032 PMIC already exists in mainline,
twl-regulator, but it has the following drawbacks:
* has no mainline users
* it does not follow the recommended regulators binding since
it uses a compatible string for every regulator;
* it is broken
** the features flag is not set, hence the TWL6032
support is broken since it depends on TWL6032_SUBCLASS flag;
** even with that fixed, bit manipulations are wrong

If this receives positive feedback, I could convert all TWL drivers
to use drvdata, then get rid of the exported symbols.

[0] https://www.spinics.net/lists/linux-omap/msg133387.html

Nicolae Rosia (5):
  mfd: twl-core: make driver DT only
  mfd: twl: remove useless header
  mfd: twl: move structure definitions to a public header
  regulator: Add support for TI TWL6032
  mfd: twl: use mfd_add_devices for TWL6032 regulator

 .../bindings/regulator/twl6032-regulator.txt       | 109 ++++
 drivers/mfd/Kconfig                                |   1 +
 drivers/mfd/twl-core.c                             | 444 ++--------------
 drivers/mfd/twl-core.h                             |  10 -
 drivers/mfd/twl4030-irq.c                          |   2 -
 drivers/mfd/twl6030-irq.c                          |   2 -
 drivers/regulator/Kconfig                          |   7 +
 drivers/regulator/Makefile                         |   1 +
 drivers/regulator/twl6032-regulator.c              | 582 +++++++++++++++++++++
 include/linux/mfd/twl-core.h                       |  35 ++
 10 files changed, 768 insertions(+), 425 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/regulator/twl6032-regulator.txt
 delete mode 100644 drivers/mfd/twl-core.h
 create mode 100644 drivers/regulator/twl6032-regulator.c
 create mode 100644 include/linux/mfd/twl-core.h

-- 
2.9.3

--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 38+ messages in thread

* [PATCH 0/5] mfd: twl: improvements and new regulator driver
@ 2016-11-26 18:13 ` Nicolae Rosia
  0 siblings, 0 replies; 38+ messages in thread
From: Nicolae Rosia @ 2016-11-26 18:13 UTC (permalink / raw)
  To: linux-arm-kernel

Hello,

The current TWL MFD driver has a number of problems which are
very well described by Russell King [0].
This series attemps to fix this by making the driver's private
structure available to child nodes.
A regulator driver for TWL6032 which makes use of the private
drvdata is introduced.
A driver for TWL6032 PMIC already exists in mainline,
twl-regulator, but it has the following drawbacks:
* has no mainline users
* it does not follow the recommended regulators binding since
it uses a compatible string for every regulator;
* it is broken
** the features flag is not set, hence the TWL6032
support is broken since it depends on TWL6032_SUBCLASS flag;
** even with that fixed, bit manipulations are wrong

If this receives positive feedback, I could convert all TWL drivers
to use drvdata, then get rid of the exported symbols.

[0] https://www.spinics.net/lists/linux-omap/msg133387.html

Nicolae Rosia (5):
  mfd: twl-core: make driver DT only
  mfd: twl: remove useless header
  mfd: twl: move structure definitions to a public header
  regulator: Add support for TI TWL6032
  mfd: twl: use mfd_add_devices for TWL6032 regulator

 .../bindings/regulator/twl6032-regulator.txt       | 109 ++++
 drivers/mfd/Kconfig                                |   1 +
 drivers/mfd/twl-core.c                             | 444 ++--------------
 drivers/mfd/twl-core.h                             |  10 -
 drivers/mfd/twl4030-irq.c                          |   2 -
 drivers/mfd/twl6030-irq.c                          |   2 -
 drivers/regulator/Kconfig                          |   7 +
 drivers/regulator/Makefile                         |   1 +
 drivers/regulator/twl6032-regulator.c              | 582 +++++++++++++++++++++
 include/linux/mfd/twl-core.h                       |  35 ++
 10 files changed, 768 insertions(+), 425 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/regulator/twl6032-regulator.txt
 delete mode 100644 drivers/mfd/twl-core.h
 create mode 100644 drivers/regulator/twl6032-regulator.c
 create mode 100644 include/linux/mfd/twl-core.h

-- 
2.9.3

^ permalink raw reply	[flat|nested] 38+ messages in thread

* [PATCH 1/5] mfd: twl-core: make driver DT only
  2016-11-26 18:13 ` Nicolae Rosia
  (?)
@ 2016-11-26 18:13   ` Nicolae Rosia
  -1 siblings, 0 replies; 38+ messages in thread
From: Nicolae Rosia @ 2016-11-26 18:13 UTC (permalink / raw)
  To: Lee Jones, Mark Brown, Rob Herring, Mark Rutland, Tony Lindgren
  Cc: Liam Girdwood, Paul Gortmaker, Graeme Gregory, Baruch Siach,
	linux-omap, linux-arm-kernel, linux-kernel, devicetree,
	Nicolae Rosia

All users are DT-only and it makes no sense to keep
unused code

Signed-off-by: Nicolae Rosia <Nicolae_Rosia@mentor.com>
---
 drivers/mfd/Kconfig    |   1 +
 drivers/mfd/twl-core.c | 399 +------------------------------------------------
 2 files changed, 8 insertions(+), 392 deletions(-)

diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig
index c6df644..c180f8b 100644
--- a/drivers/mfd/Kconfig
+++ b/drivers/mfd/Kconfig
@@ -1333,6 +1333,7 @@ config MFD_TPS80031
 config TWL4030_CORE
 	bool "TI TWL4030/TWL5030/TWL6030/TPS659x0 Support"
 	depends on I2C=y
+	depends on OF
 	select IRQ_DOMAIN
 	select REGMAP_I2C
 	help
diff --git a/drivers/mfd/twl-core.c b/drivers/mfd/twl-core.c
index c64615d..48b0668 100644
--- a/drivers/mfd/twl-core.c
+++ b/drivers/mfd/twl-core.c
@@ -13,6 +13,9 @@
  * Code cleanup and modifications to IRQ handler.
  * by syed khasim <x0khasim@ti.com>
  *
+ * Code cleanup and modifications:
+ * Copyright (C) 2016 Nicolae Rosia <nicolae.rosia@gmail.com>
+ *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
@@ -604,376 +607,6 @@ int twl_get_hfclk_rate(void)
 }
 EXPORT_SYMBOL_GPL(twl_get_hfclk_rate);
 
-static struct device *
-add_numbered_child(unsigned mod_no, const char *name, int num,
-		void *pdata, unsigned pdata_len,
-		bool can_wakeup, int irq0, int irq1)
-{
-	struct platform_device	*pdev;
-	struct twl_client	*twl;
-	int			status, sid;
-
-	if (unlikely(mod_no >= twl_get_last_module())) {
-		pr_err("%s: invalid module number %d\n", DRIVER_NAME, mod_no);
-		return ERR_PTR(-EPERM);
-	}
-	sid = twl_priv->twl_map[mod_no].sid;
-	twl = &twl_priv->twl_modules[sid];
-
-	pdev = platform_device_alloc(name, num);
-	if (!pdev)
-		return ERR_PTR(-ENOMEM);
-
-	pdev->dev.parent = &twl->client->dev;
-
-	if (pdata) {
-		status = platform_device_add_data(pdev, pdata, pdata_len);
-		if (status < 0) {
-			dev_dbg(&pdev->dev, "can't add platform_data\n");
-			goto put_device;
-		}
-	}
-
-	if (irq0) {
-		struct resource r[2] = {
-			{ .start = irq0, .flags = IORESOURCE_IRQ, },
-			{ .start = irq1, .flags = IORESOURCE_IRQ, },
-		};
-
-		status = platform_device_add_resources(pdev, r, irq1 ? 2 : 1);
-		if (status < 0) {
-			dev_dbg(&pdev->dev, "can't add irqs\n");
-			goto put_device;
-		}
-	}
-
-	status = platform_device_add(pdev);
-	if (status)
-		goto put_device;
-
-	device_init_wakeup(&pdev->dev, can_wakeup);
-
-	return &pdev->dev;
-
-put_device:
-	platform_device_put(pdev);
-	dev_err(&twl->client->dev, "failed to add device %s\n", name);
-	return ERR_PTR(status);
-}
-
-static inline struct device *add_child(unsigned mod_no, const char *name,
-		void *pdata, unsigned pdata_len,
-		bool can_wakeup, int irq0, int irq1)
-{
-	return add_numbered_child(mod_no, name, -1, pdata, pdata_len,
-		can_wakeup, irq0, irq1);
-}
-
-static struct device *
-add_regulator_linked(int num, struct regulator_init_data *pdata,
-		struct regulator_consumer_supply *consumers,
-		unsigned num_consumers, unsigned long features)
-{
-	struct twl_regulator_driver_data drv_data;
-
-	/* regulator framework demands init_data ... */
-	if (!pdata)
-		return NULL;
-
-	if (consumers) {
-		pdata->consumer_supplies = consumers;
-		pdata->num_consumer_supplies = num_consumers;
-	}
-
-	if (pdata->driver_data) {
-		/* If we have existing drv_data, just add the flags */
-		struct twl_regulator_driver_data *tmp;
-		tmp = pdata->driver_data;
-		tmp->features |= features;
-	} else {
-		/* add new driver data struct, used only during init */
-		drv_data.features = features;
-		drv_data.set_voltage = NULL;
-		drv_data.get_voltage = NULL;
-		drv_data.data = NULL;
-		pdata->driver_data = &drv_data;
-	}
-
-	/* NOTE:  we currently ignore regulator IRQs, e.g. for short circuits */
-	return add_numbered_child(TWL_MODULE_PM_MASTER, "twl_reg", num,
-		pdata, sizeof(*pdata), false, 0, 0);
-}
-
-static struct device *
-add_regulator(int num, struct regulator_init_data *pdata,
-		unsigned long features)
-{
-	return add_regulator_linked(num, pdata, NULL, 0, features);
-}
-
-/*
- * NOTE:  We know the first 8 IRQs after pdata->base_irq are
- * for the PIH, and the next are for the PWR_INT SIH, since
- * that's how twl_init_irq() sets things up.
- */
-
-static int
-add_children(struct twl4030_platform_data *pdata, unsigned irq_base,
-		unsigned long features)
-{
-	struct device	*child;
-
-	if (IS_ENABLED(CONFIG_GPIO_TWL4030) && pdata->gpio) {
-		child = add_child(TWL4030_MODULE_GPIO, "twl4030_gpio",
-				pdata->gpio, sizeof(*pdata->gpio),
-				false, irq_base + GPIO_INTR_OFFSET, 0);
-		if (IS_ERR(child))
-			return PTR_ERR(child);
-	}
-
-	if (IS_ENABLED(CONFIG_KEYBOARD_TWL4030) && pdata->keypad) {
-		child = add_child(TWL4030_MODULE_KEYPAD, "twl4030_keypad",
-				pdata->keypad, sizeof(*pdata->keypad),
-				true, irq_base + KEYPAD_INTR_OFFSET, 0);
-		if (IS_ERR(child))
-			return PTR_ERR(child);
-	}
-
-	if (IS_ENABLED(CONFIG_TWL4030_MADC) && pdata->madc &&
-	    twl_class_is_4030()) {
-		child = add_child(TWL4030_MODULE_MADC, "twl4030_madc",
-				pdata->madc, sizeof(*pdata->madc),
-				true, irq_base + MADC_INTR_OFFSET, 0);
-		if (IS_ERR(child))
-			return PTR_ERR(child);
-	}
-
-	if (IS_ENABLED(CONFIG_RTC_DRV_TWL4030)) {
-		/*
-		 * REVISIT platform_data here currently might expose the
-		 * "msecure" line ... but for now we just expect board
-		 * setup to tell the chip "it's always ok to SET_TIME".
-		 * Eventually, Linux might become more aware of such
-		 * HW security concerns, and "least privilege".
-		 */
-		child = add_child(TWL_MODULE_RTC, "twl_rtc", NULL, 0,
-				true, irq_base + RTC_INTR_OFFSET, 0);
-		if (IS_ERR(child))
-			return PTR_ERR(child);
-	}
-
-	if (IS_ENABLED(CONFIG_PWM_TWL)) {
-		child = add_child(TWL_MODULE_PWM, "twl-pwm", NULL, 0,
-				  false, 0, 0);
-		if (IS_ERR(child))
-			return PTR_ERR(child);
-	}
-
-	if (IS_ENABLED(CONFIG_PWM_TWL_LED)) {
-		child = add_child(TWL_MODULE_LED, "twl-pwmled", NULL, 0,
-				  false, 0, 0);
-		if (IS_ERR(child))
-			return PTR_ERR(child);
-	}
-
-	if (IS_ENABLED(CONFIG_TWL4030_USB) && pdata->usb &&
-	    twl_class_is_4030()) {
-
-		static struct regulator_consumer_supply usb1v5 = {
-			.supply =	"usb1v5",
-		};
-		static struct regulator_consumer_supply usb1v8 = {
-			.supply =	"usb1v8",
-		};
-		static struct regulator_consumer_supply usb3v1 = {
-			.supply =	"usb3v1",
-		};
-
-	/* First add the regulators so that they can be used by transceiver */
-		if (IS_ENABLED(CONFIG_REGULATOR_TWL4030)) {
-			/* this is a template that gets copied */
-			struct regulator_init_data usb_fixed = {
-				.constraints.valid_modes_mask =
-					REGULATOR_MODE_NORMAL
-					| REGULATOR_MODE_STANDBY,
-				.constraints.valid_ops_mask =
-					REGULATOR_CHANGE_MODE
-					| REGULATOR_CHANGE_STATUS,
-			};
-
-			child = add_regulator_linked(TWL4030_REG_VUSB1V5,
-						      &usb_fixed, &usb1v5, 1,
-						      features);
-			if (IS_ERR(child))
-				return PTR_ERR(child);
-
-			child = add_regulator_linked(TWL4030_REG_VUSB1V8,
-						      &usb_fixed, &usb1v8, 1,
-						      features);
-			if (IS_ERR(child))
-				return PTR_ERR(child);
-
-			child = add_regulator_linked(TWL4030_REG_VUSB3V1,
-						      &usb_fixed, &usb3v1, 1,
-						      features);
-			if (IS_ERR(child))
-				return PTR_ERR(child);
-
-		}
-
-		child = add_child(TWL_MODULE_USB, "twl4030_usb",
-				pdata->usb, sizeof(*pdata->usb), true,
-				/* irq0 = USB_PRES, irq1 = USB */
-				irq_base + USB_PRES_INTR_OFFSET,
-				irq_base + USB_INTR_OFFSET);
-
-		if (IS_ERR(child))
-			return PTR_ERR(child);
-
-		/* we need to connect regulators to this transceiver */
-		if (IS_ENABLED(CONFIG_REGULATOR_TWL4030) && child) {
-			usb1v5.dev_name = dev_name(child);
-			usb1v8.dev_name = dev_name(child);
-			usb3v1.dev_name = dev_name(child);
-		}
-	}
-
-	if (IS_ENABLED(CONFIG_TWL4030_WATCHDOG) && twl_class_is_4030()) {
-		child = add_child(TWL_MODULE_PM_RECEIVER, "twl4030_wdt", NULL,
-				  0, false, 0, 0);
-		if (IS_ERR(child))
-			return PTR_ERR(child);
-	}
-
-	if (IS_ENABLED(CONFIG_INPUT_TWL4030_PWRBUTTON) && twl_class_is_4030()) {
-		child = add_child(TWL_MODULE_PM_MASTER, "twl4030_pwrbutton",
-				  NULL, 0, true, irq_base + 8 + 0, 0);
-		if (IS_ERR(child))
-			return PTR_ERR(child);
-	}
-
-	if (IS_ENABLED(CONFIG_MFD_TWL4030_AUDIO) && pdata->audio &&
-	    twl_class_is_4030()) {
-		child = add_child(TWL4030_MODULE_AUDIO_VOICE, "twl4030-audio",
-				pdata->audio, sizeof(*pdata->audio),
-				false, 0, 0);
-		if (IS_ERR(child))
-			return PTR_ERR(child);
-	}
-
-	/* twl4030 regulators */
-	if (IS_ENABLED(CONFIG_REGULATOR_TWL4030) && twl_class_is_4030()) {
-		child = add_regulator(TWL4030_REG_VPLL1, pdata->vpll1,
-					features);
-		if (IS_ERR(child))
-			return PTR_ERR(child);
-
-		child = add_regulator(TWL4030_REG_VIO, pdata->vio,
-					features);
-		if (IS_ERR(child))
-			return PTR_ERR(child);
-
-		child = add_regulator(TWL4030_REG_VDD1, pdata->vdd1,
-					features);
-		if (IS_ERR(child))
-			return PTR_ERR(child);
-
-		child = add_regulator(TWL4030_REG_VDD2, pdata->vdd2,
-					features);
-		if (IS_ERR(child))
-			return PTR_ERR(child);
-
-		child = add_regulator(TWL4030_REG_VMMC1, pdata->vmmc1,
-					features);
-		if (IS_ERR(child))
-			return PTR_ERR(child);
-
-		child = add_regulator(TWL4030_REG_VDAC, pdata->vdac,
-					features);
-		if (IS_ERR(child))
-			return PTR_ERR(child);
-
-		child = add_regulator((features & TWL4030_VAUX2)
-					? TWL4030_REG_VAUX2_4030
-					: TWL4030_REG_VAUX2,
-				pdata->vaux2, features);
-		if (IS_ERR(child))
-			return PTR_ERR(child);
-
-		child = add_regulator(TWL4030_REG_VINTANA1, pdata->vintana1,
-					features);
-		if (IS_ERR(child))
-			return PTR_ERR(child);
-
-		child = add_regulator(TWL4030_REG_VINTANA2, pdata->vintana2,
-					features);
-		if (IS_ERR(child))
-			return PTR_ERR(child);
-
-		child = add_regulator(TWL4030_REG_VINTDIG, pdata->vintdig,
-					features);
-		if (IS_ERR(child))
-			return PTR_ERR(child);
-	}
-
-	/* maybe add LDOs that are omitted on cost-reduced parts */
-	if (IS_ENABLED(CONFIG_REGULATOR_TWL4030) && !(features & TPS_SUBSET)
-	  && twl_class_is_4030()) {
-		child = add_regulator(TWL4030_REG_VPLL2, pdata->vpll2,
-					features);
-		if (IS_ERR(child))
-			return PTR_ERR(child);
-
-		child = add_regulator(TWL4030_REG_VMMC2, pdata->vmmc2,
-					features);
-		if (IS_ERR(child))
-			return PTR_ERR(child);
-
-		child = add_regulator(TWL4030_REG_VSIM, pdata->vsim,
-					features);
-		if (IS_ERR(child))
-			return PTR_ERR(child);
-
-		child = add_regulator(TWL4030_REG_VAUX1, pdata->vaux1,
-					features);
-		if (IS_ERR(child))
-			return PTR_ERR(child);
-
-		child = add_regulator(TWL4030_REG_VAUX3, pdata->vaux3,
-					features);
-		if (IS_ERR(child))
-			return PTR_ERR(child);
-
-		child = add_regulator(TWL4030_REG_VAUX4, pdata->vaux4,
-					features);
-		if (IS_ERR(child))
-			return PTR_ERR(child);
-	}
-
-	if (IS_ENABLED(CONFIG_CHARGER_TWL4030) && pdata->bci &&
-			!(features & (TPS_SUBSET | TWL5031))) {
-		child = add_child(TWL_MODULE_MAIN_CHARGE, "twl4030_bci",
-				pdata->bci, sizeof(*pdata->bci), false,
-				/* irq0 = CHG_PRES, irq1 = BCI */
-				irq_base + BCI_PRES_INTR_OFFSET,
-				irq_base + BCI_INTR_OFFSET);
-		if (IS_ERR(child))
-			return PTR_ERR(child);
-	}
-
-	if (IS_ENABLED(CONFIG_TWL4030_POWER) && pdata->power) {
-		child = add_child(TWL_MODULE_PM_MASTER, "twl4030_power",
-				  pdata->power, sizeof(*pdata->power), false,
-				  0, 0);
-		if (IS_ERR(child))
-			return PTR_ERR(child);
-	}
-
-	return 0;
-}
-
-/*----------------------------------------------------------------------*/
-
 /*
  * These three functions initialize the on-chip clock framework,
  * letting it generate the right frequencies for USB, MADC, and
@@ -1000,8 +633,7 @@ static inline int __init unprotect_pm_master(void)
 	return e;
 }
 
-static void clocks_init(struct device *dev,
-			struct twl4030_clock_init_data *clock)
+static void clocks_init(struct device *dev)
 {
 	int e = 0;
 	struct clk *osc;
@@ -1031,8 +663,6 @@ static void clocks_init(struct device *dev,
 	}
 
 	ctrl |= HIGH_PERF_SQ;
-	if (clock && clock->ck32k_lowpwr_enable)
-		ctrl |= CK32K_LOWPWR_EN;
 
 	e |= unprotect_pm_master();
 	/* effect->MADC+USB ck en */
@@ -1071,16 +701,10 @@ static int twl_remove(struct i2c_client *client)
 	return 0;
 }
 
-static struct of_dev_auxdata twl_auxdata_lookup[] = {
-	OF_DEV_AUXDATA("ti,twl4030-gpio", 0, "twl4030-gpio", NULL),
-	{ /* sentinel */ },
-};
-
 /* NOTE: This driver only handles a single twl4030/tps659x0 chip */
 static int
 twl_probe(struct i2c_client *client, const struct i2c_device_id *id)
 {
-	struct twl4030_platform_data	*pdata = dev_get_platdata(&client->dev);
 	struct device_node		*node = client->dev.of_node;
 	struct platform_device		*pdev;
 	const struct regmap_config	*twl_regmap_config;
@@ -1088,8 +712,8 @@ twl_probe(struct i2c_client *client, const struct i2c_device_id *id)
 	int				status;
 	unsigned			i, num_slaves;
 
-	if (!node && !pdata) {
-		dev_err(&client->dev, "no platform data\n");
+	if (!node) {
+		dev_err(&client->dev, "no DT info\n");
 		return -EINVAL;
 	}
 
@@ -1177,7 +801,7 @@ twl_probe(struct i2c_client *client, const struct i2c_device_id *id)
 	twl_priv->ready = true;
 
 	/* setup clock framework */
-	clocks_init(&pdev->dev, pdata ? pdata->clock : NULL);
+	clocks_init(&pdev->dev);
 
 	/* read TWL IDCODE Register */
 	if (twl_class_is_4030()) {
@@ -1225,15 +849,6 @@ twl_probe(struct i2c_client *client, const struct i2c_device_id *id)
 				 TWL4030_DCDC_GLOBAL_CFG);
 	}
 
-	if (node) {
-		if (pdata)
-			twl_auxdata_lookup[0].platform_data = pdata->gpio;
-		status = of_platform_populate(node, NULL, twl_auxdata_lookup,
-					      &client->dev);
-	} else {
-		status = add_children(pdata, irq_base, id->driver_data);
-	}
-
 fail:
 	if (status < 0)
 		twl_remove(client);
-- 
2.9.3

^ permalink raw reply related	[flat|nested] 38+ messages in thread

* [PATCH 1/5] mfd: twl-core: make driver DT only
@ 2016-11-26 18:13   ` Nicolae Rosia
  0 siblings, 0 replies; 38+ messages in thread
From: Nicolae Rosia @ 2016-11-26 18:13 UTC (permalink / raw)
  To: Lee Jones, Mark Brown, Rob Herring, Mark Rutland, Tony Lindgren
  Cc: Liam Girdwood, Paul Gortmaker, Graeme Gregory, Baruch Siach,
	linux-omap, linux-arm-kernel, linux-kernel, devicetree,
	Nicolae Rosia

All users are DT-only and it makes no sense to keep
unused code

Signed-off-by: Nicolae Rosia <Nicolae_Rosia@mentor.com>
---
 drivers/mfd/Kconfig    |   1 +
 drivers/mfd/twl-core.c | 399 +------------------------------------------------
 2 files changed, 8 insertions(+), 392 deletions(-)

diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig
index c6df644..c180f8b 100644
--- a/drivers/mfd/Kconfig
+++ b/drivers/mfd/Kconfig
@@ -1333,6 +1333,7 @@ config MFD_TPS80031
 config TWL4030_CORE
 	bool "TI TWL4030/TWL5030/TWL6030/TPS659x0 Support"
 	depends on I2C=y
+	depends on OF
 	select IRQ_DOMAIN
 	select REGMAP_I2C
 	help
diff --git a/drivers/mfd/twl-core.c b/drivers/mfd/twl-core.c
index c64615d..48b0668 100644
--- a/drivers/mfd/twl-core.c
+++ b/drivers/mfd/twl-core.c
@@ -13,6 +13,9 @@
  * Code cleanup and modifications to IRQ handler.
  * by syed khasim <x0khasim@ti.com>
  *
+ * Code cleanup and modifications:
+ * Copyright (C) 2016 Nicolae Rosia <nicolae.rosia@gmail.com>
+ *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
@@ -604,376 +607,6 @@ int twl_get_hfclk_rate(void)
 }
 EXPORT_SYMBOL_GPL(twl_get_hfclk_rate);
 
-static struct device *
-add_numbered_child(unsigned mod_no, const char *name, int num,
-		void *pdata, unsigned pdata_len,
-		bool can_wakeup, int irq0, int irq1)
-{
-	struct platform_device	*pdev;
-	struct twl_client	*twl;
-	int			status, sid;
-
-	if (unlikely(mod_no >= twl_get_last_module())) {
-		pr_err("%s: invalid module number %d\n", DRIVER_NAME, mod_no);
-		return ERR_PTR(-EPERM);
-	}
-	sid = twl_priv->twl_map[mod_no].sid;
-	twl = &twl_priv->twl_modules[sid];
-
-	pdev = platform_device_alloc(name, num);
-	if (!pdev)
-		return ERR_PTR(-ENOMEM);
-
-	pdev->dev.parent = &twl->client->dev;
-
-	if (pdata) {
-		status = platform_device_add_data(pdev, pdata, pdata_len);
-		if (status < 0) {
-			dev_dbg(&pdev->dev, "can't add platform_data\n");
-			goto put_device;
-		}
-	}
-
-	if (irq0) {
-		struct resource r[2] = {
-			{ .start = irq0, .flags = IORESOURCE_IRQ, },
-			{ .start = irq1, .flags = IORESOURCE_IRQ, },
-		};
-
-		status = platform_device_add_resources(pdev, r, irq1 ? 2 : 1);
-		if (status < 0) {
-			dev_dbg(&pdev->dev, "can't add irqs\n");
-			goto put_device;
-		}
-	}
-
-	status = platform_device_add(pdev);
-	if (status)
-		goto put_device;
-
-	device_init_wakeup(&pdev->dev, can_wakeup);
-
-	return &pdev->dev;
-
-put_device:
-	platform_device_put(pdev);
-	dev_err(&twl->client->dev, "failed to add device %s\n", name);
-	return ERR_PTR(status);
-}
-
-static inline struct device *add_child(unsigned mod_no, const char *name,
-		void *pdata, unsigned pdata_len,
-		bool can_wakeup, int irq0, int irq1)
-{
-	return add_numbered_child(mod_no, name, -1, pdata, pdata_len,
-		can_wakeup, irq0, irq1);
-}
-
-static struct device *
-add_regulator_linked(int num, struct regulator_init_data *pdata,
-		struct regulator_consumer_supply *consumers,
-		unsigned num_consumers, unsigned long features)
-{
-	struct twl_regulator_driver_data drv_data;
-
-	/* regulator framework demands init_data ... */
-	if (!pdata)
-		return NULL;
-
-	if (consumers) {
-		pdata->consumer_supplies = consumers;
-		pdata->num_consumer_supplies = num_consumers;
-	}
-
-	if (pdata->driver_data) {
-		/* If we have existing drv_data, just add the flags */
-		struct twl_regulator_driver_data *tmp;
-		tmp = pdata->driver_data;
-		tmp->features |= features;
-	} else {
-		/* add new driver data struct, used only during init */
-		drv_data.features = features;
-		drv_data.set_voltage = NULL;
-		drv_data.get_voltage = NULL;
-		drv_data.data = NULL;
-		pdata->driver_data = &drv_data;
-	}
-
-	/* NOTE:  we currently ignore regulator IRQs, e.g. for short circuits */
-	return add_numbered_child(TWL_MODULE_PM_MASTER, "twl_reg", num,
-		pdata, sizeof(*pdata), false, 0, 0);
-}
-
-static struct device *
-add_regulator(int num, struct regulator_init_data *pdata,
-		unsigned long features)
-{
-	return add_regulator_linked(num, pdata, NULL, 0, features);
-}
-
-/*
- * NOTE:  We know the first 8 IRQs after pdata->base_irq are
- * for the PIH, and the next are for the PWR_INT SIH, since
- * that's how twl_init_irq() sets things up.
- */
-
-static int
-add_children(struct twl4030_platform_data *pdata, unsigned irq_base,
-		unsigned long features)
-{
-	struct device	*child;
-
-	if (IS_ENABLED(CONFIG_GPIO_TWL4030) && pdata->gpio) {
-		child = add_child(TWL4030_MODULE_GPIO, "twl4030_gpio",
-				pdata->gpio, sizeof(*pdata->gpio),
-				false, irq_base + GPIO_INTR_OFFSET, 0);
-		if (IS_ERR(child))
-			return PTR_ERR(child);
-	}
-
-	if (IS_ENABLED(CONFIG_KEYBOARD_TWL4030) && pdata->keypad) {
-		child = add_child(TWL4030_MODULE_KEYPAD, "twl4030_keypad",
-				pdata->keypad, sizeof(*pdata->keypad),
-				true, irq_base + KEYPAD_INTR_OFFSET, 0);
-		if (IS_ERR(child))
-			return PTR_ERR(child);
-	}
-
-	if (IS_ENABLED(CONFIG_TWL4030_MADC) && pdata->madc &&
-	    twl_class_is_4030()) {
-		child = add_child(TWL4030_MODULE_MADC, "twl4030_madc",
-				pdata->madc, sizeof(*pdata->madc),
-				true, irq_base + MADC_INTR_OFFSET, 0);
-		if (IS_ERR(child))
-			return PTR_ERR(child);
-	}
-
-	if (IS_ENABLED(CONFIG_RTC_DRV_TWL4030)) {
-		/*
-		 * REVISIT platform_data here currently might expose the
-		 * "msecure" line ... but for now we just expect board
-		 * setup to tell the chip "it's always ok to SET_TIME".
-		 * Eventually, Linux might become more aware of such
-		 * HW security concerns, and "least privilege".
-		 */
-		child = add_child(TWL_MODULE_RTC, "twl_rtc", NULL, 0,
-				true, irq_base + RTC_INTR_OFFSET, 0);
-		if (IS_ERR(child))
-			return PTR_ERR(child);
-	}
-
-	if (IS_ENABLED(CONFIG_PWM_TWL)) {
-		child = add_child(TWL_MODULE_PWM, "twl-pwm", NULL, 0,
-				  false, 0, 0);
-		if (IS_ERR(child))
-			return PTR_ERR(child);
-	}
-
-	if (IS_ENABLED(CONFIG_PWM_TWL_LED)) {
-		child = add_child(TWL_MODULE_LED, "twl-pwmled", NULL, 0,
-				  false, 0, 0);
-		if (IS_ERR(child))
-			return PTR_ERR(child);
-	}
-
-	if (IS_ENABLED(CONFIG_TWL4030_USB) && pdata->usb &&
-	    twl_class_is_4030()) {
-
-		static struct regulator_consumer_supply usb1v5 = {
-			.supply =	"usb1v5",
-		};
-		static struct regulator_consumer_supply usb1v8 = {
-			.supply =	"usb1v8",
-		};
-		static struct regulator_consumer_supply usb3v1 = {
-			.supply =	"usb3v1",
-		};
-
-	/* First add the regulators so that they can be used by transceiver */
-		if (IS_ENABLED(CONFIG_REGULATOR_TWL4030)) {
-			/* this is a template that gets copied */
-			struct regulator_init_data usb_fixed = {
-				.constraints.valid_modes_mask =
-					REGULATOR_MODE_NORMAL
-					| REGULATOR_MODE_STANDBY,
-				.constraints.valid_ops_mask =
-					REGULATOR_CHANGE_MODE
-					| REGULATOR_CHANGE_STATUS,
-			};
-
-			child = add_regulator_linked(TWL4030_REG_VUSB1V5,
-						      &usb_fixed, &usb1v5, 1,
-						      features);
-			if (IS_ERR(child))
-				return PTR_ERR(child);
-
-			child = add_regulator_linked(TWL4030_REG_VUSB1V8,
-						      &usb_fixed, &usb1v8, 1,
-						      features);
-			if (IS_ERR(child))
-				return PTR_ERR(child);
-
-			child = add_regulator_linked(TWL4030_REG_VUSB3V1,
-						      &usb_fixed, &usb3v1, 1,
-						      features);
-			if (IS_ERR(child))
-				return PTR_ERR(child);
-
-		}
-
-		child = add_child(TWL_MODULE_USB, "twl4030_usb",
-				pdata->usb, sizeof(*pdata->usb), true,
-				/* irq0 = USB_PRES, irq1 = USB */
-				irq_base + USB_PRES_INTR_OFFSET,
-				irq_base + USB_INTR_OFFSET);
-
-		if (IS_ERR(child))
-			return PTR_ERR(child);
-
-		/* we need to connect regulators to this transceiver */
-		if (IS_ENABLED(CONFIG_REGULATOR_TWL4030) && child) {
-			usb1v5.dev_name = dev_name(child);
-			usb1v8.dev_name = dev_name(child);
-			usb3v1.dev_name = dev_name(child);
-		}
-	}
-
-	if (IS_ENABLED(CONFIG_TWL4030_WATCHDOG) && twl_class_is_4030()) {
-		child = add_child(TWL_MODULE_PM_RECEIVER, "twl4030_wdt", NULL,
-				  0, false, 0, 0);
-		if (IS_ERR(child))
-			return PTR_ERR(child);
-	}
-
-	if (IS_ENABLED(CONFIG_INPUT_TWL4030_PWRBUTTON) && twl_class_is_4030()) {
-		child = add_child(TWL_MODULE_PM_MASTER, "twl4030_pwrbutton",
-				  NULL, 0, true, irq_base + 8 + 0, 0);
-		if (IS_ERR(child))
-			return PTR_ERR(child);
-	}
-
-	if (IS_ENABLED(CONFIG_MFD_TWL4030_AUDIO) && pdata->audio &&
-	    twl_class_is_4030()) {
-		child = add_child(TWL4030_MODULE_AUDIO_VOICE, "twl4030-audio",
-				pdata->audio, sizeof(*pdata->audio),
-				false, 0, 0);
-		if (IS_ERR(child))
-			return PTR_ERR(child);
-	}
-
-	/* twl4030 regulators */
-	if (IS_ENABLED(CONFIG_REGULATOR_TWL4030) && twl_class_is_4030()) {
-		child = add_regulator(TWL4030_REG_VPLL1, pdata->vpll1,
-					features);
-		if (IS_ERR(child))
-			return PTR_ERR(child);
-
-		child = add_regulator(TWL4030_REG_VIO, pdata->vio,
-					features);
-		if (IS_ERR(child))
-			return PTR_ERR(child);
-
-		child = add_regulator(TWL4030_REG_VDD1, pdata->vdd1,
-					features);
-		if (IS_ERR(child))
-			return PTR_ERR(child);
-
-		child = add_regulator(TWL4030_REG_VDD2, pdata->vdd2,
-					features);
-		if (IS_ERR(child))
-			return PTR_ERR(child);
-
-		child = add_regulator(TWL4030_REG_VMMC1, pdata->vmmc1,
-					features);
-		if (IS_ERR(child))
-			return PTR_ERR(child);
-
-		child = add_regulator(TWL4030_REG_VDAC, pdata->vdac,
-					features);
-		if (IS_ERR(child))
-			return PTR_ERR(child);
-
-		child = add_regulator((features & TWL4030_VAUX2)
-					? TWL4030_REG_VAUX2_4030
-					: TWL4030_REG_VAUX2,
-				pdata->vaux2, features);
-		if (IS_ERR(child))
-			return PTR_ERR(child);
-
-		child = add_regulator(TWL4030_REG_VINTANA1, pdata->vintana1,
-					features);
-		if (IS_ERR(child))
-			return PTR_ERR(child);
-
-		child = add_regulator(TWL4030_REG_VINTANA2, pdata->vintana2,
-					features);
-		if (IS_ERR(child))
-			return PTR_ERR(child);
-
-		child = add_regulator(TWL4030_REG_VINTDIG, pdata->vintdig,
-					features);
-		if (IS_ERR(child))
-			return PTR_ERR(child);
-	}
-
-	/* maybe add LDOs that are omitted on cost-reduced parts */
-	if (IS_ENABLED(CONFIG_REGULATOR_TWL4030) && !(features & TPS_SUBSET)
-	  && twl_class_is_4030()) {
-		child = add_regulator(TWL4030_REG_VPLL2, pdata->vpll2,
-					features);
-		if (IS_ERR(child))
-			return PTR_ERR(child);
-
-		child = add_regulator(TWL4030_REG_VMMC2, pdata->vmmc2,
-					features);
-		if (IS_ERR(child))
-			return PTR_ERR(child);
-
-		child = add_regulator(TWL4030_REG_VSIM, pdata->vsim,
-					features);
-		if (IS_ERR(child))
-			return PTR_ERR(child);
-
-		child = add_regulator(TWL4030_REG_VAUX1, pdata->vaux1,
-					features);
-		if (IS_ERR(child))
-			return PTR_ERR(child);
-
-		child = add_regulator(TWL4030_REG_VAUX3, pdata->vaux3,
-					features);
-		if (IS_ERR(child))
-			return PTR_ERR(child);
-
-		child = add_regulator(TWL4030_REG_VAUX4, pdata->vaux4,
-					features);
-		if (IS_ERR(child))
-			return PTR_ERR(child);
-	}
-
-	if (IS_ENABLED(CONFIG_CHARGER_TWL4030) && pdata->bci &&
-			!(features & (TPS_SUBSET | TWL5031))) {
-		child = add_child(TWL_MODULE_MAIN_CHARGE, "twl4030_bci",
-				pdata->bci, sizeof(*pdata->bci), false,
-				/* irq0 = CHG_PRES, irq1 = BCI */
-				irq_base + BCI_PRES_INTR_OFFSET,
-				irq_base + BCI_INTR_OFFSET);
-		if (IS_ERR(child))
-			return PTR_ERR(child);
-	}
-
-	if (IS_ENABLED(CONFIG_TWL4030_POWER) && pdata->power) {
-		child = add_child(TWL_MODULE_PM_MASTER, "twl4030_power",
-				  pdata->power, sizeof(*pdata->power), false,
-				  0, 0);
-		if (IS_ERR(child))
-			return PTR_ERR(child);
-	}
-
-	return 0;
-}
-
-/*----------------------------------------------------------------------*/
-
 /*
  * These three functions initialize the on-chip clock framework,
  * letting it generate the right frequencies for USB, MADC, and
@@ -1000,8 +633,7 @@ static inline int __init unprotect_pm_master(void)
 	return e;
 }
 
-static void clocks_init(struct device *dev,
-			struct twl4030_clock_init_data *clock)
+static void clocks_init(struct device *dev)
 {
 	int e = 0;
 	struct clk *osc;
@@ -1031,8 +663,6 @@ static void clocks_init(struct device *dev,
 	}
 
 	ctrl |= HIGH_PERF_SQ;
-	if (clock && clock->ck32k_lowpwr_enable)
-		ctrl |= CK32K_LOWPWR_EN;
 
 	e |= unprotect_pm_master();
 	/* effect->MADC+USB ck en */
@@ -1071,16 +701,10 @@ static int twl_remove(struct i2c_client *client)
 	return 0;
 }
 
-static struct of_dev_auxdata twl_auxdata_lookup[] = {
-	OF_DEV_AUXDATA("ti,twl4030-gpio", 0, "twl4030-gpio", NULL),
-	{ /* sentinel */ },
-};
-
 /* NOTE: This driver only handles a single twl4030/tps659x0 chip */
 static int
 twl_probe(struct i2c_client *client, const struct i2c_device_id *id)
 {
-	struct twl4030_platform_data	*pdata = dev_get_platdata(&client->dev);
 	struct device_node		*node = client->dev.of_node;
 	struct platform_device		*pdev;
 	const struct regmap_config	*twl_regmap_config;
@@ -1088,8 +712,8 @@ twl_probe(struct i2c_client *client, const struct i2c_device_id *id)
 	int				status;
 	unsigned			i, num_slaves;
 
-	if (!node && !pdata) {
-		dev_err(&client->dev, "no platform data\n");
+	if (!node) {
+		dev_err(&client->dev, "no DT info\n");
 		return -EINVAL;
 	}
 
@@ -1177,7 +801,7 @@ twl_probe(struct i2c_client *client, const struct i2c_device_id *id)
 	twl_priv->ready = true;
 
 	/* setup clock framework */
-	clocks_init(&pdev->dev, pdata ? pdata->clock : NULL);
+	clocks_init(&pdev->dev);
 
 	/* read TWL IDCODE Register */
 	if (twl_class_is_4030()) {
@@ -1225,15 +849,6 @@ twl_probe(struct i2c_client *client, const struct i2c_device_id *id)
 				 TWL4030_DCDC_GLOBAL_CFG);
 	}
 
-	if (node) {
-		if (pdata)
-			twl_auxdata_lookup[0].platform_data = pdata->gpio;
-		status = of_platform_populate(node, NULL, twl_auxdata_lookup,
-					      &client->dev);
-	} else {
-		status = add_children(pdata, irq_base, id->driver_data);
-	}
-
 fail:
 	if (status < 0)
 		twl_remove(client);
-- 
2.9.3

^ permalink raw reply related	[flat|nested] 38+ messages in thread

* [PATCH 1/5] mfd: twl-core: make driver DT only
@ 2016-11-26 18:13   ` Nicolae Rosia
  0 siblings, 0 replies; 38+ messages in thread
From: Nicolae Rosia @ 2016-11-26 18:13 UTC (permalink / raw)
  To: linux-arm-kernel

All users are DT-only and it makes no sense to keep
unused code

Signed-off-by: Nicolae Rosia <Nicolae_Rosia@mentor.com>
---
 drivers/mfd/Kconfig    |   1 +
 drivers/mfd/twl-core.c | 399 +------------------------------------------------
 2 files changed, 8 insertions(+), 392 deletions(-)

diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig
index c6df644..c180f8b 100644
--- a/drivers/mfd/Kconfig
+++ b/drivers/mfd/Kconfig
@@ -1333,6 +1333,7 @@ config MFD_TPS80031
 config TWL4030_CORE
 	bool "TI TWL4030/TWL5030/TWL6030/TPS659x0 Support"
 	depends on I2C=y
+	depends on OF
 	select IRQ_DOMAIN
 	select REGMAP_I2C
 	help
diff --git a/drivers/mfd/twl-core.c b/drivers/mfd/twl-core.c
index c64615d..48b0668 100644
--- a/drivers/mfd/twl-core.c
+++ b/drivers/mfd/twl-core.c
@@ -13,6 +13,9 @@
  * Code cleanup and modifications to IRQ handler.
  * by syed khasim <x0khasim@ti.com>
  *
+ * Code cleanup and modifications:
+ * Copyright (C) 2016 Nicolae Rosia <nicolae.rosia@gmail.com>
+ *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
@@ -604,376 +607,6 @@ int twl_get_hfclk_rate(void)
 }
 EXPORT_SYMBOL_GPL(twl_get_hfclk_rate);
 
-static struct device *
-add_numbered_child(unsigned mod_no, const char *name, int num,
-		void *pdata, unsigned pdata_len,
-		bool can_wakeup, int irq0, int irq1)
-{
-	struct platform_device	*pdev;
-	struct twl_client	*twl;
-	int			status, sid;
-
-	if (unlikely(mod_no >= twl_get_last_module())) {
-		pr_err("%s: invalid module number %d\n", DRIVER_NAME, mod_no);
-		return ERR_PTR(-EPERM);
-	}
-	sid = twl_priv->twl_map[mod_no].sid;
-	twl = &twl_priv->twl_modules[sid];
-
-	pdev = platform_device_alloc(name, num);
-	if (!pdev)
-		return ERR_PTR(-ENOMEM);
-
-	pdev->dev.parent = &twl->client->dev;
-
-	if (pdata) {
-		status = platform_device_add_data(pdev, pdata, pdata_len);
-		if (status < 0) {
-			dev_dbg(&pdev->dev, "can't add platform_data\n");
-			goto put_device;
-		}
-	}
-
-	if (irq0) {
-		struct resource r[2] = {
-			{ .start = irq0, .flags = IORESOURCE_IRQ, },
-			{ .start = irq1, .flags = IORESOURCE_IRQ, },
-		};
-
-		status = platform_device_add_resources(pdev, r, irq1 ? 2 : 1);
-		if (status < 0) {
-			dev_dbg(&pdev->dev, "can't add irqs\n");
-			goto put_device;
-		}
-	}
-
-	status = platform_device_add(pdev);
-	if (status)
-		goto put_device;
-
-	device_init_wakeup(&pdev->dev, can_wakeup);
-
-	return &pdev->dev;
-
-put_device:
-	platform_device_put(pdev);
-	dev_err(&twl->client->dev, "failed to add device %s\n", name);
-	return ERR_PTR(status);
-}
-
-static inline struct device *add_child(unsigned mod_no, const char *name,
-		void *pdata, unsigned pdata_len,
-		bool can_wakeup, int irq0, int irq1)
-{
-	return add_numbered_child(mod_no, name, -1, pdata, pdata_len,
-		can_wakeup, irq0, irq1);
-}
-
-static struct device *
-add_regulator_linked(int num, struct regulator_init_data *pdata,
-		struct regulator_consumer_supply *consumers,
-		unsigned num_consumers, unsigned long features)
-{
-	struct twl_regulator_driver_data drv_data;
-
-	/* regulator framework demands init_data ... */
-	if (!pdata)
-		return NULL;
-
-	if (consumers) {
-		pdata->consumer_supplies = consumers;
-		pdata->num_consumer_supplies = num_consumers;
-	}
-
-	if (pdata->driver_data) {
-		/* If we have existing drv_data, just add the flags */
-		struct twl_regulator_driver_data *tmp;
-		tmp = pdata->driver_data;
-		tmp->features |= features;
-	} else {
-		/* add new driver data struct, used only during init */
-		drv_data.features = features;
-		drv_data.set_voltage = NULL;
-		drv_data.get_voltage = NULL;
-		drv_data.data = NULL;
-		pdata->driver_data = &drv_data;
-	}
-
-	/* NOTE:  we currently ignore regulator IRQs, e.g. for short circuits */
-	return add_numbered_child(TWL_MODULE_PM_MASTER, "twl_reg", num,
-		pdata, sizeof(*pdata), false, 0, 0);
-}
-
-static struct device *
-add_regulator(int num, struct regulator_init_data *pdata,
-		unsigned long features)
-{
-	return add_regulator_linked(num, pdata, NULL, 0, features);
-}
-
-/*
- * NOTE:  We know the first 8 IRQs after pdata->base_irq are
- * for the PIH, and the next are for the PWR_INT SIH, since
- * that's how twl_init_irq() sets things up.
- */
-
-static int
-add_children(struct twl4030_platform_data *pdata, unsigned irq_base,
-		unsigned long features)
-{
-	struct device	*child;
-
-	if (IS_ENABLED(CONFIG_GPIO_TWL4030) && pdata->gpio) {
-		child = add_child(TWL4030_MODULE_GPIO, "twl4030_gpio",
-				pdata->gpio, sizeof(*pdata->gpio),
-				false, irq_base + GPIO_INTR_OFFSET, 0);
-		if (IS_ERR(child))
-			return PTR_ERR(child);
-	}
-
-	if (IS_ENABLED(CONFIG_KEYBOARD_TWL4030) && pdata->keypad) {
-		child = add_child(TWL4030_MODULE_KEYPAD, "twl4030_keypad",
-				pdata->keypad, sizeof(*pdata->keypad),
-				true, irq_base + KEYPAD_INTR_OFFSET, 0);
-		if (IS_ERR(child))
-			return PTR_ERR(child);
-	}
-
-	if (IS_ENABLED(CONFIG_TWL4030_MADC) && pdata->madc &&
-	    twl_class_is_4030()) {
-		child = add_child(TWL4030_MODULE_MADC, "twl4030_madc",
-				pdata->madc, sizeof(*pdata->madc),
-				true, irq_base + MADC_INTR_OFFSET, 0);
-		if (IS_ERR(child))
-			return PTR_ERR(child);
-	}
-
-	if (IS_ENABLED(CONFIG_RTC_DRV_TWL4030)) {
-		/*
-		 * REVISIT platform_data here currently might expose the
-		 * "msecure" line ... but for now we just expect board
-		 * setup to tell the chip "it's always ok to SET_TIME".
-		 * Eventually, Linux might become more aware of such
-		 * HW security concerns, and "least privilege".
-		 */
-		child = add_child(TWL_MODULE_RTC, "twl_rtc", NULL, 0,
-				true, irq_base + RTC_INTR_OFFSET, 0);
-		if (IS_ERR(child))
-			return PTR_ERR(child);
-	}
-
-	if (IS_ENABLED(CONFIG_PWM_TWL)) {
-		child = add_child(TWL_MODULE_PWM, "twl-pwm", NULL, 0,
-				  false, 0, 0);
-		if (IS_ERR(child))
-			return PTR_ERR(child);
-	}
-
-	if (IS_ENABLED(CONFIG_PWM_TWL_LED)) {
-		child = add_child(TWL_MODULE_LED, "twl-pwmled", NULL, 0,
-				  false, 0, 0);
-		if (IS_ERR(child))
-			return PTR_ERR(child);
-	}
-
-	if (IS_ENABLED(CONFIG_TWL4030_USB) && pdata->usb &&
-	    twl_class_is_4030()) {
-
-		static struct regulator_consumer_supply usb1v5 = {
-			.supply =	"usb1v5",
-		};
-		static struct regulator_consumer_supply usb1v8 = {
-			.supply =	"usb1v8",
-		};
-		static struct regulator_consumer_supply usb3v1 = {
-			.supply =	"usb3v1",
-		};
-
-	/* First add the regulators so that they can be used by transceiver */
-		if (IS_ENABLED(CONFIG_REGULATOR_TWL4030)) {
-			/* this is a template that gets copied */
-			struct regulator_init_data usb_fixed = {
-				.constraints.valid_modes_mask =
-					REGULATOR_MODE_NORMAL
-					| REGULATOR_MODE_STANDBY,
-				.constraints.valid_ops_mask =
-					REGULATOR_CHANGE_MODE
-					| REGULATOR_CHANGE_STATUS,
-			};
-
-			child = add_regulator_linked(TWL4030_REG_VUSB1V5,
-						      &usb_fixed, &usb1v5, 1,
-						      features);
-			if (IS_ERR(child))
-				return PTR_ERR(child);
-
-			child = add_regulator_linked(TWL4030_REG_VUSB1V8,
-						      &usb_fixed, &usb1v8, 1,
-						      features);
-			if (IS_ERR(child))
-				return PTR_ERR(child);
-
-			child = add_regulator_linked(TWL4030_REG_VUSB3V1,
-						      &usb_fixed, &usb3v1, 1,
-						      features);
-			if (IS_ERR(child))
-				return PTR_ERR(child);
-
-		}
-
-		child = add_child(TWL_MODULE_USB, "twl4030_usb",
-				pdata->usb, sizeof(*pdata->usb), true,
-				/* irq0 = USB_PRES, irq1 = USB */
-				irq_base + USB_PRES_INTR_OFFSET,
-				irq_base + USB_INTR_OFFSET);
-
-		if (IS_ERR(child))
-			return PTR_ERR(child);
-
-		/* we need to connect regulators to this transceiver */
-		if (IS_ENABLED(CONFIG_REGULATOR_TWL4030) && child) {
-			usb1v5.dev_name = dev_name(child);
-			usb1v8.dev_name = dev_name(child);
-			usb3v1.dev_name = dev_name(child);
-		}
-	}
-
-	if (IS_ENABLED(CONFIG_TWL4030_WATCHDOG) && twl_class_is_4030()) {
-		child = add_child(TWL_MODULE_PM_RECEIVER, "twl4030_wdt", NULL,
-				  0, false, 0, 0);
-		if (IS_ERR(child))
-			return PTR_ERR(child);
-	}
-
-	if (IS_ENABLED(CONFIG_INPUT_TWL4030_PWRBUTTON) && twl_class_is_4030()) {
-		child = add_child(TWL_MODULE_PM_MASTER, "twl4030_pwrbutton",
-				  NULL, 0, true, irq_base + 8 + 0, 0);
-		if (IS_ERR(child))
-			return PTR_ERR(child);
-	}
-
-	if (IS_ENABLED(CONFIG_MFD_TWL4030_AUDIO) && pdata->audio &&
-	    twl_class_is_4030()) {
-		child = add_child(TWL4030_MODULE_AUDIO_VOICE, "twl4030-audio",
-				pdata->audio, sizeof(*pdata->audio),
-				false, 0, 0);
-		if (IS_ERR(child))
-			return PTR_ERR(child);
-	}
-
-	/* twl4030 regulators */
-	if (IS_ENABLED(CONFIG_REGULATOR_TWL4030) && twl_class_is_4030()) {
-		child = add_regulator(TWL4030_REG_VPLL1, pdata->vpll1,
-					features);
-		if (IS_ERR(child))
-			return PTR_ERR(child);
-
-		child = add_regulator(TWL4030_REG_VIO, pdata->vio,
-					features);
-		if (IS_ERR(child))
-			return PTR_ERR(child);
-
-		child = add_regulator(TWL4030_REG_VDD1, pdata->vdd1,
-					features);
-		if (IS_ERR(child))
-			return PTR_ERR(child);
-
-		child = add_regulator(TWL4030_REG_VDD2, pdata->vdd2,
-					features);
-		if (IS_ERR(child))
-			return PTR_ERR(child);
-
-		child = add_regulator(TWL4030_REG_VMMC1, pdata->vmmc1,
-					features);
-		if (IS_ERR(child))
-			return PTR_ERR(child);
-
-		child = add_regulator(TWL4030_REG_VDAC, pdata->vdac,
-					features);
-		if (IS_ERR(child))
-			return PTR_ERR(child);
-
-		child = add_regulator((features & TWL4030_VAUX2)
-					? TWL4030_REG_VAUX2_4030
-					: TWL4030_REG_VAUX2,
-				pdata->vaux2, features);
-		if (IS_ERR(child))
-			return PTR_ERR(child);
-
-		child = add_regulator(TWL4030_REG_VINTANA1, pdata->vintana1,
-					features);
-		if (IS_ERR(child))
-			return PTR_ERR(child);
-
-		child = add_regulator(TWL4030_REG_VINTANA2, pdata->vintana2,
-					features);
-		if (IS_ERR(child))
-			return PTR_ERR(child);
-
-		child = add_regulator(TWL4030_REG_VINTDIG, pdata->vintdig,
-					features);
-		if (IS_ERR(child))
-			return PTR_ERR(child);
-	}
-
-	/* maybe add LDOs that are omitted on cost-reduced parts */
-	if (IS_ENABLED(CONFIG_REGULATOR_TWL4030) && !(features & TPS_SUBSET)
-	  && twl_class_is_4030()) {
-		child = add_regulator(TWL4030_REG_VPLL2, pdata->vpll2,
-					features);
-		if (IS_ERR(child))
-			return PTR_ERR(child);
-
-		child = add_regulator(TWL4030_REG_VMMC2, pdata->vmmc2,
-					features);
-		if (IS_ERR(child))
-			return PTR_ERR(child);
-
-		child = add_regulator(TWL4030_REG_VSIM, pdata->vsim,
-					features);
-		if (IS_ERR(child))
-			return PTR_ERR(child);
-
-		child = add_regulator(TWL4030_REG_VAUX1, pdata->vaux1,
-					features);
-		if (IS_ERR(child))
-			return PTR_ERR(child);
-
-		child = add_regulator(TWL4030_REG_VAUX3, pdata->vaux3,
-					features);
-		if (IS_ERR(child))
-			return PTR_ERR(child);
-
-		child = add_regulator(TWL4030_REG_VAUX4, pdata->vaux4,
-					features);
-		if (IS_ERR(child))
-			return PTR_ERR(child);
-	}
-
-	if (IS_ENABLED(CONFIG_CHARGER_TWL4030) && pdata->bci &&
-			!(features & (TPS_SUBSET | TWL5031))) {
-		child = add_child(TWL_MODULE_MAIN_CHARGE, "twl4030_bci",
-				pdata->bci, sizeof(*pdata->bci), false,
-				/* irq0 = CHG_PRES, irq1 = BCI */
-				irq_base + BCI_PRES_INTR_OFFSET,
-				irq_base + BCI_INTR_OFFSET);
-		if (IS_ERR(child))
-			return PTR_ERR(child);
-	}
-
-	if (IS_ENABLED(CONFIG_TWL4030_POWER) && pdata->power) {
-		child = add_child(TWL_MODULE_PM_MASTER, "twl4030_power",
-				  pdata->power, sizeof(*pdata->power), false,
-				  0, 0);
-		if (IS_ERR(child))
-			return PTR_ERR(child);
-	}
-
-	return 0;
-}
-
-/*----------------------------------------------------------------------*/
-
 /*
  * These three functions initialize the on-chip clock framework,
  * letting it generate the right frequencies for USB, MADC, and
@@ -1000,8 +633,7 @@ static inline int __init unprotect_pm_master(void)
 	return e;
 }
 
-static void clocks_init(struct device *dev,
-			struct twl4030_clock_init_data *clock)
+static void clocks_init(struct device *dev)
 {
 	int e = 0;
 	struct clk *osc;
@@ -1031,8 +663,6 @@ static void clocks_init(struct device *dev,
 	}
 
 	ctrl |= HIGH_PERF_SQ;
-	if (clock && clock->ck32k_lowpwr_enable)
-		ctrl |= CK32K_LOWPWR_EN;
 
 	e |= unprotect_pm_master();
 	/* effect->MADC+USB ck en */
@@ -1071,16 +701,10 @@ static int twl_remove(struct i2c_client *client)
 	return 0;
 }
 
-static struct of_dev_auxdata twl_auxdata_lookup[] = {
-	OF_DEV_AUXDATA("ti,twl4030-gpio", 0, "twl4030-gpio", NULL),
-	{ /* sentinel */ },
-};
-
 /* NOTE: This driver only handles a single twl4030/tps659x0 chip */
 static int
 twl_probe(struct i2c_client *client, const struct i2c_device_id *id)
 {
-	struct twl4030_platform_data	*pdata = dev_get_platdata(&client->dev);
 	struct device_node		*node = client->dev.of_node;
 	struct platform_device		*pdev;
 	const struct regmap_config	*twl_regmap_config;
@@ -1088,8 +712,8 @@ twl_probe(struct i2c_client *client, const struct i2c_device_id *id)
 	int				status;
 	unsigned			i, num_slaves;
 
-	if (!node && !pdata) {
-		dev_err(&client->dev, "no platform data\n");
+	if (!node) {
+		dev_err(&client->dev, "no DT info\n");
 		return -EINVAL;
 	}
 
@@ -1177,7 +801,7 @@ twl_probe(struct i2c_client *client, const struct i2c_device_id *id)
 	twl_priv->ready = true;
 
 	/* setup clock framework */
-	clocks_init(&pdev->dev, pdata ? pdata->clock : NULL);
+	clocks_init(&pdev->dev);
 
 	/* read TWL IDCODE Register */
 	if (twl_class_is_4030()) {
@@ -1225,15 +849,6 @@ twl_probe(struct i2c_client *client, const struct i2c_device_id *id)
 				 TWL4030_DCDC_GLOBAL_CFG);
 	}
 
-	if (node) {
-		if (pdata)
-			twl_auxdata_lookup[0].platform_data = pdata->gpio;
-		status = of_platform_populate(node, NULL, twl_auxdata_lookup,
-					      &client->dev);
-	} else {
-		status = add_children(pdata, irq_base, id->driver_data);
-	}
-
 fail:
 	if (status < 0)
 		twl_remove(client);
-- 
2.9.3

^ permalink raw reply related	[flat|nested] 38+ messages in thread

* [PATCH 2/5] mfd: twl: remove useless header
@ 2016-11-26 18:13   ` Nicolae Rosia
  0 siblings, 0 replies; 38+ messages in thread
From: Nicolae Rosia @ 2016-11-26 18:13 UTC (permalink / raw)
  To: Lee Jones, Mark Brown, Rob Herring, Mark Rutland, Tony Lindgren
  Cc: Liam Girdwood, Paul Gortmaker, Graeme Gregory, Baruch Siach,
	linux-omap, linux-arm-kernel, linux-kernel, devicetree,
	Nicolae Rosia

This header has one user, twl-core.c .
Remove it before it gets more users.

Signed-off-by: Nicolae Rosia <Nicolae_Rosia@mentor.com>
---
 drivers/mfd/twl-core.c    |  8 ++++++--
 drivers/mfd/twl-core.h    | 10 ----------
 drivers/mfd/twl4030-irq.c |  2 --
 drivers/mfd/twl6030-irq.c |  2 --
 4 files changed, 6 insertions(+), 16 deletions(-)
 delete mode 100644 drivers/mfd/twl-core.h

diff --git a/drivers/mfd/twl-core.c b/drivers/mfd/twl-core.c
index 48b0668..e16084e 100644
--- a/drivers/mfd/twl-core.c
+++ b/drivers/mfd/twl-core.c
@@ -52,8 +52,6 @@
 /* Register descriptions for audio */
 #include <linux/mfd/twl4030-audio.h>
 
-#include "twl-core.h"
-
 /*
  * The TWL4030 "Triton 2" is one of a family of a multi-function "Power
  * Management and System Companion Device" chips originally designed for
@@ -150,6 +148,12 @@
 
 /*----------------------------------------------------------------------*/
 
+int twl6030_init_irq(struct device *dev, int irq_num);
+int twl6030_exit_irq(void);
+int twl4030_init_irq(struct device *dev, int irq_num);
+int twl4030_exit_irq(void);
+int twl4030_init_chip_irq(const char *chip);
+
 /* Structure for each TWL4030/TWL6030 Slave */
 struct twl_client {
 	struct i2c_client *client;
diff --git a/drivers/mfd/twl-core.h b/drivers/mfd/twl-core.h
deleted file mode 100644
index 6ff99dc..0000000
--- a/drivers/mfd/twl-core.h
+++ /dev/null
@@ -1,10 +0,0 @@
-#ifndef __TWL_CORE_H__
-#define __TWL_CORE_H__
-
-extern int twl6030_init_irq(struct device *dev, int irq_num);
-extern int twl6030_exit_irq(void);
-extern int twl4030_init_irq(struct device *dev, int irq_num);
-extern int twl4030_exit_irq(void);
-extern int twl4030_init_chip_irq(const char *chip);
-
-#endif /*  __TWL_CORE_H__ */
diff --git a/drivers/mfd/twl4030-irq.c b/drivers/mfd/twl4030-irq.c
index b46c0cf..000c231 100644
--- a/drivers/mfd/twl4030-irq.c
+++ b/drivers/mfd/twl4030-irq.c
@@ -35,8 +35,6 @@
 #include <linux/irqdomain.h>
 #include <linux/i2c/twl.h>
 
-#include "twl-core.h"
-
 /*
  * TWL4030 IRQ handling has two stages in hardware, and thus in software.
  * The Primary Interrupt Handler (PIH) stage exposes status bits saying
diff --git a/drivers/mfd/twl6030-irq.c b/drivers/mfd/twl6030-irq.c
index 5357450..63eca76 100644
--- a/drivers/mfd/twl6030-irq.c
+++ b/drivers/mfd/twl6030-irq.c
@@ -42,8 +42,6 @@
 #include <linux/irqdomain.h>
 #include <linux/of_device.h>
 
-#include "twl-core.h"
-
 /*
  * TWL6030 (unlike its predecessors, which had two level interrupt handling)
  * three interrupt registers INT_STS_A, INT_STS_B and INT_STS_C.
-- 
2.9.3

^ permalink raw reply related	[flat|nested] 38+ messages in thread

* [PATCH 2/5] mfd: twl: remove useless header
@ 2016-11-26 18:13   ` Nicolae Rosia
  0 siblings, 0 replies; 38+ messages in thread
From: Nicolae Rosia @ 2016-11-26 18:13 UTC (permalink / raw)
  To: Lee Jones, Mark Brown, Rob Herring, Mark Rutland, Tony Lindgren
  Cc: Liam Girdwood, Paul Gortmaker, Graeme Gregory, Baruch Siach,
	linux-omap-u79uwXL29TY76Z2rM5mHXA,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	devicetree-u79uwXL29TY76Z2rM5mHXA, Nicolae Rosia

This header has one user, twl-core.c .
Remove it before it gets more users.

Signed-off-by: Nicolae Rosia <Nicolae_Rosia-nmGgyN9QBj3QT0dZR+AlfA@public.gmane.org>
---
 drivers/mfd/twl-core.c    |  8 ++++++--
 drivers/mfd/twl-core.h    | 10 ----------
 drivers/mfd/twl4030-irq.c |  2 --
 drivers/mfd/twl6030-irq.c |  2 --
 4 files changed, 6 insertions(+), 16 deletions(-)
 delete mode 100644 drivers/mfd/twl-core.h

diff --git a/drivers/mfd/twl-core.c b/drivers/mfd/twl-core.c
index 48b0668..e16084e 100644
--- a/drivers/mfd/twl-core.c
+++ b/drivers/mfd/twl-core.c
@@ -52,8 +52,6 @@
 /* Register descriptions for audio */
 #include <linux/mfd/twl4030-audio.h>
 
-#include "twl-core.h"
-
 /*
  * The TWL4030 "Triton 2" is one of a family of a multi-function "Power
  * Management and System Companion Device" chips originally designed for
@@ -150,6 +148,12 @@
 
 /*----------------------------------------------------------------------*/
 
+int twl6030_init_irq(struct device *dev, int irq_num);
+int twl6030_exit_irq(void);
+int twl4030_init_irq(struct device *dev, int irq_num);
+int twl4030_exit_irq(void);
+int twl4030_init_chip_irq(const char *chip);
+
 /* Structure for each TWL4030/TWL6030 Slave */
 struct twl_client {
 	struct i2c_client *client;
diff --git a/drivers/mfd/twl-core.h b/drivers/mfd/twl-core.h
deleted file mode 100644
index 6ff99dc..0000000
--- a/drivers/mfd/twl-core.h
+++ /dev/null
@@ -1,10 +0,0 @@
-#ifndef __TWL_CORE_H__
-#define __TWL_CORE_H__
-
-extern int twl6030_init_irq(struct device *dev, int irq_num);
-extern int twl6030_exit_irq(void);
-extern int twl4030_init_irq(struct device *dev, int irq_num);
-extern int twl4030_exit_irq(void);
-extern int twl4030_init_chip_irq(const char *chip);
-
-#endif /*  __TWL_CORE_H__ */
diff --git a/drivers/mfd/twl4030-irq.c b/drivers/mfd/twl4030-irq.c
index b46c0cf..000c231 100644
--- a/drivers/mfd/twl4030-irq.c
+++ b/drivers/mfd/twl4030-irq.c
@@ -35,8 +35,6 @@
 #include <linux/irqdomain.h>
 #include <linux/i2c/twl.h>
 
-#include "twl-core.h"
-
 /*
  * TWL4030 IRQ handling has two stages in hardware, and thus in software.
  * The Primary Interrupt Handler (PIH) stage exposes status bits saying
diff --git a/drivers/mfd/twl6030-irq.c b/drivers/mfd/twl6030-irq.c
index 5357450..63eca76 100644
--- a/drivers/mfd/twl6030-irq.c
+++ b/drivers/mfd/twl6030-irq.c
@@ -42,8 +42,6 @@
 #include <linux/irqdomain.h>
 #include <linux/of_device.h>
 
-#include "twl-core.h"
-
 /*
  * TWL6030 (unlike its predecessors, which had two level interrupt handling)
  * three interrupt registers INT_STS_A, INT_STS_B and INT_STS_C.
-- 
2.9.3

--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply related	[flat|nested] 38+ messages in thread

* [PATCH 2/5] mfd: twl: remove useless header
@ 2016-11-26 18:13   ` Nicolae Rosia
  0 siblings, 0 replies; 38+ messages in thread
From: Nicolae Rosia @ 2016-11-26 18:13 UTC (permalink / raw)
  To: linux-arm-kernel

This header has one user, twl-core.c .
Remove it before it gets more users.

Signed-off-by: Nicolae Rosia <Nicolae_Rosia@mentor.com>
---
 drivers/mfd/twl-core.c    |  8 ++++++--
 drivers/mfd/twl-core.h    | 10 ----------
 drivers/mfd/twl4030-irq.c |  2 --
 drivers/mfd/twl6030-irq.c |  2 --
 4 files changed, 6 insertions(+), 16 deletions(-)
 delete mode 100644 drivers/mfd/twl-core.h

diff --git a/drivers/mfd/twl-core.c b/drivers/mfd/twl-core.c
index 48b0668..e16084e 100644
--- a/drivers/mfd/twl-core.c
+++ b/drivers/mfd/twl-core.c
@@ -52,8 +52,6 @@
 /* Register descriptions for audio */
 #include <linux/mfd/twl4030-audio.h>
 
-#include "twl-core.h"
-
 /*
  * The TWL4030 "Triton 2" is one of a family of a multi-function "Power
  * Management and System Companion Device" chips originally designed for
@@ -150,6 +148,12 @@
 
 /*----------------------------------------------------------------------*/
 
+int twl6030_init_irq(struct device *dev, int irq_num);
+int twl6030_exit_irq(void);
+int twl4030_init_irq(struct device *dev, int irq_num);
+int twl4030_exit_irq(void);
+int twl4030_init_chip_irq(const char *chip);
+
 /* Structure for each TWL4030/TWL6030 Slave */
 struct twl_client {
 	struct i2c_client *client;
diff --git a/drivers/mfd/twl-core.h b/drivers/mfd/twl-core.h
deleted file mode 100644
index 6ff99dc..0000000
--- a/drivers/mfd/twl-core.h
+++ /dev/null
@@ -1,10 +0,0 @@
-#ifndef __TWL_CORE_H__
-#define __TWL_CORE_H__
-
-extern int twl6030_init_irq(struct device *dev, int irq_num);
-extern int twl6030_exit_irq(void);
-extern int twl4030_init_irq(struct device *dev, int irq_num);
-extern int twl4030_exit_irq(void);
-extern int twl4030_init_chip_irq(const char *chip);
-
-#endif /*  __TWL_CORE_H__ */
diff --git a/drivers/mfd/twl4030-irq.c b/drivers/mfd/twl4030-irq.c
index b46c0cf..000c231 100644
--- a/drivers/mfd/twl4030-irq.c
+++ b/drivers/mfd/twl4030-irq.c
@@ -35,8 +35,6 @@
 #include <linux/irqdomain.h>
 #include <linux/i2c/twl.h>
 
-#include "twl-core.h"
-
 /*
  * TWL4030 IRQ handling has two stages in hardware, and thus in software.
  * The Primary Interrupt Handler (PIH) stage exposes status bits saying
diff --git a/drivers/mfd/twl6030-irq.c b/drivers/mfd/twl6030-irq.c
index 5357450..63eca76 100644
--- a/drivers/mfd/twl6030-irq.c
+++ b/drivers/mfd/twl6030-irq.c
@@ -42,8 +42,6 @@
 #include <linux/irqdomain.h>
 #include <linux/of_device.h>
 
-#include "twl-core.h"
-
 /*
  * TWL6030 (unlike its predecessors, which had two level interrupt handling)
  * three interrupt registers INT_STS_A, INT_STS_B and INT_STS_C.
-- 
2.9.3

^ permalink raw reply related	[flat|nested] 38+ messages in thread

* [PATCH 3/5] mfd: twl: move structure definitions to a public header
@ 2016-11-26 18:13   ` Nicolae Rosia
  0 siblings, 0 replies; 38+ messages in thread
From: Nicolae Rosia @ 2016-11-26 18:13 UTC (permalink / raw)
  To: Lee Jones, Mark Brown, Rob Herring, Mark Rutland, Tony Lindgren
  Cc: Liam Girdwood, Paul Gortmaker, Graeme Gregory, Baruch Siach,
	linux-omap, linux-arm-kernel, linux-kernel, devicetree,
	Nicolae Rosia

We want to get rid of exported symbols and have
the child devices use structure members directly.
Move the structure definitions to header and set
drvdata so child devices can access it.

Signed-off-by: Nicolae Rosia <Nicolae_Rosia@mentor.com>
---
 drivers/mfd/twl-core.c       | 27 ++++-----------------------
 include/linux/mfd/twl-core.h | 35 +++++++++++++++++++++++++++++++++++
 2 files changed, 39 insertions(+), 23 deletions(-)
 create mode 100644 include/linux/mfd/twl-core.h

diff --git a/drivers/mfd/twl-core.c b/drivers/mfd/twl-core.c
index e16084e..409b836 100644
--- a/drivers/mfd/twl-core.c
+++ b/drivers/mfd/twl-core.c
@@ -48,6 +48,7 @@
 
 #include <linux/i2c.h>
 #include <linux/i2c/twl.h>
+#include <linux/mfd/twl-core.h>
 
 /* Register descriptions for audio */
 #include <linux/mfd/twl4030-audio.h>
@@ -154,28 +155,7 @@ int twl4030_init_irq(struct device *dev, int irq_num);
 int twl4030_exit_irq(void);
 int twl4030_init_chip_irq(const char *chip);
 
-/* Structure for each TWL4030/TWL6030 Slave */
-struct twl_client {
-	struct i2c_client *client;
-	struct regmap *regmap;
-};
-
-/* mapping the module id to slave id and base address */
-struct twl_mapping {
-	unsigned char sid;	/* Slave ID */
-	unsigned char base;	/* base address */
-};
-
-struct twl_private {
-	bool ready; /* The core driver is ready to be used */
-	u32 twl_idcode; /* TWL IDCODE Register value */
-	unsigned int twl_id;
-
-	struct twl_mapping *twl_map;
-	struct twl_client *twl_modules;
-};
-
-static struct twl_private *twl_priv;
+static struct twlcore *twl_priv;
 
 static struct twl_mapping twl4030_map[] = {
 	/*
@@ -745,7 +725,7 @@ twl_probe(struct i2c_client *client, const struct i2c_device_id *id)
 		goto free;
 	}
 
-	twl_priv = devm_kzalloc(&client->dev, sizeof(struct twl_private),
+	twl_priv = devm_kzalloc(&client->dev, sizeof(struct twlcore),
 				GFP_KERNEL);
 	if (!twl_priv) {
 		status = -ENOMEM;
@@ -803,6 +783,7 @@ twl_probe(struct i2c_client *client, const struct i2c_device_id *id)
 	}
 
 	twl_priv->ready = true;
+	dev_set_drvdata(&client->dev, twl_priv);
 
 	/* setup clock framework */
 	clocks_init(&pdev->dev);
diff --git a/include/linux/mfd/twl-core.h b/include/linux/mfd/twl-core.h
new file mode 100644
index 0000000..d1c01b3
--- /dev/null
+++ b/include/linux/mfd/twl-core.h
@@ -0,0 +1,35 @@
+/*
+ * MFD core driver for the Texas Instruments TWL PMIC family
+ *
+ * Copyright (C) 2016 Nicolae Rosia <nicolae.rosia@gmail.com>
+ *
+ * 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.
+ */
+
+#ifndef __TWL_CORE_H__
+#define __TWL_CORE_H__
+
+/* Structure for each TWL4030/TWL6030 Slave */
+struct twl_client {
+	struct i2c_client *client;
+	struct regmap *regmap;
+};
+
+/* mapping the module id to slave id and base address */
+struct twl_mapping {
+	unsigned char sid; /* Slave ID */
+	unsigned char base; /* base address */
+};
+
+struct twlcore {
+	bool ready; /* The core driver is ready to be used */
+	u32 twl_idcode; /* TWL IDCODE Register value */
+	unsigned int twl_id;
+
+	struct twl_mapping *twl_map;
+	struct twl_client *twl_modules;
+};
+
+#endif
-- 
2.9.3

^ permalink raw reply related	[flat|nested] 38+ messages in thread

* [PATCH 3/5] mfd: twl: move structure definitions to a public header
@ 2016-11-26 18:13   ` Nicolae Rosia
  0 siblings, 0 replies; 38+ messages in thread
From: Nicolae Rosia @ 2016-11-26 18:13 UTC (permalink / raw)
  To: Lee Jones, Mark Brown, Rob Herring, Mark Rutland, Tony Lindgren
  Cc: Liam Girdwood, Paul Gortmaker, Graeme Gregory, Baruch Siach,
	linux-omap-u79uwXL29TY76Z2rM5mHXA,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	devicetree-u79uwXL29TY76Z2rM5mHXA, Nicolae Rosia

We want to get rid of exported symbols and have
the child devices use structure members directly.
Move the structure definitions to header and set
drvdata so child devices can access it.

Signed-off-by: Nicolae Rosia <Nicolae_Rosia-nmGgyN9QBj3QT0dZR+AlfA@public.gmane.org>
---
 drivers/mfd/twl-core.c       | 27 ++++-----------------------
 include/linux/mfd/twl-core.h | 35 +++++++++++++++++++++++++++++++++++
 2 files changed, 39 insertions(+), 23 deletions(-)
 create mode 100644 include/linux/mfd/twl-core.h

diff --git a/drivers/mfd/twl-core.c b/drivers/mfd/twl-core.c
index e16084e..409b836 100644
--- a/drivers/mfd/twl-core.c
+++ b/drivers/mfd/twl-core.c
@@ -48,6 +48,7 @@
 
 #include <linux/i2c.h>
 #include <linux/i2c/twl.h>
+#include <linux/mfd/twl-core.h>
 
 /* Register descriptions for audio */
 #include <linux/mfd/twl4030-audio.h>
@@ -154,28 +155,7 @@ int twl4030_init_irq(struct device *dev, int irq_num);
 int twl4030_exit_irq(void);
 int twl4030_init_chip_irq(const char *chip);
 
-/* Structure for each TWL4030/TWL6030 Slave */
-struct twl_client {
-	struct i2c_client *client;
-	struct regmap *regmap;
-};
-
-/* mapping the module id to slave id and base address */
-struct twl_mapping {
-	unsigned char sid;	/* Slave ID */
-	unsigned char base;	/* base address */
-};
-
-struct twl_private {
-	bool ready; /* The core driver is ready to be used */
-	u32 twl_idcode; /* TWL IDCODE Register value */
-	unsigned int twl_id;
-
-	struct twl_mapping *twl_map;
-	struct twl_client *twl_modules;
-};
-
-static struct twl_private *twl_priv;
+static struct twlcore *twl_priv;
 
 static struct twl_mapping twl4030_map[] = {
 	/*
@@ -745,7 +725,7 @@ twl_probe(struct i2c_client *client, const struct i2c_device_id *id)
 		goto free;
 	}
 
-	twl_priv = devm_kzalloc(&client->dev, sizeof(struct twl_private),
+	twl_priv = devm_kzalloc(&client->dev, sizeof(struct twlcore),
 				GFP_KERNEL);
 	if (!twl_priv) {
 		status = -ENOMEM;
@@ -803,6 +783,7 @@ twl_probe(struct i2c_client *client, const struct i2c_device_id *id)
 	}
 
 	twl_priv->ready = true;
+	dev_set_drvdata(&client->dev, twl_priv);
 
 	/* setup clock framework */
 	clocks_init(&pdev->dev);
diff --git a/include/linux/mfd/twl-core.h b/include/linux/mfd/twl-core.h
new file mode 100644
index 0000000..d1c01b3
--- /dev/null
+++ b/include/linux/mfd/twl-core.h
@@ -0,0 +1,35 @@
+/*
+ * MFD core driver for the Texas Instruments TWL PMIC family
+ *
+ * Copyright (C) 2016 Nicolae Rosia <nicolae.rosia-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
+ *
+ * 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.
+ */
+
+#ifndef __TWL_CORE_H__
+#define __TWL_CORE_H__
+
+/* Structure for each TWL4030/TWL6030 Slave */
+struct twl_client {
+	struct i2c_client *client;
+	struct regmap *regmap;
+};
+
+/* mapping the module id to slave id and base address */
+struct twl_mapping {
+	unsigned char sid; /* Slave ID */
+	unsigned char base; /* base address */
+};
+
+struct twlcore {
+	bool ready; /* The core driver is ready to be used */
+	u32 twl_idcode; /* TWL IDCODE Register value */
+	unsigned int twl_id;
+
+	struct twl_mapping *twl_map;
+	struct twl_client *twl_modules;
+};
+
+#endif
-- 
2.9.3

--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply related	[flat|nested] 38+ messages in thread

* [PATCH 3/5] mfd: twl: move structure definitions to a public header
@ 2016-11-26 18:13   ` Nicolae Rosia
  0 siblings, 0 replies; 38+ messages in thread
From: Nicolae Rosia @ 2016-11-26 18:13 UTC (permalink / raw)
  To: linux-arm-kernel

We want to get rid of exported symbols and have
the child devices use structure members directly.
Move the structure definitions to header and set
drvdata so child devices can access it.

Signed-off-by: Nicolae Rosia <Nicolae_Rosia@mentor.com>
---
 drivers/mfd/twl-core.c       | 27 ++++-----------------------
 include/linux/mfd/twl-core.h | 35 +++++++++++++++++++++++++++++++++++
 2 files changed, 39 insertions(+), 23 deletions(-)
 create mode 100644 include/linux/mfd/twl-core.h

diff --git a/drivers/mfd/twl-core.c b/drivers/mfd/twl-core.c
index e16084e..409b836 100644
--- a/drivers/mfd/twl-core.c
+++ b/drivers/mfd/twl-core.c
@@ -48,6 +48,7 @@
 
 #include <linux/i2c.h>
 #include <linux/i2c/twl.h>
+#include <linux/mfd/twl-core.h>
 
 /* Register descriptions for audio */
 #include <linux/mfd/twl4030-audio.h>
@@ -154,28 +155,7 @@ int twl4030_init_irq(struct device *dev, int irq_num);
 int twl4030_exit_irq(void);
 int twl4030_init_chip_irq(const char *chip);
 
-/* Structure for each TWL4030/TWL6030 Slave */
-struct twl_client {
-	struct i2c_client *client;
-	struct regmap *regmap;
-};
-
-/* mapping the module id to slave id and base address */
-struct twl_mapping {
-	unsigned char sid;	/* Slave ID */
-	unsigned char base;	/* base address */
-};
-
-struct twl_private {
-	bool ready; /* The core driver is ready to be used */
-	u32 twl_idcode; /* TWL IDCODE Register value */
-	unsigned int twl_id;
-
-	struct twl_mapping *twl_map;
-	struct twl_client *twl_modules;
-};
-
-static struct twl_private *twl_priv;
+static struct twlcore *twl_priv;
 
 static struct twl_mapping twl4030_map[] = {
 	/*
@@ -745,7 +725,7 @@ twl_probe(struct i2c_client *client, const struct i2c_device_id *id)
 		goto free;
 	}
 
-	twl_priv = devm_kzalloc(&client->dev, sizeof(struct twl_private),
+	twl_priv = devm_kzalloc(&client->dev, sizeof(struct twlcore),
 				GFP_KERNEL);
 	if (!twl_priv) {
 		status = -ENOMEM;
@@ -803,6 +783,7 @@ twl_probe(struct i2c_client *client, const struct i2c_device_id *id)
 	}
 
 	twl_priv->ready = true;
+	dev_set_drvdata(&client->dev, twl_priv);
 
 	/* setup clock framework */
 	clocks_init(&pdev->dev);
diff --git a/include/linux/mfd/twl-core.h b/include/linux/mfd/twl-core.h
new file mode 100644
index 0000000..d1c01b3
--- /dev/null
+++ b/include/linux/mfd/twl-core.h
@@ -0,0 +1,35 @@
+/*
+ * MFD core driver for the Texas Instruments TWL PMIC family
+ *
+ * Copyright (C) 2016 Nicolae Rosia <nicolae.rosia@gmail.com>
+ *
+ * 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.
+ */
+
+#ifndef __TWL_CORE_H__
+#define __TWL_CORE_H__
+
+/* Structure for each TWL4030/TWL6030 Slave */
+struct twl_client {
+	struct i2c_client *client;
+	struct regmap *regmap;
+};
+
+/* mapping the module id to slave id and base address */
+struct twl_mapping {
+	unsigned char sid; /* Slave ID */
+	unsigned char base; /* base address */
+};
+
+struct twlcore {
+	bool ready; /* The core driver is ready to be used */
+	u32 twl_idcode; /* TWL IDCODE Register value */
+	unsigned int twl_id;
+
+	struct twl_mapping *twl_map;
+	struct twl_client *twl_modules;
+};
+
+#endif
-- 
2.9.3

^ permalink raw reply related	[flat|nested] 38+ messages in thread

* [PATCH 4/5] regulator: Add support for TI TWL6032
@ 2016-11-26 18:13   ` Nicolae Rosia
  0 siblings, 0 replies; 38+ messages in thread
From: Nicolae Rosia @ 2016-11-26 18:13 UTC (permalink / raw)
  To: Lee Jones, Mark Brown, Rob Herring, Mark Rutland, Tony Lindgren
  Cc: Liam Girdwood, Paul Gortmaker, Graeme Gregory, Baruch Siach,
	linux-omap, linux-arm-kernel, linux-kernel, devicetree,
	Nicolae Rosia

The TWL6032 PMIC is similar to TWL6030, has different
output names, and regulator control logic.
It is used on Barnes & Noble Nook HD and HD+.

Signed-off-by: Nicolae Rosia <Nicolae_Rosia@mentor.com>
---
 .../bindings/regulator/twl6032-regulator.txt       | 109 ++++
 drivers/regulator/Kconfig                          |   7 +
 drivers/regulator/Makefile                         |   1 +
 drivers/regulator/twl6032-regulator.c              | 582 +++++++++++++++++++++
 4 files changed, 699 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/regulator/twl6032-regulator.txt
 create mode 100644 drivers/regulator/twl6032-regulator.c

diff --git a/Documentation/devicetree/bindings/regulator/twl6032-regulator.txt b/Documentation/devicetree/bindings/regulator/twl6032-regulator.txt
new file mode 100644
index 0000000..323f5a9
--- /dev/null
+++ b/Documentation/devicetree/bindings/regulator/twl6032-regulator.txt
@@ -0,0 +1,109 @@
+TWL6032 PMIC Voltage Regulator Bindings
+
+The parent node must be MFD TWL Core, ti,twl6032.
+
+Required properties:
+- compatible: "ti,twl6032"
+
+Optional properties:
+- regulators node containing regulator childs.
+
+The child regulators  must be named after their hardware
+counterparts: LDO[1-6], LDOLN, LDOUSB and VANA.
+
+Each regulator is defined using the standard binding
+for regulators as described in ./regulator.txt
+
+Example:
+twl {
+	compatible = "ti,twl6032";
+
+	[...]
+
+	pmic {
+		compatible = "ti,twl6032-regulator";
+
+		regulators {
+			ldo1: LDO1 {
+				regulator-min-microvolt = <1800000>;
+				regulator-max-microvolt = <2500000>;
+
+				regulator-state-mem {
+					regulator-off-in-suspend;
+				};
+			};
+
+			ldo2: LDO2 {
+				regulator-min-microvolt = <1000000>;
+				regulator-max-microvolt = <3000000>;
+
+				regulator-state-mem {
+					regulator-off-in-suspend;
+				};
+			};
+
+			ldo3: LDO3 {
+				regulator-min-microvolt = <1800000>;
+				regulator-max-microvolt = <1800000>;
+				regulator-boot-on;
+
+				regulator-state-mem {
+					regulator-off-in-suspend;
+				};
+			};
+
+			ldo4: LDO4 {
+				regulator-min-microvolt = <1800000>;
+				regulator-max-microvolt = <1800000>;
+
+				regulator-state-mem {
+					regulator-off-in-suspend;
+				};
+			};
+
+			ldo5: LDO5 {
+				regulator-min-microvolt = <1200000>;
+				regulator-max-microvolt = <3000000>;
+
+				regulator-state-mem {
+					regulator-off-in-suspend;
+				};
+			};
+
+			ldo6: LDO6 {
+				regulator-min-microvolt = <1800000>;
+				regulator-max-microvolt = <1800000>;
+				regulator-always-on;
+
+				regulator-state-mem {
+					regulator-off-in-suspend;
+				};
+			};
+
+			ldo7: LDO7 {
+				regulator-min-microvolt = <1800000>;
+				regulator-max-microvolt = <1800000>;
+				regulator-boot-on;
+				regulator-always-on;
+			};
+
+			ldoln: LDOLN {
+				regulator-min-microvolt = <1000000>;
+				regulator-max-microvolt = <3000000>;
+			};
+
+			ldousb: LDOUSB {
+				regulator-min-microvolt = <1000000>;
+				regulator-max-microvolt = <3000000>;
+			};
+
+			vana: VANA {
+				regulator-min-microvolt = <2100000>;
+				regulator-max-microvolt = <2100000>;
+				regulator-always-on;
+			};
+		};
+	};
+
+	[...]
+};
diff --git a/drivers/regulator/Kconfig b/drivers/regulator/Kconfig
index 936f7cc..3168aba 100644
--- a/drivers/regulator/Kconfig
+++ b/drivers/regulator/Kconfig
@@ -843,6 +843,13 @@ config REGULATOR_TWL4030
 	  This driver supports the voltage regulators provided by
 	  this family of companion chips.
 
+config REGULATOR_TWL6032
+	tristate "TI TWL6032 PMIC"
+	depends on TWL4030_CORE
+	depends on OF || COMPILE_TEST
+	help
+	  This driver supports the Texas Instruments TWL6032 voltage regulator.
+
 config REGULATOR_VEXPRESS
 	tristate "Versatile Express regulators"
 	depends on VEXPRESS_CONFIG
diff --git a/drivers/regulator/Makefile b/drivers/regulator/Makefile
index 2142a5d..185a979 100644
--- a/drivers/regulator/Makefile
+++ b/drivers/regulator/Makefile
@@ -105,6 +105,7 @@ obj-$(CONFIG_REGULATOR_TPS65910) += tps65910-regulator.o
 obj-$(CONFIG_REGULATOR_TPS65912) += tps65912-regulator.o
 obj-$(CONFIG_REGULATOR_TPS80031) += tps80031-regulator.o
 obj-$(CONFIG_REGULATOR_TWL4030) += twl-regulator.o
+obj-$(CONFIG_REGULATOR_TWL6032) += twl6032-regulator.o
 obj-$(CONFIG_REGULATOR_VEXPRESS) += vexpress-regulator.o
 obj-$(CONFIG_REGULATOR_WM831X) += wm831x-dcdc.o
 obj-$(CONFIG_REGULATOR_WM831X) += wm831x-isink.o
diff --git a/drivers/regulator/twl6032-regulator.c b/drivers/regulator/twl6032-regulator.c
new file mode 100644
index 0000000..70a0fdf
--- /dev/null
+++ b/drivers/regulator/twl6032-regulator.c
@@ -0,0 +1,582 @@
+/*
+ * TWL6032 regulator driver
+ * Copyright (C) 2016 Nicolae Rosia <nicolae.rosia@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/err.h>
+#include <linux/platform_device.h>
+#include <linux/regulator/driver.h>
+#include <linux/regulator/machine.h>
+#include <linux/regulator/of_regulator.h>
+#include <linux/of.h>
+#include <linux/regmap.h>
+#include <linux/irq.h>
+#include <linux/mfd/twl-core.h>
+
+/* TWL6032 register offsets */
+#define TWL6032_VREG_TRANS 1
+#define TWL6032_VREG_STATE 2
+#define TWL6032_VREG_VOLTAGE 3
+
+#define TWL6032_LDO_MIN_MV 1000
+#define TWL6032_LDO_MAX_MV 3300
+
+/* TWL6030 LDO register values for CFG_TRANS */
+#define TWL6032_CFG_TRANS_STATE_MASK 0x03
+#define TWL6032_CFG_TRANS_STATE_OFF 0x00
+#define TWL6032_CFG_TRANS_STATE_AUTO 0x01
+#define TWL6032_CFG_TRANS_SLEEP_SHIFT 2
+
+#define TWL6032_CFG_STATE_MASK 0x03
+#define TWL6032_CFG_STATE_OFF 0x00
+#define TWL6032_CFG_STATE_ON 0x01
+#define TWL6032_CFG_STATE_OFF2 0x02
+#define TWL6032_CFG_STATE_SLEEP 0x03
+
+static const char *rdev_get_name(struct regulator_dev *rdev)
+{
+	if (rdev->constraints && rdev->constraints->name)
+		return rdev->constraints->name;
+	else if (rdev->desc->name)
+		return rdev->desc->name;
+	else
+		return "";
+}
+
+struct twl6032_regulator_info {
+	u8 base;
+	unsigned int min_mV;
+	struct regulator_desc desc;
+};
+
+struct twl6032_regulator {
+	struct twl6032_regulator_info *info;
+};
+
+static int twl6032_set_trans_state(struct regulator_dev *rdev, u8 shift, u8 val)
+{
+	struct twl6032_regulator *twl6032_reg = rdev_get_drvdata(rdev);
+	struct twl6032_regulator_info *info = twl6032_reg->info;
+	unsigned int state;
+	u8 mask;
+	int ret;
+
+	/* Read CFG_TRANS register of TWL6030 */
+	ret = regmap_read(rdev->regmap, info->base + TWL6032_VREG_TRANS,
+			  &state);
+	if (ret < 0) {
+		dev_err(&rdev->dev, "%s %s: regmap_read: %d\n",
+			rdev_get_name(rdev), __func__, ret);
+		return ret;
+	}
+
+	mask = TWL6032_CFG_TRANS_STATE_MASK << shift;
+	val = (val << shift) & mask;
+
+	/* If value is already set, no need to write to reg */
+	if (val == (state & mask))
+		return 0;
+
+	state &= ~mask;
+	state |= val;
+
+	return regmap_write(rdev->regmap, info->base + TWL6032_VREG_TRANS,
+			    state);
+}
+
+static int
+twl6032_ldo_list_voltage(struct regulator_dev *rdev, unsigned int sel)
+{
+	int ret;
+
+	switch (sel) {
+	case 0:
+		ret = 0;
+		break;
+	case 1 ... 24:
+		/* Linear mapping from 00000001 to 00011000:
+		 * Absolute voltage value = 1.0 V + 0.1 V × (sel – 00000001)
+		 */
+		ret = (TWL6032_LDO_MIN_MV + 100 * (sel - 1)) * 1000;
+		break;
+	case 25 ... 30:
+		ret = -EINVAL;
+		break;
+	case 31:
+		ret = 2750000;
+		break;
+	default:
+		ret = -EINVAL;
+	}
+
+	dev_dbg(&rdev->dev, "%s %s: sel: %d, mV: %d\n", rdev_get_name(rdev),
+		__func__, sel, ret);
+
+	return ret;
+}
+
+static int
+twl6032_ldo_set_voltage_sel(struct regulator_dev *rdev, unsigned int sel)
+{
+	struct twl6032_regulator *twl6032_reg = rdev_get_drvdata(rdev);
+	struct twl6032_regulator_info *info = twl6032_reg->info;
+	int ret;
+
+	dev_dbg(&rdev->dev, "%s %s: sel: 0x%02X\n", rdev_get_name(rdev),
+		__func__, sel);
+
+	ret = regmap_write(rdev->regmap, info->base + TWL6032_VREG_VOLTAGE,
+			   sel);
+	if (ret < 0) {
+		dev_err(&rdev->dev, "%s %s: regmap_write: %d\n",
+			rdev_get_name(rdev), __func__, ret);
+		return ret;
+	}
+
+	return 0;
+}
+
+static int twl6032_ldo_get_voltage_sel(struct regulator_dev *rdev)
+{
+	struct twl6032_regulator *twl6032_reg = rdev_get_drvdata(rdev);
+	struct twl6032_regulator_info *info = twl6032_reg->info;
+	unsigned int val;
+	int ret;
+
+	ret = regmap_read(rdev->regmap, info->base + TWL6032_VREG_VOLTAGE,
+			  &val);
+	if (ret < 0) {
+		dev_err(&rdev->dev, "%s %s: regmap_read: %d\n",
+			rdev_get_name(rdev), __func__, ret);
+		return ret;
+	}
+
+	dev_dbg(&rdev->dev, "%s %s: vsel: 0x%02X\n", rdev_get_name(rdev),
+		__func__, val);
+
+	return val;
+}
+
+static int twl6032_ldo_enable(struct regulator_dev *rdev)
+{
+	struct twl6032_regulator *twl6032_reg = rdev_get_drvdata(rdev);
+	struct twl6032_regulator_info *info = twl6032_reg->info;
+	int ret;
+
+	dev_dbg(&rdev->dev, "%s %s\n", rdev_get_name(rdev), __func__);
+
+	ret = regmap_write(rdev->regmap, info->base + TWL6032_VREG_STATE,
+			   TWL6032_CFG_STATE_ON);
+	if (ret < 0) {
+		dev_err(&rdev->dev, "%s %s: regmap_write: %d\n",
+			rdev_get_name(rdev), __func__, ret);
+		return ret;
+	}
+
+	ret = twl6032_set_trans_state(rdev, TWL6032_CFG_TRANS_SLEEP_SHIFT,
+				      TWL6032_CFG_TRANS_STATE_AUTO);
+	if (ret < 0) {
+		dev_err(&rdev->dev, "%s %s: twl6032_set_trans_state: %d\n",
+			rdev_get_name(rdev), __func__, ret);
+		return ret;
+	}
+
+	return 0;
+}
+
+static int twl6032_ldo_disable(struct regulator_dev *rdev)
+{
+	struct twl6032_regulator *twl6032_reg = rdev_get_drvdata(rdev);
+	struct twl6032_regulator_info *info = twl6032_reg->info;
+	int ret;
+
+	dev_dbg(&rdev->dev, "%s %s\n", rdev_get_name(rdev), __func__);
+
+	ret = regmap_write(rdev->regmap, info->base + TWL6032_VREG_STATE,
+			   TWL6032_CFG_STATE_OFF);
+	if (ret < 0) {
+		dev_err(&rdev->dev, "%s %s: regmap_write: %d\n",
+			rdev_get_name(rdev), __func__, ret);
+		return ret;
+	}
+
+	ret = twl6032_set_trans_state(rdev, TWL6032_CFG_TRANS_SLEEP_SHIFT,
+				      TWL6032_CFG_TRANS_STATE_OFF);
+	if (ret < 0) {
+		dev_err(&rdev->dev, "%s %s: twl6032_set_trans_state: %d\n",
+			rdev_get_name(rdev), __func__, ret);
+		return ret;
+	}
+
+	return 0;
+}
+
+static int twl6032_ldo_is_enabled(struct regulator_dev *rdev)
+{
+	struct twl6032_regulator *twl6032_reg = rdev_get_drvdata(rdev);
+	struct twl6032_regulator_info *info = twl6032_reg->info;
+	int ret;
+	unsigned int val;
+
+	ret = regmap_read(rdev->regmap, info->base + TWL6032_VREG_STATE, &val);
+	if (ret < 0) {
+		dev_err(&rdev->dev, "%s regmap_read: %d\n", __func__, ret);
+		return ret;
+	}
+
+	dev_dbg(&rdev->dev, "%s %s: val: 0x%02X, val-masked: 0x%02X, ret: %d\n",
+		rdev_get_name(rdev), __func__,
+		val, val & TWL6032_CFG_STATE_MASK,
+		(val & TWL6032_CFG_STATE_MASK) == TWL6032_CFG_STATE_ON);
+
+	val &= TWL6032_CFG_STATE_MASK;
+
+	return val == TWL6032_CFG_STATE_ON;
+}
+
+static int twl6032_ldo_set_mode(struct regulator_dev *rdev, unsigned int mode)
+{
+	struct twl6032_regulator *twl6032_reg = rdev_get_drvdata(rdev);
+	struct twl6032_regulator_info *info = twl6032_reg->info;
+	unsigned int val = 0;
+	int ret;
+
+	dev_dbg(&rdev->dev, "%s %s: mode: 0x%02X\n", rdev_get_name(rdev),
+		__func__, mode);
+
+	switch (mode) {
+	case REGULATOR_MODE_NORMAL:
+		val |= TWL6032_CFG_STATE_ON;
+		break;
+	case REGULATOR_MODE_STANDBY:
+		val |= TWL6032_CFG_STATE_SLEEP;
+		break;
+
+	default:
+		return -EINVAL;
+	}
+
+	ret = regmap_write(rdev->regmap, info->base + TWL6032_VREG_STATE, val);
+	if (ret < 0) {
+		dev_err(&rdev->dev, "%s %s: regmap_write: %d\n",
+			rdev_get_name(rdev), __func__, ret);
+		return ret;
+	}
+
+	return 0;
+}
+
+static int twl6032_ldo_get_status(struct regulator_dev *rdev)
+{
+	struct twl6032_regulator *twl6032_reg = rdev_get_drvdata(rdev);
+	struct twl6032_regulator_info *info = twl6032_reg->info;
+	int ret;
+	unsigned int val;
+
+	ret = regmap_read(rdev->regmap, info->base + TWL6032_VREG_STATE, &val);
+	if (ret < 0) {
+		dev_err(&rdev->dev, "%s %s: regmap_read: %d\n",
+			rdev_get_name(rdev), __func__, ret);
+		return ret;
+	}
+
+	dev_dbg(&rdev->dev, "%s %s: val: 0x%02X, val-with-mask: 0x%02X\n",
+		rdev_get_name(rdev), __func__,
+		val, val & TWL6032_CFG_STATE_MASK);
+
+	val &= TWL6032_CFG_STATE_MASK;
+
+	switch (val) {
+	case TWL6032_CFG_STATE_ON:
+		return REGULATOR_STATUS_NORMAL;
+
+	case TWL6032_CFG_STATE_SLEEP:
+		return REGULATOR_STATUS_STANDBY;
+
+	case TWL6032_CFG_STATE_OFF:
+	case TWL6032_CFG_STATE_OFF2:
+	default:
+		break;
+	}
+
+	return REGULATOR_STATUS_OFF;
+}
+
+static int twl6032_ldo_suspend_enable(struct regulator_dev *rdev)
+{
+	return twl6032_set_trans_state(rdev, TWL6032_CFG_TRANS_SLEEP_SHIFT,
+				       TWL6032_CFG_TRANS_STATE_AUTO);
+}
+
+static int twl6032_ldo_suspend_disable(struct regulator_dev *rdev)
+{
+	return twl6032_set_trans_state(rdev, TWL6032_CFG_TRANS_SLEEP_SHIFT,
+				       TWL6032_CFG_TRANS_STATE_OFF);
+}
+
+static int
+twl6032_fixed_list_voltage(struct regulator_dev *rdev, unsigned int sel)
+{
+	struct twl6032_regulator *twl6032_reg = rdev_get_drvdata(rdev);
+	struct twl6032_regulator_info *info = twl6032_reg->info;
+
+	return info->min_mV * 1000; /* mV to V */
+}
+
+static int twl6032_fixed_get_voltage(struct regulator_dev *rdev)
+{
+	struct twl6032_regulator *twl6032_reg = rdev_get_drvdata(rdev);
+	struct twl6032_regulator_info *info = twl6032_reg->info;
+
+	return info->min_mV * 1000; /* mV to V */
+}
+
+static const struct regulator_ops twl6032_ldo_ops = {
+	.list_voltage = twl6032_ldo_list_voltage,
+	.set_voltage_sel = twl6032_ldo_set_voltage_sel,
+	.get_voltage_sel = twl6032_ldo_get_voltage_sel,
+	.enable = twl6032_ldo_enable,
+	.disable = twl6032_ldo_disable,
+	.is_enabled = twl6032_ldo_is_enabled,
+	.set_mode = twl6032_ldo_set_mode,
+	.get_status = twl6032_ldo_get_status,
+	.set_suspend_enable = twl6032_ldo_suspend_enable,
+	.set_suspend_disable =  twl6032_ldo_suspend_disable,
+};
+
+static const struct regulator_ops twl6032_fixed_ops = {
+	.list_voltage = twl6032_fixed_list_voltage,
+	.get_voltage = twl6032_fixed_get_voltage,
+	.enable = twl6032_ldo_enable,
+	.disable = twl6032_ldo_disable,
+	.is_enabled = twl6032_ldo_is_enabled,
+	.set_mode = twl6032_ldo_set_mode,
+	.get_status = twl6032_ldo_get_status,
+	.set_suspend_enable = twl6032_ldo_suspend_enable,
+	.set_suspend_disable =  twl6032_ldo_suspend_disable,
+};
+
+#define TWL6032_LDO_REG_VOLTAGES \
+	((TWL6032_LDO_MAX_MV - TWL6032_LDO_MIN_MV) / 100 + 1)
+#define TWL6032_LDO_REG(_id, _reg) \
+{ \
+	.base = _reg, \
+	.desc = { \
+		.name = "twl6032-reg-" # _id, \
+		.n_voltages = TWL6032_LDO_REG_VOLTAGES, \
+		.ops = &twl6032_ldo_ops, \
+		.type = REGULATOR_VOLTAGE, \
+		.owner = THIS_MODULE, \
+	}, \
+}
+
+#define TWL6032_FIXED_REG(_id, _reg, _min_mV) \
+{ \
+	.base = _reg, \
+	.min_mV = _min_mV, \
+	.desc = { \
+		.name = "twl6032-reg-" # _id, \
+		.n_voltages = 1, \
+		.ops = &twl6032_fixed_ops, \
+		.type = REGULATOR_VOLTAGE, \
+		.owner = THIS_MODULE, \
+	}, \
+}
+
+#define TWL6032_RESOURCE_REG(_id, _reg) \
+{ \
+	.base = _reg, \
+	.desc = { \
+		.name = "twl6032-reg-" # _id, \
+		.ops = &twl6032_ldo_ops, \
+		.type = REGULATOR_VOLTAGE, \
+		.owner = THIS_MODULE, \
+	}, \
+}
+
+static struct twl6032_regulator_info twl6032_ldo_reg_info[] = {
+	TWL6032_LDO_REG(LDO1, 0x9C),
+	TWL6032_LDO_REG(LDO2, 0x84),
+	TWL6032_LDO_REG(LDO3, 0x8C),
+	TWL6032_LDO_REG(LDO4, 0x88),
+	TWL6032_LDO_REG(LDO5, 0x98),
+	TWL6032_LDO_REG(LDO6, 0x90),
+	TWL6032_LDO_REG(LDO7, 0xA4),
+	TWL6032_LDO_REG(LDOLN, 0x94),
+	TWL6032_LDO_REG(LDOUSB, 0xA0),
+};
+
+static struct twl6032_regulator_info twl6032_fixed_reg_info[] = {
+	TWL6032_FIXED_REG(VANA, 0x80, 2100),
+};
+
+static struct of_regulator_match
+twl6032_ldo_reg_matches[] = {
+	{ .name = "LDO1", },
+	{ .name = "LDO2", },
+	{ .name = "LDO3", },
+	{ .name = "LDO4", },
+	{ .name = "LDO5", },
+	{ .name = "LDO6", },
+	{ .name = "LDO7", },
+	{ .name = "LDOLN" },
+	{ .name = "LDOUSB" }
+};
+
+static struct of_regulator_match
+twl6032_fixed_reg_matches[] = {
+	{ .name = "VANA", },
+};
+
+#define TWL6032_LDO_REG_NUM ARRAY_SIZE(twl6032_ldo_reg_matches)
+#define TWL6032_FIXED_REG_NUM ARRAY_SIZE(twl6032_fixed_reg_matches)
+
+struct twl6032_regulator_priv {
+	struct twl6032_regulator ldo_regulators[TWL6032_LDO_REG_NUM];
+	struct twl6032_regulator fixed_regulators[TWL6032_FIXED_REG_NUM];
+};
+
+static int twl6032_regulator_probe(struct platform_device *pdev)
+{
+	struct device *dev = &pdev->dev;
+	struct device_node *regulators;
+	struct of_regulator_match *match;
+	struct twlcore *twl = dev_get_drvdata(pdev->dev.parent);
+	struct twl6032_regulator_priv *priv;
+	struct regulator_config config = {
+		.dev = &pdev->dev,
+	};
+	struct regulator_dev *rdev;
+	int ret, i;
+
+	if (!dev->of_node) {
+		dev_err(&pdev->dev, "no DT info\n");
+		return -EINVAL;
+	}
+
+	regulators = of_get_child_by_name(dev->of_node, "regulators");
+	if (!regulators) {
+		dev_err(dev, "regulator node not found\n");
+		return -EINVAL;
+	}
+
+	priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
+	if (!priv)
+		return -ENOMEM;
+
+	platform_set_drvdata(pdev, priv);
+
+	/* LDO regulators parsing */
+	ret = of_regulator_match(dev, regulators, twl6032_ldo_reg_matches,
+				 TWL6032_LDO_REG_NUM);
+	of_node_put(regulators);
+	if (ret < 0) {
+		dev_err(dev, "error parsing LDO reg init data: %d\n", ret);
+		return ret;
+	}
+
+	for (i = 0; i < TWL6032_LDO_REG_NUM; i++) {
+		struct twl6032_regulator *twl6032_reg;
+
+		match = &twl6032_ldo_reg_matches[i];
+		if (!match->of_node)
+			continue;
+
+		twl6032_reg = &priv->ldo_regulators[i];
+		twl6032_reg->info = &twl6032_ldo_reg_info[i];
+
+		config.init_data = match->init_data;
+		config.driver_data = &priv->ldo_regulators[i];
+		config.regmap = twl->twl_modules[0].regmap;
+		config.of_node = match->of_node;
+
+		rdev = devm_regulator_register(dev, &twl6032_reg->info->desc,
+					       &config);
+		if (IS_ERR(rdev)) {
+			ret = PTR_ERR(rdev);
+			dev_err(dev, "failed to register regulator %s: %d\n",
+				twl6032_reg->info->desc.name, ret);
+			return ret;
+		}
+	}
+
+	/* Fixed regulators parsing */
+	ret = of_regulator_match(dev, regulators, twl6032_fixed_reg_matches,
+				 TWL6032_FIXED_REG_NUM);
+	of_node_put(regulators);
+	if (ret < 0) {
+		dev_err(dev, "error parsing fixed reg init data: %d\n", ret);
+		return ret;
+	}
+
+	for (i = 0; i < TWL6032_FIXED_REG_NUM; i++) {
+		struct twl6032_regulator *twl6032_reg;
+
+		match = &twl6032_fixed_reg_matches[i];
+		if (!match->of_node)
+			continue;
+
+		twl6032_reg = &priv->fixed_regulators[i];
+		twl6032_reg->info = &twl6032_fixed_reg_info[i];
+
+		config.init_data = match->init_data;
+		config.driver_data = &priv->fixed_regulators[i];
+		config.regmap = twl->twl_modules[0].regmap;
+		config.of_node = match->of_node;
+
+		rdev = devm_regulator_register(dev, &twl6032_reg->info->desc,
+					       &config);
+		if (IS_ERR(rdev)) {
+			ret = PTR_ERR(rdev);
+			dev_err(dev, "failed to register regulator %s: %d\n",
+				twl6032_reg->info->desc.name, ret);
+			return ret;
+		}
+	}
+
+	return 0;
+}
+
+static int twl6032_regulator_remove(struct platform_device *pdev)
+{
+	return 0;
+}
+
+static const struct of_device_id twl6032_dt_match[] = {
+	{ .compatible = "ti,twl6032-regulator" },
+	{ /* last entry */ }
+};
+
+MODULE_DEVICE_TABLE(platform, twl6032_regulator_driver_ids);
+
+static struct platform_driver twl6032_regulator_driver = {
+	.driver = {
+		.name = "twl6032-regulator",
+		.of_match_table = twl6032_dt_match,
+	},
+	.probe = twl6032_regulator_probe,
+	.remove = twl6032_regulator_remove,
+};
+
+static int __init twl6032_regulator_init(void)
+{
+	return platform_driver_register(&twl6032_regulator_driver);
+}
+subsys_initcall(twl6032_regulator_init);
+
+static void __exit twl6032_regulator_exit(void)
+{
+	platform_driver_unregister(&twl6032_regulator_driver);
+}
+module_exit(twl6032_regulator_exit);
+
+MODULE_AUTHOR("Nicolae Rosia <nicolae.rosia@gmail.com>");
+MODULE_DESCRIPTION("TI TWL6032 Regulator Driver");
+MODULE_LICENSE("GPL v2");
-- 
2.9.3

^ permalink raw reply related	[flat|nested] 38+ messages in thread

* [PATCH 4/5] regulator: Add support for TI TWL6032
@ 2016-11-26 18:13   ` Nicolae Rosia
  0 siblings, 0 replies; 38+ messages in thread
From: Nicolae Rosia @ 2016-11-26 18:13 UTC (permalink / raw)
  To: Lee Jones, Mark Brown, Rob Herring, Mark Rutland, Tony Lindgren
  Cc: Liam Girdwood, Paul Gortmaker, Graeme Gregory, Baruch Siach,
	linux-omap-u79uwXL29TY76Z2rM5mHXA,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	devicetree-u79uwXL29TY76Z2rM5mHXA, Nicolae Rosia

The TWL6032 PMIC is similar to TWL6030, has different
output names, and regulator control logic.
It is used on Barnes & Noble Nook HD and HD+.

Signed-off-by: Nicolae Rosia <Nicolae_Rosia-nmGgyN9QBj3QT0dZR+AlfA@public.gmane.org>
---
 .../bindings/regulator/twl6032-regulator.txt       | 109 ++++
 drivers/regulator/Kconfig                          |   7 +
 drivers/regulator/Makefile                         |   1 +
 drivers/regulator/twl6032-regulator.c              | 582 +++++++++++++++++++++
 4 files changed, 699 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/regulator/twl6032-regulator.txt
 create mode 100644 drivers/regulator/twl6032-regulator.c

diff --git a/Documentation/devicetree/bindings/regulator/twl6032-regulator.txt b/Documentation/devicetree/bindings/regulator/twl6032-regulator.txt
new file mode 100644
index 0000000..323f5a9
--- /dev/null
+++ b/Documentation/devicetree/bindings/regulator/twl6032-regulator.txt
@@ -0,0 +1,109 @@
+TWL6032 PMIC Voltage Regulator Bindings
+
+The parent node must be MFD TWL Core, ti,twl6032.
+
+Required properties:
+- compatible: "ti,twl6032"
+
+Optional properties:
+- regulators node containing regulator childs.
+
+The child regulators  must be named after their hardware
+counterparts: LDO[1-6], LDOLN, LDOUSB and VANA.
+
+Each regulator is defined using the standard binding
+for regulators as described in ./regulator.txt
+
+Example:
+twl {
+	compatible = "ti,twl6032";
+
+	[...]
+
+	pmic {
+		compatible = "ti,twl6032-regulator";
+
+		regulators {
+			ldo1: LDO1 {
+				regulator-min-microvolt = <1800000>;
+				regulator-max-microvolt = <2500000>;
+
+				regulator-state-mem {
+					regulator-off-in-suspend;
+				};
+			};
+
+			ldo2: LDO2 {
+				regulator-min-microvolt = <1000000>;
+				regulator-max-microvolt = <3000000>;
+
+				regulator-state-mem {
+					regulator-off-in-suspend;
+				};
+			};
+
+			ldo3: LDO3 {
+				regulator-min-microvolt = <1800000>;
+				regulator-max-microvolt = <1800000>;
+				regulator-boot-on;
+
+				regulator-state-mem {
+					regulator-off-in-suspend;
+				};
+			};
+
+			ldo4: LDO4 {
+				regulator-min-microvolt = <1800000>;
+				regulator-max-microvolt = <1800000>;
+
+				regulator-state-mem {
+					regulator-off-in-suspend;
+				};
+			};
+
+			ldo5: LDO5 {
+				regulator-min-microvolt = <1200000>;
+				regulator-max-microvolt = <3000000>;
+
+				regulator-state-mem {
+					regulator-off-in-suspend;
+				};
+			};
+
+			ldo6: LDO6 {
+				regulator-min-microvolt = <1800000>;
+				regulator-max-microvolt = <1800000>;
+				regulator-always-on;
+
+				regulator-state-mem {
+					regulator-off-in-suspend;
+				};
+			};
+
+			ldo7: LDO7 {
+				regulator-min-microvolt = <1800000>;
+				regulator-max-microvolt = <1800000>;
+				regulator-boot-on;
+				regulator-always-on;
+			};
+
+			ldoln: LDOLN {
+				regulator-min-microvolt = <1000000>;
+				regulator-max-microvolt = <3000000>;
+			};
+
+			ldousb: LDOUSB {
+				regulator-min-microvolt = <1000000>;
+				regulator-max-microvolt = <3000000>;
+			};
+
+			vana: VANA {
+				regulator-min-microvolt = <2100000>;
+				regulator-max-microvolt = <2100000>;
+				regulator-always-on;
+			};
+		};
+	};
+
+	[...]
+};
diff --git a/drivers/regulator/Kconfig b/drivers/regulator/Kconfig
index 936f7cc..3168aba 100644
--- a/drivers/regulator/Kconfig
+++ b/drivers/regulator/Kconfig
@@ -843,6 +843,13 @@ config REGULATOR_TWL4030
 	  This driver supports the voltage regulators provided by
 	  this family of companion chips.
 
+config REGULATOR_TWL6032
+	tristate "TI TWL6032 PMIC"
+	depends on TWL4030_CORE
+	depends on OF || COMPILE_TEST
+	help
+	  This driver supports the Texas Instruments TWL6032 voltage regulator.
+
 config REGULATOR_VEXPRESS
 	tristate "Versatile Express regulators"
 	depends on VEXPRESS_CONFIG
diff --git a/drivers/regulator/Makefile b/drivers/regulator/Makefile
index 2142a5d..185a979 100644
--- a/drivers/regulator/Makefile
+++ b/drivers/regulator/Makefile
@@ -105,6 +105,7 @@ obj-$(CONFIG_REGULATOR_TPS65910) += tps65910-regulator.o
 obj-$(CONFIG_REGULATOR_TPS65912) += tps65912-regulator.o
 obj-$(CONFIG_REGULATOR_TPS80031) += tps80031-regulator.o
 obj-$(CONFIG_REGULATOR_TWL4030) += twl-regulator.o
+obj-$(CONFIG_REGULATOR_TWL6032) += twl6032-regulator.o
 obj-$(CONFIG_REGULATOR_VEXPRESS) += vexpress-regulator.o
 obj-$(CONFIG_REGULATOR_WM831X) += wm831x-dcdc.o
 obj-$(CONFIG_REGULATOR_WM831X) += wm831x-isink.o
diff --git a/drivers/regulator/twl6032-regulator.c b/drivers/regulator/twl6032-regulator.c
new file mode 100644
index 0000000..70a0fdf
--- /dev/null
+++ b/drivers/regulator/twl6032-regulator.c
@@ -0,0 +1,582 @@
+/*
+ * TWL6032 regulator driver
+ * Copyright (C) 2016 Nicolae Rosia <nicolae.rosia-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/err.h>
+#include <linux/platform_device.h>
+#include <linux/regulator/driver.h>
+#include <linux/regulator/machine.h>
+#include <linux/regulator/of_regulator.h>
+#include <linux/of.h>
+#include <linux/regmap.h>
+#include <linux/irq.h>
+#include <linux/mfd/twl-core.h>
+
+/* TWL6032 register offsets */
+#define TWL6032_VREG_TRANS 1
+#define TWL6032_VREG_STATE 2
+#define TWL6032_VREG_VOLTAGE 3
+
+#define TWL6032_LDO_MIN_MV 1000
+#define TWL6032_LDO_MAX_MV 3300
+
+/* TWL6030 LDO register values for CFG_TRANS */
+#define TWL6032_CFG_TRANS_STATE_MASK 0x03
+#define TWL6032_CFG_TRANS_STATE_OFF 0x00
+#define TWL6032_CFG_TRANS_STATE_AUTO 0x01
+#define TWL6032_CFG_TRANS_SLEEP_SHIFT 2
+
+#define TWL6032_CFG_STATE_MASK 0x03
+#define TWL6032_CFG_STATE_OFF 0x00
+#define TWL6032_CFG_STATE_ON 0x01
+#define TWL6032_CFG_STATE_OFF2 0x02
+#define TWL6032_CFG_STATE_SLEEP 0x03
+
+static const char *rdev_get_name(struct regulator_dev *rdev)
+{
+	if (rdev->constraints && rdev->constraints->name)
+		return rdev->constraints->name;
+	else if (rdev->desc->name)
+		return rdev->desc->name;
+	else
+		return "";
+}
+
+struct twl6032_regulator_info {
+	u8 base;
+	unsigned int min_mV;
+	struct regulator_desc desc;
+};
+
+struct twl6032_regulator {
+	struct twl6032_regulator_info *info;
+};
+
+static int twl6032_set_trans_state(struct regulator_dev *rdev, u8 shift, u8 val)
+{
+	struct twl6032_regulator *twl6032_reg = rdev_get_drvdata(rdev);
+	struct twl6032_regulator_info *info = twl6032_reg->info;
+	unsigned int state;
+	u8 mask;
+	int ret;
+
+	/* Read CFG_TRANS register of TWL6030 */
+	ret = regmap_read(rdev->regmap, info->base + TWL6032_VREG_TRANS,
+			  &state);
+	if (ret < 0) {
+		dev_err(&rdev->dev, "%s %s: regmap_read: %d\n",
+			rdev_get_name(rdev), __func__, ret);
+		return ret;
+	}
+
+	mask = TWL6032_CFG_TRANS_STATE_MASK << shift;
+	val = (val << shift) & mask;
+
+	/* If value is already set, no need to write to reg */
+	if (val == (state & mask))
+		return 0;
+
+	state &= ~mask;
+	state |= val;
+
+	return regmap_write(rdev->regmap, info->base + TWL6032_VREG_TRANS,
+			    state);
+}
+
+static int
+twl6032_ldo_list_voltage(struct regulator_dev *rdev, unsigned int sel)
+{
+	int ret;
+
+	switch (sel) {
+	case 0:
+		ret = 0;
+		break;
+	case 1 ... 24:
+		/* Linear mapping from 00000001 to 00011000:
+		 * Absolute voltage value = 1.0 V + 0.1 V × (sel – 00000001)
+		 */
+		ret = (TWL6032_LDO_MIN_MV + 100 * (sel - 1)) * 1000;
+		break;
+	case 25 ... 30:
+		ret = -EINVAL;
+		break;
+	case 31:
+		ret = 2750000;
+		break;
+	default:
+		ret = -EINVAL;
+	}
+
+	dev_dbg(&rdev->dev, "%s %s: sel: %d, mV: %d\n", rdev_get_name(rdev),
+		__func__, sel, ret);
+
+	return ret;
+}
+
+static int
+twl6032_ldo_set_voltage_sel(struct regulator_dev *rdev, unsigned int sel)
+{
+	struct twl6032_regulator *twl6032_reg = rdev_get_drvdata(rdev);
+	struct twl6032_regulator_info *info = twl6032_reg->info;
+	int ret;
+
+	dev_dbg(&rdev->dev, "%s %s: sel: 0x%02X\n", rdev_get_name(rdev),
+		__func__, sel);
+
+	ret = regmap_write(rdev->regmap, info->base + TWL6032_VREG_VOLTAGE,
+			   sel);
+	if (ret < 0) {
+		dev_err(&rdev->dev, "%s %s: regmap_write: %d\n",
+			rdev_get_name(rdev), __func__, ret);
+		return ret;
+	}
+
+	return 0;
+}
+
+static int twl6032_ldo_get_voltage_sel(struct regulator_dev *rdev)
+{
+	struct twl6032_regulator *twl6032_reg = rdev_get_drvdata(rdev);
+	struct twl6032_regulator_info *info = twl6032_reg->info;
+	unsigned int val;
+	int ret;
+
+	ret = regmap_read(rdev->regmap, info->base + TWL6032_VREG_VOLTAGE,
+			  &val);
+	if (ret < 0) {
+		dev_err(&rdev->dev, "%s %s: regmap_read: %d\n",
+			rdev_get_name(rdev), __func__, ret);
+		return ret;
+	}
+
+	dev_dbg(&rdev->dev, "%s %s: vsel: 0x%02X\n", rdev_get_name(rdev),
+		__func__, val);
+
+	return val;
+}
+
+static int twl6032_ldo_enable(struct regulator_dev *rdev)
+{
+	struct twl6032_regulator *twl6032_reg = rdev_get_drvdata(rdev);
+	struct twl6032_regulator_info *info = twl6032_reg->info;
+	int ret;
+
+	dev_dbg(&rdev->dev, "%s %s\n", rdev_get_name(rdev), __func__);
+
+	ret = regmap_write(rdev->regmap, info->base + TWL6032_VREG_STATE,
+			   TWL6032_CFG_STATE_ON);
+	if (ret < 0) {
+		dev_err(&rdev->dev, "%s %s: regmap_write: %d\n",
+			rdev_get_name(rdev), __func__, ret);
+		return ret;
+	}
+
+	ret = twl6032_set_trans_state(rdev, TWL6032_CFG_TRANS_SLEEP_SHIFT,
+				      TWL6032_CFG_TRANS_STATE_AUTO);
+	if (ret < 0) {
+		dev_err(&rdev->dev, "%s %s: twl6032_set_trans_state: %d\n",
+			rdev_get_name(rdev), __func__, ret);
+		return ret;
+	}
+
+	return 0;
+}
+
+static int twl6032_ldo_disable(struct regulator_dev *rdev)
+{
+	struct twl6032_regulator *twl6032_reg = rdev_get_drvdata(rdev);
+	struct twl6032_regulator_info *info = twl6032_reg->info;
+	int ret;
+
+	dev_dbg(&rdev->dev, "%s %s\n", rdev_get_name(rdev), __func__);
+
+	ret = regmap_write(rdev->regmap, info->base + TWL6032_VREG_STATE,
+			   TWL6032_CFG_STATE_OFF);
+	if (ret < 0) {
+		dev_err(&rdev->dev, "%s %s: regmap_write: %d\n",
+			rdev_get_name(rdev), __func__, ret);
+		return ret;
+	}
+
+	ret = twl6032_set_trans_state(rdev, TWL6032_CFG_TRANS_SLEEP_SHIFT,
+				      TWL6032_CFG_TRANS_STATE_OFF);
+	if (ret < 0) {
+		dev_err(&rdev->dev, "%s %s: twl6032_set_trans_state: %d\n",
+			rdev_get_name(rdev), __func__, ret);
+		return ret;
+	}
+
+	return 0;
+}
+
+static int twl6032_ldo_is_enabled(struct regulator_dev *rdev)
+{
+	struct twl6032_regulator *twl6032_reg = rdev_get_drvdata(rdev);
+	struct twl6032_regulator_info *info = twl6032_reg->info;
+	int ret;
+	unsigned int val;
+
+	ret = regmap_read(rdev->regmap, info->base + TWL6032_VREG_STATE, &val);
+	if (ret < 0) {
+		dev_err(&rdev->dev, "%s regmap_read: %d\n", __func__, ret);
+		return ret;
+	}
+
+	dev_dbg(&rdev->dev, "%s %s: val: 0x%02X, val-masked: 0x%02X, ret: %d\n",
+		rdev_get_name(rdev), __func__,
+		val, val & TWL6032_CFG_STATE_MASK,
+		(val & TWL6032_CFG_STATE_MASK) == TWL6032_CFG_STATE_ON);
+
+	val &= TWL6032_CFG_STATE_MASK;
+
+	return val == TWL6032_CFG_STATE_ON;
+}
+
+static int twl6032_ldo_set_mode(struct regulator_dev *rdev, unsigned int mode)
+{
+	struct twl6032_regulator *twl6032_reg = rdev_get_drvdata(rdev);
+	struct twl6032_regulator_info *info = twl6032_reg->info;
+	unsigned int val = 0;
+	int ret;
+
+	dev_dbg(&rdev->dev, "%s %s: mode: 0x%02X\n", rdev_get_name(rdev),
+		__func__, mode);
+
+	switch (mode) {
+	case REGULATOR_MODE_NORMAL:
+		val |= TWL6032_CFG_STATE_ON;
+		break;
+	case REGULATOR_MODE_STANDBY:
+		val |= TWL6032_CFG_STATE_SLEEP;
+		break;
+
+	default:
+		return -EINVAL;
+	}
+
+	ret = regmap_write(rdev->regmap, info->base + TWL6032_VREG_STATE, val);
+	if (ret < 0) {
+		dev_err(&rdev->dev, "%s %s: regmap_write: %d\n",
+			rdev_get_name(rdev), __func__, ret);
+		return ret;
+	}
+
+	return 0;
+}
+
+static int twl6032_ldo_get_status(struct regulator_dev *rdev)
+{
+	struct twl6032_regulator *twl6032_reg = rdev_get_drvdata(rdev);
+	struct twl6032_regulator_info *info = twl6032_reg->info;
+	int ret;
+	unsigned int val;
+
+	ret = regmap_read(rdev->regmap, info->base + TWL6032_VREG_STATE, &val);
+	if (ret < 0) {
+		dev_err(&rdev->dev, "%s %s: regmap_read: %d\n",
+			rdev_get_name(rdev), __func__, ret);
+		return ret;
+	}
+
+	dev_dbg(&rdev->dev, "%s %s: val: 0x%02X, val-with-mask: 0x%02X\n",
+		rdev_get_name(rdev), __func__,
+		val, val & TWL6032_CFG_STATE_MASK);
+
+	val &= TWL6032_CFG_STATE_MASK;
+
+	switch (val) {
+	case TWL6032_CFG_STATE_ON:
+		return REGULATOR_STATUS_NORMAL;
+
+	case TWL6032_CFG_STATE_SLEEP:
+		return REGULATOR_STATUS_STANDBY;
+
+	case TWL6032_CFG_STATE_OFF:
+	case TWL6032_CFG_STATE_OFF2:
+	default:
+		break;
+	}
+
+	return REGULATOR_STATUS_OFF;
+}
+
+static int twl6032_ldo_suspend_enable(struct regulator_dev *rdev)
+{
+	return twl6032_set_trans_state(rdev, TWL6032_CFG_TRANS_SLEEP_SHIFT,
+				       TWL6032_CFG_TRANS_STATE_AUTO);
+}
+
+static int twl6032_ldo_suspend_disable(struct regulator_dev *rdev)
+{
+	return twl6032_set_trans_state(rdev, TWL6032_CFG_TRANS_SLEEP_SHIFT,
+				       TWL6032_CFG_TRANS_STATE_OFF);
+}
+
+static int
+twl6032_fixed_list_voltage(struct regulator_dev *rdev, unsigned int sel)
+{
+	struct twl6032_regulator *twl6032_reg = rdev_get_drvdata(rdev);
+	struct twl6032_regulator_info *info = twl6032_reg->info;
+
+	return info->min_mV * 1000; /* mV to V */
+}
+
+static int twl6032_fixed_get_voltage(struct regulator_dev *rdev)
+{
+	struct twl6032_regulator *twl6032_reg = rdev_get_drvdata(rdev);
+	struct twl6032_regulator_info *info = twl6032_reg->info;
+
+	return info->min_mV * 1000; /* mV to V */
+}
+
+static const struct regulator_ops twl6032_ldo_ops = {
+	.list_voltage = twl6032_ldo_list_voltage,
+	.set_voltage_sel = twl6032_ldo_set_voltage_sel,
+	.get_voltage_sel = twl6032_ldo_get_voltage_sel,
+	.enable = twl6032_ldo_enable,
+	.disable = twl6032_ldo_disable,
+	.is_enabled = twl6032_ldo_is_enabled,
+	.set_mode = twl6032_ldo_set_mode,
+	.get_status = twl6032_ldo_get_status,
+	.set_suspend_enable = twl6032_ldo_suspend_enable,
+	.set_suspend_disable =  twl6032_ldo_suspend_disable,
+};
+
+static const struct regulator_ops twl6032_fixed_ops = {
+	.list_voltage = twl6032_fixed_list_voltage,
+	.get_voltage = twl6032_fixed_get_voltage,
+	.enable = twl6032_ldo_enable,
+	.disable = twl6032_ldo_disable,
+	.is_enabled = twl6032_ldo_is_enabled,
+	.set_mode = twl6032_ldo_set_mode,
+	.get_status = twl6032_ldo_get_status,
+	.set_suspend_enable = twl6032_ldo_suspend_enable,
+	.set_suspend_disable =  twl6032_ldo_suspend_disable,
+};
+
+#define TWL6032_LDO_REG_VOLTAGES \
+	((TWL6032_LDO_MAX_MV - TWL6032_LDO_MIN_MV) / 100 + 1)
+#define TWL6032_LDO_REG(_id, _reg) \
+{ \
+	.base = _reg, \
+	.desc = { \
+		.name = "twl6032-reg-" # _id, \
+		.n_voltages = TWL6032_LDO_REG_VOLTAGES, \
+		.ops = &twl6032_ldo_ops, \
+		.type = REGULATOR_VOLTAGE, \
+		.owner = THIS_MODULE, \
+	}, \
+}
+
+#define TWL6032_FIXED_REG(_id, _reg, _min_mV) \
+{ \
+	.base = _reg, \
+	.min_mV = _min_mV, \
+	.desc = { \
+		.name = "twl6032-reg-" # _id, \
+		.n_voltages = 1, \
+		.ops = &twl6032_fixed_ops, \
+		.type = REGULATOR_VOLTAGE, \
+		.owner = THIS_MODULE, \
+	}, \
+}
+
+#define TWL6032_RESOURCE_REG(_id, _reg) \
+{ \
+	.base = _reg, \
+	.desc = { \
+		.name = "twl6032-reg-" # _id, \
+		.ops = &twl6032_ldo_ops, \
+		.type = REGULATOR_VOLTAGE, \
+		.owner = THIS_MODULE, \
+	}, \
+}
+
+static struct twl6032_regulator_info twl6032_ldo_reg_info[] = {
+	TWL6032_LDO_REG(LDO1, 0x9C),
+	TWL6032_LDO_REG(LDO2, 0x84),
+	TWL6032_LDO_REG(LDO3, 0x8C),
+	TWL6032_LDO_REG(LDO4, 0x88),
+	TWL6032_LDO_REG(LDO5, 0x98),
+	TWL6032_LDO_REG(LDO6, 0x90),
+	TWL6032_LDO_REG(LDO7, 0xA4),
+	TWL6032_LDO_REG(LDOLN, 0x94),
+	TWL6032_LDO_REG(LDOUSB, 0xA0),
+};
+
+static struct twl6032_regulator_info twl6032_fixed_reg_info[] = {
+	TWL6032_FIXED_REG(VANA, 0x80, 2100),
+};
+
+static struct of_regulator_match
+twl6032_ldo_reg_matches[] = {
+	{ .name = "LDO1", },
+	{ .name = "LDO2", },
+	{ .name = "LDO3", },
+	{ .name = "LDO4", },
+	{ .name = "LDO5", },
+	{ .name = "LDO6", },
+	{ .name = "LDO7", },
+	{ .name = "LDOLN" },
+	{ .name = "LDOUSB" }
+};
+
+static struct of_regulator_match
+twl6032_fixed_reg_matches[] = {
+	{ .name = "VANA", },
+};
+
+#define TWL6032_LDO_REG_NUM ARRAY_SIZE(twl6032_ldo_reg_matches)
+#define TWL6032_FIXED_REG_NUM ARRAY_SIZE(twl6032_fixed_reg_matches)
+
+struct twl6032_regulator_priv {
+	struct twl6032_regulator ldo_regulators[TWL6032_LDO_REG_NUM];
+	struct twl6032_regulator fixed_regulators[TWL6032_FIXED_REG_NUM];
+};
+
+static int twl6032_regulator_probe(struct platform_device *pdev)
+{
+	struct device *dev = &pdev->dev;
+	struct device_node *regulators;
+	struct of_regulator_match *match;
+	struct twlcore *twl = dev_get_drvdata(pdev->dev.parent);
+	struct twl6032_regulator_priv *priv;
+	struct regulator_config config = {
+		.dev = &pdev->dev,
+	};
+	struct regulator_dev *rdev;
+	int ret, i;
+
+	if (!dev->of_node) {
+		dev_err(&pdev->dev, "no DT info\n");
+		return -EINVAL;
+	}
+
+	regulators = of_get_child_by_name(dev->of_node, "regulators");
+	if (!regulators) {
+		dev_err(dev, "regulator node not found\n");
+		return -EINVAL;
+	}
+
+	priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
+	if (!priv)
+		return -ENOMEM;
+
+	platform_set_drvdata(pdev, priv);
+
+	/* LDO regulators parsing */
+	ret = of_regulator_match(dev, regulators, twl6032_ldo_reg_matches,
+				 TWL6032_LDO_REG_NUM);
+	of_node_put(regulators);
+	if (ret < 0) {
+		dev_err(dev, "error parsing LDO reg init data: %d\n", ret);
+		return ret;
+	}
+
+	for (i = 0; i < TWL6032_LDO_REG_NUM; i++) {
+		struct twl6032_regulator *twl6032_reg;
+
+		match = &twl6032_ldo_reg_matches[i];
+		if (!match->of_node)
+			continue;
+
+		twl6032_reg = &priv->ldo_regulators[i];
+		twl6032_reg->info = &twl6032_ldo_reg_info[i];
+
+		config.init_data = match->init_data;
+		config.driver_data = &priv->ldo_regulators[i];
+		config.regmap = twl->twl_modules[0].regmap;
+		config.of_node = match->of_node;
+
+		rdev = devm_regulator_register(dev, &twl6032_reg->info->desc,
+					       &config);
+		if (IS_ERR(rdev)) {
+			ret = PTR_ERR(rdev);
+			dev_err(dev, "failed to register regulator %s: %d\n",
+				twl6032_reg->info->desc.name, ret);
+			return ret;
+		}
+	}
+
+	/* Fixed regulators parsing */
+	ret = of_regulator_match(dev, regulators, twl6032_fixed_reg_matches,
+				 TWL6032_FIXED_REG_NUM);
+	of_node_put(regulators);
+	if (ret < 0) {
+		dev_err(dev, "error parsing fixed reg init data: %d\n", ret);
+		return ret;
+	}
+
+	for (i = 0; i < TWL6032_FIXED_REG_NUM; i++) {
+		struct twl6032_regulator *twl6032_reg;
+
+		match = &twl6032_fixed_reg_matches[i];
+		if (!match->of_node)
+			continue;
+
+		twl6032_reg = &priv->fixed_regulators[i];
+		twl6032_reg->info = &twl6032_fixed_reg_info[i];
+
+		config.init_data = match->init_data;
+		config.driver_data = &priv->fixed_regulators[i];
+		config.regmap = twl->twl_modules[0].regmap;
+		config.of_node = match->of_node;
+
+		rdev = devm_regulator_register(dev, &twl6032_reg->info->desc,
+					       &config);
+		if (IS_ERR(rdev)) {
+			ret = PTR_ERR(rdev);
+			dev_err(dev, "failed to register regulator %s: %d\n",
+				twl6032_reg->info->desc.name, ret);
+			return ret;
+		}
+	}
+
+	return 0;
+}
+
+static int twl6032_regulator_remove(struct platform_device *pdev)
+{
+	return 0;
+}
+
+static const struct of_device_id twl6032_dt_match[] = {
+	{ .compatible = "ti,twl6032-regulator" },
+	{ /* last entry */ }
+};
+
+MODULE_DEVICE_TABLE(platform, twl6032_regulator_driver_ids);
+
+static struct platform_driver twl6032_regulator_driver = {
+	.driver = {
+		.name = "twl6032-regulator",
+		.of_match_table = twl6032_dt_match,
+	},
+	.probe = twl6032_regulator_probe,
+	.remove = twl6032_regulator_remove,
+};
+
+static int __init twl6032_regulator_init(void)
+{
+	return platform_driver_register(&twl6032_regulator_driver);
+}
+subsys_initcall(twl6032_regulator_init);
+
+static void __exit twl6032_regulator_exit(void)
+{
+	platform_driver_unregister(&twl6032_regulator_driver);
+}
+module_exit(twl6032_regulator_exit);
+
+MODULE_AUTHOR("Nicolae Rosia <nicolae.rosia-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>");
+MODULE_DESCRIPTION("TI TWL6032 Regulator Driver");
+MODULE_LICENSE("GPL v2");
-- 
2.9.3

--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply related	[flat|nested] 38+ messages in thread

* [PATCH 4/5] regulator: Add support for TI TWL6032
@ 2016-11-26 18:13   ` Nicolae Rosia
  0 siblings, 0 replies; 38+ messages in thread
From: Nicolae Rosia @ 2016-11-26 18:13 UTC (permalink / raw)
  To: linux-arm-kernel

The TWL6032 PMIC is similar to TWL6030, has different
output names, and regulator control logic.
It is used on Barnes & Noble Nook HD and HD+.

Signed-off-by: Nicolae Rosia <Nicolae_Rosia@mentor.com>
---
 .../bindings/regulator/twl6032-regulator.txt       | 109 ++++
 drivers/regulator/Kconfig                          |   7 +
 drivers/regulator/Makefile                         |   1 +
 drivers/regulator/twl6032-regulator.c              | 582 +++++++++++++++++++++
 4 files changed, 699 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/regulator/twl6032-regulator.txt
 create mode 100644 drivers/regulator/twl6032-regulator.c

diff --git a/Documentation/devicetree/bindings/regulator/twl6032-regulator.txt b/Documentation/devicetree/bindings/regulator/twl6032-regulator.txt
new file mode 100644
index 0000000..323f5a9
--- /dev/null
+++ b/Documentation/devicetree/bindings/regulator/twl6032-regulator.txt
@@ -0,0 +1,109 @@
+TWL6032 PMIC Voltage Regulator Bindings
+
+The parent node must be MFD TWL Core, ti,twl6032.
+
+Required properties:
+- compatible: "ti,twl6032"
+
+Optional properties:
+- regulators node containing regulator childs.
+
+The child regulators  must be named after their hardware
+counterparts: LDO[1-6], LDOLN, LDOUSB and VANA.
+
+Each regulator is defined using the standard binding
+for regulators as described in ./regulator.txt
+
+Example:
+twl {
+	compatible = "ti,twl6032";
+
+	[...]
+
+	pmic {
+		compatible = "ti,twl6032-regulator";
+
+		regulators {
+			ldo1: LDO1 {
+				regulator-min-microvolt = <1800000>;
+				regulator-max-microvolt = <2500000>;
+
+				regulator-state-mem {
+					regulator-off-in-suspend;
+				};
+			};
+
+			ldo2: LDO2 {
+				regulator-min-microvolt = <1000000>;
+				regulator-max-microvolt = <3000000>;
+
+				regulator-state-mem {
+					regulator-off-in-suspend;
+				};
+			};
+
+			ldo3: LDO3 {
+				regulator-min-microvolt = <1800000>;
+				regulator-max-microvolt = <1800000>;
+				regulator-boot-on;
+
+				regulator-state-mem {
+					regulator-off-in-suspend;
+				};
+			};
+
+			ldo4: LDO4 {
+				regulator-min-microvolt = <1800000>;
+				regulator-max-microvolt = <1800000>;
+
+				regulator-state-mem {
+					regulator-off-in-suspend;
+				};
+			};
+
+			ldo5: LDO5 {
+				regulator-min-microvolt = <1200000>;
+				regulator-max-microvolt = <3000000>;
+
+				regulator-state-mem {
+					regulator-off-in-suspend;
+				};
+			};
+
+			ldo6: LDO6 {
+				regulator-min-microvolt = <1800000>;
+				regulator-max-microvolt = <1800000>;
+				regulator-always-on;
+
+				regulator-state-mem {
+					regulator-off-in-suspend;
+				};
+			};
+
+			ldo7: LDO7 {
+				regulator-min-microvolt = <1800000>;
+				regulator-max-microvolt = <1800000>;
+				regulator-boot-on;
+				regulator-always-on;
+			};
+
+			ldoln: LDOLN {
+				regulator-min-microvolt = <1000000>;
+				regulator-max-microvolt = <3000000>;
+			};
+
+			ldousb: LDOUSB {
+				regulator-min-microvolt = <1000000>;
+				regulator-max-microvolt = <3000000>;
+			};
+
+			vana: VANA {
+				regulator-min-microvolt = <2100000>;
+				regulator-max-microvolt = <2100000>;
+				regulator-always-on;
+			};
+		};
+	};
+
+	[...]
+};
diff --git a/drivers/regulator/Kconfig b/drivers/regulator/Kconfig
index 936f7cc..3168aba 100644
--- a/drivers/regulator/Kconfig
+++ b/drivers/regulator/Kconfig
@@ -843,6 +843,13 @@ config REGULATOR_TWL4030
 	  This driver supports the voltage regulators provided by
 	  this family of companion chips.
 
+config REGULATOR_TWL6032
+	tristate "TI TWL6032 PMIC"
+	depends on TWL4030_CORE
+	depends on OF || COMPILE_TEST
+	help
+	  This driver supports the Texas Instruments TWL6032 voltage regulator.
+
 config REGULATOR_VEXPRESS
 	tristate "Versatile Express regulators"
 	depends on VEXPRESS_CONFIG
diff --git a/drivers/regulator/Makefile b/drivers/regulator/Makefile
index 2142a5d..185a979 100644
--- a/drivers/regulator/Makefile
+++ b/drivers/regulator/Makefile
@@ -105,6 +105,7 @@ obj-$(CONFIG_REGULATOR_TPS65910) += tps65910-regulator.o
 obj-$(CONFIG_REGULATOR_TPS65912) += tps65912-regulator.o
 obj-$(CONFIG_REGULATOR_TPS80031) += tps80031-regulator.o
 obj-$(CONFIG_REGULATOR_TWL4030) += twl-regulator.o
+obj-$(CONFIG_REGULATOR_TWL6032) += twl6032-regulator.o
 obj-$(CONFIG_REGULATOR_VEXPRESS) += vexpress-regulator.o
 obj-$(CONFIG_REGULATOR_WM831X) += wm831x-dcdc.o
 obj-$(CONFIG_REGULATOR_WM831X) += wm831x-isink.o
diff --git a/drivers/regulator/twl6032-regulator.c b/drivers/regulator/twl6032-regulator.c
new file mode 100644
index 0000000..70a0fdf
--- /dev/null
+++ b/drivers/regulator/twl6032-regulator.c
@@ -0,0 +1,582 @@
+/*
+ * TWL6032 regulator driver
+ * Copyright (C) 2016 Nicolae Rosia <nicolae.rosia@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/err.h>
+#include <linux/platform_device.h>
+#include <linux/regulator/driver.h>
+#include <linux/regulator/machine.h>
+#include <linux/regulator/of_regulator.h>
+#include <linux/of.h>
+#include <linux/regmap.h>
+#include <linux/irq.h>
+#include <linux/mfd/twl-core.h>
+
+/* TWL6032 register offsets */
+#define TWL6032_VREG_TRANS 1
+#define TWL6032_VREG_STATE 2
+#define TWL6032_VREG_VOLTAGE 3
+
+#define TWL6032_LDO_MIN_MV 1000
+#define TWL6032_LDO_MAX_MV 3300
+
+/* TWL6030 LDO register values for CFG_TRANS */
+#define TWL6032_CFG_TRANS_STATE_MASK 0x03
+#define TWL6032_CFG_TRANS_STATE_OFF 0x00
+#define TWL6032_CFG_TRANS_STATE_AUTO 0x01
+#define TWL6032_CFG_TRANS_SLEEP_SHIFT 2
+
+#define TWL6032_CFG_STATE_MASK 0x03
+#define TWL6032_CFG_STATE_OFF 0x00
+#define TWL6032_CFG_STATE_ON 0x01
+#define TWL6032_CFG_STATE_OFF2 0x02
+#define TWL6032_CFG_STATE_SLEEP 0x03
+
+static const char *rdev_get_name(struct regulator_dev *rdev)
+{
+	if (rdev->constraints && rdev->constraints->name)
+		return rdev->constraints->name;
+	else if (rdev->desc->name)
+		return rdev->desc->name;
+	else
+		return "";
+}
+
+struct twl6032_regulator_info {
+	u8 base;
+	unsigned int min_mV;
+	struct regulator_desc desc;
+};
+
+struct twl6032_regulator {
+	struct twl6032_regulator_info *info;
+};
+
+static int twl6032_set_trans_state(struct regulator_dev *rdev, u8 shift, u8 val)
+{
+	struct twl6032_regulator *twl6032_reg = rdev_get_drvdata(rdev);
+	struct twl6032_regulator_info *info = twl6032_reg->info;
+	unsigned int state;
+	u8 mask;
+	int ret;
+
+	/* Read CFG_TRANS register of TWL6030 */
+	ret = regmap_read(rdev->regmap, info->base + TWL6032_VREG_TRANS,
+			  &state);
+	if (ret < 0) {
+		dev_err(&rdev->dev, "%s %s: regmap_read: %d\n",
+			rdev_get_name(rdev), __func__, ret);
+		return ret;
+	}
+
+	mask = TWL6032_CFG_TRANS_STATE_MASK << shift;
+	val = (val << shift) & mask;
+
+	/* If value is already set, no need to write to reg */
+	if (val == (state & mask))
+		return 0;
+
+	state &= ~mask;
+	state |= val;
+
+	return regmap_write(rdev->regmap, info->base + TWL6032_VREG_TRANS,
+			    state);
+}
+
+static int
+twl6032_ldo_list_voltage(struct regulator_dev *rdev, unsigned int sel)
+{
+	int ret;
+
+	switch (sel) {
+	case 0:
+		ret = 0;
+		break;
+	case 1 ... 24:
+		/* Linear mapping from 00000001 to 00011000:
+		 * Absolute voltage value = 1.0 V + 0.1 V ? (sel ? 00000001)
+		 */
+		ret = (TWL6032_LDO_MIN_MV + 100 * (sel - 1)) * 1000;
+		break;
+	case 25 ... 30:
+		ret = -EINVAL;
+		break;
+	case 31:
+		ret = 2750000;
+		break;
+	default:
+		ret = -EINVAL;
+	}
+
+	dev_dbg(&rdev->dev, "%s %s: sel: %d, mV: %d\n", rdev_get_name(rdev),
+		__func__, sel, ret);
+
+	return ret;
+}
+
+static int
+twl6032_ldo_set_voltage_sel(struct regulator_dev *rdev, unsigned int sel)
+{
+	struct twl6032_regulator *twl6032_reg = rdev_get_drvdata(rdev);
+	struct twl6032_regulator_info *info = twl6032_reg->info;
+	int ret;
+
+	dev_dbg(&rdev->dev, "%s %s: sel: 0x%02X\n", rdev_get_name(rdev),
+		__func__, sel);
+
+	ret = regmap_write(rdev->regmap, info->base + TWL6032_VREG_VOLTAGE,
+			   sel);
+	if (ret < 0) {
+		dev_err(&rdev->dev, "%s %s: regmap_write: %d\n",
+			rdev_get_name(rdev), __func__, ret);
+		return ret;
+	}
+
+	return 0;
+}
+
+static int twl6032_ldo_get_voltage_sel(struct regulator_dev *rdev)
+{
+	struct twl6032_regulator *twl6032_reg = rdev_get_drvdata(rdev);
+	struct twl6032_regulator_info *info = twl6032_reg->info;
+	unsigned int val;
+	int ret;
+
+	ret = regmap_read(rdev->regmap, info->base + TWL6032_VREG_VOLTAGE,
+			  &val);
+	if (ret < 0) {
+		dev_err(&rdev->dev, "%s %s: regmap_read: %d\n",
+			rdev_get_name(rdev), __func__, ret);
+		return ret;
+	}
+
+	dev_dbg(&rdev->dev, "%s %s: vsel: 0x%02X\n", rdev_get_name(rdev),
+		__func__, val);
+
+	return val;
+}
+
+static int twl6032_ldo_enable(struct regulator_dev *rdev)
+{
+	struct twl6032_regulator *twl6032_reg = rdev_get_drvdata(rdev);
+	struct twl6032_regulator_info *info = twl6032_reg->info;
+	int ret;
+
+	dev_dbg(&rdev->dev, "%s %s\n", rdev_get_name(rdev), __func__);
+
+	ret = regmap_write(rdev->regmap, info->base + TWL6032_VREG_STATE,
+			   TWL6032_CFG_STATE_ON);
+	if (ret < 0) {
+		dev_err(&rdev->dev, "%s %s: regmap_write: %d\n",
+			rdev_get_name(rdev), __func__, ret);
+		return ret;
+	}
+
+	ret = twl6032_set_trans_state(rdev, TWL6032_CFG_TRANS_SLEEP_SHIFT,
+				      TWL6032_CFG_TRANS_STATE_AUTO);
+	if (ret < 0) {
+		dev_err(&rdev->dev, "%s %s: twl6032_set_trans_state: %d\n",
+			rdev_get_name(rdev), __func__, ret);
+		return ret;
+	}
+
+	return 0;
+}
+
+static int twl6032_ldo_disable(struct regulator_dev *rdev)
+{
+	struct twl6032_regulator *twl6032_reg = rdev_get_drvdata(rdev);
+	struct twl6032_regulator_info *info = twl6032_reg->info;
+	int ret;
+
+	dev_dbg(&rdev->dev, "%s %s\n", rdev_get_name(rdev), __func__);
+
+	ret = regmap_write(rdev->regmap, info->base + TWL6032_VREG_STATE,
+			   TWL6032_CFG_STATE_OFF);
+	if (ret < 0) {
+		dev_err(&rdev->dev, "%s %s: regmap_write: %d\n",
+			rdev_get_name(rdev), __func__, ret);
+		return ret;
+	}
+
+	ret = twl6032_set_trans_state(rdev, TWL6032_CFG_TRANS_SLEEP_SHIFT,
+				      TWL6032_CFG_TRANS_STATE_OFF);
+	if (ret < 0) {
+		dev_err(&rdev->dev, "%s %s: twl6032_set_trans_state: %d\n",
+			rdev_get_name(rdev), __func__, ret);
+		return ret;
+	}
+
+	return 0;
+}
+
+static int twl6032_ldo_is_enabled(struct regulator_dev *rdev)
+{
+	struct twl6032_regulator *twl6032_reg = rdev_get_drvdata(rdev);
+	struct twl6032_regulator_info *info = twl6032_reg->info;
+	int ret;
+	unsigned int val;
+
+	ret = regmap_read(rdev->regmap, info->base + TWL6032_VREG_STATE, &val);
+	if (ret < 0) {
+		dev_err(&rdev->dev, "%s regmap_read: %d\n", __func__, ret);
+		return ret;
+	}
+
+	dev_dbg(&rdev->dev, "%s %s: val: 0x%02X, val-masked: 0x%02X, ret: %d\n",
+		rdev_get_name(rdev), __func__,
+		val, val & TWL6032_CFG_STATE_MASK,
+		(val & TWL6032_CFG_STATE_MASK) == TWL6032_CFG_STATE_ON);
+
+	val &= TWL6032_CFG_STATE_MASK;
+
+	return val == TWL6032_CFG_STATE_ON;
+}
+
+static int twl6032_ldo_set_mode(struct regulator_dev *rdev, unsigned int mode)
+{
+	struct twl6032_regulator *twl6032_reg = rdev_get_drvdata(rdev);
+	struct twl6032_regulator_info *info = twl6032_reg->info;
+	unsigned int val = 0;
+	int ret;
+
+	dev_dbg(&rdev->dev, "%s %s: mode: 0x%02X\n", rdev_get_name(rdev),
+		__func__, mode);
+
+	switch (mode) {
+	case REGULATOR_MODE_NORMAL:
+		val |= TWL6032_CFG_STATE_ON;
+		break;
+	case REGULATOR_MODE_STANDBY:
+		val |= TWL6032_CFG_STATE_SLEEP;
+		break;
+
+	default:
+		return -EINVAL;
+	}
+
+	ret = regmap_write(rdev->regmap, info->base + TWL6032_VREG_STATE, val);
+	if (ret < 0) {
+		dev_err(&rdev->dev, "%s %s: regmap_write: %d\n",
+			rdev_get_name(rdev), __func__, ret);
+		return ret;
+	}
+
+	return 0;
+}
+
+static int twl6032_ldo_get_status(struct regulator_dev *rdev)
+{
+	struct twl6032_regulator *twl6032_reg = rdev_get_drvdata(rdev);
+	struct twl6032_regulator_info *info = twl6032_reg->info;
+	int ret;
+	unsigned int val;
+
+	ret = regmap_read(rdev->regmap, info->base + TWL6032_VREG_STATE, &val);
+	if (ret < 0) {
+		dev_err(&rdev->dev, "%s %s: regmap_read: %d\n",
+			rdev_get_name(rdev), __func__, ret);
+		return ret;
+	}
+
+	dev_dbg(&rdev->dev, "%s %s: val: 0x%02X, val-with-mask: 0x%02X\n",
+		rdev_get_name(rdev), __func__,
+		val, val & TWL6032_CFG_STATE_MASK);
+
+	val &= TWL6032_CFG_STATE_MASK;
+
+	switch (val) {
+	case TWL6032_CFG_STATE_ON:
+		return REGULATOR_STATUS_NORMAL;
+
+	case TWL6032_CFG_STATE_SLEEP:
+		return REGULATOR_STATUS_STANDBY;
+
+	case TWL6032_CFG_STATE_OFF:
+	case TWL6032_CFG_STATE_OFF2:
+	default:
+		break;
+	}
+
+	return REGULATOR_STATUS_OFF;
+}
+
+static int twl6032_ldo_suspend_enable(struct regulator_dev *rdev)
+{
+	return twl6032_set_trans_state(rdev, TWL6032_CFG_TRANS_SLEEP_SHIFT,
+				       TWL6032_CFG_TRANS_STATE_AUTO);
+}
+
+static int twl6032_ldo_suspend_disable(struct regulator_dev *rdev)
+{
+	return twl6032_set_trans_state(rdev, TWL6032_CFG_TRANS_SLEEP_SHIFT,
+				       TWL6032_CFG_TRANS_STATE_OFF);
+}
+
+static int
+twl6032_fixed_list_voltage(struct regulator_dev *rdev, unsigned int sel)
+{
+	struct twl6032_regulator *twl6032_reg = rdev_get_drvdata(rdev);
+	struct twl6032_regulator_info *info = twl6032_reg->info;
+
+	return info->min_mV * 1000; /* mV to V */
+}
+
+static int twl6032_fixed_get_voltage(struct regulator_dev *rdev)
+{
+	struct twl6032_regulator *twl6032_reg = rdev_get_drvdata(rdev);
+	struct twl6032_regulator_info *info = twl6032_reg->info;
+
+	return info->min_mV * 1000; /* mV to V */
+}
+
+static const struct regulator_ops twl6032_ldo_ops = {
+	.list_voltage = twl6032_ldo_list_voltage,
+	.set_voltage_sel = twl6032_ldo_set_voltage_sel,
+	.get_voltage_sel = twl6032_ldo_get_voltage_sel,
+	.enable = twl6032_ldo_enable,
+	.disable = twl6032_ldo_disable,
+	.is_enabled = twl6032_ldo_is_enabled,
+	.set_mode = twl6032_ldo_set_mode,
+	.get_status = twl6032_ldo_get_status,
+	.set_suspend_enable = twl6032_ldo_suspend_enable,
+	.set_suspend_disable =  twl6032_ldo_suspend_disable,
+};
+
+static const struct regulator_ops twl6032_fixed_ops = {
+	.list_voltage = twl6032_fixed_list_voltage,
+	.get_voltage = twl6032_fixed_get_voltage,
+	.enable = twl6032_ldo_enable,
+	.disable = twl6032_ldo_disable,
+	.is_enabled = twl6032_ldo_is_enabled,
+	.set_mode = twl6032_ldo_set_mode,
+	.get_status = twl6032_ldo_get_status,
+	.set_suspend_enable = twl6032_ldo_suspend_enable,
+	.set_suspend_disable =  twl6032_ldo_suspend_disable,
+};
+
+#define TWL6032_LDO_REG_VOLTAGES \
+	((TWL6032_LDO_MAX_MV - TWL6032_LDO_MIN_MV) / 100 + 1)
+#define TWL6032_LDO_REG(_id, _reg) \
+{ \
+	.base = _reg, \
+	.desc = { \
+		.name = "twl6032-reg-" # _id, \
+		.n_voltages = TWL6032_LDO_REG_VOLTAGES, \
+		.ops = &twl6032_ldo_ops, \
+		.type = REGULATOR_VOLTAGE, \
+		.owner = THIS_MODULE, \
+	}, \
+}
+
+#define TWL6032_FIXED_REG(_id, _reg, _min_mV) \
+{ \
+	.base = _reg, \
+	.min_mV = _min_mV, \
+	.desc = { \
+		.name = "twl6032-reg-" # _id, \
+		.n_voltages = 1, \
+		.ops = &twl6032_fixed_ops, \
+		.type = REGULATOR_VOLTAGE, \
+		.owner = THIS_MODULE, \
+	}, \
+}
+
+#define TWL6032_RESOURCE_REG(_id, _reg) \
+{ \
+	.base = _reg, \
+	.desc = { \
+		.name = "twl6032-reg-" # _id, \
+		.ops = &twl6032_ldo_ops, \
+		.type = REGULATOR_VOLTAGE, \
+		.owner = THIS_MODULE, \
+	}, \
+}
+
+static struct twl6032_regulator_info twl6032_ldo_reg_info[] = {
+	TWL6032_LDO_REG(LDO1, 0x9C),
+	TWL6032_LDO_REG(LDO2, 0x84),
+	TWL6032_LDO_REG(LDO3, 0x8C),
+	TWL6032_LDO_REG(LDO4, 0x88),
+	TWL6032_LDO_REG(LDO5, 0x98),
+	TWL6032_LDO_REG(LDO6, 0x90),
+	TWL6032_LDO_REG(LDO7, 0xA4),
+	TWL6032_LDO_REG(LDOLN, 0x94),
+	TWL6032_LDO_REG(LDOUSB, 0xA0),
+};
+
+static struct twl6032_regulator_info twl6032_fixed_reg_info[] = {
+	TWL6032_FIXED_REG(VANA, 0x80, 2100),
+};
+
+static struct of_regulator_match
+twl6032_ldo_reg_matches[] = {
+	{ .name = "LDO1", },
+	{ .name = "LDO2", },
+	{ .name = "LDO3", },
+	{ .name = "LDO4", },
+	{ .name = "LDO5", },
+	{ .name = "LDO6", },
+	{ .name = "LDO7", },
+	{ .name = "LDOLN" },
+	{ .name = "LDOUSB" }
+};
+
+static struct of_regulator_match
+twl6032_fixed_reg_matches[] = {
+	{ .name = "VANA", },
+};
+
+#define TWL6032_LDO_REG_NUM ARRAY_SIZE(twl6032_ldo_reg_matches)
+#define TWL6032_FIXED_REG_NUM ARRAY_SIZE(twl6032_fixed_reg_matches)
+
+struct twl6032_regulator_priv {
+	struct twl6032_regulator ldo_regulators[TWL6032_LDO_REG_NUM];
+	struct twl6032_regulator fixed_regulators[TWL6032_FIXED_REG_NUM];
+};
+
+static int twl6032_regulator_probe(struct platform_device *pdev)
+{
+	struct device *dev = &pdev->dev;
+	struct device_node *regulators;
+	struct of_regulator_match *match;
+	struct twlcore *twl = dev_get_drvdata(pdev->dev.parent);
+	struct twl6032_regulator_priv *priv;
+	struct regulator_config config = {
+		.dev = &pdev->dev,
+	};
+	struct regulator_dev *rdev;
+	int ret, i;
+
+	if (!dev->of_node) {
+		dev_err(&pdev->dev, "no DT info\n");
+		return -EINVAL;
+	}
+
+	regulators = of_get_child_by_name(dev->of_node, "regulators");
+	if (!regulators) {
+		dev_err(dev, "regulator node not found\n");
+		return -EINVAL;
+	}
+
+	priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
+	if (!priv)
+		return -ENOMEM;
+
+	platform_set_drvdata(pdev, priv);
+
+	/* LDO regulators parsing */
+	ret = of_regulator_match(dev, regulators, twl6032_ldo_reg_matches,
+				 TWL6032_LDO_REG_NUM);
+	of_node_put(regulators);
+	if (ret < 0) {
+		dev_err(dev, "error parsing LDO reg init data: %d\n", ret);
+		return ret;
+	}
+
+	for (i = 0; i < TWL6032_LDO_REG_NUM; i++) {
+		struct twl6032_regulator *twl6032_reg;
+
+		match = &twl6032_ldo_reg_matches[i];
+		if (!match->of_node)
+			continue;
+
+		twl6032_reg = &priv->ldo_regulators[i];
+		twl6032_reg->info = &twl6032_ldo_reg_info[i];
+
+		config.init_data = match->init_data;
+		config.driver_data = &priv->ldo_regulators[i];
+		config.regmap = twl->twl_modules[0].regmap;
+		config.of_node = match->of_node;
+
+		rdev = devm_regulator_register(dev, &twl6032_reg->info->desc,
+					       &config);
+		if (IS_ERR(rdev)) {
+			ret = PTR_ERR(rdev);
+			dev_err(dev, "failed to register regulator %s: %d\n",
+				twl6032_reg->info->desc.name, ret);
+			return ret;
+		}
+	}
+
+	/* Fixed regulators parsing */
+	ret = of_regulator_match(dev, regulators, twl6032_fixed_reg_matches,
+				 TWL6032_FIXED_REG_NUM);
+	of_node_put(regulators);
+	if (ret < 0) {
+		dev_err(dev, "error parsing fixed reg init data: %d\n", ret);
+		return ret;
+	}
+
+	for (i = 0; i < TWL6032_FIXED_REG_NUM; i++) {
+		struct twl6032_regulator *twl6032_reg;
+
+		match = &twl6032_fixed_reg_matches[i];
+		if (!match->of_node)
+			continue;
+
+		twl6032_reg = &priv->fixed_regulators[i];
+		twl6032_reg->info = &twl6032_fixed_reg_info[i];
+
+		config.init_data = match->init_data;
+		config.driver_data = &priv->fixed_regulators[i];
+		config.regmap = twl->twl_modules[0].regmap;
+		config.of_node = match->of_node;
+
+		rdev = devm_regulator_register(dev, &twl6032_reg->info->desc,
+					       &config);
+		if (IS_ERR(rdev)) {
+			ret = PTR_ERR(rdev);
+			dev_err(dev, "failed to register regulator %s: %d\n",
+				twl6032_reg->info->desc.name, ret);
+			return ret;
+		}
+	}
+
+	return 0;
+}
+
+static int twl6032_regulator_remove(struct platform_device *pdev)
+{
+	return 0;
+}
+
+static const struct of_device_id twl6032_dt_match[] = {
+	{ .compatible = "ti,twl6032-regulator" },
+	{ /* last entry */ }
+};
+
+MODULE_DEVICE_TABLE(platform, twl6032_regulator_driver_ids);
+
+static struct platform_driver twl6032_regulator_driver = {
+	.driver = {
+		.name = "twl6032-regulator",
+		.of_match_table = twl6032_dt_match,
+	},
+	.probe = twl6032_regulator_probe,
+	.remove = twl6032_regulator_remove,
+};
+
+static int __init twl6032_regulator_init(void)
+{
+	return platform_driver_register(&twl6032_regulator_driver);
+}
+subsys_initcall(twl6032_regulator_init);
+
+static void __exit twl6032_regulator_exit(void)
+{
+	platform_driver_unregister(&twl6032_regulator_driver);
+}
+module_exit(twl6032_regulator_exit);
+
+MODULE_AUTHOR("Nicolae Rosia <nicolae.rosia@gmail.com>");
+MODULE_DESCRIPTION("TI TWL6032 Regulator Driver");
+MODULE_LICENSE("GPL v2");
-- 
2.9.3

^ permalink raw reply related	[flat|nested] 38+ messages in thread

* [PATCH 5/5] mfd: twl: use mfd_add_devices for TWL6032 regulator
@ 2016-11-26 18:13   ` Nicolae Rosia
  0 siblings, 0 replies; 38+ messages in thread
From: Nicolae Rosia @ 2016-11-26 18:13 UTC (permalink / raw)
  To: Lee Jones, Mark Brown, Rob Herring, Mark Rutland, Tony Lindgren
  Cc: Liam Girdwood, Paul Gortmaker, Graeme Gregory, Baruch Siach,
	linux-omap, linux-arm-kernel, linux-kernel, devicetree,
	Nicolae Rosia

TWL6032 regulator driver uses the drvdata twl_priv pointer.
In order to avoid accessing an invalid drvdata
when the driver gets unbinded, make sure we remove the
child devices before deleting the drvdata.

Signed-off-by: Nicolae Rosia <Nicolae_Rosia@mentor.com>
---
 drivers/mfd/twl-core.c | 22 ++++++++++++++++++++++
 1 file changed, 22 insertions(+)

diff --git a/drivers/mfd/twl-core.c b/drivers/mfd/twl-core.c
index 409b836..1e94364 100644
--- a/drivers/mfd/twl-core.c
+++ b/drivers/mfd/twl-core.c
@@ -43,6 +43,7 @@
 #include <linux/of_platform.h>
 #include <linux/irq.h>
 #include <linux/irqdomain.h>
+#include <linux/mfd/core.h>
 
 #include <linux/regulator/machine.h>
 
@@ -155,8 +156,16 @@ int twl4030_init_irq(struct device *dev, int irq_num);
 int twl4030_exit_irq(void);
 int twl4030_init_chip_irq(const char *chip);
 
+
 static struct twlcore *twl_priv;
 
+static struct mfd_cell twl6032_devs[] = {
+	{
+		.name = "twl6032-regulator",
+		.of_compatible = "ti,twl6032-regulator",
+	},
+};
+
 static struct twl_mapping twl4030_map[] = {
 	/*
 	 * NOTE:  don't change this table without updating the
@@ -665,6 +674,8 @@ static int twl_remove(struct i2c_client *client)
 	unsigned i, num_slaves;
 	int status;
 
+	mfd_remove_devices(&client->dev);
+
 	if (twl_class_is_4030())
 		status = twl4030_exit_irq();
 	else
@@ -834,6 +845,17 @@ twl_probe(struct i2c_client *client, const struct i2c_device_id *id)
 				 TWL4030_DCDC_GLOBAL_CFG);
 	}
 
+	if (id->driver_data & TWL6032_SUBCLASS) {
+		status = mfd_add_devices(&client->dev, PLATFORM_DEVID_NONE,
+					 twl6032_devs, ARRAY_SIZE(twl6032_devs),
+					 NULL, 0, NULL);
+		if (status != 0) {
+			dev_err(&client->dev, "failed to add mfd devices: %d\n",
+				status);
+			goto fail;
+		}
+	}
+
 fail:
 	if (status < 0)
 		twl_remove(client);
-- 
2.9.3

^ permalink raw reply related	[flat|nested] 38+ messages in thread

* [PATCH 5/5] mfd: twl: use mfd_add_devices for TWL6032 regulator
@ 2016-11-26 18:13   ` Nicolae Rosia
  0 siblings, 0 replies; 38+ messages in thread
From: Nicolae Rosia @ 2016-11-26 18:13 UTC (permalink / raw)
  To: Lee Jones, Mark Brown, Rob Herring, Mark Rutland, Tony Lindgren
  Cc: Liam Girdwood, Paul Gortmaker, Graeme Gregory, Baruch Siach,
	linux-omap-u79uwXL29TY76Z2rM5mHXA,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	devicetree-u79uwXL29TY76Z2rM5mHXA, Nicolae Rosia

TWL6032 regulator driver uses the drvdata twl_priv pointer.
In order to avoid accessing an invalid drvdata
when the driver gets unbinded, make sure we remove the
child devices before deleting the drvdata.

Signed-off-by: Nicolae Rosia <Nicolae_Rosia-nmGgyN9QBj3QT0dZR+AlfA@public.gmane.org>
---
 drivers/mfd/twl-core.c | 22 ++++++++++++++++++++++
 1 file changed, 22 insertions(+)

diff --git a/drivers/mfd/twl-core.c b/drivers/mfd/twl-core.c
index 409b836..1e94364 100644
--- a/drivers/mfd/twl-core.c
+++ b/drivers/mfd/twl-core.c
@@ -43,6 +43,7 @@
 #include <linux/of_platform.h>
 #include <linux/irq.h>
 #include <linux/irqdomain.h>
+#include <linux/mfd/core.h>
 
 #include <linux/regulator/machine.h>
 
@@ -155,8 +156,16 @@ int twl4030_init_irq(struct device *dev, int irq_num);
 int twl4030_exit_irq(void);
 int twl4030_init_chip_irq(const char *chip);
 
+
 static struct twlcore *twl_priv;
 
+static struct mfd_cell twl6032_devs[] = {
+	{
+		.name = "twl6032-regulator",
+		.of_compatible = "ti,twl6032-regulator",
+	},
+};
+
 static struct twl_mapping twl4030_map[] = {
 	/*
 	 * NOTE:  don't change this table without updating the
@@ -665,6 +674,8 @@ static int twl_remove(struct i2c_client *client)
 	unsigned i, num_slaves;
 	int status;
 
+	mfd_remove_devices(&client->dev);
+
 	if (twl_class_is_4030())
 		status = twl4030_exit_irq();
 	else
@@ -834,6 +845,17 @@ twl_probe(struct i2c_client *client, const struct i2c_device_id *id)
 				 TWL4030_DCDC_GLOBAL_CFG);
 	}
 
+	if (id->driver_data & TWL6032_SUBCLASS) {
+		status = mfd_add_devices(&client->dev, PLATFORM_DEVID_NONE,
+					 twl6032_devs, ARRAY_SIZE(twl6032_devs),
+					 NULL, 0, NULL);
+		if (status != 0) {
+			dev_err(&client->dev, "failed to add mfd devices: %d\n",
+				status);
+			goto fail;
+		}
+	}
+
 fail:
 	if (status < 0)
 		twl_remove(client);
-- 
2.9.3

--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply related	[flat|nested] 38+ messages in thread

* [PATCH 5/5] mfd: twl: use mfd_add_devices for TWL6032 regulator
@ 2016-11-26 18:13   ` Nicolae Rosia
  0 siblings, 0 replies; 38+ messages in thread
From: Nicolae Rosia @ 2016-11-26 18:13 UTC (permalink / raw)
  To: linux-arm-kernel

TWL6032 regulator driver uses the drvdata twl_priv pointer.
In order to avoid accessing an invalid drvdata
when the driver gets unbinded, make sure we remove the
child devices before deleting the drvdata.

Signed-off-by: Nicolae Rosia <Nicolae_Rosia@mentor.com>
---
 drivers/mfd/twl-core.c | 22 ++++++++++++++++++++++
 1 file changed, 22 insertions(+)

diff --git a/drivers/mfd/twl-core.c b/drivers/mfd/twl-core.c
index 409b836..1e94364 100644
--- a/drivers/mfd/twl-core.c
+++ b/drivers/mfd/twl-core.c
@@ -43,6 +43,7 @@
 #include <linux/of_platform.h>
 #include <linux/irq.h>
 #include <linux/irqdomain.h>
+#include <linux/mfd/core.h>
 
 #include <linux/regulator/machine.h>
 
@@ -155,8 +156,16 @@ int twl4030_init_irq(struct device *dev, int irq_num);
 int twl4030_exit_irq(void);
 int twl4030_init_chip_irq(const char *chip);
 
+
 static struct twlcore *twl_priv;
 
+static struct mfd_cell twl6032_devs[] = {
+	{
+		.name = "twl6032-regulator",
+		.of_compatible = "ti,twl6032-regulator",
+	},
+};
+
 static struct twl_mapping twl4030_map[] = {
 	/*
 	 * NOTE:  don't change this table without updating the
@@ -665,6 +674,8 @@ static int twl_remove(struct i2c_client *client)
 	unsigned i, num_slaves;
 	int status;
 
+	mfd_remove_devices(&client->dev);
+
 	if (twl_class_is_4030())
 		status = twl4030_exit_irq();
 	else
@@ -834,6 +845,17 @@ twl_probe(struct i2c_client *client, const struct i2c_device_id *id)
 				 TWL4030_DCDC_GLOBAL_CFG);
 	}
 
+	if (id->driver_data & TWL6032_SUBCLASS) {
+		status = mfd_add_devices(&client->dev, PLATFORM_DEVID_NONE,
+					 twl6032_devs, ARRAY_SIZE(twl6032_devs),
+					 NULL, 0, NULL);
+		if (status != 0) {
+			dev_err(&client->dev, "failed to add mfd devices: %d\n",
+				status);
+			goto fail;
+		}
+	}
+
 fail:
 	if (status < 0)
 		twl_remove(client);
-- 
2.9.3

^ permalink raw reply related	[flat|nested] 38+ messages in thread

* Re: [PATCH 4/5] regulator: Add support for TI TWL6032
@ 2016-11-26 18:55     ` kbuild test robot
  0 siblings, 0 replies; 38+ messages in thread
From: kbuild test robot @ 2016-11-26 18:55 UTC (permalink / raw)
  To: Nicolae Rosia
  Cc: kbuild-all, Lee Jones, Mark Brown, Rob Herring, Mark Rutland,
	Tony Lindgren, Liam Girdwood, Paul Gortmaker, Graeme Gregory,
	Baruch Siach, linux-omap, linux-arm-kernel, linux-kernel,
	devicetree, Nicolae Rosia

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

Hi Nicolae,

[auto build test ERROR on omap/for-next]
[also build test ERROR on v4.9-rc6]
[cannot apply to next-20161125]
[if your patch is applied to the wrong git tree, please drop us a note to help improve the system]

url:    https://github.com/0day-ci/linux/commits/Nicolae-Rosia/mfd-twl-improvements-and-new-regulator-driver/20161127-022201
base:   https://git.kernel.org/pub/scm/linux/kernel/git/tmlind/linux-omap.git for-next
config: i386-allmodconfig (attached as .config)
compiler: gcc-6 (Debian 6.2.0-3) 6.2.0 20160901
reproduce:
        # save the attached .config to linux build tree
        make ARCH=i386 

All error/warnings (new ones prefixed by >>):

   In file included from drivers/regulator/twl6032-regulator.c:11:0:
>> drivers/regulator/twl6032-regulator.c:557:31: error: 'twl6032_regulator_driver_ids' undeclared here (not in a function)
    MODULE_DEVICE_TABLE(platform, twl6032_regulator_driver_ids);
                                  ^
   include/linux/module.h:213:21: note: in definition of macro 'MODULE_DEVICE_TABLE'
    extern const typeof(name) __mod_##type##__##name##_device_table  \
                        ^~~~
>> include/linux/module.h:213:27: error: '__mod_platform__twl6032_regulator_driver_ids_device_table' aliased to undefined symbol 'twl6032_regulator_driver_ids'
    extern const typeof(name) __mod_##type##__##name##_device_table  \
                              ^
>> drivers/regulator/twl6032-regulator.c:557:1: note: in expansion of macro 'MODULE_DEVICE_TABLE'
    MODULE_DEVICE_TABLE(platform, twl6032_regulator_driver_ids);
    ^~~~~~~~~~~~~~~~~~~

vim +/twl6032_regulator_driver_ids +557 drivers/regulator/twl6032-regulator.c

   551	
   552	static const struct of_device_id twl6032_dt_match[] = {
   553		{ .compatible = "ti,twl6032-regulator" },
   554		{ /* last entry */ }
   555	};
   556	
 > 557	MODULE_DEVICE_TABLE(platform, twl6032_regulator_driver_ids);
   558	
   559	static struct platform_driver twl6032_regulator_driver = {
   560		.driver = {

---
0-DAY kernel test infrastructure                Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all                   Intel Corporation

[-- Attachment #2: .config.gz --]
[-- Type: application/gzip, Size: 56830 bytes --]

^ permalink raw reply	[flat|nested] 38+ messages in thread

* Re: [PATCH 4/5] regulator: Add support for TI TWL6032
@ 2016-11-26 18:55     ` kbuild test robot
  0 siblings, 0 replies; 38+ messages in thread
From: kbuild test robot @ 2016-11-26 18:55 UTC (permalink / raw)
  Cc: kbuild-all-JC7UmRfGjtg, Lee Jones, Mark Brown, Rob Herring,
	Mark Rutland, Tony Lindgren, Liam Girdwood, Paul Gortmaker,
	Graeme Gregory, Baruch Siach, linux-omap-u79uwXL29TY76Z2rM5mHXA,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	devicetree-u79uwXL29TY76Z2rM5mHXA, Nicolae Rosia

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

Hi Nicolae,

[auto build test ERROR on omap/for-next]
[also build test ERROR on v4.9-rc6]
[cannot apply to next-20161125]
[if your patch is applied to the wrong git tree, please drop us a note to help improve the system]

url:    https://github.com/0day-ci/linux/commits/Nicolae-Rosia/mfd-twl-improvements-and-new-regulator-driver/20161127-022201
base:   https://git.kernel.org/pub/scm/linux/kernel/git/tmlind/linux-omap.git for-next
config: i386-allmodconfig (attached as .config)
compiler: gcc-6 (Debian 6.2.0-3) 6.2.0 20160901
reproduce:
        # save the attached .config to linux build tree
        make ARCH=i386 

All error/warnings (new ones prefixed by >>):

   In file included from drivers/regulator/twl6032-regulator.c:11:0:
>> drivers/regulator/twl6032-regulator.c:557:31: error: 'twl6032_regulator_driver_ids' undeclared here (not in a function)
    MODULE_DEVICE_TABLE(platform, twl6032_regulator_driver_ids);
                                  ^
   include/linux/module.h:213:21: note: in definition of macro 'MODULE_DEVICE_TABLE'
    extern const typeof(name) __mod_##type##__##name##_device_table  \
                        ^~~~
>> include/linux/module.h:213:27: error: '__mod_platform__twl6032_regulator_driver_ids_device_table' aliased to undefined symbol 'twl6032_regulator_driver_ids'
    extern const typeof(name) __mod_##type##__##name##_device_table  \
                              ^
>> drivers/regulator/twl6032-regulator.c:557:1: note: in expansion of macro 'MODULE_DEVICE_TABLE'
    MODULE_DEVICE_TABLE(platform, twl6032_regulator_driver_ids);
    ^~~~~~~~~~~~~~~~~~~

vim +/twl6032_regulator_driver_ids +557 drivers/regulator/twl6032-regulator.c

   551	
   552	static const struct of_device_id twl6032_dt_match[] = {
   553		{ .compatible = "ti,twl6032-regulator" },
   554		{ /* last entry */ }
   555	};
   556	
 > 557	MODULE_DEVICE_TABLE(platform, twl6032_regulator_driver_ids);
   558	
   559	static struct platform_driver twl6032_regulator_driver = {
   560		.driver = {

---
0-DAY kernel test infrastructure                Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all                   Intel Corporation

[-- Attachment #2: .config.gz --]
[-- Type: application/gzip, Size: 56830 bytes --]

^ permalink raw reply	[flat|nested] 38+ messages in thread

* [PATCH 4/5] regulator: Add support for TI TWL6032
@ 2016-11-26 18:55     ` kbuild test robot
  0 siblings, 0 replies; 38+ messages in thread
From: kbuild test robot @ 2016-11-26 18:55 UTC (permalink / raw)
  To: linux-arm-kernel

Hi Nicolae,

[auto build test ERROR on omap/for-next]
[also build test ERROR on v4.9-rc6]
[cannot apply to next-20161125]
[if your patch is applied to the wrong git tree, please drop us a note to help improve the system]

url:    https://github.com/0day-ci/linux/commits/Nicolae-Rosia/mfd-twl-improvements-and-new-regulator-driver/20161127-022201
base:   https://git.kernel.org/pub/scm/linux/kernel/git/tmlind/linux-omap.git for-next
config: i386-allmodconfig (attached as .config)
compiler: gcc-6 (Debian 6.2.0-3) 6.2.0 20160901
reproduce:
        # save the attached .config to linux build tree
        make ARCH=i386 

All error/warnings (new ones prefixed by >>):

   In file included from drivers/regulator/twl6032-regulator.c:11:0:
>> drivers/regulator/twl6032-regulator.c:557:31: error: 'twl6032_regulator_driver_ids' undeclared here (not in a function)
    MODULE_DEVICE_TABLE(platform, twl6032_regulator_driver_ids);
                                  ^
   include/linux/module.h:213:21: note: in definition of macro 'MODULE_DEVICE_TABLE'
    extern const typeof(name) __mod_##type##__##name##_device_table  \
                        ^~~~
>> include/linux/module.h:213:27: error: '__mod_platform__twl6032_regulator_driver_ids_device_table' aliased to undefined symbol 'twl6032_regulator_driver_ids'
    extern const typeof(name) __mod_##type##__##name##_device_table  \
                              ^
>> drivers/regulator/twl6032-regulator.c:557:1: note: in expansion of macro 'MODULE_DEVICE_TABLE'
    MODULE_DEVICE_TABLE(platform, twl6032_regulator_driver_ids);
    ^~~~~~~~~~~~~~~~~~~

vim +/twl6032_regulator_driver_ids +557 drivers/regulator/twl6032-regulator.c

   551	
   552	static const struct of_device_id twl6032_dt_match[] = {
   553		{ .compatible = "ti,twl6032-regulator" },
   554		{ /* last entry */ }
   555	};
   556	
 > 557	MODULE_DEVICE_TABLE(platform, twl6032_regulator_driver_ids);
   558	
   559	static struct platform_driver twl6032_regulator_driver = {
   560		.driver = {

---
0-DAY kernel test infrastructure                Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all                   Intel Corporation
-------------- next part --------------
A non-text attachment was scrubbed...
Name: .config.gz
Type: application/gzip
Size: 56830 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20161127/cdcde6ff/attachment-0001.gz>

^ permalink raw reply	[flat|nested] 38+ messages in thread

* Re: [PATCH 4/5] regulator: Add support for TI TWL6032
  2016-11-26 18:55     ` kbuild test robot
  (?)
@ 2016-11-26 20:24       ` Rosia, Nicolae
  -1 siblings, 0 replies; 38+ messages in thread
From: Rosia, Nicolae @ 2016-11-26 20:24 UTC (permalink / raw)
  To: lkp
  Cc: linux-kernel, gg, robh+dt, devicetree, lee.jones, linux-omap,
	broonie, baruch, mark.rutland, lgirdwood, linux-arm-kernel,
	paul.gortmaker, tony

Hi,

On Sun, 2016-11-27 at 02:55 +0800, kbuild test robot wrote:
> Hi Nicolae,
> 
> [auto build test ERROR on omap/for-next]
> [also build test ERROR on v4.9-rc6]
> [cannot apply to next-20161125]
> [if your patch is applied to the wrong git tree, please drop us a
> note to help improve the system]
> 
> url:    https://github.com/0day-ci/linux/commits/Nicolae-Rosia/mfd-tw
> l-improvements-and-new-regulator-driver/20161127-022201
> base:   https://git.kernel.org/pub/scm/linux/kernel/git/tmlind/linux-
> omap.git for-next
> config: i386-allmodconfig (attached as .config)
> compiler: gcc-6 (Debian 6.2.0-3) 6.2.0 20160901
> reproduce:
>         # save the attached .config to linux build tree
>         make ARCH=i386 
> 
> All error/warnings (new ones prefixed by >>):
> 
>    In file included from drivers/regulator/twl6032-regulator.c:11:0:
> > > drivers/regulator/twl6032-regulator.c:557:31: error:
> > > 'twl6032_regulator_driver_ids' undeclared here (not in a
> > > function)
> 
>     MODULE_DEVICE_TABLE(platform, twl6032_regulator_driver_ids);
>                                   ^
>    include/linux/module.h:213:21: note: in definition of macro
> 'MODULE_DEVICE_TABLE'
>     extern const typeof(name)
> __mod_##type##__##name##_device_table  \
>                         ^~~~
> > > include/linux/module.h:213:27: error:
> > > '__mod_platform__twl6032_regulator_driver_ids_device_table'
> > > aliased to undefined symbol 'twl6032_regulator_driver_ids'
> 
>     extern const typeof(name)
> __mod_##type##__##name##_device_table  \
>                               ^
> > > drivers/regulator/twl6032-regulator.c:557:1: note: in expansion
> > > of macro 'MODULE_DEVICE_TABLE'
> 
>     MODULE_DEVICE_TABLE(platform, twl6032_regulator_driver_ids);
>     ^~~~~~~~~~~~~~~~~~~
> 
> vim +/twl6032_regulator_driver_ids +557 drivers/regulator/twl6032-
> regulator.c
> 
>    551	
>    552	static const struct of_device_id twl6032_dt_match[] = {
>    553		{ .compatible = "ti,twl6032-regulator" },
>    554		{ /* last entry */ }
>    555	};
>    556	
>  > 557	MODULE_DEVICE_TABLE(platform,
> twl6032_regulator_driver_ids);
>    558	
>    559	static struct platform_driver twl6032_regulator_driver
> = {
>    560		.driver = {

Thanks, I did not notice this since I was only testing using built-in
module.
I will wait for comments before sending V2, untill then here's an
inline patch with the fix.


Best regards,
Nicolae

^ permalink raw reply	[flat|nested] 38+ messages in thread

* Re: [PATCH 4/5] regulator: Add support for TI TWL6032
@ 2016-11-26 20:24       ` Rosia, Nicolae
  0 siblings, 0 replies; 38+ messages in thread
From: Rosia, Nicolae @ 2016-11-26 20:24 UTC (permalink / raw)
  To: lkp
  Cc: linux-kernel, gg, robh+dt, devicetree, lee.jones, linux-omap,
	broonie, baruch, mark.rutland, lgirdwood, linux-arm-kernel,
	paul.gortmaker, tony

Hi,

On Sun, 2016-11-27 at 02:55 +0800, kbuild test robot wrote:
> Hi Nicolae,
> 
> [auto build test ERROR on omap/for-next]
> [also build test ERROR on v4.9-rc6]
> [cannot apply to next-20161125]
> [if your patch is applied to the wrong git tree, please drop us a
> note to help improve the system]
> 
> url:    https://github.com/0day-ci/linux/commits/Nicolae-Rosia/mfd-tw
> l-improvements-and-new-regulator-driver/20161127-022201
> base:   https://git.kernel.org/pub/scm/linux/kernel/git/tmlind/linux-
> omap.git for-next
> config: i386-allmodconfig (attached as .config)
> compiler: gcc-6 (Debian 6.2.0-3) 6.2.0 20160901
> reproduce:
>         # save the attached .config to linux build tree
>         make ARCH=i386 
> 
> All error/warnings (new ones prefixed by >>):
> 
>    In file included from drivers/regulator/twl6032-regulator.c:11:0:
> > > drivers/regulator/twl6032-regulator.c:557:31: error:
> > > 'twl6032_regulator_driver_ids' undeclared here (not in a
> > > function)
> 
>     MODULE_DEVICE_TABLE(platform, twl6032_regulator_driver_ids);
>                                   ^
>    include/linux/module.h:213:21: note: in definition of macro
> 'MODULE_DEVICE_TABLE'
>     extern const typeof(name)
> __mod_##type##__##name##_device_table  \
>                         ^~~~
> > > include/linux/module.h:213:27: error:
> > > '__mod_platform__twl6032_regulator_driver_ids_device_table'
> > > aliased to undefined symbol 'twl6032_regulator_driver_ids'
> 
>     extern const typeof(name)
> __mod_##type##__##name##_device_table  \
>                               ^
> > > drivers/regulator/twl6032-regulator.c:557:1: note: in expansion
> > > of macro 'MODULE_DEVICE_TABLE'
> 
>     MODULE_DEVICE_TABLE(platform, twl6032_regulator_driver_ids);
>     ^~~~~~~~~~~~~~~~~~~
> 
> vim +/twl6032_regulator_driver_ids +557 drivers/regulator/twl6032-
> regulator.c
> 
>    551	
>    552	static const struct of_device_id twl6032_dt_match[] = {
>    553		{ .compatible = "ti,twl6032-regulator" },
>    554		{ /* last entry */ }
>    555	};
>    556	
>  > 557	MODULE_DEVICE_TABLE(platform,
> twl6032_regulator_driver_ids);
>    558	
>    559	static struct platform_driver twl6032_regulator_driver
> = {
>    560		.driver = {

Thanks, I did not notice this since I was only testing using built-in
module.
I will wait for comments before sending V2, untill then here's an
inline patch with the fix.


Best regards,
Nicolae


^ permalink raw reply	[flat|nested] 38+ messages in thread

* [PATCH 4/5] regulator: Add support for TI TWL6032
@ 2016-11-26 20:24       ` Rosia, Nicolae
  0 siblings, 0 replies; 38+ messages in thread
From: Rosia, Nicolae @ 2016-11-26 20:24 UTC (permalink / raw)
  To: linux-arm-kernel

Hi,

On Sun, 2016-11-27 at 02:55 +0800, kbuild test robot wrote:
> Hi Nicolae,
> 
> [auto build test ERROR on omap/for-next]
> [also build test ERROR on v4.9-rc6]
> [cannot apply to next-20161125]
> [if your patch is applied to the wrong git tree, please drop us a
> note to help improve the system]
> 
> url:????https://github.com/0day-ci/linux/commits/Nicolae-Rosia/mfd-tw
> l-improvements-and-new-regulator-driver/20161127-022201
> base:???https://git.kernel.org/pub/scm/linux/kernel/git/tmlind/linux-
> omap.git for-next
> config: i386-allmodconfig (attached as .config)
> compiler: gcc-6 (Debian 6.2.0-3) 6.2.0 20160901
> reproduce:
> ????????# save the attached .config to linux build tree
> ????????make ARCH=i386?
> 
> All error/warnings (new ones prefixed by >>):
> 
> ???In file included from drivers/regulator/twl6032-regulator.c:11:0:
> > > drivers/regulator/twl6032-regulator.c:557:31: error:
> > > 'twl6032_regulator_driver_ids' undeclared here (not in a
> > > function)
> 
> ????MODULE_DEVICE_TABLE(platform, twl6032_regulator_driver_ids);
> ??????????????????????????????????^
> ???include/linux/module.h:213:21: note: in definition of macro
> 'MODULE_DEVICE_TABLE'
> ????extern const typeof(name)
> __mod_##type##__##name##_device_table??\
> ????????????????????????^~~~
> > > include/linux/module.h:213:27: error:
> > > '__mod_platform__twl6032_regulator_driver_ids_device_table'
> > > aliased to undefined symbol 'twl6032_regulator_driver_ids'
> 
> ????extern const typeof(name)
> __mod_##type##__##name##_device_table??\
> ??????????????????????????????^
> > > drivers/regulator/twl6032-regulator.c:557:1: note: in expansion
> > > of macro 'MODULE_DEVICE_TABLE'
> 
> ????MODULE_DEVICE_TABLE(platform, twl6032_regulator_driver_ids);
> ????^~~~~~~~~~~~~~~~~~~
> 
> vim +/twl6032_regulator_driver_ids +557 drivers/regulator/twl6032-
> regulator.c
> 
> ???551	
> ???552	static const struct of_device_id twl6032_dt_match[] = {
> ???553		{ .compatible = "ti,twl6032-regulator" },
> ???554		{ /* last entry */ }
> ???555	};
> ???556	
> ?> 557	MODULE_DEVICE_TABLE(platform,
> twl6032_regulator_driver_ids);
> ???558	
> ???559	static struct platform_driver twl6032_regulator_driver
> = {
> ???560		.driver = {

Thanks, I did not notice this since I was only testing using built-in
module.
I will wait for comments before sending V2, untill then here's an
inline patch with the fix.


Best regards,
Nicolae

^ permalink raw reply	[flat|nested] 38+ messages in thread

* Re: [PATCH 4/5] regulator: Add support for TI TWL6032
  2016-11-26 18:13   ` Nicolae Rosia
@ 2016-12-01 16:10     ` Rob Herring
  -1 siblings, 0 replies; 38+ messages in thread
From: Rob Herring @ 2016-12-01 16:10 UTC (permalink / raw)
  To: Nicolae Rosia
  Cc: Lee Jones, Mark Brown, Mark Rutland, Tony Lindgren,
	Liam Girdwood, Paul Gortmaker, Graeme Gregory, Baruch Siach,
	linux-omap, linux-arm-kernel, linux-kernel, devicetree

On Sat, Nov 26, 2016 at 08:13:25PM +0200, Nicolae Rosia wrote:
> The TWL6032 PMIC is similar to TWL6030, has different
> output names, and regulator control logic.
> It is used on Barnes & Noble Nook HD and HD+.
> 
> Signed-off-by: Nicolae Rosia <Nicolae_Rosia@mentor.com>
> ---
>  .../bindings/regulator/twl6032-regulator.txt       | 109 ++++
>  drivers/regulator/Kconfig                          |   7 +
>  drivers/regulator/Makefile                         |   1 +
>  drivers/regulator/twl6032-regulator.c              | 582 +++++++++++++++++++++
>  4 files changed, 699 insertions(+)
>  create mode 100644 Documentation/devicetree/bindings/regulator/twl6032-regulator.txt
>  create mode 100644 drivers/regulator/twl6032-regulator.c
> 
> diff --git a/Documentation/devicetree/bindings/regulator/twl6032-regulator.txt b/Documentation/devicetree/bindings/regulator/twl6032-regulator.txt
> new file mode 100644
> index 0000000..323f5a9
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/regulator/twl6032-regulator.txt
> @@ -0,0 +1,109 @@
> +TWL6032 PMIC Voltage Regulator Bindings
> +
> +The parent node must be MFD TWL Core, ti,twl6032.
> +
> +Required properties:
> +- compatible: "ti,twl6032"
> +
> +Optional properties:
> +- regulators node containing regulator childs.

s/childs/children/

regulators node is not a property.

> +
> +The child regulators  must be named after their hardware

extra space             ^

> +counterparts: LDO[1-6], LDOLN, LDOUSB and VANA.
> +
> +Each regulator is defined using the standard binding
> +for regulators as described in ./regulator.txt
> +
> +Example:
> +twl {
> +	compatible = "ti,twl6032";
> +
> +	[...]
> +
> +	pmic {
> +		compatible = "ti,twl6032-regulator";

Not documented.

> +
> +		regulators {

Do you really need pmic node and regulators node?

> +			ldo1: LDO1 {
> +				regulator-min-microvolt = <1800000>;
> +				regulator-max-microvolt = <2500000>;
> +
> +				regulator-state-mem {
> +					regulator-off-in-suspend;
> +				};
> +			};
> +
> +			ldo2: LDO2 {
> +				regulator-min-microvolt = <1000000>;
> +				regulator-max-microvolt = <3000000>;
> +
> +				regulator-state-mem {
> +					regulator-off-in-suspend;
> +				};
> +			};
> +
> +			ldo3: LDO3 {
> +				regulator-min-microvolt = <1800000>;
> +				regulator-max-microvolt = <1800000>;
> +				regulator-boot-on;
> +
> +				regulator-state-mem {
> +					regulator-off-in-suspend;
> +				};
> +			};
> +
> +			ldo4: LDO4 {
> +				regulator-min-microvolt = <1800000>;
> +				regulator-max-microvolt = <1800000>;
> +
> +				regulator-state-mem {
> +					regulator-off-in-suspend;
> +				};
> +			};
> +
> +			ldo5: LDO5 {
> +				regulator-min-microvolt = <1200000>;
> +				regulator-max-microvolt = <3000000>;
> +
> +				regulator-state-mem {
> +					regulator-off-in-suspend;
> +				};
> +			};
> +
> +			ldo6: LDO6 {
> +				regulator-min-microvolt = <1800000>;
> +				regulator-max-microvolt = <1800000>;
> +				regulator-always-on;
> +
> +				regulator-state-mem {
> +					regulator-off-in-suspend;
> +				};
> +			};
> +
> +			ldo7: LDO7 {
> +				regulator-min-microvolt = <1800000>;
> +				regulator-max-microvolt = <1800000>;
> +				regulator-boot-on;
> +				regulator-always-on;
> +			};
> +
> +			ldoln: LDOLN {
> +				regulator-min-microvolt = <1000000>;
> +				regulator-max-microvolt = <3000000>;
> +			};
> +
> +			ldousb: LDOUSB {
> +				regulator-min-microvolt = <1000000>;
> +				regulator-max-microvolt = <3000000>;
> +			};
> +
> +			vana: VANA {
> +				regulator-min-microvolt = <2100000>;
> +				regulator-max-microvolt = <2100000>;
> +				regulator-always-on;
> +			};
> +		};
> +	};
> +
> +	[...]
> +};

^ permalink raw reply	[flat|nested] 38+ messages in thread

* [PATCH 4/5] regulator: Add support for TI TWL6032
@ 2016-12-01 16:10     ` Rob Herring
  0 siblings, 0 replies; 38+ messages in thread
From: Rob Herring @ 2016-12-01 16:10 UTC (permalink / raw)
  To: linux-arm-kernel

On Sat, Nov 26, 2016 at 08:13:25PM +0200, Nicolae Rosia wrote:
> The TWL6032 PMIC is similar to TWL6030, has different
> output names, and regulator control logic.
> It is used on Barnes & Noble Nook HD and HD+.
> 
> Signed-off-by: Nicolae Rosia <Nicolae_Rosia@mentor.com>
> ---
>  .../bindings/regulator/twl6032-regulator.txt       | 109 ++++
>  drivers/regulator/Kconfig                          |   7 +
>  drivers/regulator/Makefile                         |   1 +
>  drivers/regulator/twl6032-regulator.c              | 582 +++++++++++++++++++++
>  4 files changed, 699 insertions(+)
>  create mode 100644 Documentation/devicetree/bindings/regulator/twl6032-regulator.txt
>  create mode 100644 drivers/regulator/twl6032-regulator.c
> 
> diff --git a/Documentation/devicetree/bindings/regulator/twl6032-regulator.txt b/Documentation/devicetree/bindings/regulator/twl6032-regulator.txt
> new file mode 100644
> index 0000000..323f5a9
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/regulator/twl6032-regulator.txt
> @@ -0,0 +1,109 @@
> +TWL6032 PMIC Voltage Regulator Bindings
> +
> +The parent node must be MFD TWL Core, ti,twl6032.
> +
> +Required properties:
> +- compatible: "ti,twl6032"
> +
> +Optional properties:
> +- regulators node containing regulator childs.

s/childs/children/

regulators node is not a property.

> +
> +The child regulators  must be named after their hardware

extra space             ^

> +counterparts: LDO[1-6], LDOLN, LDOUSB and VANA.
> +
> +Each regulator is defined using the standard binding
> +for regulators as described in ./regulator.txt
> +
> +Example:
> +twl {
> +	compatible = "ti,twl6032";
> +
> +	[...]
> +
> +	pmic {
> +		compatible = "ti,twl6032-regulator";

Not documented.

> +
> +		regulators {

Do you really need pmic node and regulators node?

> +			ldo1: LDO1 {
> +				regulator-min-microvolt = <1800000>;
> +				regulator-max-microvolt = <2500000>;
> +
> +				regulator-state-mem {
> +					regulator-off-in-suspend;
> +				};
> +			};
> +
> +			ldo2: LDO2 {
> +				regulator-min-microvolt = <1000000>;
> +				regulator-max-microvolt = <3000000>;
> +
> +				regulator-state-mem {
> +					regulator-off-in-suspend;
> +				};
> +			};
> +
> +			ldo3: LDO3 {
> +				regulator-min-microvolt = <1800000>;
> +				regulator-max-microvolt = <1800000>;
> +				regulator-boot-on;
> +
> +				regulator-state-mem {
> +					regulator-off-in-suspend;
> +				};
> +			};
> +
> +			ldo4: LDO4 {
> +				regulator-min-microvolt = <1800000>;
> +				regulator-max-microvolt = <1800000>;
> +
> +				regulator-state-mem {
> +					regulator-off-in-suspend;
> +				};
> +			};
> +
> +			ldo5: LDO5 {
> +				regulator-min-microvolt = <1200000>;
> +				regulator-max-microvolt = <3000000>;
> +
> +				regulator-state-mem {
> +					regulator-off-in-suspend;
> +				};
> +			};
> +
> +			ldo6: LDO6 {
> +				regulator-min-microvolt = <1800000>;
> +				regulator-max-microvolt = <1800000>;
> +				regulator-always-on;
> +
> +				regulator-state-mem {
> +					regulator-off-in-suspend;
> +				};
> +			};
> +
> +			ldo7: LDO7 {
> +				regulator-min-microvolt = <1800000>;
> +				regulator-max-microvolt = <1800000>;
> +				regulator-boot-on;
> +				regulator-always-on;
> +			};
> +
> +			ldoln: LDOLN {
> +				regulator-min-microvolt = <1000000>;
> +				regulator-max-microvolt = <3000000>;
> +			};
> +
> +			ldousb: LDOUSB {
> +				regulator-min-microvolt = <1000000>;
> +				regulator-max-microvolt = <3000000>;
> +			};
> +
> +			vana: VANA {
> +				regulator-min-microvolt = <2100000>;
> +				regulator-max-microvolt = <2100000>;
> +				regulator-always-on;
> +			};
> +		};
> +	};
> +
> +	[...]
> +};

^ permalink raw reply	[flat|nested] 38+ messages in thread

* Re: [PATCH 1/5] mfd: twl-core: make driver DT only
  2016-11-26 18:13   ` Nicolae Rosia
  (?)
@ 2017-01-03 15:00     ` Lee Jones
  -1 siblings, 0 replies; 38+ messages in thread
From: Lee Jones @ 2017-01-03 15:00 UTC (permalink / raw)
  To: Nicolae Rosia
  Cc: Mark Brown, Rob Herring, Mark Rutland, Tony Lindgren,
	Liam Girdwood, Paul Gortmaker, Graeme Gregory, Baruch Siach,
	linux-omap, linux-arm-kernel, linux-kernel, devicetree

On Sat, 26 Nov 2016, Nicolae Rosia wrote:

> All users are DT-only and it makes no sense to keep
> unused code
> 
> Signed-off-by: Nicolae Rosia <Nicolae_Rosia@mentor.com>
> ---
>  drivers/mfd/Kconfig    |   1 +
>  drivers/mfd/twl-core.c | 399 +------------------------------------------------
>  2 files changed, 8 insertions(+), 392 deletions(-)
> 
> diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig
> index c6df644..c180f8b 100644
> --- a/drivers/mfd/Kconfig
> +++ b/drivers/mfd/Kconfig
> @@ -1333,6 +1333,7 @@ config MFD_TPS80031
>  config TWL4030_CORE
>  	bool "TI TWL4030/TWL5030/TWL6030/TPS659x0 Support"
>  	depends on I2C=y
> +	depends on OF
>  	select IRQ_DOMAIN
>  	select REGMAP_I2C
>  	help
> diff --git a/drivers/mfd/twl-core.c b/drivers/mfd/twl-core.c
> index c64615d..48b0668 100644
> --- a/drivers/mfd/twl-core.c
> +++ b/drivers/mfd/twl-core.c
> @@ -13,6 +13,9 @@
>   * Code cleanup and modifications to IRQ handler.
>   * by syed khasim <x0khasim@ti.com>
>   *
> + * Code cleanup and modifications:
> + * Copyright (C) 2016 Nicolae Rosia <nicolae.rosia@gmail.com>

This header comment is not a changelog.  There is no need for everyone
who makes a change to adopt copyright.  Removing !DT support is a big
change regards to line diff, but it's not a re-write.

Apart from that, patch looks good.

For my own reference:
  Acked-for-MFD-by: Lee Jones <lee.jones@linaro.org>

>   * This program is free software; you can redistribute it and/or modify
>   * it under the terms of the GNU General Public License as published by
>   * the Free Software Foundation; either version 2 of the License, or
> @@ -604,376 +607,6 @@ int twl_get_hfclk_rate(void)
>  }
>  EXPORT_SYMBOL_GPL(twl_get_hfclk_rate);
>  
> -static struct device *
> -add_numbered_child(unsigned mod_no, const char *name, int num,
> -		void *pdata, unsigned pdata_len,
> -		bool can_wakeup, int irq0, int irq1)
> -{
> -	struct platform_device	*pdev;
> -	struct twl_client	*twl;
> -	int			status, sid;
> -
> -	if (unlikely(mod_no >= twl_get_last_module())) {
> -		pr_err("%s: invalid module number %d\n", DRIVER_NAME, mod_no);
> -		return ERR_PTR(-EPERM);
> -	}
> -	sid = twl_priv->twl_map[mod_no].sid;
> -	twl = &twl_priv->twl_modules[sid];
> -
> -	pdev = platform_device_alloc(name, num);
> -	if (!pdev)
> -		return ERR_PTR(-ENOMEM);
> -
> -	pdev->dev.parent = &twl->client->dev;
> -
> -	if (pdata) {
> -		status = platform_device_add_data(pdev, pdata, pdata_len);
> -		if (status < 0) {
> -			dev_dbg(&pdev->dev, "can't add platform_data\n");
> -			goto put_device;
> -		}
> -	}
> -
> -	if (irq0) {
> -		struct resource r[2] = {
> -			{ .start = irq0, .flags = IORESOURCE_IRQ, },
> -			{ .start = irq1, .flags = IORESOURCE_IRQ, },
> -		};
> -
> -		status = platform_device_add_resources(pdev, r, irq1 ? 2 : 1);
> -		if (status < 0) {
> -			dev_dbg(&pdev->dev, "can't add irqs\n");
> -			goto put_device;
> -		}
> -	}
> -
> -	status = platform_device_add(pdev);
> -	if (status)
> -		goto put_device;
> -
> -	device_init_wakeup(&pdev->dev, can_wakeup);
> -
> -	return &pdev->dev;
> -
> -put_device:
> -	platform_device_put(pdev);
> -	dev_err(&twl->client->dev, "failed to add device %s\n", name);
> -	return ERR_PTR(status);
> -}
> -
> -static inline struct device *add_child(unsigned mod_no, const char *name,
> -		void *pdata, unsigned pdata_len,
> -		bool can_wakeup, int irq0, int irq1)
> -{
> -	return add_numbered_child(mod_no, name, -1, pdata, pdata_len,
> -		can_wakeup, irq0, irq1);
> -}
> -
> -static struct device *
> -add_regulator_linked(int num, struct regulator_init_data *pdata,
> -		struct regulator_consumer_supply *consumers,
> -		unsigned num_consumers, unsigned long features)
> -{
> -	struct twl_regulator_driver_data drv_data;
> -
> -	/* regulator framework demands init_data ... */
> -	if (!pdata)
> -		return NULL;
> -
> -	if (consumers) {
> -		pdata->consumer_supplies = consumers;
> -		pdata->num_consumer_supplies = num_consumers;
> -	}
> -
> -	if (pdata->driver_data) {
> -		/* If we have existing drv_data, just add the flags */
> -		struct twl_regulator_driver_data *tmp;
> -		tmp = pdata->driver_data;
> -		tmp->features |= features;
> -	} else {
> -		/* add new driver data struct, used only during init */
> -		drv_data.features = features;
> -		drv_data.set_voltage = NULL;
> -		drv_data.get_voltage = NULL;
> -		drv_data.data = NULL;
> -		pdata->driver_data = &drv_data;
> -	}
> -
> -	/* NOTE:  we currently ignore regulator IRQs, e.g. for short circuits */
> -	return add_numbered_child(TWL_MODULE_PM_MASTER, "twl_reg", num,
> -		pdata, sizeof(*pdata), false, 0, 0);
> -}
> -
> -static struct device *
> -add_regulator(int num, struct regulator_init_data *pdata,
> -		unsigned long features)
> -{
> -	return add_regulator_linked(num, pdata, NULL, 0, features);
> -}
> -
> -/*
> - * NOTE:  We know the first 8 IRQs after pdata->base_irq are
> - * for the PIH, and the next are for the PWR_INT SIH, since
> - * that's how twl_init_irq() sets things up.
> - */
> -
> -static int
> -add_children(struct twl4030_platform_data *pdata, unsigned irq_base,
> -		unsigned long features)
> -{
> -	struct device	*child;
> -
> -	if (IS_ENABLED(CONFIG_GPIO_TWL4030) && pdata->gpio) {
> -		child = add_child(TWL4030_MODULE_GPIO, "twl4030_gpio",
> -				pdata->gpio, sizeof(*pdata->gpio),
> -				false, irq_base + GPIO_INTR_OFFSET, 0);
> -		if (IS_ERR(child))
> -			return PTR_ERR(child);
> -	}
> -
> -	if (IS_ENABLED(CONFIG_KEYBOARD_TWL4030) && pdata->keypad) {
> -		child = add_child(TWL4030_MODULE_KEYPAD, "twl4030_keypad",
> -				pdata->keypad, sizeof(*pdata->keypad),
> -				true, irq_base + KEYPAD_INTR_OFFSET, 0);
> -		if (IS_ERR(child))
> -			return PTR_ERR(child);
> -	}
> -
> -	if (IS_ENABLED(CONFIG_TWL4030_MADC) && pdata->madc &&
> -	    twl_class_is_4030()) {
> -		child = add_child(TWL4030_MODULE_MADC, "twl4030_madc",
> -				pdata->madc, sizeof(*pdata->madc),
> -				true, irq_base + MADC_INTR_OFFSET, 0);
> -		if (IS_ERR(child))
> -			return PTR_ERR(child);
> -	}
> -
> -	if (IS_ENABLED(CONFIG_RTC_DRV_TWL4030)) {
> -		/*
> -		 * REVISIT platform_data here currently might expose the
> -		 * "msecure" line ... but for now we just expect board
> -		 * setup to tell the chip "it's always ok to SET_TIME".
> -		 * Eventually, Linux might become more aware of such
> -		 * HW security concerns, and "least privilege".
> -		 */
> -		child = add_child(TWL_MODULE_RTC, "twl_rtc", NULL, 0,
> -				true, irq_base + RTC_INTR_OFFSET, 0);
> -		if (IS_ERR(child))
> -			return PTR_ERR(child);
> -	}
> -
> -	if (IS_ENABLED(CONFIG_PWM_TWL)) {
> -		child = add_child(TWL_MODULE_PWM, "twl-pwm", NULL, 0,
> -				  false, 0, 0);
> -		if (IS_ERR(child))
> -			return PTR_ERR(child);
> -	}
> -
> -	if (IS_ENABLED(CONFIG_PWM_TWL_LED)) {
> -		child = add_child(TWL_MODULE_LED, "twl-pwmled", NULL, 0,
> -				  false, 0, 0);
> -		if (IS_ERR(child))
> -			return PTR_ERR(child);
> -	}
> -
> -	if (IS_ENABLED(CONFIG_TWL4030_USB) && pdata->usb &&
> -	    twl_class_is_4030()) {
> -
> -		static struct regulator_consumer_supply usb1v5 = {
> -			.supply =	"usb1v5",
> -		};
> -		static struct regulator_consumer_supply usb1v8 = {
> -			.supply =	"usb1v8",
> -		};
> -		static struct regulator_consumer_supply usb3v1 = {
> -			.supply =	"usb3v1",
> -		};
> -
> -	/* First add the regulators so that they can be used by transceiver */
> -		if (IS_ENABLED(CONFIG_REGULATOR_TWL4030)) {
> -			/* this is a template that gets copied */
> -			struct regulator_init_data usb_fixed = {
> -				.constraints.valid_modes_mask =
> -					REGULATOR_MODE_NORMAL
> -					| REGULATOR_MODE_STANDBY,
> -				.constraints.valid_ops_mask =
> -					REGULATOR_CHANGE_MODE
> -					| REGULATOR_CHANGE_STATUS,
> -			};
> -
> -			child = add_regulator_linked(TWL4030_REG_VUSB1V5,
> -						      &usb_fixed, &usb1v5, 1,
> -						      features);
> -			if (IS_ERR(child))
> -				return PTR_ERR(child);
> -
> -			child = add_regulator_linked(TWL4030_REG_VUSB1V8,
> -						      &usb_fixed, &usb1v8, 1,
> -						      features);
> -			if (IS_ERR(child))
> -				return PTR_ERR(child);
> -
> -			child = add_regulator_linked(TWL4030_REG_VUSB3V1,
> -						      &usb_fixed, &usb3v1, 1,
> -						      features);
> -			if (IS_ERR(child))
> -				return PTR_ERR(child);
> -
> -		}
> -
> -		child = add_child(TWL_MODULE_USB, "twl4030_usb",
> -				pdata->usb, sizeof(*pdata->usb), true,
> -				/* irq0 = USB_PRES, irq1 = USB */
> -				irq_base + USB_PRES_INTR_OFFSET,
> -				irq_base + USB_INTR_OFFSET);
> -
> -		if (IS_ERR(child))
> -			return PTR_ERR(child);
> -
> -		/* we need to connect regulators to this transceiver */
> -		if (IS_ENABLED(CONFIG_REGULATOR_TWL4030) && child) {
> -			usb1v5.dev_name = dev_name(child);
> -			usb1v8.dev_name = dev_name(child);
> -			usb3v1.dev_name = dev_name(child);
> -		}
> -	}
> -
> -	if (IS_ENABLED(CONFIG_TWL4030_WATCHDOG) && twl_class_is_4030()) {
> -		child = add_child(TWL_MODULE_PM_RECEIVER, "twl4030_wdt", NULL,
> -				  0, false, 0, 0);
> -		if (IS_ERR(child))
> -			return PTR_ERR(child);
> -	}
> -
> -	if (IS_ENABLED(CONFIG_INPUT_TWL4030_PWRBUTTON) && twl_class_is_4030()) {
> -		child = add_child(TWL_MODULE_PM_MASTER, "twl4030_pwrbutton",
> -				  NULL, 0, true, irq_base + 8 + 0, 0);
> -		if (IS_ERR(child))
> -			return PTR_ERR(child);
> -	}
> -
> -	if (IS_ENABLED(CONFIG_MFD_TWL4030_AUDIO) && pdata->audio &&
> -	    twl_class_is_4030()) {
> -		child = add_child(TWL4030_MODULE_AUDIO_VOICE, "twl4030-audio",
> -				pdata->audio, sizeof(*pdata->audio),
> -				false, 0, 0);
> -		if (IS_ERR(child))
> -			return PTR_ERR(child);
> -	}
> -
> -	/* twl4030 regulators */
> -	if (IS_ENABLED(CONFIG_REGULATOR_TWL4030) && twl_class_is_4030()) {
> -		child = add_regulator(TWL4030_REG_VPLL1, pdata->vpll1,
> -					features);
> -		if (IS_ERR(child))
> -			return PTR_ERR(child);
> -
> -		child = add_regulator(TWL4030_REG_VIO, pdata->vio,
> -					features);
> -		if (IS_ERR(child))
> -			return PTR_ERR(child);
> -
> -		child = add_regulator(TWL4030_REG_VDD1, pdata->vdd1,
> -					features);
> -		if (IS_ERR(child))
> -			return PTR_ERR(child);
> -
> -		child = add_regulator(TWL4030_REG_VDD2, pdata->vdd2,
> -					features);
> -		if (IS_ERR(child))
> -			return PTR_ERR(child);
> -
> -		child = add_regulator(TWL4030_REG_VMMC1, pdata->vmmc1,
> -					features);
> -		if (IS_ERR(child))
> -			return PTR_ERR(child);
> -
> -		child = add_regulator(TWL4030_REG_VDAC, pdata->vdac,
> -					features);
> -		if (IS_ERR(child))
> -			return PTR_ERR(child);
> -
> -		child = add_regulator((features & TWL4030_VAUX2)
> -					? TWL4030_REG_VAUX2_4030
> -					: TWL4030_REG_VAUX2,
> -				pdata->vaux2, features);
> -		if (IS_ERR(child))
> -			return PTR_ERR(child);
> -
> -		child = add_regulator(TWL4030_REG_VINTANA1, pdata->vintana1,
> -					features);
> -		if (IS_ERR(child))
> -			return PTR_ERR(child);
> -
> -		child = add_regulator(TWL4030_REG_VINTANA2, pdata->vintana2,
> -					features);
> -		if (IS_ERR(child))
> -			return PTR_ERR(child);
> -
> -		child = add_regulator(TWL4030_REG_VINTDIG, pdata->vintdig,
> -					features);
> -		if (IS_ERR(child))
> -			return PTR_ERR(child);
> -	}
> -
> -	/* maybe add LDOs that are omitted on cost-reduced parts */
> -	if (IS_ENABLED(CONFIG_REGULATOR_TWL4030) && !(features & TPS_SUBSET)
> -	  && twl_class_is_4030()) {
> -		child = add_regulator(TWL4030_REG_VPLL2, pdata->vpll2,
> -					features);
> -		if (IS_ERR(child))
> -			return PTR_ERR(child);
> -
> -		child = add_regulator(TWL4030_REG_VMMC2, pdata->vmmc2,
> -					features);
> -		if (IS_ERR(child))
> -			return PTR_ERR(child);
> -
> -		child = add_regulator(TWL4030_REG_VSIM, pdata->vsim,
> -					features);
> -		if (IS_ERR(child))
> -			return PTR_ERR(child);
> -
> -		child = add_regulator(TWL4030_REG_VAUX1, pdata->vaux1,
> -					features);
> -		if (IS_ERR(child))
> -			return PTR_ERR(child);
> -
> -		child = add_regulator(TWL4030_REG_VAUX3, pdata->vaux3,
> -					features);
> -		if (IS_ERR(child))
> -			return PTR_ERR(child);
> -
> -		child = add_regulator(TWL4030_REG_VAUX4, pdata->vaux4,
> -					features);
> -		if (IS_ERR(child))
> -			return PTR_ERR(child);
> -	}
> -
> -	if (IS_ENABLED(CONFIG_CHARGER_TWL4030) && pdata->bci &&
> -			!(features & (TPS_SUBSET | TWL5031))) {
> -		child = add_child(TWL_MODULE_MAIN_CHARGE, "twl4030_bci",
> -				pdata->bci, sizeof(*pdata->bci), false,
> -				/* irq0 = CHG_PRES, irq1 = BCI */
> -				irq_base + BCI_PRES_INTR_OFFSET,
> -				irq_base + BCI_INTR_OFFSET);
> -		if (IS_ERR(child))
> -			return PTR_ERR(child);
> -	}
> -
> -	if (IS_ENABLED(CONFIG_TWL4030_POWER) && pdata->power) {
> -		child = add_child(TWL_MODULE_PM_MASTER, "twl4030_power",
> -				  pdata->power, sizeof(*pdata->power), false,
> -				  0, 0);
> -		if (IS_ERR(child))
> -			return PTR_ERR(child);
> -	}
> -
> -	return 0;
> -}
> -
> -/*----------------------------------------------------------------------*/
> -
>  /*
>   * These three functions initialize the on-chip clock framework,
>   * letting it generate the right frequencies for USB, MADC, and
> @@ -1000,8 +633,7 @@ static inline int __init unprotect_pm_master(void)
>  	return e;
>  }
>  
> -static void clocks_init(struct device *dev,
> -			struct twl4030_clock_init_data *clock)
> +static void clocks_init(struct device *dev)
>  {
>  	int e = 0;
>  	struct clk *osc;
> @@ -1031,8 +663,6 @@ static void clocks_init(struct device *dev,
>  	}
>  
>  	ctrl |= HIGH_PERF_SQ;
> -	if (clock && clock->ck32k_lowpwr_enable)
> -		ctrl |= CK32K_LOWPWR_EN;
>  
>  	e |= unprotect_pm_master();
>  	/* effect->MADC+USB ck en */
> @@ -1071,16 +701,10 @@ static int twl_remove(struct i2c_client *client)
>  	return 0;
>  }
>  
> -static struct of_dev_auxdata twl_auxdata_lookup[] = {
> -	OF_DEV_AUXDATA("ti,twl4030-gpio", 0, "twl4030-gpio", NULL),
> -	{ /* sentinel */ },
> -};
> -
>  /* NOTE: This driver only handles a single twl4030/tps659x0 chip */
>  static int
>  twl_probe(struct i2c_client *client, const struct i2c_device_id *id)
>  {
> -	struct twl4030_platform_data	*pdata = dev_get_platdata(&client->dev);
>  	struct device_node		*node = client->dev.of_node;
>  	struct platform_device		*pdev;
>  	const struct regmap_config	*twl_regmap_config;
> @@ -1088,8 +712,8 @@ twl_probe(struct i2c_client *client, const struct i2c_device_id *id)
>  	int				status;
>  	unsigned			i, num_slaves;
>  
> -	if (!node && !pdata) {
> -		dev_err(&client->dev, "no platform data\n");
> +	if (!node) {
> +		dev_err(&client->dev, "no DT info\n");
>  		return -EINVAL;
>  	}
>  
> @@ -1177,7 +801,7 @@ twl_probe(struct i2c_client *client, const struct i2c_device_id *id)
>  	twl_priv->ready = true;
>  
>  	/* setup clock framework */
> -	clocks_init(&pdev->dev, pdata ? pdata->clock : NULL);
> +	clocks_init(&pdev->dev);
>  
>  	/* read TWL IDCODE Register */
>  	if (twl_class_is_4030()) {
> @@ -1225,15 +849,6 @@ twl_probe(struct i2c_client *client, const struct i2c_device_id *id)
>  				 TWL4030_DCDC_GLOBAL_CFG);
>  	}
>  
> -	if (node) {
> -		if (pdata)
> -			twl_auxdata_lookup[0].platform_data = pdata->gpio;
> -		status = of_platform_populate(node, NULL, twl_auxdata_lookup,
> -					      &client->dev);
> -	} else {
> -		status = add_children(pdata, irq_base, id->driver_data);
> -	}
> -
>  fail:
>  	if (status < 0)
>  		twl_remove(client);

-- 
Lee Jones
Linaro STMicroelectronics Landing Team Lead
Linaro.org │ Open source software for ARM SoCs
Follow Linaro: Facebook | Twitter | Blog

^ permalink raw reply	[flat|nested] 38+ messages in thread

* Re: [PATCH 1/5] mfd: twl-core: make driver DT only
@ 2017-01-03 15:00     ` Lee Jones
  0 siblings, 0 replies; 38+ messages in thread
From: Lee Jones @ 2017-01-03 15:00 UTC (permalink / raw)
  To: Nicolae Rosia
  Cc: Mark Rutland, devicetree, Baruch Siach, Tony Lindgren,
	Liam Girdwood, Rob Herring, linux-kernel, Paul Gortmaker,
	Mark Brown, Graeme Gregory, linux-omap, linux-arm-kernel

On Sat, 26 Nov 2016, Nicolae Rosia wrote:

> All users are DT-only and it makes no sense to keep
> unused code
> 
> Signed-off-by: Nicolae Rosia <Nicolae_Rosia@mentor.com>
> ---
>  drivers/mfd/Kconfig    |   1 +
>  drivers/mfd/twl-core.c | 399 +------------------------------------------------
>  2 files changed, 8 insertions(+), 392 deletions(-)
> 
> diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig
> index c6df644..c180f8b 100644
> --- a/drivers/mfd/Kconfig
> +++ b/drivers/mfd/Kconfig
> @@ -1333,6 +1333,7 @@ config MFD_TPS80031
>  config TWL4030_CORE
>  	bool "TI TWL4030/TWL5030/TWL6030/TPS659x0 Support"
>  	depends on I2C=y
> +	depends on OF
>  	select IRQ_DOMAIN
>  	select REGMAP_I2C
>  	help
> diff --git a/drivers/mfd/twl-core.c b/drivers/mfd/twl-core.c
> index c64615d..48b0668 100644
> --- a/drivers/mfd/twl-core.c
> +++ b/drivers/mfd/twl-core.c
> @@ -13,6 +13,9 @@
>   * Code cleanup and modifications to IRQ handler.
>   * by syed khasim <x0khasim@ti.com>
>   *
> + * Code cleanup and modifications:
> + * Copyright (C) 2016 Nicolae Rosia <nicolae.rosia@gmail.com>

This header comment is not a changelog.  There is no need for everyone
who makes a change to adopt copyright.  Removing !DT support is a big
change regards to line diff, but it's not a re-write.

Apart from that, patch looks good.

For my own reference:
  Acked-for-MFD-by: Lee Jones <lee.jones@linaro.org>

>   * This program is free software; you can redistribute it and/or modify
>   * it under the terms of the GNU General Public License as published by
>   * the Free Software Foundation; either version 2 of the License, or
> @@ -604,376 +607,6 @@ int twl_get_hfclk_rate(void)
>  }
>  EXPORT_SYMBOL_GPL(twl_get_hfclk_rate);
>  
> -static struct device *
> -add_numbered_child(unsigned mod_no, const char *name, int num,
> -		void *pdata, unsigned pdata_len,
> -		bool can_wakeup, int irq0, int irq1)
> -{
> -	struct platform_device	*pdev;
> -	struct twl_client	*twl;
> -	int			status, sid;
> -
> -	if (unlikely(mod_no >= twl_get_last_module())) {
> -		pr_err("%s: invalid module number %d\n", DRIVER_NAME, mod_no);
> -		return ERR_PTR(-EPERM);
> -	}
> -	sid = twl_priv->twl_map[mod_no].sid;
> -	twl = &twl_priv->twl_modules[sid];
> -
> -	pdev = platform_device_alloc(name, num);
> -	if (!pdev)
> -		return ERR_PTR(-ENOMEM);
> -
> -	pdev->dev.parent = &twl->client->dev;
> -
> -	if (pdata) {
> -		status = platform_device_add_data(pdev, pdata, pdata_len);
> -		if (status < 0) {
> -			dev_dbg(&pdev->dev, "can't add platform_data\n");
> -			goto put_device;
> -		}
> -	}
> -
> -	if (irq0) {
> -		struct resource r[2] = {
> -			{ .start = irq0, .flags = IORESOURCE_IRQ, },
> -			{ .start = irq1, .flags = IORESOURCE_IRQ, },
> -		};
> -
> -		status = platform_device_add_resources(pdev, r, irq1 ? 2 : 1);
> -		if (status < 0) {
> -			dev_dbg(&pdev->dev, "can't add irqs\n");
> -			goto put_device;
> -		}
> -	}
> -
> -	status = platform_device_add(pdev);
> -	if (status)
> -		goto put_device;
> -
> -	device_init_wakeup(&pdev->dev, can_wakeup);
> -
> -	return &pdev->dev;
> -
> -put_device:
> -	platform_device_put(pdev);
> -	dev_err(&twl->client->dev, "failed to add device %s\n", name);
> -	return ERR_PTR(status);
> -}
> -
> -static inline struct device *add_child(unsigned mod_no, const char *name,
> -		void *pdata, unsigned pdata_len,
> -		bool can_wakeup, int irq0, int irq1)
> -{
> -	return add_numbered_child(mod_no, name, -1, pdata, pdata_len,
> -		can_wakeup, irq0, irq1);
> -}
> -
> -static struct device *
> -add_regulator_linked(int num, struct regulator_init_data *pdata,
> -		struct regulator_consumer_supply *consumers,
> -		unsigned num_consumers, unsigned long features)
> -{
> -	struct twl_regulator_driver_data drv_data;
> -
> -	/* regulator framework demands init_data ... */
> -	if (!pdata)
> -		return NULL;
> -
> -	if (consumers) {
> -		pdata->consumer_supplies = consumers;
> -		pdata->num_consumer_supplies = num_consumers;
> -	}
> -
> -	if (pdata->driver_data) {
> -		/* If we have existing drv_data, just add the flags */
> -		struct twl_regulator_driver_data *tmp;
> -		tmp = pdata->driver_data;
> -		tmp->features |= features;
> -	} else {
> -		/* add new driver data struct, used only during init */
> -		drv_data.features = features;
> -		drv_data.set_voltage = NULL;
> -		drv_data.get_voltage = NULL;
> -		drv_data.data = NULL;
> -		pdata->driver_data = &drv_data;
> -	}
> -
> -	/* NOTE:  we currently ignore regulator IRQs, e.g. for short circuits */
> -	return add_numbered_child(TWL_MODULE_PM_MASTER, "twl_reg", num,
> -		pdata, sizeof(*pdata), false, 0, 0);
> -}
> -
> -static struct device *
> -add_regulator(int num, struct regulator_init_data *pdata,
> -		unsigned long features)
> -{
> -	return add_regulator_linked(num, pdata, NULL, 0, features);
> -}
> -
> -/*
> - * NOTE:  We know the first 8 IRQs after pdata->base_irq are
> - * for the PIH, and the next are for the PWR_INT SIH, since
> - * that's how twl_init_irq() sets things up.
> - */
> -
> -static int
> -add_children(struct twl4030_platform_data *pdata, unsigned irq_base,
> -		unsigned long features)
> -{
> -	struct device	*child;
> -
> -	if (IS_ENABLED(CONFIG_GPIO_TWL4030) && pdata->gpio) {
> -		child = add_child(TWL4030_MODULE_GPIO, "twl4030_gpio",
> -				pdata->gpio, sizeof(*pdata->gpio),
> -				false, irq_base + GPIO_INTR_OFFSET, 0);
> -		if (IS_ERR(child))
> -			return PTR_ERR(child);
> -	}
> -
> -	if (IS_ENABLED(CONFIG_KEYBOARD_TWL4030) && pdata->keypad) {
> -		child = add_child(TWL4030_MODULE_KEYPAD, "twl4030_keypad",
> -				pdata->keypad, sizeof(*pdata->keypad),
> -				true, irq_base + KEYPAD_INTR_OFFSET, 0);
> -		if (IS_ERR(child))
> -			return PTR_ERR(child);
> -	}
> -
> -	if (IS_ENABLED(CONFIG_TWL4030_MADC) && pdata->madc &&
> -	    twl_class_is_4030()) {
> -		child = add_child(TWL4030_MODULE_MADC, "twl4030_madc",
> -				pdata->madc, sizeof(*pdata->madc),
> -				true, irq_base + MADC_INTR_OFFSET, 0);
> -		if (IS_ERR(child))
> -			return PTR_ERR(child);
> -	}
> -
> -	if (IS_ENABLED(CONFIG_RTC_DRV_TWL4030)) {
> -		/*
> -		 * REVISIT platform_data here currently might expose the
> -		 * "msecure" line ... but for now we just expect board
> -		 * setup to tell the chip "it's always ok to SET_TIME".
> -		 * Eventually, Linux might become more aware of such
> -		 * HW security concerns, and "least privilege".
> -		 */
> -		child = add_child(TWL_MODULE_RTC, "twl_rtc", NULL, 0,
> -				true, irq_base + RTC_INTR_OFFSET, 0);
> -		if (IS_ERR(child))
> -			return PTR_ERR(child);
> -	}
> -
> -	if (IS_ENABLED(CONFIG_PWM_TWL)) {
> -		child = add_child(TWL_MODULE_PWM, "twl-pwm", NULL, 0,
> -				  false, 0, 0);
> -		if (IS_ERR(child))
> -			return PTR_ERR(child);
> -	}
> -
> -	if (IS_ENABLED(CONFIG_PWM_TWL_LED)) {
> -		child = add_child(TWL_MODULE_LED, "twl-pwmled", NULL, 0,
> -				  false, 0, 0);
> -		if (IS_ERR(child))
> -			return PTR_ERR(child);
> -	}
> -
> -	if (IS_ENABLED(CONFIG_TWL4030_USB) && pdata->usb &&
> -	    twl_class_is_4030()) {
> -
> -		static struct regulator_consumer_supply usb1v5 = {
> -			.supply =	"usb1v5",
> -		};
> -		static struct regulator_consumer_supply usb1v8 = {
> -			.supply =	"usb1v8",
> -		};
> -		static struct regulator_consumer_supply usb3v1 = {
> -			.supply =	"usb3v1",
> -		};
> -
> -	/* First add the regulators so that they can be used by transceiver */
> -		if (IS_ENABLED(CONFIG_REGULATOR_TWL4030)) {
> -			/* this is a template that gets copied */
> -			struct regulator_init_data usb_fixed = {
> -				.constraints.valid_modes_mask =
> -					REGULATOR_MODE_NORMAL
> -					| REGULATOR_MODE_STANDBY,
> -				.constraints.valid_ops_mask =
> -					REGULATOR_CHANGE_MODE
> -					| REGULATOR_CHANGE_STATUS,
> -			};
> -
> -			child = add_regulator_linked(TWL4030_REG_VUSB1V5,
> -						      &usb_fixed, &usb1v5, 1,
> -						      features);
> -			if (IS_ERR(child))
> -				return PTR_ERR(child);
> -
> -			child = add_regulator_linked(TWL4030_REG_VUSB1V8,
> -						      &usb_fixed, &usb1v8, 1,
> -						      features);
> -			if (IS_ERR(child))
> -				return PTR_ERR(child);
> -
> -			child = add_regulator_linked(TWL4030_REG_VUSB3V1,
> -						      &usb_fixed, &usb3v1, 1,
> -						      features);
> -			if (IS_ERR(child))
> -				return PTR_ERR(child);
> -
> -		}
> -
> -		child = add_child(TWL_MODULE_USB, "twl4030_usb",
> -				pdata->usb, sizeof(*pdata->usb), true,
> -				/* irq0 = USB_PRES, irq1 = USB */
> -				irq_base + USB_PRES_INTR_OFFSET,
> -				irq_base + USB_INTR_OFFSET);
> -
> -		if (IS_ERR(child))
> -			return PTR_ERR(child);
> -
> -		/* we need to connect regulators to this transceiver */
> -		if (IS_ENABLED(CONFIG_REGULATOR_TWL4030) && child) {
> -			usb1v5.dev_name = dev_name(child);
> -			usb1v8.dev_name = dev_name(child);
> -			usb3v1.dev_name = dev_name(child);
> -		}
> -	}
> -
> -	if (IS_ENABLED(CONFIG_TWL4030_WATCHDOG) && twl_class_is_4030()) {
> -		child = add_child(TWL_MODULE_PM_RECEIVER, "twl4030_wdt", NULL,
> -				  0, false, 0, 0);
> -		if (IS_ERR(child))
> -			return PTR_ERR(child);
> -	}
> -
> -	if (IS_ENABLED(CONFIG_INPUT_TWL4030_PWRBUTTON) && twl_class_is_4030()) {
> -		child = add_child(TWL_MODULE_PM_MASTER, "twl4030_pwrbutton",
> -				  NULL, 0, true, irq_base + 8 + 0, 0);
> -		if (IS_ERR(child))
> -			return PTR_ERR(child);
> -	}
> -
> -	if (IS_ENABLED(CONFIG_MFD_TWL4030_AUDIO) && pdata->audio &&
> -	    twl_class_is_4030()) {
> -		child = add_child(TWL4030_MODULE_AUDIO_VOICE, "twl4030-audio",
> -				pdata->audio, sizeof(*pdata->audio),
> -				false, 0, 0);
> -		if (IS_ERR(child))
> -			return PTR_ERR(child);
> -	}
> -
> -	/* twl4030 regulators */
> -	if (IS_ENABLED(CONFIG_REGULATOR_TWL4030) && twl_class_is_4030()) {
> -		child = add_regulator(TWL4030_REG_VPLL1, pdata->vpll1,
> -					features);
> -		if (IS_ERR(child))
> -			return PTR_ERR(child);
> -
> -		child = add_regulator(TWL4030_REG_VIO, pdata->vio,
> -					features);
> -		if (IS_ERR(child))
> -			return PTR_ERR(child);
> -
> -		child = add_regulator(TWL4030_REG_VDD1, pdata->vdd1,
> -					features);
> -		if (IS_ERR(child))
> -			return PTR_ERR(child);
> -
> -		child = add_regulator(TWL4030_REG_VDD2, pdata->vdd2,
> -					features);
> -		if (IS_ERR(child))
> -			return PTR_ERR(child);
> -
> -		child = add_regulator(TWL4030_REG_VMMC1, pdata->vmmc1,
> -					features);
> -		if (IS_ERR(child))
> -			return PTR_ERR(child);
> -
> -		child = add_regulator(TWL4030_REG_VDAC, pdata->vdac,
> -					features);
> -		if (IS_ERR(child))
> -			return PTR_ERR(child);
> -
> -		child = add_regulator((features & TWL4030_VAUX2)
> -					? TWL4030_REG_VAUX2_4030
> -					: TWL4030_REG_VAUX2,
> -				pdata->vaux2, features);
> -		if (IS_ERR(child))
> -			return PTR_ERR(child);
> -
> -		child = add_regulator(TWL4030_REG_VINTANA1, pdata->vintana1,
> -					features);
> -		if (IS_ERR(child))
> -			return PTR_ERR(child);
> -
> -		child = add_regulator(TWL4030_REG_VINTANA2, pdata->vintana2,
> -					features);
> -		if (IS_ERR(child))
> -			return PTR_ERR(child);
> -
> -		child = add_regulator(TWL4030_REG_VINTDIG, pdata->vintdig,
> -					features);
> -		if (IS_ERR(child))
> -			return PTR_ERR(child);
> -	}
> -
> -	/* maybe add LDOs that are omitted on cost-reduced parts */
> -	if (IS_ENABLED(CONFIG_REGULATOR_TWL4030) && !(features & TPS_SUBSET)
> -	  && twl_class_is_4030()) {
> -		child = add_regulator(TWL4030_REG_VPLL2, pdata->vpll2,
> -					features);
> -		if (IS_ERR(child))
> -			return PTR_ERR(child);
> -
> -		child = add_regulator(TWL4030_REG_VMMC2, pdata->vmmc2,
> -					features);
> -		if (IS_ERR(child))
> -			return PTR_ERR(child);
> -
> -		child = add_regulator(TWL4030_REG_VSIM, pdata->vsim,
> -					features);
> -		if (IS_ERR(child))
> -			return PTR_ERR(child);
> -
> -		child = add_regulator(TWL4030_REG_VAUX1, pdata->vaux1,
> -					features);
> -		if (IS_ERR(child))
> -			return PTR_ERR(child);
> -
> -		child = add_regulator(TWL4030_REG_VAUX3, pdata->vaux3,
> -					features);
> -		if (IS_ERR(child))
> -			return PTR_ERR(child);
> -
> -		child = add_regulator(TWL4030_REG_VAUX4, pdata->vaux4,
> -					features);
> -		if (IS_ERR(child))
> -			return PTR_ERR(child);
> -	}
> -
> -	if (IS_ENABLED(CONFIG_CHARGER_TWL4030) && pdata->bci &&
> -			!(features & (TPS_SUBSET | TWL5031))) {
> -		child = add_child(TWL_MODULE_MAIN_CHARGE, "twl4030_bci",
> -				pdata->bci, sizeof(*pdata->bci), false,
> -				/* irq0 = CHG_PRES, irq1 = BCI */
> -				irq_base + BCI_PRES_INTR_OFFSET,
> -				irq_base + BCI_INTR_OFFSET);
> -		if (IS_ERR(child))
> -			return PTR_ERR(child);
> -	}
> -
> -	if (IS_ENABLED(CONFIG_TWL4030_POWER) && pdata->power) {
> -		child = add_child(TWL_MODULE_PM_MASTER, "twl4030_power",
> -				  pdata->power, sizeof(*pdata->power), false,
> -				  0, 0);
> -		if (IS_ERR(child))
> -			return PTR_ERR(child);
> -	}
> -
> -	return 0;
> -}
> -
> -/*----------------------------------------------------------------------*/
> -
>  /*
>   * These three functions initialize the on-chip clock framework,
>   * letting it generate the right frequencies for USB, MADC, and
> @@ -1000,8 +633,7 @@ static inline int __init unprotect_pm_master(void)
>  	return e;
>  }
>  
> -static void clocks_init(struct device *dev,
> -			struct twl4030_clock_init_data *clock)
> +static void clocks_init(struct device *dev)
>  {
>  	int e = 0;
>  	struct clk *osc;
> @@ -1031,8 +663,6 @@ static void clocks_init(struct device *dev,
>  	}
>  
>  	ctrl |= HIGH_PERF_SQ;
> -	if (clock && clock->ck32k_lowpwr_enable)
> -		ctrl |= CK32K_LOWPWR_EN;
>  
>  	e |= unprotect_pm_master();
>  	/* effect->MADC+USB ck en */
> @@ -1071,16 +701,10 @@ static int twl_remove(struct i2c_client *client)
>  	return 0;
>  }
>  
> -static struct of_dev_auxdata twl_auxdata_lookup[] = {
> -	OF_DEV_AUXDATA("ti,twl4030-gpio", 0, "twl4030-gpio", NULL),
> -	{ /* sentinel */ },
> -};
> -
>  /* NOTE: This driver only handles a single twl4030/tps659x0 chip */
>  static int
>  twl_probe(struct i2c_client *client, const struct i2c_device_id *id)
>  {
> -	struct twl4030_platform_data	*pdata = dev_get_platdata(&client->dev);
>  	struct device_node		*node = client->dev.of_node;
>  	struct platform_device		*pdev;
>  	const struct regmap_config	*twl_regmap_config;
> @@ -1088,8 +712,8 @@ twl_probe(struct i2c_client *client, const struct i2c_device_id *id)
>  	int				status;
>  	unsigned			i, num_slaves;
>  
> -	if (!node && !pdata) {
> -		dev_err(&client->dev, "no platform data\n");
> +	if (!node) {
> +		dev_err(&client->dev, "no DT info\n");
>  		return -EINVAL;
>  	}
>  
> @@ -1177,7 +801,7 @@ twl_probe(struct i2c_client *client, const struct i2c_device_id *id)
>  	twl_priv->ready = true;
>  
>  	/* setup clock framework */
> -	clocks_init(&pdev->dev, pdata ? pdata->clock : NULL);
> +	clocks_init(&pdev->dev);
>  
>  	/* read TWL IDCODE Register */
>  	if (twl_class_is_4030()) {
> @@ -1225,15 +849,6 @@ twl_probe(struct i2c_client *client, const struct i2c_device_id *id)
>  				 TWL4030_DCDC_GLOBAL_CFG);
>  	}
>  
> -	if (node) {
> -		if (pdata)
> -			twl_auxdata_lookup[0].platform_data = pdata->gpio;
> -		status = of_platform_populate(node, NULL, twl_auxdata_lookup,
> -					      &client->dev);
> -	} else {
> -		status = add_children(pdata, irq_base, id->driver_data);
> -	}
> -
>  fail:
>  	if (status < 0)
>  		twl_remove(client);

-- 
Lee Jones
Linaro STMicroelectronics Landing Team Lead
Linaro.org │ Open source software for ARM SoCs
Follow Linaro: Facebook | Twitter | Blog

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply	[flat|nested] 38+ messages in thread

* [PATCH 1/5] mfd: twl-core: make driver DT only
@ 2017-01-03 15:00     ` Lee Jones
  0 siblings, 0 replies; 38+ messages in thread
From: Lee Jones @ 2017-01-03 15:00 UTC (permalink / raw)
  To: linux-arm-kernel

On Sat, 26 Nov 2016, Nicolae Rosia wrote:

> All users are DT-only and it makes no sense to keep
> unused code
> 
> Signed-off-by: Nicolae Rosia <Nicolae_Rosia@mentor.com>
> ---
>  drivers/mfd/Kconfig    |   1 +
>  drivers/mfd/twl-core.c | 399 +------------------------------------------------
>  2 files changed, 8 insertions(+), 392 deletions(-)
> 
> diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig
> index c6df644..c180f8b 100644
> --- a/drivers/mfd/Kconfig
> +++ b/drivers/mfd/Kconfig
> @@ -1333,6 +1333,7 @@ config MFD_TPS80031
>  config TWL4030_CORE
>  	bool "TI TWL4030/TWL5030/TWL6030/TPS659x0 Support"
>  	depends on I2C=y
> +	depends on OF
>  	select IRQ_DOMAIN
>  	select REGMAP_I2C
>  	help
> diff --git a/drivers/mfd/twl-core.c b/drivers/mfd/twl-core.c
> index c64615d..48b0668 100644
> --- a/drivers/mfd/twl-core.c
> +++ b/drivers/mfd/twl-core.c
> @@ -13,6 +13,9 @@
>   * Code cleanup and modifications to IRQ handler.
>   * by syed khasim <x0khasim@ti.com>
>   *
> + * Code cleanup and modifications:
> + * Copyright (C) 2016 Nicolae Rosia <nicolae.rosia@gmail.com>

This header comment is not a changelog.  There is no need for everyone
who makes a change to adopt copyright.  Removing !DT support is a big
change regards to line diff, but it's not a re-write.

Apart from that, patch looks good.

For my own reference:
  Acked-for-MFD-by: Lee Jones <lee.jones@linaro.org>

>   * This program is free software; you can redistribute it and/or modify
>   * it under the terms of the GNU General Public License as published by
>   * the Free Software Foundation; either version 2 of the License, or
> @@ -604,376 +607,6 @@ int twl_get_hfclk_rate(void)
>  }
>  EXPORT_SYMBOL_GPL(twl_get_hfclk_rate);
>  
> -static struct device *
> -add_numbered_child(unsigned mod_no, const char *name, int num,
> -		void *pdata, unsigned pdata_len,
> -		bool can_wakeup, int irq0, int irq1)
> -{
> -	struct platform_device	*pdev;
> -	struct twl_client	*twl;
> -	int			status, sid;
> -
> -	if (unlikely(mod_no >= twl_get_last_module())) {
> -		pr_err("%s: invalid module number %d\n", DRIVER_NAME, mod_no);
> -		return ERR_PTR(-EPERM);
> -	}
> -	sid = twl_priv->twl_map[mod_no].sid;
> -	twl = &twl_priv->twl_modules[sid];
> -
> -	pdev = platform_device_alloc(name, num);
> -	if (!pdev)
> -		return ERR_PTR(-ENOMEM);
> -
> -	pdev->dev.parent = &twl->client->dev;
> -
> -	if (pdata) {
> -		status = platform_device_add_data(pdev, pdata, pdata_len);
> -		if (status < 0) {
> -			dev_dbg(&pdev->dev, "can't add platform_data\n");
> -			goto put_device;
> -		}
> -	}
> -
> -	if (irq0) {
> -		struct resource r[2] = {
> -			{ .start = irq0, .flags = IORESOURCE_IRQ, },
> -			{ .start = irq1, .flags = IORESOURCE_IRQ, },
> -		};
> -
> -		status = platform_device_add_resources(pdev, r, irq1 ? 2 : 1);
> -		if (status < 0) {
> -			dev_dbg(&pdev->dev, "can't add irqs\n");
> -			goto put_device;
> -		}
> -	}
> -
> -	status = platform_device_add(pdev);
> -	if (status)
> -		goto put_device;
> -
> -	device_init_wakeup(&pdev->dev, can_wakeup);
> -
> -	return &pdev->dev;
> -
> -put_device:
> -	platform_device_put(pdev);
> -	dev_err(&twl->client->dev, "failed to add device %s\n", name);
> -	return ERR_PTR(status);
> -}
> -
> -static inline struct device *add_child(unsigned mod_no, const char *name,
> -		void *pdata, unsigned pdata_len,
> -		bool can_wakeup, int irq0, int irq1)
> -{
> -	return add_numbered_child(mod_no, name, -1, pdata, pdata_len,
> -		can_wakeup, irq0, irq1);
> -}
> -
> -static struct device *
> -add_regulator_linked(int num, struct regulator_init_data *pdata,
> -		struct regulator_consumer_supply *consumers,
> -		unsigned num_consumers, unsigned long features)
> -{
> -	struct twl_regulator_driver_data drv_data;
> -
> -	/* regulator framework demands init_data ... */
> -	if (!pdata)
> -		return NULL;
> -
> -	if (consumers) {
> -		pdata->consumer_supplies = consumers;
> -		pdata->num_consumer_supplies = num_consumers;
> -	}
> -
> -	if (pdata->driver_data) {
> -		/* If we have existing drv_data, just add the flags */
> -		struct twl_regulator_driver_data *tmp;
> -		tmp = pdata->driver_data;
> -		tmp->features |= features;
> -	} else {
> -		/* add new driver data struct, used only during init */
> -		drv_data.features = features;
> -		drv_data.set_voltage = NULL;
> -		drv_data.get_voltage = NULL;
> -		drv_data.data = NULL;
> -		pdata->driver_data = &drv_data;
> -	}
> -
> -	/* NOTE:  we currently ignore regulator IRQs, e.g. for short circuits */
> -	return add_numbered_child(TWL_MODULE_PM_MASTER, "twl_reg", num,
> -		pdata, sizeof(*pdata), false, 0, 0);
> -}
> -
> -static struct device *
> -add_regulator(int num, struct regulator_init_data *pdata,
> -		unsigned long features)
> -{
> -	return add_regulator_linked(num, pdata, NULL, 0, features);
> -}
> -
> -/*
> - * NOTE:  We know the first 8 IRQs after pdata->base_irq are
> - * for the PIH, and the next are for the PWR_INT SIH, since
> - * that's how twl_init_irq() sets things up.
> - */
> -
> -static int
> -add_children(struct twl4030_platform_data *pdata, unsigned irq_base,
> -		unsigned long features)
> -{
> -	struct device	*child;
> -
> -	if (IS_ENABLED(CONFIG_GPIO_TWL4030) && pdata->gpio) {
> -		child = add_child(TWL4030_MODULE_GPIO, "twl4030_gpio",
> -				pdata->gpio, sizeof(*pdata->gpio),
> -				false, irq_base + GPIO_INTR_OFFSET, 0);
> -		if (IS_ERR(child))
> -			return PTR_ERR(child);
> -	}
> -
> -	if (IS_ENABLED(CONFIG_KEYBOARD_TWL4030) && pdata->keypad) {
> -		child = add_child(TWL4030_MODULE_KEYPAD, "twl4030_keypad",
> -				pdata->keypad, sizeof(*pdata->keypad),
> -				true, irq_base + KEYPAD_INTR_OFFSET, 0);
> -		if (IS_ERR(child))
> -			return PTR_ERR(child);
> -	}
> -
> -	if (IS_ENABLED(CONFIG_TWL4030_MADC) && pdata->madc &&
> -	    twl_class_is_4030()) {
> -		child = add_child(TWL4030_MODULE_MADC, "twl4030_madc",
> -				pdata->madc, sizeof(*pdata->madc),
> -				true, irq_base + MADC_INTR_OFFSET, 0);
> -		if (IS_ERR(child))
> -			return PTR_ERR(child);
> -	}
> -
> -	if (IS_ENABLED(CONFIG_RTC_DRV_TWL4030)) {
> -		/*
> -		 * REVISIT platform_data here currently might expose the
> -		 * "msecure" line ... but for now we just expect board
> -		 * setup to tell the chip "it's always ok to SET_TIME".
> -		 * Eventually, Linux might become more aware of such
> -		 * HW security concerns, and "least privilege".
> -		 */
> -		child = add_child(TWL_MODULE_RTC, "twl_rtc", NULL, 0,
> -				true, irq_base + RTC_INTR_OFFSET, 0);
> -		if (IS_ERR(child))
> -			return PTR_ERR(child);
> -	}
> -
> -	if (IS_ENABLED(CONFIG_PWM_TWL)) {
> -		child = add_child(TWL_MODULE_PWM, "twl-pwm", NULL, 0,
> -				  false, 0, 0);
> -		if (IS_ERR(child))
> -			return PTR_ERR(child);
> -	}
> -
> -	if (IS_ENABLED(CONFIG_PWM_TWL_LED)) {
> -		child = add_child(TWL_MODULE_LED, "twl-pwmled", NULL, 0,
> -				  false, 0, 0);
> -		if (IS_ERR(child))
> -			return PTR_ERR(child);
> -	}
> -
> -	if (IS_ENABLED(CONFIG_TWL4030_USB) && pdata->usb &&
> -	    twl_class_is_4030()) {
> -
> -		static struct regulator_consumer_supply usb1v5 = {
> -			.supply =	"usb1v5",
> -		};
> -		static struct regulator_consumer_supply usb1v8 = {
> -			.supply =	"usb1v8",
> -		};
> -		static struct regulator_consumer_supply usb3v1 = {
> -			.supply =	"usb3v1",
> -		};
> -
> -	/* First add the regulators so that they can be used by transceiver */
> -		if (IS_ENABLED(CONFIG_REGULATOR_TWL4030)) {
> -			/* this is a template that gets copied */
> -			struct regulator_init_data usb_fixed = {
> -				.constraints.valid_modes_mask =
> -					REGULATOR_MODE_NORMAL
> -					| REGULATOR_MODE_STANDBY,
> -				.constraints.valid_ops_mask =
> -					REGULATOR_CHANGE_MODE
> -					| REGULATOR_CHANGE_STATUS,
> -			};
> -
> -			child = add_regulator_linked(TWL4030_REG_VUSB1V5,
> -						      &usb_fixed, &usb1v5, 1,
> -						      features);
> -			if (IS_ERR(child))
> -				return PTR_ERR(child);
> -
> -			child = add_regulator_linked(TWL4030_REG_VUSB1V8,
> -						      &usb_fixed, &usb1v8, 1,
> -						      features);
> -			if (IS_ERR(child))
> -				return PTR_ERR(child);
> -
> -			child = add_regulator_linked(TWL4030_REG_VUSB3V1,
> -						      &usb_fixed, &usb3v1, 1,
> -						      features);
> -			if (IS_ERR(child))
> -				return PTR_ERR(child);
> -
> -		}
> -
> -		child = add_child(TWL_MODULE_USB, "twl4030_usb",
> -				pdata->usb, sizeof(*pdata->usb), true,
> -				/* irq0 = USB_PRES, irq1 = USB */
> -				irq_base + USB_PRES_INTR_OFFSET,
> -				irq_base + USB_INTR_OFFSET);
> -
> -		if (IS_ERR(child))
> -			return PTR_ERR(child);
> -
> -		/* we need to connect regulators to this transceiver */
> -		if (IS_ENABLED(CONFIG_REGULATOR_TWL4030) && child) {
> -			usb1v5.dev_name = dev_name(child);
> -			usb1v8.dev_name = dev_name(child);
> -			usb3v1.dev_name = dev_name(child);
> -		}
> -	}
> -
> -	if (IS_ENABLED(CONFIG_TWL4030_WATCHDOG) && twl_class_is_4030()) {
> -		child = add_child(TWL_MODULE_PM_RECEIVER, "twl4030_wdt", NULL,
> -				  0, false, 0, 0);
> -		if (IS_ERR(child))
> -			return PTR_ERR(child);
> -	}
> -
> -	if (IS_ENABLED(CONFIG_INPUT_TWL4030_PWRBUTTON) && twl_class_is_4030()) {
> -		child = add_child(TWL_MODULE_PM_MASTER, "twl4030_pwrbutton",
> -				  NULL, 0, true, irq_base + 8 + 0, 0);
> -		if (IS_ERR(child))
> -			return PTR_ERR(child);
> -	}
> -
> -	if (IS_ENABLED(CONFIG_MFD_TWL4030_AUDIO) && pdata->audio &&
> -	    twl_class_is_4030()) {
> -		child = add_child(TWL4030_MODULE_AUDIO_VOICE, "twl4030-audio",
> -				pdata->audio, sizeof(*pdata->audio),
> -				false, 0, 0);
> -		if (IS_ERR(child))
> -			return PTR_ERR(child);
> -	}
> -
> -	/* twl4030 regulators */
> -	if (IS_ENABLED(CONFIG_REGULATOR_TWL4030) && twl_class_is_4030()) {
> -		child = add_regulator(TWL4030_REG_VPLL1, pdata->vpll1,
> -					features);
> -		if (IS_ERR(child))
> -			return PTR_ERR(child);
> -
> -		child = add_regulator(TWL4030_REG_VIO, pdata->vio,
> -					features);
> -		if (IS_ERR(child))
> -			return PTR_ERR(child);
> -
> -		child = add_regulator(TWL4030_REG_VDD1, pdata->vdd1,
> -					features);
> -		if (IS_ERR(child))
> -			return PTR_ERR(child);
> -
> -		child = add_regulator(TWL4030_REG_VDD2, pdata->vdd2,
> -					features);
> -		if (IS_ERR(child))
> -			return PTR_ERR(child);
> -
> -		child = add_regulator(TWL4030_REG_VMMC1, pdata->vmmc1,
> -					features);
> -		if (IS_ERR(child))
> -			return PTR_ERR(child);
> -
> -		child = add_regulator(TWL4030_REG_VDAC, pdata->vdac,
> -					features);
> -		if (IS_ERR(child))
> -			return PTR_ERR(child);
> -
> -		child = add_regulator((features & TWL4030_VAUX2)
> -					? TWL4030_REG_VAUX2_4030
> -					: TWL4030_REG_VAUX2,
> -				pdata->vaux2, features);
> -		if (IS_ERR(child))
> -			return PTR_ERR(child);
> -
> -		child = add_regulator(TWL4030_REG_VINTANA1, pdata->vintana1,
> -					features);
> -		if (IS_ERR(child))
> -			return PTR_ERR(child);
> -
> -		child = add_regulator(TWL4030_REG_VINTANA2, pdata->vintana2,
> -					features);
> -		if (IS_ERR(child))
> -			return PTR_ERR(child);
> -
> -		child = add_regulator(TWL4030_REG_VINTDIG, pdata->vintdig,
> -					features);
> -		if (IS_ERR(child))
> -			return PTR_ERR(child);
> -	}
> -
> -	/* maybe add LDOs that are omitted on cost-reduced parts */
> -	if (IS_ENABLED(CONFIG_REGULATOR_TWL4030) && !(features & TPS_SUBSET)
> -	  && twl_class_is_4030()) {
> -		child = add_regulator(TWL4030_REG_VPLL2, pdata->vpll2,
> -					features);
> -		if (IS_ERR(child))
> -			return PTR_ERR(child);
> -
> -		child = add_regulator(TWL4030_REG_VMMC2, pdata->vmmc2,
> -					features);
> -		if (IS_ERR(child))
> -			return PTR_ERR(child);
> -
> -		child = add_regulator(TWL4030_REG_VSIM, pdata->vsim,
> -					features);
> -		if (IS_ERR(child))
> -			return PTR_ERR(child);
> -
> -		child = add_regulator(TWL4030_REG_VAUX1, pdata->vaux1,
> -					features);
> -		if (IS_ERR(child))
> -			return PTR_ERR(child);
> -
> -		child = add_regulator(TWL4030_REG_VAUX3, pdata->vaux3,
> -					features);
> -		if (IS_ERR(child))
> -			return PTR_ERR(child);
> -
> -		child = add_regulator(TWL4030_REG_VAUX4, pdata->vaux4,
> -					features);
> -		if (IS_ERR(child))
> -			return PTR_ERR(child);
> -	}
> -
> -	if (IS_ENABLED(CONFIG_CHARGER_TWL4030) && pdata->bci &&
> -			!(features & (TPS_SUBSET | TWL5031))) {
> -		child = add_child(TWL_MODULE_MAIN_CHARGE, "twl4030_bci",
> -				pdata->bci, sizeof(*pdata->bci), false,
> -				/* irq0 = CHG_PRES, irq1 = BCI */
> -				irq_base + BCI_PRES_INTR_OFFSET,
> -				irq_base + BCI_INTR_OFFSET);
> -		if (IS_ERR(child))
> -			return PTR_ERR(child);
> -	}
> -
> -	if (IS_ENABLED(CONFIG_TWL4030_POWER) && pdata->power) {
> -		child = add_child(TWL_MODULE_PM_MASTER, "twl4030_power",
> -				  pdata->power, sizeof(*pdata->power), false,
> -				  0, 0);
> -		if (IS_ERR(child))
> -			return PTR_ERR(child);
> -	}
> -
> -	return 0;
> -}
> -
> -/*----------------------------------------------------------------------*/
> -
>  /*
>   * These three functions initialize the on-chip clock framework,
>   * letting it generate the right frequencies for USB, MADC, and
> @@ -1000,8 +633,7 @@ static inline int __init unprotect_pm_master(void)
>  	return e;
>  }
>  
> -static void clocks_init(struct device *dev,
> -			struct twl4030_clock_init_data *clock)
> +static void clocks_init(struct device *dev)
>  {
>  	int e = 0;
>  	struct clk *osc;
> @@ -1031,8 +663,6 @@ static void clocks_init(struct device *dev,
>  	}
>  
>  	ctrl |= HIGH_PERF_SQ;
> -	if (clock && clock->ck32k_lowpwr_enable)
> -		ctrl |= CK32K_LOWPWR_EN;
>  
>  	e |= unprotect_pm_master();
>  	/* effect->MADC+USB ck en */
> @@ -1071,16 +701,10 @@ static int twl_remove(struct i2c_client *client)
>  	return 0;
>  }
>  
> -static struct of_dev_auxdata twl_auxdata_lookup[] = {
> -	OF_DEV_AUXDATA("ti,twl4030-gpio", 0, "twl4030-gpio", NULL),
> -	{ /* sentinel */ },
> -};
> -
>  /* NOTE: This driver only handles a single twl4030/tps659x0 chip */
>  static int
>  twl_probe(struct i2c_client *client, const struct i2c_device_id *id)
>  {
> -	struct twl4030_platform_data	*pdata = dev_get_platdata(&client->dev);
>  	struct device_node		*node = client->dev.of_node;
>  	struct platform_device		*pdev;
>  	const struct regmap_config	*twl_regmap_config;
> @@ -1088,8 +712,8 @@ twl_probe(struct i2c_client *client, const struct i2c_device_id *id)
>  	int				status;
>  	unsigned			i, num_slaves;
>  
> -	if (!node && !pdata) {
> -		dev_err(&client->dev, "no platform data\n");
> +	if (!node) {
> +		dev_err(&client->dev, "no DT info\n");
>  		return -EINVAL;
>  	}
>  
> @@ -1177,7 +801,7 @@ twl_probe(struct i2c_client *client, const struct i2c_device_id *id)
>  	twl_priv->ready = true;
>  
>  	/* setup clock framework */
> -	clocks_init(&pdev->dev, pdata ? pdata->clock : NULL);
> +	clocks_init(&pdev->dev);
>  
>  	/* read TWL IDCODE Register */
>  	if (twl_class_is_4030()) {
> @@ -1225,15 +849,6 @@ twl_probe(struct i2c_client *client, const struct i2c_device_id *id)
>  				 TWL4030_DCDC_GLOBAL_CFG);
>  	}
>  
> -	if (node) {
> -		if (pdata)
> -			twl_auxdata_lookup[0].platform_data = pdata->gpio;
> -		status = of_platform_populate(node, NULL, twl_auxdata_lookup,
> -					      &client->dev);
> -	} else {
> -		status = add_children(pdata, irq_base, id->driver_data);
> -	}
> -
>  fail:
>  	if (status < 0)
>  		twl_remove(client);

-- 
Lee Jones
Linaro STMicroelectronics Landing Team Lead
Linaro.org ? Open source software for ARM SoCs
Follow Linaro: Facebook | Twitter | Blog

^ permalink raw reply	[flat|nested] 38+ messages in thread

* Re: [PATCH 2/5] mfd: twl: remove useless header
  2016-11-26 18:13   ` Nicolae Rosia
  (?)
@ 2017-01-03 15:30     ` Lee Jones
  -1 siblings, 0 replies; 38+ messages in thread
From: Lee Jones @ 2017-01-03 15:30 UTC (permalink / raw)
  To: Nicolae Rosia
  Cc: Mark Brown, Rob Herring, Mark Rutland, Tony Lindgren,
	Liam Girdwood, Paul Gortmaker, Graeme Gregory, Baruch Siach,
	linux-omap, linux-arm-kernel, linux-kernel, devicetree

On Sat, 26 Nov 2016, Nicolae Rosia wrote:

> This header has one user, twl-core.c .
> Remove it before it gets more users.

The header is not useless.  It prevents us from having to place
external prototypes into C files.

> Signed-off-by: Nicolae Rosia <Nicolae_Rosia@mentor.com>
> ---
>  drivers/mfd/twl-core.c    |  8 ++++++--
>  drivers/mfd/twl-core.h    | 10 ----------
>  drivers/mfd/twl4030-irq.c |  2 --
>  drivers/mfd/twl6030-irq.c |  2 --
>  4 files changed, 6 insertions(+), 16 deletions(-)
>  delete mode 100644 drivers/mfd/twl-core.h
> 
> diff --git a/drivers/mfd/twl-core.c b/drivers/mfd/twl-core.c
> index 48b0668..e16084e 100644
> --- a/drivers/mfd/twl-core.c
> +++ b/drivers/mfd/twl-core.c
> @@ -52,8 +52,6 @@
>  /* Register descriptions for audio */
>  #include <linux/mfd/twl4030-audio.h>
>  
> -#include "twl-core.h"
> -
>  /*
>   * The TWL4030 "Triton 2" is one of a family of a multi-function "Power
>   * Management and System Companion Device" chips originally designed for
> @@ -150,6 +148,12 @@
>  
>  /*----------------------------------------------------------------------*/
>  
> +int twl6030_init_irq(struct device *dev, int irq_num);
> +int twl6030_exit_irq(void);
> +int twl4030_init_irq(struct device *dev, int irq_num);
> +int twl4030_exit_irq(void);
> +int twl4030_init_chip_irq(const char *chip);
> +
>  /* Structure for each TWL4030/TWL6030 Slave */
>  struct twl_client {
>  	struct i2c_client *client;
> diff --git a/drivers/mfd/twl-core.h b/drivers/mfd/twl-core.h
> deleted file mode 100644
> index 6ff99dc..0000000
> --- a/drivers/mfd/twl-core.h
> +++ /dev/null
> @@ -1,10 +0,0 @@
> -#ifndef __TWL_CORE_H__
> -#define __TWL_CORE_H__
> -
> -extern int twl6030_init_irq(struct device *dev, int irq_num);
> -extern int twl6030_exit_irq(void);
> -extern int twl4030_init_irq(struct device *dev, int irq_num);
> -extern int twl4030_exit_irq(void);
> -extern int twl4030_init_chip_irq(const char *chip);
> -
> -#endif /*  __TWL_CORE_H__ */
> diff --git a/drivers/mfd/twl4030-irq.c b/drivers/mfd/twl4030-irq.c
> index b46c0cf..000c231 100644
> --- a/drivers/mfd/twl4030-irq.c
> +++ b/drivers/mfd/twl4030-irq.c
> @@ -35,8 +35,6 @@
>  #include <linux/irqdomain.h>
>  #include <linux/i2c/twl.h>
>  
> -#include "twl-core.h"
> -
>  /*
>   * TWL4030 IRQ handling has two stages in hardware, and thus in software.
>   * The Primary Interrupt Handler (PIH) stage exposes status bits saying
> diff --git a/drivers/mfd/twl6030-irq.c b/drivers/mfd/twl6030-irq.c
> index 5357450..63eca76 100644
> --- a/drivers/mfd/twl6030-irq.c
> +++ b/drivers/mfd/twl6030-irq.c
> @@ -42,8 +42,6 @@
>  #include <linux/irqdomain.h>
>  #include <linux/of_device.h>
>  
> -#include "twl-core.h"
> -
>  /*
>   * TWL6030 (unlike its predecessors, which had two level interrupt handling)
>   * three interrupt registers INT_STS_A, INT_STS_B and INT_STS_C.

-- 
Lee Jones
Linaro STMicroelectronics Landing Team Lead
Linaro.org │ Open source software for ARM SoCs
Follow Linaro: Facebook | Twitter | Blog

^ permalink raw reply	[flat|nested] 38+ messages in thread

* Re: [PATCH 2/5] mfd: twl: remove useless header
@ 2017-01-03 15:30     ` Lee Jones
  0 siblings, 0 replies; 38+ messages in thread
From: Lee Jones @ 2017-01-03 15:30 UTC (permalink / raw)
  To: Nicolae Rosia
  Cc: Mark Rutland, devicetree, Baruch Siach, Tony Lindgren,
	Liam Girdwood, Rob Herring, linux-kernel, Paul Gortmaker,
	Mark Brown, Graeme Gregory, linux-omap, linux-arm-kernel

On Sat, 26 Nov 2016, Nicolae Rosia wrote:

> This header has one user, twl-core.c .
> Remove it before it gets more users.

The header is not useless.  It prevents us from having to place
external prototypes into C files.

> Signed-off-by: Nicolae Rosia <Nicolae_Rosia@mentor.com>
> ---
>  drivers/mfd/twl-core.c    |  8 ++++++--
>  drivers/mfd/twl-core.h    | 10 ----------
>  drivers/mfd/twl4030-irq.c |  2 --
>  drivers/mfd/twl6030-irq.c |  2 --
>  4 files changed, 6 insertions(+), 16 deletions(-)
>  delete mode 100644 drivers/mfd/twl-core.h
> 
> diff --git a/drivers/mfd/twl-core.c b/drivers/mfd/twl-core.c
> index 48b0668..e16084e 100644
> --- a/drivers/mfd/twl-core.c
> +++ b/drivers/mfd/twl-core.c
> @@ -52,8 +52,6 @@
>  /* Register descriptions for audio */
>  #include <linux/mfd/twl4030-audio.h>
>  
> -#include "twl-core.h"
> -
>  /*
>   * The TWL4030 "Triton 2" is one of a family of a multi-function "Power
>   * Management and System Companion Device" chips originally designed for
> @@ -150,6 +148,12 @@
>  
>  /*----------------------------------------------------------------------*/
>  
> +int twl6030_init_irq(struct device *dev, int irq_num);
> +int twl6030_exit_irq(void);
> +int twl4030_init_irq(struct device *dev, int irq_num);
> +int twl4030_exit_irq(void);
> +int twl4030_init_chip_irq(const char *chip);
> +
>  /* Structure for each TWL4030/TWL6030 Slave */
>  struct twl_client {
>  	struct i2c_client *client;
> diff --git a/drivers/mfd/twl-core.h b/drivers/mfd/twl-core.h
> deleted file mode 100644
> index 6ff99dc..0000000
> --- a/drivers/mfd/twl-core.h
> +++ /dev/null
> @@ -1,10 +0,0 @@
> -#ifndef __TWL_CORE_H__
> -#define __TWL_CORE_H__
> -
> -extern int twl6030_init_irq(struct device *dev, int irq_num);
> -extern int twl6030_exit_irq(void);
> -extern int twl4030_init_irq(struct device *dev, int irq_num);
> -extern int twl4030_exit_irq(void);
> -extern int twl4030_init_chip_irq(const char *chip);
> -
> -#endif /*  __TWL_CORE_H__ */
> diff --git a/drivers/mfd/twl4030-irq.c b/drivers/mfd/twl4030-irq.c
> index b46c0cf..000c231 100644
> --- a/drivers/mfd/twl4030-irq.c
> +++ b/drivers/mfd/twl4030-irq.c
> @@ -35,8 +35,6 @@
>  #include <linux/irqdomain.h>
>  #include <linux/i2c/twl.h>
>  
> -#include "twl-core.h"
> -
>  /*
>   * TWL4030 IRQ handling has two stages in hardware, and thus in software.
>   * The Primary Interrupt Handler (PIH) stage exposes status bits saying
> diff --git a/drivers/mfd/twl6030-irq.c b/drivers/mfd/twl6030-irq.c
> index 5357450..63eca76 100644
> --- a/drivers/mfd/twl6030-irq.c
> +++ b/drivers/mfd/twl6030-irq.c
> @@ -42,8 +42,6 @@
>  #include <linux/irqdomain.h>
>  #include <linux/of_device.h>
>  
> -#include "twl-core.h"
> -
>  /*
>   * TWL6030 (unlike its predecessors, which had two level interrupt handling)
>   * three interrupt registers INT_STS_A, INT_STS_B and INT_STS_C.

-- 
Lee Jones
Linaro STMicroelectronics Landing Team Lead
Linaro.org │ Open source software for ARM SoCs
Follow Linaro: Facebook | Twitter | Blog

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply	[flat|nested] 38+ messages in thread

* [PATCH 2/5] mfd: twl: remove useless header
@ 2017-01-03 15:30     ` Lee Jones
  0 siblings, 0 replies; 38+ messages in thread
From: Lee Jones @ 2017-01-03 15:30 UTC (permalink / raw)
  To: linux-arm-kernel

On Sat, 26 Nov 2016, Nicolae Rosia wrote:

> This header has one user, twl-core.c .
> Remove it before it gets more users.

The header is not useless.  It prevents us from having to place
external prototypes into C files.

> Signed-off-by: Nicolae Rosia <Nicolae_Rosia@mentor.com>
> ---
>  drivers/mfd/twl-core.c    |  8 ++++++--
>  drivers/mfd/twl-core.h    | 10 ----------
>  drivers/mfd/twl4030-irq.c |  2 --
>  drivers/mfd/twl6030-irq.c |  2 --
>  4 files changed, 6 insertions(+), 16 deletions(-)
>  delete mode 100644 drivers/mfd/twl-core.h
> 
> diff --git a/drivers/mfd/twl-core.c b/drivers/mfd/twl-core.c
> index 48b0668..e16084e 100644
> --- a/drivers/mfd/twl-core.c
> +++ b/drivers/mfd/twl-core.c
> @@ -52,8 +52,6 @@
>  /* Register descriptions for audio */
>  #include <linux/mfd/twl4030-audio.h>
>  
> -#include "twl-core.h"
> -
>  /*
>   * The TWL4030 "Triton 2" is one of a family of a multi-function "Power
>   * Management and System Companion Device" chips originally designed for
> @@ -150,6 +148,12 @@
>  
>  /*----------------------------------------------------------------------*/
>  
> +int twl6030_init_irq(struct device *dev, int irq_num);
> +int twl6030_exit_irq(void);
> +int twl4030_init_irq(struct device *dev, int irq_num);
> +int twl4030_exit_irq(void);
> +int twl4030_init_chip_irq(const char *chip);
> +
>  /* Structure for each TWL4030/TWL6030 Slave */
>  struct twl_client {
>  	struct i2c_client *client;
> diff --git a/drivers/mfd/twl-core.h b/drivers/mfd/twl-core.h
> deleted file mode 100644
> index 6ff99dc..0000000
> --- a/drivers/mfd/twl-core.h
> +++ /dev/null
> @@ -1,10 +0,0 @@
> -#ifndef __TWL_CORE_H__
> -#define __TWL_CORE_H__
> -
> -extern int twl6030_init_irq(struct device *dev, int irq_num);
> -extern int twl6030_exit_irq(void);
> -extern int twl4030_init_irq(struct device *dev, int irq_num);
> -extern int twl4030_exit_irq(void);
> -extern int twl4030_init_chip_irq(const char *chip);
> -
> -#endif /*  __TWL_CORE_H__ */
> diff --git a/drivers/mfd/twl4030-irq.c b/drivers/mfd/twl4030-irq.c
> index b46c0cf..000c231 100644
> --- a/drivers/mfd/twl4030-irq.c
> +++ b/drivers/mfd/twl4030-irq.c
> @@ -35,8 +35,6 @@
>  #include <linux/irqdomain.h>
>  #include <linux/i2c/twl.h>
>  
> -#include "twl-core.h"
> -
>  /*
>   * TWL4030 IRQ handling has two stages in hardware, and thus in software.
>   * The Primary Interrupt Handler (PIH) stage exposes status bits saying
> diff --git a/drivers/mfd/twl6030-irq.c b/drivers/mfd/twl6030-irq.c
> index 5357450..63eca76 100644
> --- a/drivers/mfd/twl6030-irq.c
> +++ b/drivers/mfd/twl6030-irq.c
> @@ -42,8 +42,6 @@
>  #include <linux/irqdomain.h>
>  #include <linux/of_device.h>
>  
> -#include "twl-core.h"
> -
>  /*
>   * TWL6030 (unlike its predecessors, which had two level interrupt handling)
>   * three interrupt registers INT_STS_A, INT_STS_B and INT_STS_C.

-- 
Lee Jones
Linaro STMicroelectronics Landing Team Lead
Linaro.org ? Open source software for ARM SoCs
Follow Linaro: Facebook | Twitter | Blog

^ permalink raw reply	[flat|nested] 38+ messages in thread

* Re: [PATCH 3/5] mfd: twl: move structure definitions to a public header
  2016-11-26 18:13   ` Nicolae Rosia
  (?)
@ 2017-01-03 15:40     ` Lee Jones
  -1 siblings, 0 replies; 38+ messages in thread
From: Lee Jones @ 2017-01-03 15:40 UTC (permalink / raw)
  To: Nicolae Rosia
  Cc: Mark Brown, Rob Herring, Mark Rutland, Tony Lindgren,
	Liam Girdwood, Paul Gortmaker, Graeme Gregory, Baruch Siach,
	linux-omap, linux-arm-kernel, linux-kernel, devicetree

On Sat, 26 Nov 2016, Nicolae Rosia wrote:

> We want to get rid of exported symbols and have
> the child devices use structure members directly.
> Move the structure definitions to header and set
> drvdata so child devices can access it.

  < Please use all 75 chars allocated to the commitlog before line wrapping >

> Signed-off-by: Nicolae Rosia <Nicolae_Rosia@mentor.com>
> ---
>  drivers/mfd/twl-core.c       | 27 ++++-----------------------
>  include/linux/mfd/twl-core.h | 35 +++++++++++++++++++++++++++++++++++
>  2 files changed, 39 insertions(+), 23 deletions(-)
>  create mode 100644 include/linux/mfd/twl-core.h
> 
> diff --git a/drivers/mfd/twl-core.c b/drivers/mfd/twl-core.c
> index e16084e..409b836 100644
> --- a/drivers/mfd/twl-core.c
> +++ b/drivers/mfd/twl-core.c
> @@ -48,6 +48,7 @@
>  
>  #include <linux/i2c.h>
>  #include <linux/i2c/twl.h>
> +#include <linux/mfd/twl-core.h>
>  
>  /* Register descriptions for audio */
>  #include <linux/mfd/twl4030-audio.h>
> @@ -154,28 +155,7 @@ int twl4030_init_irq(struct device *dev, int irq_num);
>  int twl4030_exit_irq(void);
>  int twl4030_init_chip_irq(const char *chip);
>  
> -/* Structure for each TWL4030/TWL6030 Slave */
> -struct twl_client {
> -	struct i2c_client *client;
> -	struct regmap *regmap;
> -};
> -
> -/* mapping the module id to slave id and base address */
> -struct twl_mapping {
> -	unsigned char sid;	/* Slave ID */
> -	unsigned char base;	/* base address */
> -};
> -
> -struct twl_private {
> -	bool ready; /* The core driver is ready to be used */
> -	u32 twl_idcode; /* TWL IDCODE Register value */
> -	unsigned int twl_id;
> -
> -	struct twl_mapping *twl_map;
> -	struct twl_client *twl_modules;
> -};
> -
> -static struct twl_private *twl_priv;
> +static struct twlcore *twl_priv;

I'm guessing when you remove the exported functions, you can remove this?

>  static struct twl_mapping twl4030_map[] = {
>  	/*
> @@ -745,7 +725,7 @@ twl_probe(struct i2c_client *client, const struct i2c_device_id *id)
>  		goto free;
>  	}
>  
> -	twl_priv = devm_kzalloc(&client->dev, sizeof(struct twl_private),
> +	twl_priv = devm_kzalloc(&client->dev, sizeof(struct twlcore),
>  				GFP_KERNEL);
>  	if (!twl_priv) {
>  		status = -ENOMEM;
> @@ -803,6 +783,7 @@ twl_probe(struct i2c_client *client, const struct i2c_device_id *id)
>  	}
>  
>  	twl_priv->ready = true;
> +	dev_set_drvdata(&client->dev, twl_priv);
>  
>  	/* setup clock framework */
>  	clocks_init(&pdev->dev);
> diff --git a/include/linux/mfd/twl-core.h b/include/linux/mfd/twl-core.h
> new file mode 100644
> index 0000000..d1c01b3
> --- /dev/null
> +++ b/include/linux/mfd/twl-core.h
> @@ -0,0 +1,35 @@
> +/*
> + * MFD core driver for the Texas Instruments TWL PMIC family
> + *
> + * Copyright (C) 2016 Nicolae Rosia <nicolae.rosia@gmail.com>

Your sign-off and SoB are different?  Why?

> + * 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.
> + */
> +
> +#ifndef __TWL_CORE_H__
> +#define __TWL_CORE_H__

_MFD_

> +/* Structure for each TWL4030/TWL6030 Slave */
> +struct twl_client {
> +	struct i2c_client *client;
> +	struct regmap *regmap;
> +};
> +
> +/* mapping the module id to slave id and base address */
> +struct twl_mapping {
> +	unsigned char sid; /* Slave ID */
> +	unsigned char base; /* base address */
> +};
> +
> +struct twlcore {
> +	bool ready; /* The core driver is ready to be used */
> +	u32 twl_idcode; /* TWL IDCODE Register value */
> +	unsigned int twl_id;
> +
> +	struct twl_mapping *twl_map;
> +	struct twl_client *twl_modules;
> +};
> +
> +#endif

-- 
Lee Jones
Linaro STMicroelectronics Landing Team Lead
Linaro.org │ Open source software for ARM SoCs
Follow Linaro: Facebook | Twitter | Blog

^ permalink raw reply	[flat|nested] 38+ messages in thread

* Re: [PATCH 3/5] mfd: twl: move structure definitions to a public header
@ 2017-01-03 15:40     ` Lee Jones
  0 siblings, 0 replies; 38+ messages in thread
From: Lee Jones @ 2017-01-03 15:40 UTC (permalink / raw)
  To: Nicolae Rosia
  Cc: Mark Rutland, devicetree, Baruch Siach, Tony Lindgren,
	Liam Girdwood, Rob Herring, linux-kernel, Paul Gortmaker,
	Mark Brown, Graeme Gregory, linux-omap, linux-arm-kernel

On Sat, 26 Nov 2016, Nicolae Rosia wrote:

> We want to get rid of exported symbols and have
> the child devices use structure members directly.
> Move the structure definitions to header and set
> drvdata so child devices can access it.

  < Please use all 75 chars allocated to the commitlog before line wrapping >

> Signed-off-by: Nicolae Rosia <Nicolae_Rosia@mentor.com>
> ---
>  drivers/mfd/twl-core.c       | 27 ++++-----------------------
>  include/linux/mfd/twl-core.h | 35 +++++++++++++++++++++++++++++++++++
>  2 files changed, 39 insertions(+), 23 deletions(-)
>  create mode 100644 include/linux/mfd/twl-core.h
> 
> diff --git a/drivers/mfd/twl-core.c b/drivers/mfd/twl-core.c
> index e16084e..409b836 100644
> --- a/drivers/mfd/twl-core.c
> +++ b/drivers/mfd/twl-core.c
> @@ -48,6 +48,7 @@
>  
>  #include <linux/i2c.h>
>  #include <linux/i2c/twl.h>
> +#include <linux/mfd/twl-core.h>
>  
>  /* Register descriptions for audio */
>  #include <linux/mfd/twl4030-audio.h>
> @@ -154,28 +155,7 @@ int twl4030_init_irq(struct device *dev, int irq_num);
>  int twl4030_exit_irq(void);
>  int twl4030_init_chip_irq(const char *chip);
>  
> -/* Structure for each TWL4030/TWL6030 Slave */
> -struct twl_client {
> -	struct i2c_client *client;
> -	struct regmap *regmap;
> -};
> -
> -/* mapping the module id to slave id and base address */
> -struct twl_mapping {
> -	unsigned char sid;	/* Slave ID */
> -	unsigned char base;	/* base address */
> -};
> -
> -struct twl_private {
> -	bool ready; /* The core driver is ready to be used */
> -	u32 twl_idcode; /* TWL IDCODE Register value */
> -	unsigned int twl_id;
> -
> -	struct twl_mapping *twl_map;
> -	struct twl_client *twl_modules;
> -};
> -
> -static struct twl_private *twl_priv;
> +static struct twlcore *twl_priv;

I'm guessing when you remove the exported functions, you can remove this?

>  static struct twl_mapping twl4030_map[] = {
>  	/*
> @@ -745,7 +725,7 @@ twl_probe(struct i2c_client *client, const struct i2c_device_id *id)
>  		goto free;
>  	}
>  
> -	twl_priv = devm_kzalloc(&client->dev, sizeof(struct twl_private),
> +	twl_priv = devm_kzalloc(&client->dev, sizeof(struct twlcore),
>  				GFP_KERNEL);
>  	if (!twl_priv) {
>  		status = -ENOMEM;
> @@ -803,6 +783,7 @@ twl_probe(struct i2c_client *client, const struct i2c_device_id *id)
>  	}
>  
>  	twl_priv->ready = true;
> +	dev_set_drvdata(&client->dev, twl_priv);
>  
>  	/* setup clock framework */
>  	clocks_init(&pdev->dev);
> diff --git a/include/linux/mfd/twl-core.h b/include/linux/mfd/twl-core.h
> new file mode 100644
> index 0000000..d1c01b3
> --- /dev/null
> +++ b/include/linux/mfd/twl-core.h
> @@ -0,0 +1,35 @@
> +/*
> + * MFD core driver for the Texas Instruments TWL PMIC family
> + *
> + * Copyright (C) 2016 Nicolae Rosia <nicolae.rosia@gmail.com>

Your sign-off and SoB are different?  Why?

> + * 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.
> + */
> +
> +#ifndef __TWL_CORE_H__
> +#define __TWL_CORE_H__

_MFD_

> +/* Structure for each TWL4030/TWL6030 Slave */
> +struct twl_client {
> +	struct i2c_client *client;
> +	struct regmap *regmap;
> +};
> +
> +/* mapping the module id to slave id and base address */
> +struct twl_mapping {
> +	unsigned char sid; /* Slave ID */
> +	unsigned char base; /* base address */
> +};
> +
> +struct twlcore {
> +	bool ready; /* The core driver is ready to be used */
> +	u32 twl_idcode; /* TWL IDCODE Register value */
> +	unsigned int twl_id;
> +
> +	struct twl_mapping *twl_map;
> +	struct twl_client *twl_modules;
> +};
> +
> +#endif

-- 
Lee Jones
Linaro STMicroelectronics Landing Team Lead
Linaro.org │ Open source software for ARM SoCs
Follow Linaro: Facebook | Twitter | Blog

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply	[flat|nested] 38+ messages in thread

* [PATCH 3/5] mfd: twl: move structure definitions to a public header
@ 2017-01-03 15:40     ` Lee Jones
  0 siblings, 0 replies; 38+ messages in thread
From: Lee Jones @ 2017-01-03 15:40 UTC (permalink / raw)
  To: linux-arm-kernel

On Sat, 26 Nov 2016, Nicolae Rosia wrote:

> We want to get rid of exported symbols and have
> the child devices use structure members directly.
> Move the structure definitions to header and set
> drvdata so child devices can access it.

  < Please use all 75 chars allocated to the commitlog before line wrapping >

> Signed-off-by: Nicolae Rosia <Nicolae_Rosia@mentor.com>
> ---
>  drivers/mfd/twl-core.c       | 27 ++++-----------------------
>  include/linux/mfd/twl-core.h | 35 +++++++++++++++++++++++++++++++++++
>  2 files changed, 39 insertions(+), 23 deletions(-)
>  create mode 100644 include/linux/mfd/twl-core.h
> 
> diff --git a/drivers/mfd/twl-core.c b/drivers/mfd/twl-core.c
> index e16084e..409b836 100644
> --- a/drivers/mfd/twl-core.c
> +++ b/drivers/mfd/twl-core.c
> @@ -48,6 +48,7 @@
>  
>  #include <linux/i2c.h>
>  #include <linux/i2c/twl.h>
> +#include <linux/mfd/twl-core.h>
>  
>  /* Register descriptions for audio */
>  #include <linux/mfd/twl4030-audio.h>
> @@ -154,28 +155,7 @@ int twl4030_init_irq(struct device *dev, int irq_num);
>  int twl4030_exit_irq(void);
>  int twl4030_init_chip_irq(const char *chip);
>  
> -/* Structure for each TWL4030/TWL6030 Slave */
> -struct twl_client {
> -	struct i2c_client *client;
> -	struct regmap *regmap;
> -};
> -
> -/* mapping the module id to slave id and base address */
> -struct twl_mapping {
> -	unsigned char sid;	/* Slave ID */
> -	unsigned char base;	/* base address */
> -};
> -
> -struct twl_private {
> -	bool ready; /* The core driver is ready to be used */
> -	u32 twl_idcode; /* TWL IDCODE Register value */
> -	unsigned int twl_id;
> -
> -	struct twl_mapping *twl_map;
> -	struct twl_client *twl_modules;
> -};
> -
> -static struct twl_private *twl_priv;
> +static struct twlcore *twl_priv;

I'm guessing when you remove the exported functions, you can remove this?

>  static struct twl_mapping twl4030_map[] = {
>  	/*
> @@ -745,7 +725,7 @@ twl_probe(struct i2c_client *client, const struct i2c_device_id *id)
>  		goto free;
>  	}
>  
> -	twl_priv = devm_kzalloc(&client->dev, sizeof(struct twl_private),
> +	twl_priv = devm_kzalloc(&client->dev, sizeof(struct twlcore),
>  				GFP_KERNEL);
>  	if (!twl_priv) {
>  		status = -ENOMEM;
> @@ -803,6 +783,7 @@ twl_probe(struct i2c_client *client, const struct i2c_device_id *id)
>  	}
>  
>  	twl_priv->ready = true;
> +	dev_set_drvdata(&client->dev, twl_priv);
>  
>  	/* setup clock framework */
>  	clocks_init(&pdev->dev);
> diff --git a/include/linux/mfd/twl-core.h b/include/linux/mfd/twl-core.h
> new file mode 100644
> index 0000000..d1c01b3
> --- /dev/null
> +++ b/include/linux/mfd/twl-core.h
> @@ -0,0 +1,35 @@
> +/*
> + * MFD core driver for the Texas Instruments TWL PMIC family
> + *
> + * Copyright (C) 2016 Nicolae Rosia <nicolae.rosia@gmail.com>

Your sign-off and SoB are different?  Why?

> + * 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.
> + */
> +
> +#ifndef __TWL_CORE_H__
> +#define __TWL_CORE_H__

_MFD_

> +/* Structure for each TWL4030/TWL6030 Slave */
> +struct twl_client {
> +	struct i2c_client *client;
> +	struct regmap *regmap;
> +};
> +
> +/* mapping the module id to slave id and base address */
> +struct twl_mapping {
> +	unsigned char sid; /* Slave ID */
> +	unsigned char base; /* base address */
> +};
> +
> +struct twlcore {
> +	bool ready; /* The core driver is ready to be used */
> +	u32 twl_idcode; /* TWL IDCODE Register value */
> +	unsigned int twl_id;
> +
> +	struct twl_mapping *twl_map;
> +	struct twl_client *twl_modules;
> +};
> +
> +#endif

-- 
Lee Jones
Linaro STMicroelectronics Landing Team Lead
Linaro.org ? Open source software for ARM SoCs
Follow Linaro: Facebook | Twitter | Blog

^ permalink raw reply	[flat|nested] 38+ messages in thread

* Re: [PATCH 5/5] mfd: twl: use mfd_add_devices for TWL6032 regulator
  2016-11-26 18:13   ` Nicolae Rosia
  (?)
@ 2017-01-03 15:46     ` Lee Jones
  -1 siblings, 0 replies; 38+ messages in thread
From: Lee Jones @ 2017-01-03 15:46 UTC (permalink / raw)
  To: Nicolae Rosia
  Cc: Mark Brown, Rob Herring, Mark Rutland, Tony Lindgren,
	Liam Girdwood, Paul Gortmaker, Graeme Gregory, Baruch Siach,
	linux-omap, linux-arm-kernel, linux-kernel, devicetree

On Sat, 26 Nov 2016, Nicolae Rosia wrote:

> TWL6032 regulator driver uses the drvdata twl_priv pointer.
> In order to avoid accessing an invalid drvdata
> when the driver gets unbinded, make sure we remove the
> child devices before deleting the drvdata.

This doesn't really describe the change.

Surely we're really just registering the regulator driver?

The fact that we then remove the device during .remove() is
incidental. 

> Signed-off-by: Nicolae Rosia <Nicolae_Rosia@mentor.com>
> ---
>  drivers/mfd/twl-core.c | 22 ++++++++++++++++++++++
>  1 file changed, 22 insertions(+)
> 
> diff --git a/drivers/mfd/twl-core.c b/drivers/mfd/twl-core.c
> index 409b836..1e94364 100644
> --- a/drivers/mfd/twl-core.c
> +++ b/drivers/mfd/twl-core.c
> @@ -43,6 +43,7 @@
>  #include <linux/of_platform.h>
>  #include <linux/irq.h>
>  #include <linux/irqdomain.h>
> +#include <linux/mfd/core.h>
>  
>  #include <linux/regulator/machine.h>
>  
> @@ -155,8 +156,16 @@ int twl4030_init_irq(struct device *dev, int irq_num);
>  int twl4030_exit_irq(void);
>  int twl4030_init_chip_irq(const char *chip);
>  
> +

?

>  static struct twlcore *twl_priv;
>  
> +static struct mfd_cell twl6032_devs[] = {
> +	{
> +		.name = "twl6032-regulator",
> +		.of_compatible = "ti,twl6032-regulator",
> +	},
> +};
> +
>  static struct twl_mapping twl4030_map[] = {
>  	/*
>  	 * NOTE:  don't change this table without updating the
> @@ -665,6 +674,8 @@ static int twl_remove(struct i2c_client *client)
>  	unsigned i, num_slaves;
>  	int status;
>  
> +	mfd_remove_devices(&client->dev);
> +
>  	if (twl_class_is_4030())
>  		status = twl4030_exit_irq();
>  	else
> @@ -834,6 +845,17 @@ twl_probe(struct i2c_client *client, const struct i2c_device_id *id)
>  				 TWL4030_DCDC_GLOBAL_CFG);
>  	}
>  
> +	if (id->driver_data & TWL6032_SUBCLASS) {
> +		status = mfd_add_devices(&client->dev, PLATFORM_DEVID_NONE,
> +					 twl6032_devs, ARRAY_SIZE(twl6032_devs),
> +					 NULL, 0, NULL);
> +		if (status != 0) {
> +			dev_err(&client->dev, "failed to add mfd devices: %d\n",
> +				status);
> +			goto fail;
> +		}
> +	}
> +
>  fail:
>  	if (status < 0)
>  		twl_remove(client);

-- 
Lee Jones
Linaro STMicroelectronics Landing Team Lead
Linaro.org │ Open source software for ARM SoCs
Follow Linaro: Facebook | Twitter | Blog

^ permalink raw reply	[flat|nested] 38+ messages in thread

* Re: [PATCH 5/5] mfd: twl: use mfd_add_devices for TWL6032 regulator
@ 2017-01-03 15:46     ` Lee Jones
  0 siblings, 0 replies; 38+ messages in thread
From: Lee Jones @ 2017-01-03 15:46 UTC (permalink / raw)
  To: Nicolae Rosia
  Cc: Mark Rutland, devicetree, Baruch Siach, Tony Lindgren,
	Liam Girdwood, Rob Herring, linux-kernel, Paul Gortmaker,
	Mark Brown, Graeme Gregory, linux-omap, linux-arm-kernel

On Sat, 26 Nov 2016, Nicolae Rosia wrote:

> TWL6032 regulator driver uses the drvdata twl_priv pointer.
> In order to avoid accessing an invalid drvdata
> when the driver gets unbinded, make sure we remove the
> child devices before deleting the drvdata.

This doesn't really describe the change.

Surely we're really just registering the regulator driver?

The fact that we then remove the device during .remove() is
incidental. 

> Signed-off-by: Nicolae Rosia <Nicolae_Rosia@mentor.com>
> ---
>  drivers/mfd/twl-core.c | 22 ++++++++++++++++++++++
>  1 file changed, 22 insertions(+)
> 
> diff --git a/drivers/mfd/twl-core.c b/drivers/mfd/twl-core.c
> index 409b836..1e94364 100644
> --- a/drivers/mfd/twl-core.c
> +++ b/drivers/mfd/twl-core.c
> @@ -43,6 +43,7 @@
>  #include <linux/of_platform.h>
>  #include <linux/irq.h>
>  #include <linux/irqdomain.h>
> +#include <linux/mfd/core.h>
>  
>  #include <linux/regulator/machine.h>
>  
> @@ -155,8 +156,16 @@ int twl4030_init_irq(struct device *dev, int irq_num);
>  int twl4030_exit_irq(void);
>  int twl4030_init_chip_irq(const char *chip);
>  
> +

?

>  static struct twlcore *twl_priv;
>  
> +static struct mfd_cell twl6032_devs[] = {
> +	{
> +		.name = "twl6032-regulator",
> +		.of_compatible = "ti,twl6032-regulator",
> +	},
> +};
> +
>  static struct twl_mapping twl4030_map[] = {
>  	/*
>  	 * NOTE:  don't change this table without updating the
> @@ -665,6 +674,8 @@ static int twl_remove(struct i2c_client *client)
>  	unsigned i, num_slaves;
>  	int status;
>  
> +	mfd_remove_devices(&client->dev);
> +
>  	if (twl_class_is_4030())
>  		status = twl4030_exit_irq();
>  	else
> @@ -834,6 +845,17 @@ twl_probe(struct i2c_client *client, const struct i2c_device_id *id)
>  				 TWL4030_DCDC_GLOBAL_CFG);
>  	}
>  
> +	if (id->driver_data & TWL6032_SUBCLASS) {
> +		status = mfd_add_devices(&client->dev, PLATFORM_DEVID_NONE,
> +					 twl6032_devs, ARRAY_SIZE(twl6032_devs),
> +					 NULL, 0, NULL);
> +		if (status != 0) {
> +			dev_err(&client->dev, "failed to add mfd devices: %d\n",
> +				status);
> +			goto fail;
> +		}
> +	}
> +
>  fail:
>  	if (status < 0)
>  		twl_remove(client);

-- 
Lee Jones
Linaro STMicroelectronics Landing Team Lead
Linaro.org │ Open source software for ARM SoCs
Follow Linaro: Facebook | Twitter | Blog

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply	[flat|nested] 38+ messages in thread

* [PATCH 5/5] mfd: twl: use mfd_add_devices for TWL6032 regulator
@ 2017-01-03 15:46     ` Lee Jones
  0 siblings, 0 replies; 38+ messages in thread
From: Lee Jones @ 2017-01-03 15:46 UTC (permalink / raw)
  To: linux-arm-kernel

On Sat, 26 Nov 2016, Nicolae Rosia wrote:

> TWL6032 regulator driver uses the drvdata twl_priv pointer.
> In order to avoid accessing an invalid drvdata
> when the driver gets unbinded, make sure we remove the
> child devices before deleting the drvdata.

This doesn't really describe the change.

Surely we're really just registering the regulator driver?

The fact that we then remove the device during .remove() is
incidental. 

> Signed-off-by: Nicolae Rosia <Nicolae_Rosia@mentor.com>
> ---
>  drivers/mfd/twl-core.c | 22 ++++++++++++++++++++++
>  1 file changed, 22 insertions(+)
> 
> diff --git a/drivers/mfd/twl-core.c b/drivers/mfd/twl-core.c
> index 409b836..1e94364 100644
> --- a/drivers/mfd/twl-core.c
> +++ b/drivers/mfd/twl-core.c
> @@ -43,6 +43,7 @@
>  #include <linux/of_platform.h>
>  #include <linux/irq.h>
>  #include <linux/irqdomain.h>
> +#include <linux/mfd/core.h>
>  
>  #include <linux/regulator/machine.h>
>  
> @@ -155,8 +156,16 @@ int twl4030_init_irq(struct device *dev, int irq_num);
>  int twl4030_exit_irq(void);
>  int twl4030_init_chip_irq(const char *chip);
>  
> +

?

>  static struct twlcore *twl_priv;
>  
> +static struct mfd_cell twl6032_devs[] = {
> +	{
> +		.name = "twl6032-regulator",
> +		.of_compatible = "ti,twl6032-regulator",
> +	},
> +};
> +
>  static struct twl_mapping twl4030_map[] = {
>  	/*
>  	 * NOTE:  don't change this table without updating the
> @@ -665,6 +674,8 @@ static int twl_remove(struct i2c_client *client)
>  	unsigned i, num_slaves;
>  	int status;
>  
> +	mfd_remove_devices(&client->dev);
> +
>  	if (twl_class_is_4030())
>  		status = twl4030_exit_irq();
>  	else
> @@ -834,6 +845,17 @@ twl_probe(struct i2c_client *client, const struct i2c_device_id *id)
>  				 TWL4030_DCDC_GLOBAL_CFG);
>  	}
>  
> +	if (id->driver_data & TWL6032_SUBCLASS) {
> +		status = mfd_add_devices(&client->dev, PLATFORM_DEVID_NONE,
> +					 twl6032_devs, ARRAY_SIZE(twl6032_devs),
> +					 NULL, 0, NULL);
> +		if (status != 0) {
> +			dev_err(&client->dev, "failed to add mfd devices: %d\n",
> +				status);
> +			goto fail;
> +		}
> +	}
> +
>  fail:
>  	if (status < 0)
>  		twl_remove(client);

-- 
Lee Jones
Linaro STMicroelectronics Landing Team Lead
Linaro.org ? Open source software for ARM SoCs
Follow Linaro: Facebook | Twitter | Blog

^ permalink raw reply	[flat|nested] 38+ messages in thread

end of thread, other threads:[~2017-01-03 15:46 UTC | newest]

Thread overview: 38+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2016-11-26 18:13 [PATCH 0/5] mfd: twl: improvements and new regulator driver Nicolae Rosia
2016-11-26 18:13 ` Nicolae Rosia
2016-11-26 18:13 ` Nicolae Rosia
2016-11-26 18:13 ` [PATCH 1/5] mfd: twl-core: make driver DT only Nicolae Rosia
2016-11-26 18:13   ` Nicolae Rosia
2016-11-26 18:13   ` Nicolae Rosia
2017-01-03 15:00   ` Lee Jones
2017-01-03 15:00     ` Lee Jones
2017-01-03 15:00     ` Lee Jones
2016-11-26 18:13 ` [PATCH 2/5] mfd: twl: remove useless header Nicolae Rosia
2016-11-26 18:13   ` Nicolae Rosia
2016-11-26 18:13   ` Nicolae Rosia
2017-01-03 15:30   ` Lee Jones
2017-01-03 15:30     ` Lee Jones
2017-01-03 15:30     ` Lee Jones
2016-11-26 18:13 ` [PATCH 3/5] mfd: twl: move structure definitions to a public header Nicolae Rosia
2016-11-26 18:13   ` Nicolae Rosia
2016-11-26 18:13   ` Nicolae Rosia
2017-01-03 15:40   ` Lee Jones
2017-01-03 15:40     ` Lee Jones
2017-01-03 15:40     ` Lee Jones
2016-11-26 18:13 ` [PATCH 4/5] regulator: Add support for TI TWL6032 Nicolae Rosia
2016-11-26 18:13   ` Nicolae Rosia
2016-11-26 18:13   ` Nicolae Rosia
2016-11-26 18:55   ` kbuild test robot
2016-11-26 18:55     ` kbuild test robot
2016-11-26 18:55     ` kbuild test robot
2016-11-26 20:24     ` Rosia, Nicolae
2016-11-26 20:24       ` Rosia, Nicolae
2016-11-26 20:24       ` Rosia, Nicolae
2016-12-01 16:10   ` Rob Herring
2016-12-01 16:10     ` Rob Herring
2016-11-26 18:13 ` [PATCH 5/5] mfd: twl: use mfd_add_devices for TWL6032 regulator Nicolae Rosia
2016-11-26 18:13   ` Nicolae Rosia
2016-11-26 18:13   ` Nicolae Rosia
2017-01-03 15:46   ` Lee Jones
2017-01-03 15:46     ` Lee Jones
2017-01-03 15:46     ` Lee Jones

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.