Linux-i2c Archive on lore.kernel.org
 help / color / Atom feed
From: Serge Semin <Sergey.Semin@baikalelectronics.ru>
To: Jarkko Nikula <jarkko.nikula@linux.intel.com>,
	Andy Shevchenko <andriy.shevchenko@linux.intel.com>,
	Mika Westerberg <mika.westerberg@linux.intel.com>
Cc: Serge Semin <Sergey.Semin@baikalelectronics.ru>,
	Serge Semin <fancer.lancer@gmail.com>,
	Alexey Malahov <Alexey.Malahov@baikalelectronics.ru>,
	Thomas Bogendoerfer <tsbogend@alpha.franken.de>,
	Paul Burton <paulburton@kernel.org>,
	Ralf Baechle <ralf@linux-mips.org>,
	Rob Herring <robh+dt@kernel.org>,
	Frank Rowand <frowand.list@gmail.com>,
	<linux-mips@vger.kernel.org>, <devicetree@vger.kernel.org>,
	Wolfram Sang <wsa@the-dreams.de>,
	"Rafael J. Wysocki" <rafael.j.wysocki@intel.com>,
	Hanjun Guo <guohanjun@huawei.com>,
	Hans de Goede <hdegoede@redhat.com>,
	<linux-kernel@vger.kernel.org>, <linux-i2c@vger.kernel.org>
Subject: [PATCH v2 08/12] i2c: designware: Introduce platform drivers glue layer interface
Date: Sun, 10 May 2020 12:50:14 +0300
Message-ID: <20200510095019.20981-9-Sergey.Semin@baikalelectronics.ru> (raw)
In-Reply-To: <20200510095019.20981-1-Sergey.Semin@baikalelectronics.ru>

Seeing the DW I2C platform driver is getting overcomplicated with a lot of
vendor-specific configs let's introduce a glue-layer interface so new
platforms which equipped with Synopsys Designware APB I2C IP-core would
be able to handle their peculiarities in the dedicated objects.

The generic platform setups and cleanups can now be performed by means of
two new functions exported from the Dw I2C platform driver:

int i2c_dw_plat_setup(struct dw_i2c_dev *dev);
int i2c_dw_plat_clear(struct dw_i2c_dev *dev);

They also install and remove the I2C controller respectively. In addition
if device supports the PM interface a glue driver can use the generic
platform PM callbacks collected into the PM dev ops structure:

const struct dev_pm_ops i2c_dw_plat_dev_pm_ops;

Before setting the platform DW I2C device up the glue probe code is
supposed to create an instance of `struct dw_i2c_dev` and pre-initialize
its `struct device` pointer together with optional platform-specific
flags. Currently the ACCESS_NO_IRQ_SUSPEND and ACCESS_INTR_MASK flags are
supported.

Note we moved the platform driver private data setup to the generic
platform probe method. By doing so the driver data pointer will be free
to be used by the glue-layer driver.

Suggested-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
Signed-off-by: Serge Semin <Sergey.Semin@baikalelectronics.ru>
Cc: Alexey Malahov <Alexey.Malahov@baikalelectronics.ru>
Cc: Thomas Bogendoerfer <tsbogend@alpha.franken.de>
Cc: Paul Burton <paulburton@kernel.org>
Cc: Ralf Baechle <ralf@linux-mips.org>
Cc: Rob Herring <robh+dt@kernel.org>
Cc: Frank Rowand <frowand.list@gmail.com>
Cc: linux-mips@vger.kernel.org
Cc: devicetree@vger.kernel.org
---
 drivers/i2c/busses/i2c-designware-core.h    |  4 +
 drivers/i2c/busses/i2c-designware-platdrv.c | 84 +++++++++++++--------
 drivers/i2c/busses/i2c-designware-platdrv.h | 16 ++++
 3 files changed, 71 insertions(+), 33 deletions(-)
 create mode 100644 drivers/i2c/busses/i2c-designware-platdrv.h

diff --git a/drivers/i2c/busses/i2c-designware-core.h b/drivers/i2c/busses/i2c-designware-core.h
index b5b981c1bb0d..10606266b30c 100644
--- a/drivers/i2c/busses/i2c-designware-core.h
+++ b/drivers/i2c/busses/i2c-designware-core.h
@@ -8,6 +8,8 @@
  * Copyright (C) 2007 MontaVista Software Inc.
  * Copyright (C) 2009 Provigent Ltd.
  */
+#ifndef __I2C_DESIGNWARE_CORE_H__
+#define __I2C_DESIGNWARE_CORE_H__
 
 #include <linux/i2c.h>
 #include <linux/regmap.h>
@@ -324,3 +326,5 @@ extern int i2c_dw_probe_lock_support(struct dw_i2c_dev *dev);
 #else
 static inline int i2c_dw_probe_lock_support(struct dw_i2c_dev *dev) { return 0; }
 #endif
+
+#endif /* __I2C_DESIGNWARE_CORE_H__ */
diff --git a/drivers/i2c/busses/i2c-designware-platdrv.c b/drivers/i2c/busses/i2c-designware-platdrv.c
index 5536673060cc..274953155569 100644
--- a/drivers/i2c/busses/i2c-designware-platdrv.c
+++ b/drivers/i2c/busses/i2c-designware-platdrv.c
@@ -32,6 +32,7 @@
 #include <linux/suspend.h>
 
 #include "i2c-designware-core.h"
+#include "i2c-designware-platdrv.h"
 
 static u32 i2c_dw_get_clk_rate_khz(struct dw_i2c_dev *dev)
 {
@@ -80,9 +81,9 @@ static void dw_i2c_acpi_params(struct platform_device *pdev, char method[],
 	kfree(buf.pointer);
 }
 
-static int dw_i2c_acpi_configure(struct platform_device *pdev)
+static int dw_i2c_acpi_configure(struct dw_i2c_dev *dev)
 {
-	struct dw_i2c_dev *dev = platform_get_drvdata(pdev);
+	struct platform_device *pdev = to_platform_device(dev->dev);
 	struct i2c_timings *t = &dev->timings;
 	u32 ss_ht = 0, fp_ht = 0, hs_ht = 0, fs_ht = 0;
 
@@ -135,7 +136,7 @@ static const struct acpi_device_id dw_i2c_acpi_match[] = {
 };
 MODULE_DEVICE_TABLE(acpi, dw_i2c_acpi_match);
 #else
-static inline int dw_i2c_acpi_configure(struct platform_device *pdev)
+static inline int dw_i2c_acpi_configure(struct dw_i2c_dev *dev)
 {
 	return -ENODEV;
 }
@@ -154,9 +155,9 @@ static int mscc_twi_set_sda_hold_time(struct dw_i2c_dev *dev)
 	return 0;
 }
 
-static int dw_i2c_of_configure(struct platform_device *pdev)
+static int dw_i2c_of_configure(struct dw_i2c_dev *dev)
 {
-	struct dw_i2c_dev *dev = platform_get_drvdata(pdev);
+	struct platform_device *pdev = to_platform_device(dev->dev);
 	struct resource *mem;
 
 	switch (dev->flags & MODEL_MASK) {
@@ -180,7 +181,7 @@ static const struct of_device_id dw_i2c_of_match[] = {
 };
 MODULE_DEVICE_TABLE(of, dw_i2c_of_match);
 #else
-static inline int dw_i2c_of_configure(struct platform_device *pdev)
+static inline int dw_i2c_of_configure(struct dw_i2c_dev *dev)
 {
 	return -ENODEV;
 }
@@ -234,33 +235,25 @@ static const u32 supported_speeds[] = {
 	I2C_MAX_STANDARD_MODE_FREQ,
 };
 
-static int dw_i2c_plat_probe(struct platform_device *pdev)
+int i2c_dw_plat_setup(struct dw_i2c_dev *dev)
 {
+	struct platform_device *pdev = to_platform_device(dev->dev);
 	struct dw_i2c_platform_data *pdata = dev_get_platdata(&pdev->dev);
 	struct i2c_adapter *adap;
-	struct dw_i2c_dev *dev;
 	struct i2c_timings *t;
 	u32 acpi_speed;
 	struct resource *mem;
-	int i, irq, ret;
+	int i, ret;
 
-	irq = platform_get_irq(pdev, 0);
-	if (irq < 0)
-		return irq;
-
-	dev = devm_kzalloc(&pdev->dev, sizeof(struct dw_i2c_dev), GFP_KERNEL);
-	if (!dev)
-		return -ENOMEM;
+	dev->irq = platform_get_irq(pdev, 0);
+	if (dev->irq < 0)
+		return dev->irq;
 
 	mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 	dev->base = devm_ioremap_resource(&pdev->dev, mem);
 	if (IS_ERR(dev->base))
 		return PTR_ERR(dev->base);
 
-	dev->dev = &pdev->dev;
-	dev->irq = irq;
-	platform_set_drvdata(pdev, dev);
-
 	dev->rst = devm_reset_control_get_optional_exclusive(&pdev->dev, NULL);
 	if (IS_ERR(dev->rst))
 		return PTR_ERR(dev->rst);
@@ -295,13 +288,11 @@ static int dw_i2c_plat_probe(struct platform_device *pdev)
 	else
 		t->bus_freq_hz = I2C_MAX_FAST_MODE_FREQ;
 
-	dev->flags |= (uintptr_t)device_get_match_data(&pdev->dev);
-
 	if (pdev->dev.of_node)
-		dw_i2c_of_configure(pdev);
+		dw_i2c_of_configure(dev);
 
 	if (has_acpi_companion(&pdev->dev))
-		dw_i2c_acpi_configure(pdev);
+		dw_i2c_acpi_configure(dev);
 
 	/*
 	 * Only standard mode at 100kHz, fast mode at 400kHz,
@@ -393,10 +384,11 @@ static int dw_i2c_plat_probe(struct platform_device *pdev)
 	reset_control_assert(dev->rst);
 	return ret;
 }
+EXPORT_SYMBOL_GPL(i2c_dw_plat_setup);
 
-static int dw_i2c_plat_remove(struct platform_device *pdev)
+int i2c_dw_plat_clear(struct dw_i2c_dev *dev)
 {
-	struct dw_i2c_dev *dev = platform_get_drvdata(pdev);
+	struct platform_device *pdev = to_platform_device(dev->dev);
 
 	pm_runtime_get_sync(&pdev->dev);
 
@@ -412,6 +404,29 @@ static int dw_i2c_plat_remove(struct platform_device *pdev)
 
 	return 0;
 }
+EXPORT_SYMBOL_GPL(i2c_dw_plat_clear);
+
+static int dw_i2c_plat_probe(struct platform_device *pdev)
+{
+	struct dw_i2c_dev *dev;
+
+	dev = devm_kzalloc(&pdev->dev, sizeof(*dev), GFP_KERNEL);
+	if (!dev)
+		return -ENOMEM;
+
+	dev->dev = &pdev->dev;
+	dev->flags |= (uintptr_t)device_get_match_data(dev->dev);
+	platform_set_drvdata(pdev, dev);
+
+	return i2c_dw_plat_setup(dev);
+}
+
+static int dw_i2c_plat_remove(struct platform_device *pdev)
+{
+	struct dw_i2c_dev *dev = platform_get_drvdata(pdev);
+
+	return i2c_dw_plat_clear(dev);
+}
 
 #ifdef CONFIG_PM_SLEEP
 static int dw_i2c_plat_prepare(struct device *dev)
@@ -470,17 +485,20 @@ static int dw_i2c_plat_resume(struct device *dev)
 	return 0;
 }
 
-static const struct dev_pm_ops dw_i2c_dev_pm_ops = {
+#else
+
+#define dw_i2c_plat_prepare	NULL
+#define dw_i2c_plat_complete	NULL
+
+#endif
+
+const struct dev_pm_ops i2c_dw_plat_dev_pm_ops = {
 	.prepare = dw_i2c_plat_prepare,
 	.complete = dw_i2c_plat_complete,
 	SET_LATE_SYSTEM_SLEEP_PM_OPS(dw_i2c_plat_suspend, dw_i2c_plat_resume)
 	SET_RUNTIME_PM_OPS(dw_i2c_plat_suspend, dw_i2c_plat_resume, NULL)
 };
-
-#define DW_I2C_DEV_PMOPS (&dw_i2c_dev_pm_ops)
-#else
-#define DW_I2C_DEV_PMOPS NULL
-#endif
+EXPORT_SYMBOL_GPL(i2c_dw_plat_dev_pm_ops);
 
 /* Work with hotplug and coldplug */
 MODULE_ALIAS("platform:i2c_designware");
@@ -492,7 +510,7 @@ static struct platform_driver dw_i2c_driver = {
 		.name	= "i2c_designware",
 		.of_match_table = of_match_ptr(dw_i2c_of_match),
 		.acpi_match_table = ACPI_PTR(dw_i2c_acpi_match),
-		.pm	= DW_I2C_DEV_PMOPS,
+		.pm	= &i2c_dw_plat_dev_pm_ops,
 	},
 };
 
diff --git a/drivers/i2c/busses/i2c-designware-platdrv.h b/drivers/i2c/busses/i2c-designware-platdrv.h
new file mode 100644
index 000000000000..8916c4f61d7f
--- /dev/null
+++ b/drivers/i2c/busses/i2c-designware-platdrv.h
@@ -0,0 +1,16 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ * Synopsys DesignWare I2C adapter driver.
+ */
+#ifndef __I2C_DESIGNWARE_PLATDRV_H__
+#define __I2C_DESIGNWARE_PLATDRV_H__
+
+#include <linux/pm.h>
+
+#include "i2c-designware-core.h"
+
+extern int i2c_dw_plat_setup(struct dw_i2c_dev *dev);
+extern int i2c_dw_plat_clear(struct dw_i2c_dev *dev);
+extern const struct dev_pm_ops i2c_dw_plat_dev_pm_ops;
+
+#endif /* __I2C_DESIGNWARE_PLATDRV_H__ */
-- 
2.25.1


  parent reply index

Thread overview: 38+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2020-03-06 13:19 [PATCH 0/6] i2c: designeware: Add Baikal-T1 SoC DW I2C specifics support Sergey.Semin-UN2wsyeM1qLJ45LvJ/SUn8gurn75+9Lz
2020-03-06 13:54 ` Andy Shevchenko
     [not found] ` <20200306135451.4AF0480307C4@mail.baikalelectronics.ru>
2020-03-31 11:48   ` Sergey Semin
2020-03-31 14:25     ` Andy Shevchenko
     [not found]       ` <20200331142530.GM1922688-XvqNBM/wLWRrdx17CPfAsdBPR1lH4CV8@public.gmane.org>
2020-03-31 16:28         ` Sergey Semin
2020-03-31 17:17           ` Andy Shevchenko
2020-03-31 19:14             ` Sergey Semin
2020-05-10  9:50 ` [PATCH v2 00/12] i2c: designeware: Add Baikal-T1 System I2C support Serge Semin
2020-05-10  9:50   ` [PATCH v2 01/12] scripts/dtc: check: Add 10bit/slave i2c reg flags support Serge Semin
2020-05-10  9:50   ` [PATCH v2 02/12] dt-bindings: i2c: Convert DW I2C binding to DT schema Serge Semin
2020-05-11 16:09     ` Rob Herring
2020-05-11 19:50       ` Serge Semin
2020-05-10  9:50   ` [PATCH v2 03/12] dt-bindings: i2c: dw: Add Baikal-T1 SoC I2C controller Serge Semin
2020-05-18 20:33     ` Rob Herring
2020-05-18 21:39       ` Serge Semin
2020-05-10  9:50   ` [PATCH v2 04/12] i2c: designware: Convert driver to using regmap API Serge Semin
2020-05-20 12:16     ` Jarkko Nikula
2020-05-21  2:02       ` Serge Semin
2020-05-10  9:50   ` [PATCH v2 05/12] i2c: designware: Use `-y` to build multi-object modules Serge Semin
2020-05-20 12:16     ` Jarkko Nikula
2020-05-10  9:50   ` [PATCH v2 06/12] i2c: designware: slave: Set DW I2C core module dependency Serge Semin
2020-05-20 12:15     ` Jarkko Nikula
2020-05-10  9:50   ` [PATCH v2 07/12] i2c: designware: Move Baytrail sem config to the platform if-clause Serge Semin
2020-05-20 12:16     ` Jarkko Nikula
2020-05-21  2:22       ` Serge Semin
2020-05-25 13:01         ` Jarkko Nikula
2020-05-26 18:40           ` Serge Semin
2020-05-10  9:50   ` Serge Semin [this message]
2020-05-20 12:46     ` [PATCH v2 08/12] i2c: designware: Introduce platform drivers glue layer interface Jarkko Nikula
2020-05-21  2:37       ` Serge Semin
2020-05-25 13:16         ` Jarkko Nikula
2020-05-25 13:42           ` Andy Shevchenko
2020-05-26 20:38           ` Serge Semin
2020-05-10  9:50   ` [PATCH v2 09/12] i2c: designware: Unpin Microsemi Ocelot I2C into a glue driver Serge Semin
2020-05-10  9:50   ` [PATCH v2 10/12] i2c: designware: Discard Cherry Trail model flag Serge Semin
2020-05-20 12:17     ` Jarkko Nikula
2020-05-10  9:50   ` [PATCH v2 11/12] i2c: designware: Use provided regmap instead of reg resource Serge Semin
2020-05-10  9:50   ` [PATCH v2 12/12] i2c: designware: Add Baikal-T1 System I2C glue driver Serge Semin

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20200510095019.20981-9-Sergey.Semin@baikalelectronics.ru \
    --to=sergey.semin@baikalelectronics.ru \
    --cc=Alexey.Malahov@baikalelectronics.ru \
    --cc=andriy.shevchenko@linux.intel.com \
    --cc=devicetree@vger.kernel.org \
    --cc=fancer.lancer@gmail.com \
    --cc=frowand.list@gmail.com \
    --cc=guohanjun@huawei.com \
    --cc=hdegoede@redhat.com \
    --cc=jarkko.nikula@linux.intel.com \
    --cc=linux-i2c@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-mips@vger.kernel.org \
    --cc=mika.westerberg@linux.intel.com \
    --cc=paulburton@kernel.org \
    --cc=rafael.j.wysocki@intel.com \
    --cc=ralf@linux-mips.org \
    --cc=robh+dt@kernel.org \
    --cc=tsbogend@alpha.franken.de \
    --cc=wsa@the-dreams.de \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link

Linux-i2c Archive on lore.kernel.org

Archives are clonable:
	git clone --mirror https://lore.kernel.org/linux-i2c/0 linux-i2c/git/0.git

	# If you have public-inbox 1.1+ installed, you may
	# initialize and index your mirror using the following commands:
	public-inbox-init -V2 linux-i2c linux-i2c/ https://lore.kernel.org/linux-i2c \
		linux-i2c@vger.kernel.org
	public-inbox-index linux-i2c

Example config snippet for mirrors

Newsgroup available over NNTP:
	nntp://nntp.lore.kernel.org/org.kernel.vger.linux-i2c


AGPL code for this site: git clone https://public-inbox.org/public-inbox.git