* Re: [PATCH v2 3/3] of: Make of_match_node() an inline stub for CONFIG_OF=n
From: kbuild test robot @ 2017-04-12 18:58 UTC (permalink / raw)
Cc: kbuild-all-JC7UmRfGjtg, linux-kernel-u79uwXL29TY76Z2rM5mHXA,
andrew-g2DYL2Zd6BY,
vivien.didelot-4ysUXcep3aM1wj+D4I0NRVaTQe2KTcn/, Florian Fainelli,
Lee Jones, Nicolas Ferre, Rob Herring, Frank Rowand,
open list:NETWORKING DRIVERS,
open list:OPEN FIRMWARE AND FLATTENED DEVICE TREE
In-Reply-To: <20170412044156.17351-4-f.fainelli-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
[-- Attachment #1: Type: text/plain, Size: 4084 bytes --]
Hi Florian,
[auto build test ERROR on ljones-mfd/for-mfd-next]
[also build test ERROR on v4.11-rc6 next-20170412]
[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/Florian-Fainelli/of-Make-of_match_node-an-inline-stub-for-CONFIG_OF-n/20170412-160916
base: https://git.kernel.org/pub/scm/linux/kernel/git/lee/mfd.git for-mfd-next
config: arm-s3c2410_defconfig (attached as .config)
compiler: arm-linux-gnueabi-gcc (Debian 6.1.1-9) 6.1.1 20160705
reproduce:
wget https://raw.githubusercontent.com/01org/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross
chmod +x ~/bin/make.cross
# save the attached .config to linux build tree
make.cross ARCH=arm
All errors (new ones prefixed by >>):
drivers/i2c/busses/i2c-s3c2410.c: In function 's3c24xx_get_device_quirks':
>> drivers/i2c/busses/i2c-s3c2410.c:174:25: error: 's3c24xx_i2c_match' undeclared (first use in this function)
match = of_match_node(s3c24xx_i2c_match, pdev->dev.of_node);
^~~~~~~~~~~~~~~~~
drivers/i2c/busses/i2c-s3c2410.c:174:25: note: each undeclared identifier is reported only once for each function it appears in
--
drivers/watchdog/s3c2410_wdt.c: In function 's3c2410_get_wdt_drv_data':
>> drivers/watchdog/s3c2410_wdt.c:515:25: error: 's3c2410_wdt_match' undeclared (first use in this function)
match = of_match_node(s3c2410_wdt_match, pdev->dev.of_node);
^~~~~~~~~~~~~~~~~
drivers/watchdog/s3c2410_wdt.c:515:25: note: each undeclared identifier is reported only once for each function it appears in
vim +/s3c24xx_i2c_match +174 drivers/i2c/busses/i2c-s3c2410.c
faf93ff6 Giridhar Maruthy 2013-01-24 158 .data = (void *)(QUIRK_S3C2440 | QUIRK_NO_GPIO) },
117053f7 Vasanth Ananthan 2013-11-11 159 { .compatible = "samsung,exynos5-sata-phy-i2c",
117053f7 Vasanth Ananthan 2013-11-11 160 .data = (void *)(QUIRK_S3C2440 | QUIRK_POLL | QUIRK_NO_GPIO) },
27452498 Karol Lewandowski 2012-04-23 161 {},
27452498 Karol Lewandowski 2012-04-23 162 };
27452498 Karol Lewandowski 2012-04-23 163 MODULE_DEVICE_TABLE(of, s3c24xx_i2c_match);
27452498 Karol Lewandowski 2012-04-23 164 #endif
^1da177e Linus Torvalds 2005-04-16 165
ec7c34a4 Krzysztof Kozlowski 2016-04-21 166 /*
27452498 Karol Lewandowski 2012-04-23 167 * Get controller type either from device tree or platform device variant.
^1da177e Linus Torvalds 2005-04-16 168 */
5f1b1155 Pankaj Dubey 2014-01-15 169 static inline kernel_ulong_t s3c24xx_get_device_quirks(struct platform_device *pdev)
^1da177e Linus Torvalds 2005-04-16 170 {
27452498 Karol Lewandowski 2012-04-23 171 if (pdev->dev.of_node) {
27452498 Karol Lewandowski 2012-04-23 172 const struct of_device_id *match;
0915833b Krzysztof Kozlowski 2016-04-21 173
b900ba4c Karol Lewandowski 2012-05-30 @174 match = of_match_node(s3c24xx_i2c_match, pdev->dev.of_node);
5f1b1155 Pankaj Dubey 2014-01-15 175 return (kernel_ulong_t)match->data;
27452498 Karol Lewandowski 2012-04-23 176 }
5a5f5080 Thomas Abraham 2011-09-13 177
27452498 Karol Lewandowski 2012-04-23 178 return platform_get_device_id(pdev)->driver_data;
^1da177e Linus Torvalds 2005-04-16 179 }
^1da177e Linus Torvalds 2005-04-16 180
ec7c34a4 Krzysztof Kozlowski 2016-04-21 181 /*
ec7c34a4 Krzysztof Kozlowski 2016-04-21 182 * Complete the message and wake up the caller, using the given return code,
:::::: The code at line 174 was first introduced by commit
:::::: b900ba4c1513a8c9a2fab8dca4cc6f50b17d6861 i2c: s3c2410: Fix pointer type passed to of_match_node()
:::::: TO: Karol Lewandowski <k.lewandowsk-Sze3O3UU22JBDgjK7y7TUQ@public.gmane.org>
:::::: CC: Wolfram Sang <w.sang-bIcnvbaLZ9MEGnE8C9+IrQ@public.gmane.org>
---
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: 22646 bytes --]
^ permalink raw reply
* [PATCH v5 8/8] ARM: ux500: Add vendor prefix to tps61052 node
From: Javier Martinez Canillas @ 2017-04-12 17:27 UTC (permalink / raw)
To: linux-kernel-u79uwXL29TY76Z2rM5mHXA
Cc: Aaro Koskinen, devicetree-u79uwXL29TY76Z2rM5mHXA, Rob Herring,
Tony Lindgren, Lee Jones, Javier Martinez Canillas, Mark Rutland,
Russell King, linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r
In-Reply-To: <20170412172800.23035-1-javier-JPH+aEBZ4P+UEJcrhfAQsw@public.gmane.org>
The tps61052 device node doesn't have a vendor prefix
in its compatible string, fix it by adding one.
Signed-off-by: Javier Martinez Canillas <javier-JPH+aEBZ4P+UEJcrhfAQsw@public.gmane.org>
Acked-by: Rob Herring <robh-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org>
Acked-by: Tony Lindgren <tony-4v6yS6AI5VpBDgjK7y7TUQ@public.gmane.org>
---
Changes in v5:
- Add Rob Herring's Acked-by tag.
- Add Acked-by: Tony Lindgren <tony-4v6yS6AI5VpBDgjK7y7TUQ@public.gmane.org>'s Acked-by tag.
Changes in v4: None
Changes in v3: None
Changes in v2: None
arch/arm/boot/dts/ste-hrefprev60.dtsi | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/arch/arm/boot/dts/ste-hrefprev60.dtsi b/arch/arm/boot/dts/ste-hrefprev60.dtsi
index 5882a2606ac3..3f14b4df69b4 100644
--- a/arch/arm/boot/dts/ste-hrefprev60.dtsi
+++ b/arch/arm/boot/dts/ste-hrefprev60.dtsi
@@ -30,7 +30,7 @@
i2c@80004000 {
tps61052@33 {
- compatible = "tps61052";
+ compatible = "ti,tps61052";
reg = <0x33>;
};
--
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
* [PATCH v5 7/8] mfd: tps6105x: Add OF device ID table
From: Javier Martinez Canillas @ 2017-04-12 17:27 UTC (permalink / raw)
To: linux-kernel
Cc: Aaro Koskinen, devicetree, Rob Herring, Tony Lindgren, Lee Jones,
Javier Martinez Canillas
In-Reply-To: <20170412172800.23035-1-javier@osg.samsung.com>
The driver doesn't have a struct of_device_id table but supported devices
are registered via Device Trees. This is working on the assumption that a
I2C device registered via OF will always match a legacy I2C device ID and
that the MODALIAS reported will always be of the form i2c:<device>.
But this could change in the future so the correct approach is to have a
OF device ID table if the devices are registered via OF.
Signed-off-by: Javier Martinez Canillas <javier@osg.samsung.com>
Acked-by: Rob Herring <robh@kernel.org>
Acked-by: Tony Lindgren <tony@atomide.com>
Acked-by: Lee Jones <lee.jones@linaro.org>
---
Changes in v5:
- Add Rob Herring's Acked-by tag.
- Add Acked-by: Tony Lindgren <tony@atomide.com>'s Acked-by tag.
- Add Lee Jones <lee.jones@linaro.org>'s Acked-by tag.
Changes in v4: None
Changes in v3:
- Add a vendor prefix to the compatible string (Rob Herring).
Changes in v2:
- Don't use of_match_ptr() to avoid build warning when CONFIG_OF is disabled.
drivers/mfd/tps6105x.c | 8 ++++++++
1 file changed, 8 insertions(+)
diff --git a/drivers/mfd/tps6105x.c b/drivers/mfd/tps6105x.c
index baa12ea666fb..187848c93779 100644
--- a/drivers/mfd/tps6105x.c
+++ b/drivers/mfd/tps6105x.c
@@ -173,9 +173,17 @@ static const struct i2c_device_id tps6105x_id[] = {
};
MODULE_DEVICE_TABLE(i2c, tps6105x_id);
+static const struct of_device_id tps6105x_of_match[] = {
+ { .compatible = "ti,tps61050" },
+ { .compatible = "ti,tps61052" },
+ { },
+};
+MODULE_DEVICE_TABLE(of, tps6105x_of_match);
+
static struct i2c_driver tps6105x_driver = {
.driver = {
.name = "tps6105x",
+ .of_match_table = tps6105x_of_match,
},
.probe = tps6105x_probe,
.remove = tps6105x_remove,
--
2.9.3
^ permalink raw reply related
* [PATCH v5 6/8] dt-bindings: mfd: Add TI tps6105x chip bindings
From: Javier Martinez Canillas @ 2017-04-12 17:27 UTC (permalink / raw)
To: linux-kernel
Cc: Aaro Koskinen, devicetree, Rob Herring, Tony Lindgren, Lee Jones,
Javier Martinez Canillas, Mark Rutland
In-Reply-To: <20170412172800.23035-1-javier@osg.samsung.com>
There are Device Tree source files defining a device node for the
tps61050/61052 I2C chip but there isn't a binding document for it.
Signed-off-by: Javier Martinez Canillas <javier@osg.samsung.com>
Acked-by: Rob Herring <robh@kernel.org>
Acked-by: Tony Lindgren <tony@atomide.com>
---
Changes in v5:
- Add Rob Herring's Acked-by tag.
- Add Acked-by: Tony Lindgren <tony@atomide.com>'s Acked-by tag.
Changes in v4:
- Use "dt-bindings: mfd:" prefix in subject line (Rob Herring).
- Add information about what functions the device serve (Lee Jones).
Changes in v3: None
Changes in v2: None
Documentation/devicetree/bindings/mfd/tps6105x.txt | 17 +++++++++++++++++
1 file changed, 17 insertions(+)
create mode 100644 Documentation/devicetree/bindings/mfd/tps6105x.txt
diff --git a/Documentation/devicetree/bindings/mfd/tps6105x.txt b/Documentation/devicetree/bindings/mfd/tps6105x.txt
new file mode 100644
index 000000000000..93602c7a19c8
--- /dev/null
+++ b/Documentation/devicetree/bindings/mfd/tps6105x.txt
@@ -0,0 +1,17 @@
+* Device tree bindings for TI TPS61050/61052 Boost Converters
+
+The TP61050/TPS61052 is a high-power "white LED driver". The
+device provides LED, GPIO and regulator functionalities.
+
+Required properties:
+- compatible: "ti,tps61050" or "ti,tps61052"
+- reg: Specifies the I2C slave address
+
+Example:
+
+i2c0 {
+ tps61052@33 {
+ compatible = "ti,tps61052";
+ reg = <0x33>;
+ };
+};
--
2.9.3
^ permalink raw reply related
* [PATCH v5 5/8] i2c: i2c-cbus-gpio: Add vendor prefix to retu node in example
From: Javier Martinez Canillas @ 2017-04-12 17:27 UTC (permalink / raw)
To: linux-kernel
Cc: Aaro Koskinen, devicetree, Rob Herring, Tony Lindgren, Lee Jones,
Javier Martinez Canillas, Wolfram Sang, linux-i2c, Mark Rutland
In-Reply-To: <20170412172800.23035-1-javier@osg.samsung.com>
The example contains a device node for a retu device, but
its compatible string doesn't have a vendor prefix.
While being there, drop the -mfd suffix since isn't correct.
Signed-off-by: Javier Martinez Canillas <javier@osg.samsung.com>
Acked-by: Rob Herring <robh@kernel.org>
Acked-by: Aaro Koskinen <aaro.koskinen@iki.fi>
Acked-by: Tony Lindgren <tony@atomide.com>
---
Changes in v5:
- Add Rob Herring's Acked-by tag.
- Add Aaro Koskinen's Acked-by tag.
- Add Acked-by: Tony Lindgren <tony@atomide.com>'s Acked-by tag.
Changes in v4:
- Avoid using MFD in Device Tree (Lee Jones).
Changes in v3: None
Changes in v2: None
Documentation/devicetree/bindings/i2c/i2c-cbus-gpio.txt | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/Documentation/devicetree/bindings/i2c/i2c-cbus-gpio.txt b/Documentation/devicetree/bindings/i2c/i2c-cbus-gpio.txt
index 8ce9cd2855b5..c143948b2a37 100644
--- a/Documentation/devicetree/bindings/i2c/i2c-cbus-gpio.txt
+++ b/Documentation/devicetree/bindings/i2c/i2c-cbus-gpio.txt
@@ -20,8 +20,8 @@ i2c@0 {
#address-cells = <1>;
#size-cells = <0>;
- retu-mfd: retu@1 {
- compatible = "retu-mfd";
+ retu: retu@1 {
+ compatible = "nokia,retu";
reg = <0x1>;
};
};
--
2.9.3
^ permalink raw reply related
* [PATCH v5 4/8] ARM: dts: n8x0: Add vendor prefix to retu node
From: Javier Martinez Canillas @ 2017-04-12 17:27 UTC (permalink / raw)
To: linux-kernel
Cc: Aaro Koskinen, devicetree, Rob Herring, Tony Lindgren, Lee Jones,
Javier Martinez Canillas, Benoît Cousson, Mark Rutland,
linux-omap, Russell King, linux-arm-kernel
In-Reply-To: <20170412172800.23035-1-javier@osg.samsung.com>
The retu device node doesn't have a vendor prefix
in its compatible string, fix it by adding one.
Signed-off-by: Javier Martinez Canillas <javier@osg.samsung.com>
Acked-by: Rob Herring <robh@kernel.org>
Acked-by: Aaro Koskinen <aaro.koskinen@iki.fi>
Acked-by: Tony Lindgren <tony@atomide.com>
---
Changes in v5:
- Add Rob Herring's Acked-by tag.
- Add Aaro Koskinen's Acked-by tag.
- Add Acked-by: Tony Lindgren <tony@atomide.com>'s Acked-by tag.
Changes in v4: None
Changes in v3: None
Changes in v2: None
arch/arm/boot/dts/omap2420-n8x0-common.dtsi | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/arch/arm/boot/dts/omap2420-n8x0-common.dtsi b/arch/arm/boot/dts/omap2420-n8x0-common.dtsi
index 1b06430c8013..91886231e5a8 100644
--- a/arch/arm/boot/dts/omap2420-n8x0-common.dtsi
+++ b/arch/arm/boot/dts/omap2420-n8x0-common.dtsi
@@ -16,7 +16,7 @@
#address-cells = <1>;
#size-cells = <0>;
retu: retu@1 {
- compatible = "retu";
+ compatible = "nokia,retu";
interrupt-parent = <&gpio4>;
interrupts = <12 IRQ_TYPE_EDGE_RISING>;
reg = <0x1>;
--
2.9.3
^ permalink raw reply related
* [PATCH v5 3/8] mfd: retu: Add OF device ID table
From: Javier Martinez Canillas @ 2017-04-12 17:27 UTC (permalink / raw)
To: linux-kernel-u79uwXL29TY76Z2rM5mHXA
Cc: Aaro Koskinen, devicetree-u79uwXL29TY76Z2rM5mHXA, Rob Herring,
Tony Lindgren, Lee Jones, Javier Martinez Canillas
In-Reply-To: <20170412172800.23035-1-javier-JPH+aEBZ4P+UEJcrhfAQsw@public.gmane.org>
The driver doesn't have a struct of_device_id table but supported devices
are registered via Device Trees. This is working on the assumption that a
I2C device registered via OF will always match a legacy I2C device ID and
that the MODALIAS reported will always be of the form i2c:<device>.
But this could change in the future so the correct approach is to have a
OF device ID table if the devices are registered via OF.
Signed-off-by: Javier Martinez Canillas <javier-JPH+aEBZ4P+UEJcrhfAQsw@public.gmane.org>
Acked-by: Rob Herring <robh-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org>
Acked-by: Aaro Koskinen <aaro.koskinen-X3B1VOXEql0@public.gmane.org>
Acked-by: Tony Lindgren <tony-4v6yS6AI5VpBDgjK7y7TUQ@public.gmane.org>
Acked-by: Lee Jones <lee.jones-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
---
Changes in v5:
- Add Rob Herring's Acked-by tag.
- Add Aaro Koskinen's Acked-by tag.
- Add Acked-by: Tony Lindgren <tony-4v6yS6AI5VpBDgjK7y7TUQ@public.gmane.org>'s Acked-by tag.
- Add Lee Jones <lee.jones-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>'s Acked-by tag.
Changes in v4:
- Drop -mfd suffix in compatible string (Lee Jones).
Changes in v3:
- Add a vendor prefix to the compatible string (Rob Herring).
Changes in v2:
- Don't use of_match_ptr() to avoid build warning when CONFIG_OF is disabled.
drivers/mfd/retu-mfd.c | 8 ++++++++
1 file changed, 8 insertions(+)
diff --git a/drivers/mfd/retu-mfd.c b/drivers/mfd/retu-mfd.c
index 53e1d386d2c0..e7d27b7861c1 100644
--- a/drivers/mfd/retu-mfd.c
+++ b/drivers/mfd/retu-mfd.c
@@ -308,9 +308,17 @@ static const struct i2c_device_id retu_id[] = {
};
MODULE_DEVICE_TABLE(i2c, retu_id);
+static const struct of_device_id retu_of_match[] = {
+ { .compatible = "nokia,retu" },
+ { .compatible = "nokia,tahvo" },
+ { }
+};
+MODULE_DEVICE_TABLE(of, retu_of_match);
+
static struct i2c_driver retu_driver = {
.driver = {
.name = "retu-mfd",
+ .of_match_table = retu_of_match,
},
.probe = retu_probe,
.remove = retu_remove,
--
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
* [PATCH v5 2/8] mfd: retu: Drop -mfd suffix from I2C device ID name
From: Javier Martinez Canillas @ 2017-04-12 17:27 UTC (permalink / raw)
To: linux-kernel
Cc: Aaro Koskinen, devicetree, Rob Herring, Tony Lindgren, Lee Jones,
Javier Martinez Canillas, Benoît Cousson, Mark Rutland,
linux-omap, Russell King, linux-arm-kernel
In-Reply-To: <20170412172800.23035-1-javier@osg.samsung.com>
It's not correct to encode the subsystem in the I2C device name, so
drop the -mfd suffix. To maintain bisect-ability, change driver and
platform code / DTS users in the same patch.
Suggested-by: Lee Jones <lee.jones@linaro.org>
Signed-off-by: Javier Martinez Canillas <javier@osg.samsung.com>
Acked-by: Rob Herring <robh@kernel.org>
Acked-by: Aaro Koskinen <aaro.koskinen@iki.fi>
Acked-by: Tony Lindgren <tony@atomide.com>
---
Changes in v5:
- Add Rob Herring's Acked-by tag.
- Add Aaro Koskinen's Acked-by tag.
- Add Acked-by: Tony Lindgren <tony@atomide.com>'s Acked-by tag.
Changes in v4: None
Changes in v3: None
Changes in v2: None
arch/arm/boot/dts/omap2420-n8x0-common.dtsi | 4 ++--
arch/arm/mach-omap1/board-nokia770.c | 4 ++--
drivers/mfd/retu-mfd.c | 4 ++--
3 files changed, 6 insertions(+), 6 deletions(-)
diff --git a/arch/arm/boot/dts/omap2420-n8x0-common.dtsi b/arch/arm/boot/dts/omap2420-n8x0-common.dtsi
index 7e5ffc583c90..1b06430c8013 100644
--- a/arch/arm/boot/dts/omap2420-n8x0-common.dtsi
+++ b/arch/arm/boot/dts/omap2420-n8x0-common.dtsi
@@ -15,8 +15,8 @@
>;
#address-cells = <1>;
#size-cells = <0>;
- retu_mfd: retu@1 {
- compatible = "retu-mfd";
+ retu: retu@1 {
+ compatible = "retu";
interrupt-parent = <&gpio4>;
interrupts = <12 IRQ_TYPE_EDGE_RISING>;
reg = <0x1>;
diff --git a/arch/arm/mach-omap1/board-nokia770.c b/arch/arm/mach-omap1/board-nokia770.c
index ee8d9f553db4..06243c0b12d2 100644
--- a/arch/arm/mach-omap1/board-nokia770.c
+++ b/arch/arm/mach-omap1/board-nokia770.c
@@ -233,10 +233,10 @@ static struct platform_device nokia770_cbus_device = {
static struct i2c_board_info nokia770_i2c_board_info_2[] __initdata = {
{
- I2C_BOARD_INFO("retu-mfd", 0x01),
+ I2C_BOARD_INFO("retu", 0x01),
},
{
- I2C_BOARD_INFO("tahvo-mfd", 0x02),
+ I2C_BOARD_INFO("tahvo", 0x02),
},
};
diff --git a/drivers/mfd/retu-mfd.c b/drivers/mfd/retu-mfd.c
index d4c114abeb75..53e1d386d2c0 100644
--- a/drivers/mfd/retu-mfd.c
+++ b/drivers/mfd/retu-mfd.c
@@ -302,8 +302,8 @@ static int retu_remove(struct i2c_client *i2c)
}
static const struct i2c_device_id retu_id[] = {
- { "retu-mfd", 0 },
- { "tahvo-mfd", 0 },
+ { "retu", 0 },
+ { "tahvo", 0 },
{ }
};
MODULE_DEVICE_TABLE(i2c, retu_id);
--
2.9.3
^ permalink raw reply related
* [PATCH v5 1/8] dt-bindings: mfd: Add retu/tahvo ASIC chips bindings
From: Javier Martinez Canillas @ 2017-04-12 17:27 UTC (permalink / raw)
To: linux-kernel
Cc: Aaro Koskinen, devicetree, Rob Herring, Tony Lindgren, Lee Jones,
Javier Martinez Canillas, Mark Rutland
In-Reply-To: <20170412172800.23035-1-javier@osg.samsung.com>
There are Device Tree source files defining a device node for the
retu/tahvo I2C chip, but there isn't a DT binding document for it.
Signed-off-by: Javier Martinez Canillas <javier@osg.samsung.com>
Acked-by: Rob Herring <robh@kernel.org>
Acked-by: Aaro Koskinen <aaro.koskinen@iki.fi>
Acked-by: Tony Lindgren <tony@atomide.com>
Acked-by: Lee Jones <lee.jones@linaro.org>
---
Changes in v5:
- Add missing properties for interrupts to DT binding doc (Rob Herring).
- Add Rob Herring's Acked-by tag.
- Add Aaro Koskinen's Acked-by tag.
- Add Acked-by: Tony Lindgren <tony@atomide.com>'s Acked-by tag.
- Add Lee Jones <lee.jones@linaro.org>'s Acked-by tag.
Changes in v4:
- Use "dt-bindings: mfd:" prefix in subject line (Rob Herring).
- Add information about what functions the device serve (Lee Jones).
- Avoid using MFD in Device Tree (Lee Jones).
Changes in v3: None
Changes in v2: None
Documentation/devicetree/bindings/mfd/retu.txt | 23 +++++++++++++++++++++++
1 file changed, 23 insertions(+)
create mode 100644 Documentation/devicetree/bindings/mfd/retu.txt
diff --git a/Documentation/devicetree/bindings/mfd/retu.txt b/Documentation/devicetree/bindings/mfd/retu.txt
new file mode 100644
index 000000000000..e1ea3a36a038
--- /dev/null
+++ b/Documentation/devicetree/bindings/mfd/retu.txt
@@ -0,0 +1,23 @@
+* Device tree bindings for Nokia Retu and Tahvo multi-function device
+
+Retu and Tahvo are a multi-function devices found on Nokia Internet
+Tablets (770, N800 and N810). The Retu chip provides watchdog timer
+and power button control functionalities while Tahvo chip provides
+USB transceiver functionality.
+
+Required properties:
+- compatible: "nokia,retu" or "nokia,tahvo"
+- reg: Specifies the I2C slave address of the ASIC chip
+- interrupts: The interrupt line the device is connected to
+- interrupt-parent: The parent interrupt controller
+
+Example:
+
+i2c0 {
+ retu: retu@1 {
+ compatible = "nokia,retu";
+ interrupt-parent = <&gpio4>;
+ interrupts = <12 IRQ_TYPE_EDGE_RISING>;
+ reg = <0x1>;
+ };
+};
--
2.9.3
^ permalink raw reply related
* [PATCH v5 0/8] mfd: Add OF device table to I2C drivers that are missing it
From: Javier Martinez Canillas @ 2017-04-12 17:27 UTC (permalink / raw)
To: linux-kernel
Cc: Aaro Koskinen, devicetree, Rob Herring, Tony Lindgren, Lee Jones,
Javier Martinez Canillas, Benoît Cousson, Wolfram Sang,
Mark Rutland, linux-omap, Russell King, linux-arm-kernel,
linux-i2c
Hello,
This series add OF device ID tables to mfd I2C drivers whose devices are
either used in Device Tree source files or are listed in binding docs as
a compatible string.
That's done because the plan is to change the I2C core to report proper OF
modaliases instead of always reporting a MODALIAS=i2c:<foo> regardless if
a device was registered via DT or using the legacy platform data mechanism.
So these patches will make sure that mfd I2C drivers modules will continue
to be autoloaded once the I2C core is changed to report proper OF modalias.
Users didn't have a vendor prefix in the used compatible strings, but since
there wasn't a DT binding document for these drivers, it can be said that
were working for mere luck and so this series fixes the users and add a DT
binding doc for the drivers.
Most patches can be applied independently, with the exception of patches
2 to 4 that should be applied in the same tree to keep bisect-ability. I
suggest these to go through the MFD subsystem tree.
Best regards,
Javier
Changes in v5:
- Add missing properties for interrupts to DT binding doc (Rob Herring).
- Add Rob Herring's Acked-by tag.
- Add Aaro Koskinen's Acked-by tag.
- Add Acked-by: Tony Lindgren <tony@atomide.com>'s Acked-by tag.
- Add Lee Jones <lee.jones@linaro.org>'s Acked-by tag.
- Add Rob Herring's Acked-by tag.
- Add Aaro Koskinen's Acked-by tag.
- Add Acked-by: Tony Lindgren <tony@atomide.com>'s Acked-by tag.
- Add Rob Herring's Acked-by tag.
- Add Aaro Koskinen's Acked-by tag.
- Add Acked-by: Tony Lindgren <tony@atomide.com>'s Acked-by tag.
- Add Lee Jones <lee.jones@linaro.org>'s Acked-by tag.
- Add Rob Herring's Acked-by tag.
- Add Aaro Koskinen's Acked-by tag.
- Add Acked-by: Tony Lindgren <tony@atomide.com>'s Acked-by tag.
- Add Rob Herring's Acked-by tag.
- Add Aaro Koskinen's Acked-by tag.
- Add Acked-by: Tony Lindgren <tony@atomide.com>'s Acked-by tag.
- Add Rob Herring's Acked-by tag.
- Add Acked-by: Tony Lindgren <tony@atomide.com>'s Acked-by tag.
- Add Rob Herring's Acked-by tag.
- Add Acked-by: Tony Lindgren <tony@atomide.com>'s Acked-by tag.
- Add Lee Jones <lee.jones@linaro.org>'s Acked-by tag.
- Add Rob Herring's Acked-by tag.
- Add Acked-by: Tony Lindgren <tony@atomide.com>'s Acked-by tag.
Changes in v4:
- Use "dt-bindings: mfd:" prefix in subject line (Rob Herring).
- Add information about what functions the device serve (Lee Jones).
- Avoid using MFD in Device Tree (Lee Jones).
- Drop -mfd suffix in compatible string (Lee Jones).
- Avoid using MFD in Device Tree (Lee Jones).
- Use "dt-bindings: mfd:" prefix in subject line (Rob Herring).
- Add information about what functions the device serve (Lee Jones).
Changes in v3:
- Add a vendor prefix to the compatible string (Rob Herring).
- Add a vendor prefix to the compatible string (Rob Herring).
Changes in v2:
- Don't use of_match_ptr() to avoid build warning when CONFIG_OF is disabled.
- Don't use of_match_ptr() to avoid build warning when CONFIG_OF is disabled.
Javier Martinez Canillas (8):
dt-bindings: mfd: Add retu/tahvo ASIC chips bindings
mfd: retu: Drop -mfd suffix from I2C device ID name
mfd: retu: Add OF device ID table
ARM: dts: n8x0: Add vendor prefix to retu node
i2c: i2c-cbus-gpio: Add vendor prefix to retu node in example
dt-bindings: mfd: Add TI tps6105x chip bindings
mfd: tps6105x: Add OF device ID table
ARM: ux500: Add vendor prefix to tps61052 node
.../devicetree/bindings/i2c/i2c-cbus-gpio.txt | 4 ++--
Documentation/devicetree/bindings/mfd/retu.txt | 23 ++++++++++++++++++++++
Documentation/devicetree/bindings/mfd/tps6105x.txt | 17 ++++++++++++++++
arch/arm/boot/dts/omap2420-n8x0-common.dtsi | 4 ++--
arch/arm/boot/dts/ste-hrefprev60.dtsi | 2 +-
arch/arm/mach-omap1/board-nokia770.c | 4 ++--
drivers/mfd/retu-mfd.c | 12 +++++++++--
drivers/mfd/tps6105x.c | 8 ++++++++
8 files changed, 65 insertions(+), 9 deletions(-)
create mode 100644 Documentation/devicetree/bindings/mfd/retu.txt
create mode 100644 Documentation/devicetree/bindings/mfd/tps6105x.txt
--
2.9.3
^ permalink raw reply
* Re: [PATCH v5 1/4] gpio: mvebu: Add limited PWM support
From: Thierry Reding @ 2017-04-12 17:21 UTC (permalink / raw)
To: Ralph Sennhauser
Cc: Andrew Lunn, Linus Walleij, Alexandre Courbot, Rob Herring,
Mark Rutland, Jason Cooper, Gregory Clement,
Sebastian Hesselbarth, Russell King, linux-pwm, linux-gpio,
devicetree, linux-kernel, linux-arm-kernel
In-Reply-To: <20170409180931.4884-2-ralph.sennhauser@gmail.com>
[-- Attachment #1: Type: text/plain, Size: 2739 bytes --]
On Sun, Apr 09, 2017 at 08:09:27PM +0200, Ralph Sennhauser wrote:
> From: Andrew Lunn <andrew@lunn.ch>
>
> Armada 370/XP devices can 'blink' GPIO lines with a configurable on
> and off period. This can be modelled as a PWM.
>
> However, there are only two sets of PWM configuration registers for
> all the GPIO lines. This driver simply allows a single GPIO line per
> GPIO chip of 32 lines to be used as a PWM. Attempts to use more return
> EBUSY.
>
> Due to the interleaving of registers it is not simple to separate the
> PWM driver from the GPIO driver. Thus the GPIO driver has been
> extended with a PWM driver.
>
> Signed-off-by: Andrew Lunn <andrew@lunn.ch>
> URL: https://patchwork.ozlabs.org/patch/427287/
> URL: https://patchwork.ozlabs.org/patch/427295/
> [Ralph Sennhauser:
> * Port forward
> * Merge PWM portion into gpio-mvebu.c
> * Switch to atomic PWM API
> * Add new compatible string marvell,armada-370-xp-gpio
> * Update and merge documentation patch
> * Update MAINTAINERS]
> Signed-off-by: Ralph Sennhauser <ralph.sennhauser@gmail.com>
> Tested-by: Andrew Lunn <andrew@lunn.ch>
> ---
> .../devicetree/bindings/gpio/gpio-mvebu.txt | 32 ++
> MAINTAINERS | 2 +
> drivers/gpio/gpio-mvebu.c | 324 ++++++++++++++++++++-
> 3 files changed, 346 insertions(+), 12 deletions(-)
>
> diff --git a/Documentation/devicetree/bindings/gpio/gpio-mvebu.txt b/Documentation/devicetree/bindings/gpio/gpio-mvebu.txt
> index a6f3bec..fe49e9d 100644
> --- a/Documentation/devicetree/bindings/gpio/gpio-mvebu.txt
> +++ b/Documentation/devicetree/bindings/gpio/gpio-mvebu.txt
> @@ -38,6 +38,24 @@ Required properties:
> - #gpio-cells: Should be two. The first cell is the pin number. The
> second cell is reserved for flags, unused at the moment.
>
> +Optional properties:
> +
> +In order to use the gpio lines in PWM mode, some additional optional
> +properties are required. Only Armada 370 and XP support these properties.
> +
> +- compatible: Must contain "marvell,armada-370-xp-gpio"
> +
> +- reg: an additional register set is needed, for the GPIO Blink
> + Counter on/off registers.
> +
> +- reg-names: Must contain an entry "pwm" corresponding to the
> + additional register range needed for pwm operation.
> +
> +- #pwm-cells: Should be two. The first cell is the GPIO line number. The
> + second cell is the period in nanoseconds.
> +
> +- clocks: Must be a phandle to the clock for the gpio controller.
One other thing: there's a mix of pwm/PWM and gpio/GPIO in this hunk. In
prose, always use the all-uppercase variants because they are
abbreviations.
Thierry
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]
^ permalink raw reply
* Re: [PATCH V3 2/4] pwm: tegra: Increase precision in pwm rate calculation
From: Thierry Reding @ 2017-04-12 17:19 UTC (permalink / raw)
To: Laxman Dewangan
Cc: robh+dt-DgEjT+Ai2ygdnm+yROfE0A, jonathanh-DDmLM1+adcrQT0dZR+AlfA,
mark.rutland-5wv7dgnIgG8, linux-pwm-u79uwXL29TY76Z2rM5mHXA,
devicetree-u79uwXL29TY76Z2rM5mHXA,
linux-tegra-u79uwXL29TY76Z2rM5mHXA,
linux-kernel-u79uwXL29TY76Z2rM5mHXA
In-Reply-To: <1491557642-15940-3-git-send-email-ldewangan-DDmLM1+adcrQT0dZR+AlfA@public.gmane.org>
[-- Attachment #1: Type: text/plain, Size: 2516 bytes --]
On Fri, Apr 07, 2017 at 03:04:00PM +0530, Laxman Dewangan wrote:
> The rate of the PWM calculated as follows:
> hz = NSEC_PER_SEC / period_ns;
> rate = (rate + (hz / 2)) / hz;
>
> This has the precision loss in lower PWM rate.
>
> Change this to have more precision as:
> hz = DIV_ROUND_CLOSEST_ULL(NSEC_PER_SEC * 100, period_ns);
> rate = DIV_ROUND_CLOSEST(rate * 100, hz)
>
> Example:
> 1. period_ns = 16672000, PWM clock rate is 200KHz.
> Based on old formula
> hz = NSEC_PER_SEC / period_ns
> = 1000000000ul/16672000
> = 59 (59.98)
> rate = (200K + 59/2)/59 = 3390
>
> Based on new method:
> hz = 5998
> rate = DIV_ROUND_CLOSE(200000*100, 5998) = 3334
>
> If we measure the PWM signal rate, we will get more accurate period
> with rate value of 3334 instead of 3390.
>
> 2. period_ns = 16803898, PWM clock rate is 200KHz.
> Based on old formula:
> hz = 59, rate = 3390
> Based on new formula:
> hz = 5951, rate = 3360
>
> The PWM signal rate of 3360 is more near to requested period than 3333.
>
> Signed-off-by: Laxman Dewangan <ldewangan-DDmLM1+adcrQT0dZR+AlfA@public.gmane.org>
>
> ---
> Changes from v1:
> - None
>
> Changes from V2:
> - Fix the commit message with exact formula used.
> ---
> drivers/pwm/pwm-tegra.c | 7 +++++--
> 1 file changed, 5 insertions(+), 2 deletions(-)
>
> diff --git a/drivers/pwm/pwm-tegra.c b/drivers/pwm/pwm-tegra.c
> index 0a688da..21518be 100644
> --- a/drivers/pwm/pwm-tegra.c
> +++ b/drivers/pwm/pwm-tegra.c
> @@ -76,6 +76,7 @@ static int tegra_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm,
> struct tegra_pwm_chip *pc = to_tegra_pwm_chip(chip);
> unsigned long long c = duty_ns;
> unsigned long rate, hz;
> + unsigned long long ns100 = NSEC_PER_SEC;
> u32 val = 0;
> int err;
>
> @@ -94,9 +95,11 @@ static int tegra_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm,
> * cycles at the PWM clock rate will take period_ns nanoseconds.
> */
> rate = clk_get_rate(pc->clk) >> PWM_DUTY_WIDTH;
> - hz = NSEC_PER_SEC / period_ns;
>
> - rate = (rate + (hz / 2)) / hz;
> + /* Consider precision in PWM_SCALE_WIDTH rate calculation */
> + ns100 *= 100;
> + hz = DIV_ROUND_CLOSEST_ULL(ns100, period_ns);
I think hz could overflow for small enough values of period_ns. I've
sent a patch that makes hz unsigned long long. While at it, the patch
also removes the ns100 variable which isn't really necessary here.
Thierry
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]
^ permalink raw reply
* Re: [PATCH V3 0/4] pwm: tegra: Pin configuration in suspend/resume and cleanups
From: Thierry Reding @ 2017-04-12 17:18 UTC (permalink / raw)
To: Laxman Dewangan
Cc: robh+dt-DgEjT+Ai2ygdnm+yROfE0A, jonathanh-DDmLM1+adcrQT0dZR+AlfA,
mark.rutland-5wv7dgnIgG8, linux-pwm-u79uwXL29TY76Z2rM5mHXA,
devicetree-u79uwXL29TY76Z2rM5mHXA,
linux-tegra-u79uwXL29TY76Z2rM5mHXA,
linux-kernel-u79uwXL29TY76Z2rM5mHXA
In-Reply-To: <1491557642-15940-1-git-send-email-ldewangan-DDmLM1+adcrQT0dZR+AlfA@public.gmane.org>
[-- Attachment #1: Type: text/plain, Size: 1206 bytes --]
On Fri, Apr 07, 2017 at 03:03:58PM +0530, Laxman Dewangan wrote:
> This patch series have following fixes:
> - Add more precession in PWM period register value calculation
> for lower pwm frequency.
> - Add support to configure PWM pins in different state in the
> suspend/resume.
>
> Changes from v1:
> - Use standard pinctrl names for sleep and active state.
> - Use API pinctrl_pm_select_*()
>
> Changes from V2:
> - Type fixes, rephrases commit message and use pinctrl_pm_state* return
> value.
>
> Laxman Dewangan (4):
> pwm: tegra: Use DIV_ROUND_CLOSEST_ULL() instead of local
> implementation
> pwm: tegra: Increase precision in pwm rate calculation
> pwm: tegra: Add DT binding details to configure pin in suspends/resume
> pwm: tegra: Add support to configure pin state in suspends/resume
>
> .../devicetree/bindings/pwm/nvidia,tegra20-pwm.txt | 43 ++++++++++++
> drivers/pwm/pwm-tegra.c | 77 ++++++++++++++++++++--
> 2 files changed, 116 insertions(+), 4 deletions(-)
All four patches applied to for-4.12/drivers, thanks.
I've slightly modified the commit messages of some patches for "pwm" ->
"PWM".
Thierry
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]
^ permalink raw reply
* Re: [PATCH v5 0/4] gpio: mvebu: Add PWM fan support
From: Thierry Reding @ 2017-04-12 17:16 UTC (permalink / raw)
To: Ralph Sennhauser
Cc: Linus Walleij, Alexandre Courbot, Rob Herring, Mark Rutland,
Jason Cooper, Andrew Lunn, Gregory Clement, Sebastian Hesselbarth,
Russell King, linux-pwm, linux-gpio, devicetree, linux-kernel,
linux-arm-kernel
In-Reply-To: <20170409180931.4884-1-ralph.sennhauser@gmail.com>
[-- Attachment #1: Type: text/plain, Size: 2217 bytes --]
On Sun, Apr 09, 2017 at 08:09:26PM +0200, Ralph Sennhauser wrote:
> Hi Therry,
>
> Resending this as v5 with some minor changes since v4. What is missing is
> an ACK from you so Linus can merge the driver and Gregory the dts
> changes. For this driver to make it into 4.12 it would be nice to have
> it in next soon. I hope you can make some room in your schedule to have
> another look at this series.
>
> Thanks
> Ralph
>
> ---
>
> Notes:
>
> About npwm = 1:
> The only way I can think of to achieve that requires reading the
> GPIO line from the device tree. This would prevent a user to
> dynamically choose a line. Which is fine for the fan found on Mamba
> but let's take some development board with freely accessible GPIOs
> and suddenly we limit the use of this driver. Given the above, npwm
> = ngpio with only one usable at a time is a more accurate
I think "accurate" is perhaps not the word I'd choose. "npwm" is defined
as "number of PWMs controlled by this chip", and that's effectively just
the one. It's implied that all PWMs exposed by a chip can be used
concurrently.
Anyway, I can see how npwm = ngpio might be more convenient, and if that
is what you want to do, I don't feel strongly enough to object.
> description of the situation. The only downside is some "wasted"
> space.
>
> About the new compatible string:
> Orion was chosen for the SoC variant for the same reason as in
> commit 5f79c651e81e ("arm: mvebu: use global interrupts for GPIOs on
> Armada XP").
> The "pwm" property remains optional for the new compatible string so
> the compatiple string "marvell,armada-370-xp-gpio" can be used by
> all and not just the first two GPIO chips. A property to select "Set
> A" / "Set B" registers could be invented though.
>
> ---
>
> Pending:
> * Needs ACK from Thierry Reding to be merged via linux-gpio tree by Linus
> Walleij. (fine with the general approach, requested changes which
> should have been taken care of now)
As I said elsewhere, I haven't seen an Acked-by on the binding changes,
so that would be another pending item here.
Thierry
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]
^ permalink raw reply
* [PATCH 2/2] drm/panel: simple: add support for NLT NL192108AC18-02D
From: Lucas Stach @ 2017-04-12 17:15 UTC (permalink / raw)
To: Thierry Reding, Rob Herring
Cc: Mark Rutland, devicetree, kernel, dri-devel, patchwork-lst
In-Reply-To: <20170412171526.32393-1-l.stach@pengutronix.de>
This adds support for the NLT Technologies NL192108AC18-02D
15.6" LVDS FullHD TFT LCD panel, which can be supported
by the simple panel driver.
Timings are taken from the preliminary datasheet, as a final
one is not yet available.
Signed-off-by: Lucas Stach <l.stach@pengutronix.de>
---
.../display/panel/nlt,nl192108ac18-02d.txt | 7 ++++++
drivers/gpu/drm/panel/panel-simple.c | 29 ++++++++++++++++++++++
2 files changed, 36 insertions(+)
create mode 100644 Documentation/devicetree/bindings/display/panel/nlt,nl192108ac18-02d.txt
diff --git a/Documentation/devicetree/bindings/display/panel/nlt,nl192108ac18-02d.txt b/Documentation/devicetree/bindings/display/panel/nlt,nl192108ac18-02d.txt
new file mode 100644
index 000000000000..edc34fbd2131
--- /dev/null
+++ b/Documentation/devicetree/bindings/display/panel/nlt,nl192108ac18-02d.txt
@@ -0,0 +1,7 @@
+NLT Technologies, Ltd. 15.6" FHD (1920x1080) LVDS TFT LCD panel
+
+Required properties:
+- compatible: should be "nlt,nl192108ac18-02d"
+
+This binding is compatible with the simple-panel binding, which is specified
+in simple-panel.txt in this directory.
diff --git a/drivers/gpu/drm/panel/panel-simple.c b/drivers/gpu/drm/panel/panel-simple.c
index 89eb0422821c..888c3a22dcd9 100644
--- a/drivers/gpu/drm/panel/panel-simple.c
+++ b/drivers/gpu/drm/panel/panel-simple.c
@@ -1346,6 +1346,32 @@ static const struct panel_desc netron_dy_e231732 = {
.bus_format = MEDIA_BUS_FMT_RGB666_1X18,
};
+static const struct display_timing nlt_nl192108ac18_02d_timing = {
+ .pixelclock = { 130000000, 148350000, 163000000 },
+ .hactive = { 1920, 1920, 1920 },
+ .hfront_porch = { 80, 100, 100 },
+ .hback_porch = { 100, 120, 120 },
+ .hsync_len = { 50, 60, 60 },
+ .vactive = { 1080, 1080, 1080 },
+ .vfront_porch = { 12, 30, 30 },
+ .vback_porch = { 4, 10, 10 },
+ .vsync_len = { 4, 5, 5 },
+};
+
+static const struct panel_desc nlt_nl192108ac18_02d = {
+ .timings = &nlt_nl192108ac18_02d_timing,
+ .num_timings = 1,
+ .bpc = 8,
+ .size = {
+ .width = 344,
+ .height = 194,
+ },
+ .delay = {
+ .unprepare = 500,
+ },
+ .bus_format = MEDIA_BUS_FMT_RGB888_1X7X4_SPWG,
+};
+
static const struct drm_display_mode nvd_9128_mode = {
.clock = 29500,
.hdisplay = 800,
@@ -1925,6 +1951,9 @@ static const struct of_device_id platform_of_match[] = {
.compatible = "netron-dy,e231732",
.data = &netron_dy_e231732,
}, {
+ .compatible = "nlt,nl192108ac18-02d",
+ .data = &nlt_nl192108ac18_02d,
+ }, {
.compatible = "nvd,9128",
.data = &nvd_9128,
}, {
--
2.11.0
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel
^ permalink raw reply related
* [PATCH 1/2] dt-bindings: add vendor prefix for NLT Technologies, Ltd.
From: Lucas Stach @ 2017-04-12 17:15 UTC (permalink / raw)
To: Thierry Reding, Rob Herring
Cc: Mark Rutland, devicetree, kernel, dri-devel, patchwork-lst
NLT technologies is the former NEC display business, but changed its
name to NLT Technologies when forming a joint venture with
Shenzhen AVIC OPTOELECTRONICS, Ltd.
Signed-off-by: Lucas Stach <l.stach@pengutronix.de>
---
Documentation/devicetree/bindings/vendor-prefixes.txt | 1 +
1 file changed, 1 insertion(+)
diff --git a/Documentation/devicetree/bindings/vendor-prefixes.txt b/Documentation/devicetree/bindings/vendor-prefixes.txt
index 4686f4bdaca0..b9edc2f4cb94 100644
--- a/Documentation/devicetree/bindings/vendor-prefixes.txt
+++ b/Documentation/devicetree/bindings/vendor-prefixes.txt
@@ -212,6 +212,7 @@ nexbox Nexbox
newhaven Newhaven Display International
ni National Instruments
nintendo Nintendo
+nlt NLT Technologies, Ltd.
nokia Nokia
nuvoton Nuvoton Technology Corporation
nvd New Vision Display
--
2.11.0
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel
^ permalink raw reply related
* Re: [PATCH v5 1/4] gpio: mvebu: Add limited PWM support
From: Thierry Reding @ 2017-04-12 17:11 UTC (permalink / raw)
To: Ralph Sennhauser
Cc: Andrew Lunn, Linus Walleij, Alexandre Courbot, Rob Herring,
Mark Rutland, Jason Cooper, Gregory Clement,
Sebastian Hesselbarth, Russell King, linux-pwm, linux-gpio,
devicetree, linux-kernel, linux-arm-kernel
In-Reply-To: <20170409180931.4884-2-ralph.sennhauser@gmail.com>
[-- Attachment #1: Type: text/plain, Size: 17676 bytes --]
On Sun, Apr 09, 2017 at 08:09:27PM +0200, Ralph Sennhauser wrote:
> From: Andrew Lunn <andrew@lunn.ch>
>
> Armada 370/XP devices can 'blink' GPIO lines with a configurable on
> and off period. This can be modelled as a PWM.
>
> However, there are only two sets of PWM configuration registers for
> all the GPIO lines. This driver simply allows a single GPIO line per
> GPIO chip of 32 lines to be used as a PWM. Attempts to use more return
> EBUSY.
>
> Due to the interleaving of registers it is not simple to separate the
> PWM driver from the GPIO driver. Thus the GPIO driver has been
> extended with a PWM driver.
>
> Signed-off-by: Andrew Lunn <andrew@lunn.ch>
> URL: https://patchwork.ozlabs.org/patch/427287/
> URL: https://patchwork.ozlabs.org/patch/427295/
> [Ralph Sennhauser:
> * Port forward
> * Merge PWM portion into gpio-mvebu.c
> * Switch to atomic PWM API
> * Add new compatible string marvell,armada-370-xp-gpio
> * Update and merge documentation patch
> * Update MAINTAINERS]
> Signed-off-by: Ralph Sennhauser <ralph.sennhauser@gmail.com>
> Tested-by: Andrew Lunn <andrew@lunn.ch>
> ---
> .../devicetree/bindings/gpio/gpio-mvebu.txt | 32 ++
> MAINTAINERS | 2 +
> drivers/gpio/gpio-mvebu.c | 324 ++++++++++++++++++++-
> 3 files changed, 346 insertions(+), 12 deletions(-)
>
> diff --git a/Documentation/devicetree/bindings/gpio/gpio-mvebu.txt b/Documentation/devicetree/bindings/gpio/gpio-mvebu.txt
> index a6f3bec..fe49e9d 100644
> --- a/Documentation/devicetree/bindings/gpio/gpio-mvebu.txt
> +++ b/Documentation/devicetree/bindings/gpio/gpio-mvebu.txt
> @@ -38,6 +38,24 @@ Required properties:
> - #gpio-cells: Should be two. The first cell is the pin number. The
> second cell is reserved for flags, unused at the moment.
>
> +Optional properties:
> +
> +In order to use the gpio lines in PWM mode, some additional optional
> +properties are required. Only Armada 370 and XP support these properties.
> +
> +- compatible: Must contain "marvell,armada-370-xp-gpio"
> +
> +- reg: an additional register set is needed, for the GPIO Blink
> + Counter on/off registers.
> +
> +- reg-names: Must contain an entry "pwm" corresponding to the
> + additional register range needed for pwm operation.
> +
> +- #pwm-cells: Should be two. The first cell is the GPIO line number. The
> + second cell is the period in nanoseconds.
> +
> +- clocks: Must be a phandle to the clock for the gpio controller.
> +
> Example:
>
> gpio0: gpio@d0018100 {
> @@ -51,3 +69,17 @@ Example:
> #interrupt-cells = <2>;
> interrupts = <16>, <17>, <18>, <19>;
> };
> +
> + gpio1: gpio@18140 {
> + compatible = "marvell,armada-370-xp-gpio";
> + reg = <0x18140 0x40>, <0x181c8 0x08>;
> + reg-names = "gpio", "pwm";
> + ngpios = <17>;
> + gpio-controller;
> + #gpio-cells = <2>;
> + #pwm-cells = <2>;
> + interrupt-controller;
> + #interrupt-cells = <2>;
> + interrupts = <87>, <88>, <89>;
> + clocks = <&coreclk 0>;
> + };
This is going to need an Acked-by from one of the device tree
maintainers. Rob and devicetree@vger.kernel.org are on Cc, but I suspect
nobody might look for the binding change "hidden" in this patch.
Maybe best to split this off into a separate patch, or explicitly ping
Rob to look at this patch.
> diff --git a/MAINTAINERS b/MAINTAINERS
> index 58b3a22..19382f5 100644
> --- a/MAINTAINERS
> +++ b/MAINTAINERS
> @@ -10295,6 +10295,8 @@ F: include/linux/pwm.h
> F: drivers/pwm/
> F: drivers/video/backlight/pwm_bl.c
> F: include/linux/pwm_backlight.h
> +F: drivers/gpio/gpio-mvebu.c
> +F: Documentation/devicetree/bindings/gpio/gpio-mvebu.txt
>
> PXA2xx/PXA3xx SUPPORT
> M: Daniel Mack <daniel@zonque.org>
> diff --git a/drivers/gpio/gpio-mvebu.c b/drivers/gpio/gpio-mvebu.c
> index fae4db6..e310951 100644
> --- a/drivers/gpio/gpio-mvebu.c
> +++ b/drivers/gpio/gpio-mvebu.c
> @@ -42,22 +42,34 @@
> #include <linux/io.h>
> #include <linux/of_irq.h>
> #include <linux/of_device.h>
> +#include <linux/pwm.h>
> #include <linux/clk.h>
> #include <linux/pinctrl/consumer.h>
> #include <linux/irqchip/chained_irq.h>
> +#include <linux/platform_device.h>
> #include <linux/bitops.h>
>
> +#include "gpiolib.h"
> +
> /*
> * GPIO unit register offsets.
> */
> -#define GPIO_OUT_OFF 0x0000
> -#define GPIO_IO_CONF_OFF 0x0004
> -#define GPIO_BLINK_EN_OFF 0x0008
> -#define GPIO_IN_POL_OFF 0x000c
> -#define GPIO_DATA_IN_OFF 0x0010
> -#define GPIO_EDGE_CAUSE_OFF 0x0014
> -#define GPIO_EDGE_MASK_OFF 0x0018
> -#define GPIO_LEVEL_MASK_OFF 0x001c
> +#define GPIO_OUT_OFF 0x0000
> +#define GPIO_IO_CONF_OFF 0x0004
> +#define GPIO_BLINK_EN_OFF 0x0008
> +#define GPIO_IN_POL_OFF 0x000c
> +#define GPIO_DATA_IN_OFF 0x0010
> +#define GPIO_EDGE_CAUSE_OFF 0x0014
> +#define GPIO_EDGE_MASK_OFF 0x0018
> +#define GPIO_LEVEL_MASK_OFF 0x001c
> +#define GPIO_BLINK_CNT_SELECT_OFF 0x0020
> +
> +/*
> + * PWM register offsets.
> + */
> +#define PWM_BLINK_ON_DURATION_OFF 0x0
> +#define PWM_BLINK_OFF_DURATION_OFF 0x4
> +
>
> /* The MV78200 has per-CPU registers for edge mask and level mask */
> #define GPIO_EDGE_MASK_MV78200_OFF(cpu) ((cpu) ? 0x30 : 0x18)
> @@ -78,6 +90,20 @@
>
> #define MVEBU_MAX_GPIO_PER_BANK 32
>
> +struct mvebu_pwm {
> + void __iomem *membase;
> + unsigned long clk_rate;
> + bool used;
I think you could've probably made this a little simpler by making bool
used into struct gpio_desc *gpio; and reference that rather than having
to convert with gpio_to_desc(). More on why I think that's important
below.
> + struct pwm_chip chip;
> + spinlock_t lock;
> + struct mvebu_gpio_chip *mvchip;
> +
> + /* Used to preserve GPIO/PWM registers across suspend/resume */
> + u32 blink_select;
> + u32 blink_on_duration;
> + u32 blink_off_duration;
> +};
> +
> struct mvebu_gpio_chip {
> struct gpio_chip chip;
> spinlock_t lock;
> @@ -87,6 +113,10 @@ struct mvebu_gpio_chip {
> struct irq_domain *domain;
> int soc_variant;
>
> + /* Used for PWM support */
> + struct clk *clk;
> + struct mvebu_pwm *mvpwm;
> +
> /* Used to preserve GPIO registers across suspend/resume */
> u32 out_reg;
> u32 io_conf_reg;
> @@ -110,6 +140,12 @@ static void __iomem *mvebu_gpioreg_blink(struct mvebu_gpio_chip *mvchip)
> return mvchip->membase + GPIO_BLINK_EN_OFF;
> }
>
> +static void __iomem *mvebu_gpioreg_blink_counter_select(struct mvebu_gpio_chip
> + *mvchip)
> +{
> + return mvchip->membase + GPIO_BLINK_CNT_SELECT_OFF;
> +}
> +
> static void __iomem *mvebu_gpioreg_io_conf(struct mvebu_gpio_chip *mvchip)
> {
> return mvchip->membase + GPIO_IO_CONF_OFF;
> @@ -181,6 +217,20 @@ static void __iomem *mvebu_gpioreg_level_mask(struct mvebu_gpio_chip *mvchip)
> }
>
> /*
> + * Functions returning addresses of individual registers for a given
> + * PWM controller.
> + */
> +static void __iomem *mvebu_pwmreg_blink_on_duration(struct mvebu_pwm *mvpwm)
> +{
> + return mvpwm->membase + PWM_BLINK_ON_DURATION_OFF;
> +}
> +
> +static void __iomem *mvebu_pwmreg_blink_off_duration(struct mvebu_pwm *mvpwm)
> +{
> + return mvpwm->membase + PWM_BLINK_OFF_DURATION_OFF;
> +}
> +
> +/*
> * Functions implementing the gpio_chip methods
> */
> static void mvebu_gpio_set(struct gpio_chip *chip, unsigned int pin, int value)
> @@ -484,6 +534,243 @@ static void mvebu_gpio_irq_handler(struct irq_desc *desc)
> chained_irq_exit(chip, desc);
> }
>
> +/*
> + * Functions implementing the pwm_chip methods
> + */
> +static struct mvebu_pwm *to_mvebu_pwm(struct pwm_chip *chip)
> +{
> + return container_of(chip, struct mvebu_pwm, chip);
> +}
> +
> +static int mvebu_pwm_request(struct pwm_chip *chip, struct pwm_device *pwm)
> +{
> + struct mvebu_pwm *mvpwm = to_mvebu_pwm(chip);
> + struct gpio_desc *desc = gpio_to_desc(pwm->pwm);
This assumes that the GPIO chip base and the PWM chip base are the same.
You make sure of that by setting the PWM chip base to be the same as the
GPIO chip base, which is the easy way out. It's also somewhat brittle
because some other PWM chip may have occupied the region that you want
to use. It's fairly unlikely, but I think you can very easily side-step
any issues by simply doing:
struct mvebu_gpio_chip *mvchip = mvpwm->mvchip;
desc = gpio_to_desc(mvchip->chip.base + pwm->hwpwm);
Now that's somewhat complicated, but you only have to do it once if you
store the desc in mvpwm->gpio as pointed out above.
> + unsigned long flags;
> + int ret = 0;
> +
> + spin_lock_irqsave(&mvpwm->lock, flags);
> + if (mvpwm->used) {
> + ret = -EBUSY;
Then you can also easily use mvpwm->gpio to check for -EBUSY here.
> + } else {
> + if (!desc) {
> + ret = -ENODEV;
> + goto out;
> + }
> + ret = gpiod_request(desc, "mvebu-pwm");
> + if (ret)
> + goto out;
> +
> + ret = gpiod_direction_output(desc, 0);
> + if (ret) {
> + gpiod_free(desc);
> + goto out;
> + }
> +
> + mvpwm->used = true;
> + }
> +
> +out:
> + spin_unlock_irqrestore(&mvpwm->lock, flags);
> + return ret;
> +}
> +
> +static void mvebu_pwm_free(struct pwm_chip *chip, struct pwm_device *pwm)
> +{
> + struct mvebu_pwm *mvpwm = to_mvebu_pwm(chip);
> + struct gpio_desc *desc = gpio_to_desc(pwm->pwm);
> + unsigned long flags;
> +
> + spin_lock_irqsave(&mvpwm->lock, flags);
> + gpiod_free(desc);
> + mvpwm->used = false;
> + spin_unlock_irqrestore(&mvpwm->lock, flags);
> +}
> +
> +static void mvebu_pwm_get_state(struct pwm_chip *chip,
> + struct pwm_device *pwm,
> + struct pwm_state *state) {
> +
> + struct mvebu_pwm *mvpwm = to_mvebu_pwm(chip);
> + struct mvebu_gpio_chip *mvchip = mvpwm->mvchip;
> + unsigned long long val;
> + unsigned long flags;
> + u32 u;
> +
> + spin_lock_irqsave(&mvpwm->lock, flags);
> +
> + val = (unsigned long long)
> + readl_relaxed(mvebu_pwmreg_blink_on_duration);
> + val *= NSEC_PER_SEC;
> + do_div(val, mvpwm->clk_rate);
> + if (val > UINT_MAX)
> + state->duty_cycle = UINT_MAX;
> + else if (val)
> + state->duty_cycle = val;
> + else
> + state->duty_cycle = 1;
> +
> + val = (unsigned long long)
> + readl_relaxed(mvebu_pwmreg_blink_off_duration);
> + val *= NSEC_PER_SEC;
> + do_div(val, mvpwm->clk_rate);
> + if (val < state->duty_cycle) {
> + state->period = 1;
> + } else {
> + val -= state->duty_cycle;
> + if (val > UINT_MAX)
> + state->period = UINT_MAX;
> + else if (val)
> + state->period = val;
> + else
> + state->period = 1;
> + }
> +
> + u = readl_relaxed(mvebu_gpioreg_blink(mvchip));
> + if (u)
> + state->enabled = true;
> + else
> + state->enabled = false;
> +
> + spin_unlock_irqrestore(&mvpwm->lock, flags);
> +}
> +
> +static int mvebu_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm,
> + struct pwm_state *state)
> +{
> + struct mvebu_pwm *mvpwm = to_mvebu_pwm(chip);
> + struct mvebu_gpio_chip *mvchip = mvpwm->mvchip;
> + unsigned long long val;
> + unsigned long flags;
> + unsigned int on, off;
> +
> + val = (unsigned long long) mvpwm->clk_rate * state->duty_cycle;
> + do_div(val, NSEC_PER_SEC);
> + if (val > UINT_MAX)
> + return -EINVAL;
> + if (val)
> + on = val;
> + else
> + on = 1;
> +
> + val = (unsigned long long) mvpwm->clk_rate *
> + (state->period - state->duty_cycle);
> + do_div(val, NSEC_PER_SEC);
> + if (val > UINT_MAX)
> + return -EINVAL;
> + if (val)
> + off = val;
> + else
> + off = 1;
> +
> + spin_lock_irqsave(&mvpwm->lock, flags);
> +
> + writel_relaxed(on, mvebu_pwmreg_blink_on_duration(mvpwm));
> + writel_relaxed(off, mvebu_pwmreg_blink_off_duration(mvpwm));
> + if (state->enabled)
> + mvebu_gpio_blink(&mvchip->chip, pwm->hwpwm, 1);
> + else
> + mvebu_gpio_blink(&mvchip->chip, pwm->hwpwm, 0);
> +
> + spin_unlock_irqrestore(&mvpwm->lock, flags);
> +
> + return 0;
> +}
> +
> +static const struct pwm_ops mvebu_pwm_ops = {
> + .request = mvebu_pwm_request,
> + .free = mvebu_pwm_free,
> + .get_state = mvebu_pwm_get_state,
> + .apply = mvebu_pwm_apply,
> + .owner = THIS_MODULE,
> +};
> +
> +static void __maybe_unused mvebu_pwm_suspend(struct mvebu_gpio_chip *mvchip)
> +{
> + struct mvebu_pwm *mvpwm = mvchip->mvpwm;
> +
> + mvpwm->blink_select =
> + readl_relaxed(mvebu_gpioreg_blink_counter_select(mvchip));
> + mvpwm->blink_on_duration =
> + readl_relaxed(mvebu_pwmreg_blink_on_duration(mvpwm));
> + mvpwm->blink_off_duration =
> + readl_relaxed(mvebu_pwmreg_blink_off_duration(mvpwm));
> +}
> +
> +static void __maybe_unused mvebu_pwm_resume(struct mvebu_gpio_chip *mvchip)
> +{
> + struct mvebu_pwm *mvpwm = mvchip->mvpwm;
> +
> + writel_relaxed(mvpwm->blink_select,
> + mvebu_gpioreg_blink_counter_select(mvchip));
> + writel_relaxed(mvpwm->blink_on_duration,
> + mvebu_pwmreg_blink_on_duration(mvpwm));
> + writel_relaxed(mvpwm->blink_off_duration,
> + mvebu_pwmreg_blink_off_duration(mvpwm));
> +}
> +
> +static int mvebu_pwm_probe(struct platform_device *pdev,
> + struct mvebu_gpio_chip *mvchip,
> + int id)
> +{
> + struct device *dev = &pdev->dev;
> + struct mvebu_pwm *mvpwm;
> + struct resource *res;
> +
> + if (!of_device_is_compatible(mvchip->chip.of_node,
> + "marvell,armada-370-xp-gpio"))
> + return 0;
> + /*
> + * There are only two sets of PWM configuration registers for
> + * all the GPIO lines on those SoCs which this driver reserves
> + * for the first two GPIO chips. So if the resource is missing
> + * we can't treat it as an error.
> + */
> + res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "pwm");
> + if (!res)
> + return 0;
> +
> + /*
> + * Use set A for lines of GPIO chip with id 0, B for GPIO chip
> + * with id 1. Don't allow further GPIO chips to be used for PWM.
> + */
> + if (id == 0)
> + writel_relaxed(0, mvebu_gpioreg_blink_counter_select(mvchip));
> + else if (id == 1)
> + writel_relaxed(U32_MAX,
> + mvebu_gpioreg_blink_counter_select(mvchip));
You could've just set a variable and then call writel_relaxed() after
the return -EINVAL below.
> + else
> + return -EINVAL;
> +
> + mvpwm = devm_kzalloc(dev, sizeof(struct mvebu_pwm), GFP_KERNEL);
> + if (!mvpwm)
> + return -ENOMEM;
> + mvchip->mvpwm = mvpwm;
> + mvpwm->mvchip = mvchip;
> +
> + mvpwm->membase = devm_ioremap_resource(dev, res);
> + if (IS_ERR(mvpwm->membase))
> + return PTR_ERR(mvpwm->membase);
> +
> + if (IS_ERR(mvchip->clk))
> + return PTR_ERR(mvchip->clk);
Maybe do this much earlier to avoid all the unnecessary register
accesses, allocations and mappings?
> +
> + mvpwm->clk_rate = clk_get_rate(mvchip->clk);
> + if (!mvpwm->clk_rate) {
> + dev_err(dev, "failed to get clock rate\n");
> + return -EINVAL;
> + }
> +
> + mvpwm->chip.dev = dev;
> + mvpwm->chip.ops = &mvebu_pwm_ops;
> + mvpwm->chip.base = mvchip->chip.base;
> + mvpwm->chip.npwm = mvchip->chip.ngpio;
I still would've done this differently. If you use this with a PWM user
you have to hook it up via DT anyway, so it doesn't matter whether you
specify the PWM index or the GPIO via some other property. The _only_
use-case where this might actually be an advantage is if you request a
PWM via the sysfs interface.
> + spin_lock_init(&mvpwm->lock);
> +
> + return pwmchip_add(&mvpwm->chip);
> +}
> +
> #ifdef CONFIG_DEBUG_FS
> #include <linux/seq_file.h>
>
> @@ -555,6 +842,10 @@ static const struct of_device_id mvebu_gpio_of_match[] = {
> .data = (void *) MVEBU_GPIO_SOC_VARIANT_ARMADAXP,
> },
> {
> + .compatible = "marvell,armada-370-xp-gpio",
> + .data = (void *) MVEBU_GPIO_SOC_VARIANT_ORION,
> + },
> + {
> /* sentinel */
> },
> };
> @@ -600,6 +891,9 @@ static int mvebu_gpio_suspend(struct platform_device *pdev, pm_message_t state)
> BUG();
> }
>
> + if (IS_ENABLED(CONFIG_PWM))
> + mvebu_pwm_suspend(mvchip);
> +
> return 0;
> }
>
> @@ -643,6 +937,9 @@ static int mvebu_gpio_resume(struct platform_device *pdev)
> BUG();
> }
>
> + if (IS_ENABLED(CONFIG_PWM))
> + mvebu_pwm_resume(mvchip);
> +
> return 0;
> }
>
> @@ -654,7 +951,6 @@ static int mvebu_gpio_probe(struct platform_device *pdev)
> struct resource *res;
> struct irq_chip_generic *gc;
> struct irq_chip_type *ct;
> - struct clk *clk;
> unsigned int ngpios;
> bool have_irqs;
> int soc_variant;
> @@ -688,10 +984,10 @@ static int mvebu_gpio_probe(struct platform_device *pdev)
> return id;
> }
>
> - clk = devm_clk_get(&pdev->dev, NULL);
> + mvchip->clk = devm_clk_get(&pdev->dev, NULL);
> /* Not all SoCs require a clock.*/
> - if (!IS_ERR(clk))
> - clk_prepare_enable(clk);
> + if (!IS_ERR(mvchip->clk))
> + clk_prepare_enable(mvchip->clk);
>
> mvchip->soc_variant = soc_variant;
> mvchip->chip.label = dev_name(&pdev->dev);
> @@ -822,6 +1118,10 @@ static int mvebu_gpio_probe(struct platform_device *pdev)
> mvchip);
> }
>
> + /* Armada 370/XP has simple PWM support for GPIO lines */
> + if (IS_ENABLED(CONFIG_PWM))
> + return mvebu_pwm_probe(pdev, mvchip, id);
> +
> return 0;
>
> err_domain:
> --
> 2.10.2
All of my comments are effectively of a bikeshed nature, so from a PWM
perspective this is:
Acked-by: Thierry Reding <thierry.reding@gmail.com>
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]
^ permalink raw reply
* [PATCH v3 2/2] mtd: spi-nor: add driver for STM32 quad spi flash controller
From: Ludovic Barre @ 2017-04-12 17:06 UTC (permalink / raw)
To: Cyrille Pitchen, Marek Vasut
Cc: David Woodhouse, Brian Norris, Boris Brezillon,
Richard Weinberger, Alexandre Torgue, Rob Herring, linux-mtd,
linux-kernel, devicetree
In-Reply-To: <1492016785-24976-1-git-send-email-ludovic.Barre@st.com>
From: Ludovic Barre <ludovic.barre@st.com>
The quadspi is a specialized communication interface targeting single,
dual or quad SPI Flash memories.
It can operate in any of the following modes:
-indirect mode: all the operations are performed using the quadspi
registers
-read memory-mapped mode: the external Flash memory is mapped to the
microcontroller address space and is seen by the system as if it was
an internal memory
Signed-off-by: Ludovic Barre <ludovic.barre@st.com>
---
drivers/mtd/spi-nor/Kconfig | 7 +
drivers/mtd/spi-nor/Makefile | 1 +
drivers/mtd/spi-nor/stm32-quadspi.c | 693 ++++++++++++++++++++++++++++++++++++
3 files changed, 701 insertions(+)
create mode 100644 drivers/mtd/spi-nor/stm32-quadspi.c
diff --git a/drivers/mtd/spi-nor/Kconfig b/drivers/mtd/spi-nor/Kconfig
index 7252087..bfdfb1e 100644
--- a/drivers/mtd/spi-nor/Kconfig
+++ b/drivers/mtd/spi-nor/Kconfig
@@ -106,4 +106,11 @@ config SPI_INTEL_SPI_PLATFORM
To compile this driver as a module, choose M here: the module
will be called intel-spi-platform.
+config SPI_STM32_QUADSPI
+ tristate "STM32 Quad SPI controller"
+ depends on ARCH_STM32
+ help
+ This enables support for the STM32 Quad SPI controller.
+ We only connect the NOR to this controller.
+
endif # MTD_SPI_NOR
diff --git a/drivers/mtd/spi-nor/Makefile b/drivers/mtd/spi-nor/Makefile
index 72238a7..285aab8 100644
--- a/drivers/mtd/spi-nor/Makefile
+++ b/drivers/mtd/spi-nor/Makefile
@@ -8,3 +8,4 @@ obj-$(CONFIG_MTD_MT81xx_NOR) += mtk-quadspi.o
obj-$(CONFIG_SPI_NXP_SPIFI) += nxp-spifi.o
obj-$(CONFIG_SPI_INTEL_SPI) += intel-spi.o
obj-$(CONFIG_SPI_INTEL_SPI_PLATFORM) += intel-spi-platform.o
+obj-$(CONFIG_SPI_STM32_QUADSPI) += stm32-quadspi.o
\ No newline at end of file
diff --git a/drivers/mtd/spi-nor/stm32-quadspi.c b/drivers/mtd/spi-nor/stm32-quadspi.c
new file mode 100644
index 0000000..9e90dee
--- /dev/null
+++ b/drivers/mtd/spi-nor/stm32-quadspi.c
@@ -0,0 +1,693 @@
+/*
+ * stm32_quadspi.c
+ *
+ * Copyright (C) 2017, Ludovic Barre
+ *
+ * License terms: GNU General Public License (GPL), version 2
+ */
+#include <linux/clk.h>
+#include <linux/errno.h>
+#include <linux/io.h>
+#include <linux/iopoll.h>
+#include <linux/interrupt.h>
+#include <linux/module.h>
+#include <linux/mtd/mtd.h>
+#include <linux/mtd/partitions.h>
+#include <linux/mtd/spi-nor.h>
+#include <linux/mutex.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/platform_device.h>
+#include <linux/reset.h>
+
+#define QUADSPI_CR 0x00
+#define CR_EN BIT(0)
+#define CR_ABORT BIT(1)
+#define CR_DMAEN BIT(2)
+#define CR_TCEN BIT(3)
+#define CR_SSHIFT BIT(4)
+#define CR_DFM BIT(6)
+#define CR_FSEL BIT(7)
+#define CR_FTHRES_SHIFT 8
+#define CR_FTHRES_MASK GENMASK(12, 8)
+#define CR_FTHRES(n) (((n) << CR_FTHRES_SHIFT) & CR_FTHRES_MASK)
+#define CR_TEIE BIT(16)
+#define CR_TCIE BIT(17)
+#define CR_FTIE BIT(18)
+#define CR_SMIE BIT(19)
+#define CR_TOIE BIT(20)
+#define CR_PRESC_SHIFT 24
+#define CR_PRESC_MASK GENMASK(31, 24)
+#define CR_PRESC(n) (((n) << CR_PRESC_SHIFT) & CR_PRESC_MASK)
+
+#define QUADSPI_DCR 0x04
+#define DCR_CSHT_SHIFT 8
+#define DCR_CSHT_MASK GENMASK(10, 8)
+#define DCR_CSHT(n) (((n) << DCR_CSHT_SHIFT) & DCR_CSHT_MASK)
+#define DCR_FSIZE_SHIFT 16
+#define DCR_FSIZE_MASK GENMASK(20, 16)
+#define DCR_FSIZE(n) (((n) << DCR_FSIZE_SHIFT) & DCR_FSIZE_MASK)
+
+#define QUADSPI_SR 0x08
+#define SR_TEF BIT(0)
+#define SR_TCF BIT(1)
+#define SR_FTF BIT(2)
+#define SR_SMF BIT(3)
+#define SR_TOF BIT(4)
+#define SR_BUSY BIT(5)
+#define SR_FLEVEL_SHIFT 8
+#define SR_FLEVEL_MASK GENMASK(13, 8)
+
+#define QUADSPI_FCR 0x0c
+#define FCR_CTCF BIT(1)
+
+#define QUADSPI_DLR 0x10
+
+#define QUADSPI_CCR 0x14
+#define CCR_INST_SHIFT 0
+#define CCR_INST_MASK GENMASK(7, 0)
+#define CCR_INST(n) (((n) << CCR_INST_SHIFT) & CCR_INST_MASK)
+#define CCR_IMODE_NONE (0 << 8)
+#define CCR_IMODE_1 (1 << 8)
+#define CCR_IMODE_2 (2 << 8)
+#define CCR_IMODE_4 (3 << 8)
+#define CCR_ADMODE_NONE (0 << 10)
+#define CCR_ADMODE_1 (1 << 10)
+#define CCR_ADMODE_2 (2 << 10)
+#define CCR_ADMODE_4 (3 << 10)
+#define CCR_ADSIZE_SHIFT 12
+#define CCR_ADSIZE_MASK GENMASK(13, 12)
+#define CCR_ADSIZE(n) (((n) << CCR_ADSIZE_SHIFT) & CCR_ADSIZE_MASK)
+#define CCR_ABMODE_NONE (0 << 14)
+#define CCR_ABMODE_1 (1 << 14)
+#define CCR_ABMODE_2 (2 << 14)
+#define CCR_ABMODE_4 (3 << 14)
+#define CCR_ABSIZE_8 (0 << 16)
+#define CCR_ABSIZE_16 (1 << 16)
+#define CCR_ABSIZE_24 (2 << 16)
+#define CCR_ABSIZE_32 (3 << 16)
+#define CCR_DCYC_SHIFT 18
+#define CCR_DCYC_MASK GENMASK(22, 18)
+#define CCR_DCYC(n) (((n) << CCR_DCYC_SHIFT) & CCR_DCYC_MASK)
+#define CCR_DMODE_NONE (0 << 24)
+#define CCR_DMODE_1 (1 << 24)
+#define CCR_DMODE_2 (2 << 24)
+#define CCR_DMODE_4 (3 << 24)
+#define CCR_FMODE_INDW (0 << 26)
+#define CCR_FMODE_INDR (1 << 26)
+#define CCR_FMODE_APM (2 << 26)
+#define CCR_FMODE_MM (3 << 26)
+
+#define QUADSPI_AR 0x18
+#define QUADSPI_ABR 0x1c
+#define QUADSPI_DR 0x20
+#define QUADSPI_PSMKR 0x24
+#define QUADSPI_PSMAR 0x28
+#define QUADSPI_PIR 0x2c
+#define QUADSPI_LPTR 0x30
+#define LPTR_DFT_TIMEOUT 0x10
+
+#define FSIZE_VAL(size) (__fls(size) - 1)
+
+#define STM32_MAX_MMAP_SZ SZ_256M
+#define STM32_MAX_NORCHIP 2
+
+#define STM32_QSPI_FIFO_TIMEOUT_US 30000
+#define STM32_QSPI_BUSY_TIMEOUT_US 100000
+
+struct stm32_qspi_flash {
+ struct spi_nor nor;
+ u32 cs;
+ u32 fsize;
+ u32 presc;
+ u32 read_mode;
+ struct stm32_qspi *qspi;
+};
+
+struct stm32_qspi {
+ struct device *dev;
+ void __iomem *io_base;
+ void __iomem *mm_base;
+ resource_size_t mm_size;
+ u32 nor_num;
+ struct clk *clk;
+ u32 clk_rate;
+ struct stm32_qspi_flash flash[STM32_MAX_NORCHIP];
+ struct completion cmd_completion;
+
+ /*
+ * to protect device configuration, could be different between
+ * 2 flash access (bk1, bk2)
+ */
+ struct mutex lock;
+};
+
+struct stm32_qspi_cmd {
+ u8 addr_width;
+ u8 dummy;
+ bool tx_data;
+ u8 opcode;
+ u32 framemode;
+ u32 qspimode;
+ u32 addr;
+ size_t len;
+ void *buf;
+};
+
+static int stm32_qspi_wait_cmd(struct stm32_qspi *qspi)
+{
+ u32 cr;
+ int err = 0;
+
+ if (readl_relaxed(qspi->io_base + QUADSPI_SR) & SR_TCF)
+ return 0;
+
+ reinit_completion(&qspi->cmd_completion);
+ cr = readl_relaxed(qspi->io_base + QUADSPI_CR);
+ writel_relaxed(cr | CR_TCIE, qspi->io_base + QUADSPI_CR);
+
+ if (!wait_for_completion_interruptible_timeout(&qspi->cmd_completion,
+ msecs_to_jiffies(1000)))
+ err = -ETIMEDOUT;
+
+ writel_relaxed(cr, qspi->io_base + QUADSPI_CR);
+ return err;
+}
+
+static int stm32_qspi_wait_nobusy(struct stm32_qspi *qspi)
+{
+ u32 sr;
+
+ return readl_relaxed_poll_timeout(qspi->io_base + QUADSPI_SR, sr,
+ !(sr & SR_BUSY), 10,
+ STM32_QSPI_BUSY_TIMEOUT_US);
+}
+
+static void stm32_qspi_set_framemode(struct spi_nor *nor,
+ struct stm32_qspi_cmd *cmd, bool read)
+{
+ u32 dmode = CCR_DMODE_1;
+
+ cmd->framemode = CCR_IMODE_1;
+
+ if (read) {
+ switch (nor->flash_read) {
+ case SPI_NOR_NORMAL:
+ case SPI_NOR_FAST:
+ dmode = CCR_DMODE_1;
+ break;
+ case SPI_NOR_DUAL:
+ dmode = CCR_DMODE_2;
+ break;
+ case SPI_NOR_QUAD:
+ dmode = CCR_DMODE_4;
+ break;
+ }
+ }
+
+ cmd->framemode |= cmd->tx_data ? dmode : 0;
+ cmd->framemode |= cmd->addr_width ? CCR_ADMODE_1 : 0;
+}
+
+static void stm32_qspi_read_fifo(u8 *val, void __iomem *addr)
+{
+ *val = readb_relaxed(addr);
+}
+
+static void stm32_qspi_write_fifo(u8 *val, void __iomem *addr)
+{
+ writeb_relaxed(*val, addr);
+}
+
+static int stm32_qspi_tx_poll(struct stm32_qspi *qspi,
+ const struct stm32_qspi_cmd *cmd)
+{
+ void (*tx_fifo)(u8 *, void __iomem *);
+ u32 len = cmd->len, sr;
+ u8 *buf = cmd->buf;
+ int ret;
+
+ if (cmd->qspimode == CCR_FMODE_INDW)
+ tx_fifo = stm32_qspi_write_fifo;
+ else
+ tx_fifo = stm32_qspi_read_fifo;
+
+ while (len--) {
+ ret = readl_relaxed_poll_timeout(qspi->io_base + QUADSPI_SR,
+ sr, (sr & SR_FTF), 10,
+ STM32_QSPI_FIFO_TIMEOUT_US);
+ if (ret) {
+ dev_err(qspi->dev, "fifo timeout (stat:%#x)\n", sr);
+ break;
+ }
+ tx_fifo(buf++, qspi->io_base + QUADSPI_DR);
+ }
+
+ return ret;
+}
+
+static int stm32_qspi_tx_mm(struct stm32_qspi *qspi,
+ const struct stm32_qspi_cmd *cmd)
+{
+ memcpy_fromio(cmd->buf, qspi->mm_base + cmd->addr, cmd->len);
+ return 0;
+}
+
+static int stm32_qspi_tx(struct stm32_qspi *qspi,
+ const struct stm32_qspi_cmd *cmd)
+{
+ if (!cmd->tx_data)
+ return 0;
+
+ if (cmd->qspimode == CCR_FMODE_MM)
+ return stm32_qspi_tx_mm(qspi, cmd);
+
+ return stm32_qspi_tx_poll(qspi, cmd);
+}
+
+static int stm32_qspi_send(struct stm32_qspi_flash *flash,
+ const struct stm32_qspi_cmd *cmd)
+{
+ struct stm32_qspi *qspi = flash->qspi;
+ u32 ccr, dcr, cr;
+ int err;
+
+ err = stm32_qspi_wait_nobusy(qspi);
+ if (err)
+ goto abort;
+
+ dcr = readl_relaxed(qspi->io_base + QUADSPI_DCR) & ~DCR_FSIZE_MASK;
+ dcr |= DCR_FSIZE(flash->fsize);
+ writel_relaxed(dcr, qspi->io_base + QUADSPI_DCR);
+
+ cr = readl_relaxed(qspi->io_base + QUADSPI_CR);
+ cr &= ~CR_PRESC_MASK & ~CR_FSEL;
+ cr |= CR_PRESC(flash->presc);
+ cr |= flash->cs ? CR_FSEL : 0;
+ writel_relaxed(cr, qspi->io_base + QUADSPI_CR);
+
+ if (cmd->tx_data)
+ writel_relaxed(cmd->len - 1, qspi->io_base + QUADSPI_DLR);
+
+ ccr = cmd->framemode | cmd->qspimode;
+
+ if (cmd->dummy)
+ ccr |= CCR_DCYC(cmd->dummy);
+
+ if (cmd->addr_width)
+ ccr |= CCR_ADSIZE(cmd->addr_width - 1);
+
+ ccr |= CCR_INST(cmd->opcode);
+ writel_relaxed(ccr, qspi->io_base + QUADSPI_CCR);
+
+ if (cmd->addr_width && cmd->qspimode != CCR_FMODE_MM)
+ writel_relaxed(cmd->addr, qspi->io_base + QUADSPI_AR);
+
+ err = stm32_qspi_tx(qspi, cmd);
+ if (err)
+ goto abort;
+
+ if (cmd->qspimode != CCR_FMODE_MM) {
+ err = stm32_qspi_wait_cmd(qspi);
+ if (err)
+ goto abort;
+ writel_relaxed(FCR_CTCF, qspi->io_base + QUADSPI_FCR);
+ }
+
+ return err;
+
+abort:
+ cr = readl_relaxed(qspi->io_base + QUADSPI_CR) | CR_ABORT;
+ writel_relaxed(cr, qspi->io_base + QUADSPI_CR);
+
+ dev_err(qspi->dev, "%s abort err:%d\n", __func__, err);
+ return err;
+}
+
+static int stm32_qspi_read_reg(struct spi_nor *nor,
+ u8 opcode, u8 *buf, int len)
+{
+ struct stm32_qspi_flash *flash = nor->priv;
+ struct device *dev = flash->qspi->dev;
+ struct stm32_qspi_cmd cmd;
+
+ dev_dbg(dev, "read_reg: cmd:%#.2x buf:%p len:%#x\n", opcode, buf, len);
+
+ memset(&cmd, 0, sizeof(cmd));
+ cmd.opcode = opcode;
+ cmd.tx_data = true;
+ cmd.len = len;
+ cmd.buf = buf;
+ cmd.qspimode = CCR_FMODE_INDR;
+
+ stm32_qspi_set_framemode(nor, &cmd, false);
+
+ return stm32_qspi_send(flash, &cmd);
+}
+
+static int stm32_qspi_write_reg(struct spi_nor *nor, u8 opcode,
+ u8 *buf, int len)
+{
+ struct stm32_qspi_flash *flash = nor->priv;
+ struct device *dev = flash->qspi->dev;
+ struct stm32_qspi_cmd cmd;
+
+ dev_dbg(dev, "write_reg: cmd:%#.2x buf:%p len:%#x\n", opcode, buf, len);
+
+ memset(&cmd, 0, sizeof(cmd));
+ cmd.opcode = opcode;
+ cmd.tx_data = !!(buf && len > 0);
+ cmd.len = len;
+ cmd.buf = buf;
+ cmd.qspimode = CCR_FMODE_INDW;
+
+ stm32_qspi_set_framemode(nor, &cmd, false);
+
+ return stm32_qspi_send(flash, &cmd);
+}
+
+static ssize_t stm32_qspi_read(struct spi_nor *nor, loff_t from, size_t len,
+ u_char *buf)
+{
+ struct stm32_qspi_flash *flash = nor->priv;
+ struct stm32_qspi *qspi = flash->qspi;
+ struct stm32_qspi_cmd cmd;
+ int err;
+
+ dev_dbg(qspi->dev, "read(%#.2x): buf:%p from:%#.8x len:%#x\n",
+ nor->read_opcode, buf, (u32)from, len);
+
+ memset(&cmd, 0, sizeof(cmd));
+ cmd.opcode = nor->read_opcode;
+ cmd.addr_width = nor->addr_width;
+ cmd.addr = (u32)from;
+ cmd.tx_data = true;
+ cmd.dummy = nor->read_dummy;
+ cmd.len = len;
+ cmd.buf = buf;
+ cmd.qspimode = flash->read_mode;
+
+ stm32_qspi_set_framemode(nor, &cmd, true);
+ err = stm32_qspi_send(flash, &cmd);
+
+ return err ? err : len;
+}
+
+static ssize_t stm32_qspi_write(struct spi_nor *nor, loff_t to, size_t len,
+ const u_char *buf)
+{
+ struct stm32_qspi_flash *flash = nor->priv;
+ struct device *dev = flash->qspi->dev;
+ struct stm32_qspi_cmd cmd;
+ int err;
+
+ dev_dbg(dev, "write(%#.2x): buf:%p to:%#.8x len:%#x\n",
+ nor->program_opcode, buf, (u32)to, len);
+
+ memset(&cmd, 0, sizeof(cmd));
+ cmd.opcode = nor->program_opcode;
+ cmd.addr_width = nor->addr_width;
+ cmd.addr = (u32)to;
+ cmd.tx_data = true;
+ cmd.len = len;
+ cmd.buf = (void *)buf;
+ cmd.qspimode = CCR_FMODE_INDW;
+
+ stm32_qspi_set_framemode(nor, &cmd, false);
+ err = stm32_qspi_send(flash, &cmd);
+
+ return err ? err : len;
+}
+
+static int stm32_qspi_erase(struct spi_nor *nor, loff_t offs)
+{
+ struct stm32_qspi_flash *flash = nor->priv;
+ struct device *dev = flash->qspi->dev;
+ struct stm32_qspi_cmd cmd;
+
+ dev_dbg(dev, "erase(%#.2x):offs:%#x\n", nor->erase_opcode, (u32)offs);
+
+ memset(&cmd, 0, sizeof(cmd));
+ cmd.opcode = nor->erase_opcode;
+ cmd.addr_width = nor->addr_width;
+ cmd.addr = (u32)offs;
+ cmd.qspimode = CCR_FMODE_INDW;
+
+ stm32_qspi_set_framemode(nor, &cmd, false);
+
+ return stm32_qspi_send(flash, &cmd);
+}
+
+static irqreturn_t stm32_qspi_irq(int irq, void *dev_id)
+{
+ struct stm32_qspi *qspi = (struct stm32_qspi *)dev_id;
+ u32 cr, sr, fcr = 0;
+
+ cr = readl_relaxed(qspi->io_base + QUADSPI_CR);
+ sr = readl_relaxed(qspi->io_base + QUADSPI_SR);
+
+ if ((cr & CR_TCIE) && (sr & SR_TCF)) {
+ /* tx complete */
+ fcr |= FCR_CTCF;
+ complete(&qspi->cmd_completion);
+ } else {
+ dev_info_ratelimited(qspi->dev, "spurious interrupt\n");
+ }
+
+ writel_relaxed(fcr, qspi->io_base + QUADSPI_FCR);
+
+ return IRQ_HANDLED;
+}
+
+static int stm32_qspi_prep(struct spi_nor *nor, enum spi_nor_ops ops)
+{
+ struct stm32_qspi_flash *flash = nor->priv;
+ struct stm32_qspi *qspi = flash->qspi;
+
+ mutex_lock(&qspi->lock);
+ return 0;
+}
+
+static void stm32_qspi_unprep(struct spi_nor *nor, enum spi_nor_ops ops)
+{
+ struct stm32_qspi_flash *flash = nor->priv;
+ struct stm32_qspi *qspi = flash->qspi;
+
+ mutex_unlock(&qspi->lock);
+}
+
+static int stm32_qspi_flash_setup(struct stm32_qspi *qspi,
+ struct device_node *np)
+{
+ u32 width, flash_read, presc, cs_num, max_rate = 0;
+ struct stm32_qspi_flash *flash;
+ struct mtd_info *mtd;
+ int ret;
+
+ of_property_read_u32(np, "reg", &cs_num);
+ if (cs_num >= STM32_MAX_NORCHIP)
+ return -EINVAL;
+
+ of_property_read_u32(np, "spi-max-frequency", &max_rate);
+ if (!max_rate)
+ return -EINVAL;
+
+ presc = DIV_ROUND_UP(qspi->clk_rate, max_rate) - 1;
+
+ if (of_property_read_u32(np, "spi-rx-bus-width", &width))
+ width = 1;
+
+ if (width == 4)
+ flash_read = SPI_NOR_QUAD;
+ else if (width == 2)
+ flash_read = SPI_NOR_DUAL;
+ else if (width == 1)
+ flash_read = SPI_NOR_NORMAL;
+ else
+ return -EINVAL;
+
+ flash = &qspi->flash[cs_num];
+ flash->qspi = qspi;
+ flash->cs = cs_num;
+ flash->presc = presc;
+
+ flash->nor.dev = qspi->dev;
+ spi_nor_set_flash_node(&flash->nor, np);
+ flash->nor.priv = flash;
+ mtd = &flash->nor.mtd;
+ mtd->priv = &flash->nor;
+
+ flash->nor.read = stm32_qspi_read;
+ flash->nor.write = stm32_qspi_write;
+ flash->nor.erase = stm32_qspi_erase;
+ flash->nor.read_reg = stm32_qspi_read_reg;
+ flash->nor.write_reg = stm32_qspi_write_reg;
+ flash->nor.prepare = stm32_qspi_prep;
+ flash->nor.unprepare = stm32_qspi_unprep;
+
+ writel_relaxed(LPTR_DFT_TIMEOUT, qspi->io_base + QUADSPI_LPTR);
+
+ writel_relaxed(CR_PRESC(presc) | CR_FTHRES(3) | CR_TCEN | CR_SSHIFT
+ | CR_EN, qspi->io_base + QUADSPI_CR);
+
+ /*
+ * in stm32 qspi controller, QUADSPI_DCR register has a fsize field
+ * which define the size of nor flash.
+ * if fsize is NULL, the controller can't sent spi-nor command.
+ * set a temporary value just to discover the nor flash with
+ * "spi_nor_scan". After, the right value (mtd->size) can be set.
+ */
+ flash->fsize = FSIZE_VAL(SZ_1K);
+
+ ret = spi_nor_scan(&flash->nor, NULL, flash_read);
+ if (ret) {
+ dev_err(qspi->dev, "device scan failed\n");
+ return ret;
+ }
+
+ flash->fsize = FSIZE_VAL(mtd->size);
+
+ flash->read_mode = CCR_FMODE_MM;
+ if (mtd->size > qspi->mm_size)
+ flash->read_mode = CCR_FMODE_INDR;
+
+ writel_relaxed(DCR_CSHT(1), qspi->io_base + QUADSPI_DCR);
+
+ ret = mtd_device_register(mtd, NULL, 0);
+ if (ret) {
+ dev_err(qspi->dev, "mtd device parse failed\n");
+ return ret;
+ }
+
+ dev_dbg(qspi->dev, "read mm:%s cs:%d bus:%d\n",
+ flash->read_mode == CCR_FMODE_MM ? "yes" : "no", cs_num, width);
+
+ return 0;
+}
+
+static void stm32_qspi_mtd_free(struct stm32_qspi *qspi)
+{
+ int i;
+
+ for (i = 0; i < STM32_MAX_NORCHIP; i++) {
+ if (qspi->flash[i].qspi)
+ mtd_device_unregister(&qspi->flash[i].nor.mtd);
+ }
+}
+
+static int stm32_qspi_probe(struct platform_device *pdev)
+{
+ struct device *dev = &pdev->dev;
+ struct device_node *flash_np;
+ struct reset_control *rstc;
+ struct stm32_qspi *qspi;
+ struct resource *res;
+ int ret, irq;
+
+ qspi = devm_kzalloc(dev, sizeof(*qspi), GFP_KERNEL);
+ if (!qspi)
+ return -ENOMEM;
+
+ qspi->nor_num = of_get_child_count(dev->of_node);
+ if (!qspi->nor_num || qspi->nor_num > STM32_MAX_NORCHIP)
+ return -ENODEV;
+
+ res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "qspi");
+ qspi->io_base = devm_ioremap_resource(dev, res);
+ if (IS_ERR(qspi->io_base))
+ return PTR_ERR(qspi->io_base);
+
+ res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "qspi_mm");
+ qspi->mm_base = devm_ioremap_resource(dev, res);
+ if (IS_ERR(qspi->mm_base))
+ return PTR_ERR(qspi->mm_base);
+
+ qspi->mm_size = resource_size(res);
+
+ irq = platform_get_irq(pdev, 0);
+ ret = devm_request_irq(dev, irq, stm32_qspi_irq, 0,
+ dev_name(dev), qspi);
+ if (ret) {
+ dev_err(dev, "failed to request irq\n");
+ return ret;
+ }
+
+ init_completion(&qspi->cmd_completion);
+
+ qspi->clk = devm_clk_get(dev, NULL);
+ if (IS_ERR(qspi->clk))
+ return PTR_ERR(qspi->clk);
+
+ qspi->clk_rate = clk_get_rate(qspi->clk);
+ if (!qspi->clk_rate)
+ return -EINVAL;
+
+ ret = clk_prepare_enable(qspi->clk);
+ if (ret) {
+ dev_err(dev, "can not enable the clock\n");
+ return ret;
+ }
+
+ rstc = devm_reset_control_get(dev, NULL);
+ if (!IS_ERR(rstc)) {
+ reset_control_assert(rstc);
+ udelay(2);
+ reset_control_deassert(rstc);
+ }
+
+ qspi->dev = dev;
+ platform_set_drvdata(pdev, qspi);
+ mutex_init(&qspi->lock);
+
+ for_each_available_child_of_node(dev->of_node, flash_np) {
+ ret = stm32_qspi_flash_setup(qspi, flash_np);
+ if (ret) {
+ dev_err(dev, "unable to setup flash chip\n");
+ goto err_flash;
+ }
+ }
+
+ return 0;
+
+err_flash:
+ mutex_destroy(&qspi->lock);
+ stm32_qspi_mtd_free(qspi);
+
+ clk_disable_unprepare(qspi->clk);
+ return ret;
+}
+
+static int stm32_qspi_remove(struct platform_device *pdev)
+{
+ struct stm32_qspi *qspi = platform_get_drvdata(pdev);
+
+ /* disable qspi */
+ writel_relaxed(0, qspi->io_base + QUADSPI_CR);
+
+ stm32_qspi_mtd_free(qspi);
+ mutex_destroy(&qspi->lock);
+
+ clk_disable_unprepare(qspi->clk);
+ return 0;
+}
+
+static const struct of_device_id stm32_qspi_match[] = {
+ {.compatible = "st,stm32f469-qspi"},
+ {}
+};
+MODULE_DEVICE_TABLE(of, stm32_qspi_match);
+
+static struct platform_driver stm32_qspi_driver = {
+ .probe = stm32_qspi_probe,
+ .remove = stm32_qspi_remove,
+ .driver = {
+ .name = "stm32-quadspi",
+ .of_match_table = stm32_qspi_match,
+ },
+};
+module_platform_driver(stm32_qspi_driver);
+
+MODULE_ALIAS("platform:" DRIVER_NAME);
+MODULE_AUTHOR("Ludovic Barre <ludovic.barre@st.com>");
+MODULE_DESCRIPTION("STMicroelectronics STM32 quad spi driver");
+MODULE_LICENSE("GPL v2");
--
2.7.4
^ permalink raw reply related
* [PATCH v3 1/2] dt-bindings: Document the STM32 QSPI bindings
From: Ludovic Barre @ 2017-04-12 17:06 UTC (permalink / raw)
To: Cyrille Pitchen, Marek Vasut
Cc: David Woodhouse, Brian Norris, Boris Brezillon,
Richard Weinberger, Alexandre Torgue, Rob Herring,
linux-mtd-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
linux-kernel-u79uwXL29TY76Z2rM5mHXA,
devicetree-u79uwXL29TY76Z2rM5mHXA
In-Reply-To: <1492016785-24976-1-git-send-email-ludovic.Barre-qxv4g6HH51o@public.gmane.org>
From: Ludovic Barre <ludovic.barre-qxv4g6HH51o@public.gmane.org>
This patch adds documentation of device tree bindings for the STM32
QSPI controller.
Signed-off-by: Ludovic Barre <ludovic.barre-qxv4g6HH51o@public.gmane.org>
---
.../devicetree/bindings/mtd/stm32-quadspi.txt | 43 ++++++++++++++++++++++
1 file changed, 43 insertions(+)
create mode 100644 Documentation/devicetree/bindings/mtd/stm32-quadspi.txt
diff --git a/Documentation/devicetree/bindings/mtd/stm32-quadspi.txt b/Documentation/devicetree/bindings/mtd/stm32-quadspi.txt
new file mode 100644
index 0000000..ddd18c1
--- /dev/null
+++ b/Documentation/devicetree/bindings/mtd/stm32-quadspi.txt
@@ -0,0 +1,43 @@
+* STMicroelectronics Quad Serial Peripheral Interface(QuadSPI)
+
+Required properties:
+- compatible: should be "st,stm32f469-qspi"
+- reg: the first contains the register location and length.
+ the second contains the memory mapping address and length
+- reg-names: should contain the reg names "qspi" "qspi_mm"
+- interrupts: should contain the interrupt for the device
+- clocks: the phandle of the clock needed by the QSPI controller
+- A pinctrl must be defined to set pins in mode of operation for QSPI transfer
+
+Optional properties:
+- resets: must contain the phandle to the reset controller.
+
+A spi flash must be a child of the nor_flash node and could have some
+properties. Also see jedec,spi-nor.txt.
+
+Required properties:
+- reg: chip-Select number (QSPI controller may connect 2 nor flashes)
+- spi-max-frequency: max frequency of spi bus
+
+Optional property:
+- spi-rx-bus-width: see ../spi/spi-bus.txt for the description
+
+Example:
+
+qspi: spi@a0001000 {
+ compatible = "st,stm32f469-qspi";
+ reg = <0xa0001000 0x1000>, <0x90000000 0x10000000>;
+ reg-names = "qspi", "qspi_mm";
+ interrupts = <91>;
+ resets = <&rcc STM32F4_AHB3_RESET(QSPI)>;
+ clocks = <&rcc 0 STM32F4_AHB3_CLOCK(QSPI)>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_qspi0>;
+
+ flash@0 {
+ reg = <0>;
+ spi-rx-bus-width = <4>;
+ spi-max-frequency = <108000000>;
+ ...
+ };
+};
--
2.7.4
--
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
* [PATCH v3 0/2] mtd: spi-nor: add stm32 qspi driver
From: Ludovic Barre @ 2017-04-12 17:06 UTC (permalink / raw)
To: Cyrille Pitchen, Marek Vasut
Cc: David Woodhouse, Brian Norris, Boris Brezillon,
Richard Weinberger, Alexandre Torgue, Rob Herring,
linux-mtd-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
linux-kernel-u79uwXL29TY76Z2rM5mHXA,
devicetree-u79uwXL29TY76Z2rM5mHXA
From: Ludovic Barre <ludovic.barre-qxv4g6HH51o@public.gmane.org>
This patch set adds a SPI-NOR driver for stm32 QSPI controller.
It is a specialized SPI interface for serial Flash devices.
It supports 1 or 2 Flash device with single, dual and quad SPI Flash memories.
It can operate in any of the following modes:
-indirect mode: all the operations are performed using the quadspi
registers
-read memory-mapped mode: the external Flash memory is mapped to the
microcontroller address space and is seen by the system as if it was
an internal memory
Changes in v3:
-dt-bindings: qspi_mm not optional
-dt-bindings: see ../spi/spi-bus.txt
-dt-bindings: spi@...
-cmd flat struct
-ratelimit
-macro to avoid hard value "25"
Changes in v2:
-awful construct: s/u32/u8
-add define for timeout
-Use a helper variable
-add comment on "stm32 qspi controller fsize issue
Ludovic Barre (2):
dt-bindings: Document the STM32 QSPI bindings
mtd: spi-nor: add driver for STM32 quad spi flash controller
.../devicetree/bindings/mtd/stm32-quadspi.txt | 43 ++
drivers/mtd/spi-nor/Kconfig | 7 +
drivers/mtd/spi-nor/Makefile | 1 +
drivers/mtd/spi-nor/stm32-quadspi.c | 693 +++++++++++++++++++++
4 files changed, 744 insertions(+)
create mode 100644 Documentation/devicetree/bindings/mtd/stm32-quadspi.txt
create mode 100644 drivers/mtd/spi-nor/stm32-quadspi.c
--
2.7.4
--
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
* Re: [PATCH V4 1/9] PM / OPP: Allow OPP table to be used for power-domains
From: Sudeep Holla @ 2017-04-12 17:05 UTC (permalink / raw)
To: Viresh Kumar, Rafael Wysocki, ulf.hansson-QSEj5FYQhm4dnm+yROfE0A,
Kevin Hilman, Viresh Kumar, Nishanth Menon, Stephen Boyd
Cc: Sudeep Holla, linaro-kernel-cunTk1MwBs8s++Sfvej+rw,
linux-pm-u79uwXL29TY76Z2rM5mHXA,
linux-kernel-u79uwXL29TY76Z2rM5mHXA, Vincent Guittot,
robh+dt-DgEjT+Ai2ygdnm+yROfE0A, lina.iyer-QSEj5FYQhm4dnm+yROfE0A,
rnayak-sgV2jX0FEOL9JmXXK+q4OQ, devicetree-u79uwXL29TY76Z2rM5mHXA
In-Reply-To: <e772e67a5445319bb8e0f312846ace666adc097f.1490001099.git.viresh.kumar-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
On 20/03/17 09:32, Viresh Kumar wrote:
[...]
> +
> +Example 7: domain-Performance-state:
> +(example: For 1GHz require domain state 1 and for 1.1 & 1.2 GHz require state 2)
> +
> +/ {
> + domain_opp_table: opp_table0 {
> + compatible = "operating-points-v2";
> +
> + opp@1 {
> + domain-performance-state = <1>;
> + opp-microvolt = <975000 970000 985000>;
> + };
> + opp@2 {
> + domain-performance-state = <2>;
> + opp-microvolt = <1075000 1000000 1085000>;
> + };
> + };
> +
> + foo_domain: power-controller@12340000 {
> + compatible = "foo,power-controller";
> + reg = <0x12340000 0x1000>;
> + #power-domain-cells = <0>;
> + operating-points-v2 = <&domain_opp_table>;
> + }
> +
> + cpu0_opp_table: opp_table1 {
> + compatible = "operating-points-v2";
> + opp-shared;
> +
> + opp@1000000000 {
> + opp-hz = /bits/ 64 <1000000000>;
> + domain-performance-state = <1>;
> + };
> + opp@1100000000 {
> + opp-hz = /bits/ 64 <1100000000>;
> + domain-performance-state = <2>;
> + };
> + opp@1200000000 {
> + opp-hz = /bits/ 64 <1200000000>;
> + domain-performance-state = <2>;
> + };
> + };
> +
> + cpus {
> + #address-cells = <1>;
> + #size-cells = <0>;
> +
> + cpu@0 {
> + compatible = "arm,cortex-a9";
> + reg = <0>;
> + clocks = <&clk_controller 0>;
> + clock-names = "cpu";
> + operating-points-v2 = <&cpu0_opp_table>;
> + power-domains = <&foo_domain>;
> + };
> + };
> +};
Thinking more about this above example, I think you need more
explanation. So in the above case you have cpu with clock controller,
power-domain and the OPP table info, I can think of few things that need
to be explicit:
1. How does the precedence look like ?
2. Since power-domains with OPP table control the performance state, do
we ignore clock and operating-points-v2 in the above case completely?
3. Will the power-domain drive the OPP ?
--
Regards,
Sudeep
--
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
* Re: [PATCH V4 2/9] PM / Domains: Use OPP tables for power-domains
From: Sudeep Holla @ 2017-04-12 16:58 UTC (permalink / raw)
To: Viresh Kumar
Cc: Rafael Wysocki, ulf.hansson-QSEj5FYQhm4dnm+yROfE0A, Kevin Hilman,
Sudeep Holla, linaro-kernel-cunTk1MwBs8s++Sfvej+rw,
linux-pm-u79uwXL29TY76Z2rM5mHXA,
linux-kernel-u79uwXL29TY76Z2rM5mHXA, Vincent Guittot,
Stephen Boyd, Nishanth Menon, robh+dt-DgEjT+Ai2ygdnm+yROfE0A,
lina.iyer-QSEj5FYQhm4dnm+yROfE0A, rnayak-sgV2jX0FEOL9JmXXK+q4OQ,
devicetree-u79uwXL29TY76Z2rM5mHXA
In-Reply-To: <5619ac7777689f282f8aafabbde22d71b46a979b.1490001099.git.viresh.kumar-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
On 20/03/17 09:32, Viresh Kumar wrote:
> The OPP table bindings contains all the necessary fields to support
> power-domains now. Update the power-domain bindings to allow
> "operating-points-v2" to be present within the power-domain node.
>
> Also allow consumer devices, that don't use OPP tables, to specify the
> parent power-domain's performance level using the
> "domain-performance-state" property.
>
> Signed-off-by: Viresh Kumar <viresh.kumar-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
> ---
> .../devicetree/bindings/power/power_domain.txt | 42 ++++++++++++++++++++++
> 1 file changed, 42 insertions(+)
>
> diff --git a/Documentation/devicetree/bindings/power/power_domain.txt b/Documentation/devicetree/bindings/power/power_domain.txt
> index 723e1ad937da..5db112fa5d7c 100644
> --- a/Documentation/devicetree/bindings/power/power_domain.txt
> +++ b/Documentation/devicetree/bindings/power/power_domain.txt
> @@ -38,6 +38,9 @@ phandle arguments (so called PM domain specifiers) of length specified by the
> domain's idle states. In the absence of this property, the domain would be
> considered as capable of being powered-on or powered-off.
>
> +- operating-points-v2 : This describes the performance states of a PM domain.
> + Refer to ../opp/opp.txt for more information.
> +
> Example:
>
> power: power-controller@12340000 {
> @@ -118,4 +121,43 @@ The node above defines a typical PM domain consumer device, which is located
> inside a PM domain with index 0 of a power controller represented by a node
> with the label "power".
>
> +Optional properties:
> +- domain-performance-state: A positive integer value representing the minimum
> + power-domain performance level required by the consumer device. The integer
> + value '0' represents the lowest performance level and the higher values
> + represent higher performance levels. The value of "domain-performance-state"
> + field should match the "domain-performance-state" field of one of the OPP
> + nodes in the parent power-domain's OPP table.
> +
> +
> +
> +Example:
> +
> + domain_opp_table: opp_table {
> + compatible = "operating-points-v2";
> +
> + opp@1 {
> + domain-performance-state = <1>;
> + opp-microvolt = <975000 970000 985000>;
> + };
> + opp@2 {
> + domain-performance-state = <2>;
> + opp-microvolt = <1075000 1000000 1085000>;
> + };
> + };
> +
> + parent: power-controller@12340000 {
> + compatible = "foo,power-controller";
> + reg = <0x12340000 0x1000>;
> + #power-domain-cells = <0>;
> + operating-points-v2 = <&domain_opp_table>;
As mentioned in the other email, it would be good to consider
scalability with multiple power domains in a PM domain provider.
i.e case of #power-domain-cells = <1> or more
--
Regards,
Sudeep
--
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
* Re: [PATCH v5 2/2] i2c: mux: ltc4306: LTC4306 and LTC4305 I2C multiplexer/switch
From: Peter Rosin @ 2017-04-12 16:53 UTC (permalink / raw)
To: Linus Walleij, Michael Hennerich
Cc: Wolfram Sang, Rob Herring, Mark Rutland,
linux-i2c@vger.kernel.org, devicetree@vger.kernel.org,
linux-gpio@vger.kernel.org, linux-kernel@vger.kernel.org
In-Reply-To: <CACRpkdbOQtJvwtNRuPWh9VQyupH3kXK9-3Vu7qMemngg6O5j1w@mail.gmail.com>
On 2017-04-12 10:26, Linus Walleij wrote:
> On Tue, Apr 11, 2017 at 2:16 PM, <michael.hennerich@analog.com> wrote:
>
>> From: Michael Hennerich <michael.hennerich@analog.com>
>>
>> This patch adds support for the Analog Devices / Linear Technology
>> LTC4306 and LTC4305 4/2 Channel I2C Bus Multiplexer/Switches.
>> The LTC4306 optionally provides two general purpose input/output pins
>> (GPIOs) that can be configured as logic inputs, opendrain outputs or
>> push-pull outputs via the generic GPIOLIB framework.
Great, thanks for your contribution Michael! Both patches pushed to the
for-next branch of the i2c-mux tree.
>> Signed-off-by: Michael Hennerich <michael.hennerich@analog.com>
> (...)
>> Changes since v4:
>
> Reviewed-by: Linus Walleij <linus.walleij@linaro.org>
>
> Please go ahead and merge to the i2c tree if you like.
Yup, thanks for the review! (But not merged directly to the i2c tree,
although they will get there eventually...)
Cheers,
peda
^ permalink raw reply
* Re: [PATCH V4 1/9] PM / OPP: Allow OPP table to be used for power-domains
From: Sudeep Holla @ 2017-04-12 16:49 UTC (permalink / raw)
To: Viresh Kumar
Cc: Rafael Wysocki, ulf.hansson, Kevin Hilman, Viresh Kumar,
Nishanth Menon, Stephen Boyd, Sudeep Holla, linaro-kernel,
linux-pm, linux-kernel, Vincent Guittot, robh+dt, lina.iyer,
rnayak, devicetree
In-Reply-To: <e772e67a5445319bb8e0f312846ace666adc097f.1490001099.git.viresh.kumar@linaro.org>
On 20/03/17 09:32, Viresh Kumar wrote:
> Power-domains need to express their active states in DT and what's
> better than OPP table for that.
>
> This patch allows power-domains to reuse OPP tables to express their
> active states. The "opp-hz" property isn't a required property anymore
> as power-domains may not always use them.
>
> Add a new property "domain-performance-state", which will contain
> positive integer values to represent performance levels of the
> power-domains as described in this patch.
>
> Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org>
> ---
> Documentation/devicetree/bindings/opp/opp.txt | 73 ++++++++++++++++++++++++++-
> 1 file changed, 71 insertions(+), 2 deletions(-)
>
> diff --git a/Documentation/devicetree/bindings/opp/opp.txt b/Documentation/devicetree/bindings/opp/opp.txt
> index 63725498bd20..d0b95c9e1011 100644
> --- a/Documentation/devicetree/bindings/opp/opp.txt
> +++ b/Documentation/devicetree/bindings/opp/opp.txt
> @@ -76,10 +76,9 @@ This describes the OPPs belonging to a device. This node can have following
> This defines voltage-current-frequency combinations along with other related
> properties.
>
> -Required properties:
> +Optional properties:
> - opp-hz: Frequency in Hz, expressed as a 64-bit big-endian integer.
>
> -Optional properties:
> - opp-microvolt: voltage in micro Volts.
>
> A single regulator's voltage is specified with an array of size one or three.
> @@ -154,6 +153,19 @@ properties.
>
> - status: Marks the node enabled/disabled.
>
> +- domain-performance-state: A positive integer value representing the minimum
> + power-domain performance level required by the device for the OPP node. The
So the above definition is when this field in in the device node rather
than the OPP table entry, right ? For simplicity why not have the
properties named slightly different or just use phandle to an entry in
the device node for this purpose.
> + The integer value '0' represents the lowest performance level and the higher
> + values represent higher performance levels.
needs to be changed as OPP table entry.
> When present in the OPP table of a
> + power-domain, it represents the performance level of the domain. When present
again "performance level of the domain corresponding to that OPP entry"
on something similar
> + in the OPP table of a normal device, it represents the performance level of
what do you mean by normal device ? needs description as that's
something new introduced here.
> + the parent power-domain. The OPP table can contain the
> + "domain-performance-state" property, only if the device node contains the
> + "power-domains" or "#power-domain-cells" property.
Why such a restriction ?
> The OPP nodes aren't
> + allowed to contain the "domain-performance-state" property partially, i.e.
> + Either all OPP nodes in the OPP table have the "domain-performance-state"
> + property or none of them have it.
> +
> Example 1: Single cluster Dual-core ARM cortex A9, switch DVFS states together.
>
> / {
> @@ -528,3 +540,60 @@ Example 5: opp-supported-hw
> };
> };
> };
> +
> +Example 7: domain-Performance-state:
> +(example: For 1GHz require domain state 1 and for 1.1 & 1.2 GHz require state 2)
> +
> +/ {
> + domain_opp_table: opp_table0 {
> + compatible = "operating-points-v2";
> +
> + opp@1 {
> + domain-performance-state = <1>;
> + opp-microvolt = <975000 970000 985000>;
> + };
> + opp@2 {
> + domain-performance-state = <2>;
> + opp-microvolt = <1075000 1000000 1085000>;
> + };
> + };
> +
> + foo_domain: power-controller@12340000 {
> + compatible = "foo,power-controller";
> + reg = <0x12340000 0x1000>;
> + #power-domain-cells = <0>;
> + operating-points-v2 = <&domain_opp_table>;
How does it scale with power domain providers with multiple power domain ?
> + }
> +
> + cpu0_opp_table: opp_table1 {
> + compatible = "operating-points-v2";
> + opp-shared;
> +
> + opp@1000000000 {
> + opp-hz = /bits/ 64 <1000000000>;
> + domain-performance-state = <1>;
> + };
> + opp@1100000000 {
> + opp-hz = /bits/ 64 <1100000000>;
> + domain-performance-state = <2>;
> + };
> + opp@1200000000 {
> + opp-hz = /bits/ 64 <1200000000>;
> + domain-performance-state = <2>;
> + };
> + };
> +
> + cpus {
> + #address-cells = <1>;
> + #size-cells = <0>;
> +
> + cpu@0 {
> + compatible = "arm,cortex-a9";
> + reg = <0>;
> + clocks = <&clk_controller 0>;
> + clock-names = "cpu";
> + operating-points-v2 = <&cpu0_opp_table>;
Do we ignore operating-points-v2 above as this device/cpu node contains
power domain which has operating-points-v2 property ? In other words
how do they correlate ?
> + power-domains = <&foo_domain>;
> + };
> + };
> +};
>
--
Regards,
Sudeep
^ permalink raw reply
* [PATCH v8 6/6] i2c: designware: enable SLAVE in platform module
From: Luis Oliveira @ 2017-04-12 16:47 UTC (permalink / raw)
To: wsa, robh+dt, mark.rutland, jarkko.nikula, andriy.shevchenko,
mika.westerberg, linux-i2c, devicetree, linux-kernel
Cc: Luis.Oliveira, Ramiro.Oliveira, Joao.Pinto, CARLOS.PALMINHA
In-Reply-To: <cover.1492014220.git.lolivei@synopsys.com>
- Slave mode selected in platform module if the support is detected in
the DT.
Signed-off-by: Luis Oliveira <lolivei@synopsys.com>
---
v7-v8
- moved "bool mode;" comment/description to this patch
drivers/i2c/busses/Kconfig | 1 +
drivers/i2c/busses/i2c-designware-core.h | 2 ++
drivers/i2c/busses/i2c-designware-platdrv.c | 41 +++++++++++++++++++++++++----
3 files changed, 39 insertions(+), 5 deletions(-)
diff --git a/drivers/i2c/busses/Kconfig b/drivers/i2c/busses/Kconfig
index 84efa57f90b3..ada037186ff8 100644
--- a/drivers/i2c/busses/Kconfig
+++ b/drivers/i2c/busses/Kconfig
@@ -484,6 +484,7 @@ config I2C_DESIGNWARE_SLAVE
select I2C_SLAVE
select I2C_SLAVE_EEPROM
depends on I2C_DESIGNWARE_PLATFORM
+ default y
help
If you say yes to this option, support will be included for the
Synopsys DesignWare I2C slave adapter.
diff --git a/drivers/i2c/busses/i2c-designware-core.h b/drivers/i2c/busses/i2c-designware-core.h
index fc3227782082..e96b75869959 100644
--- a/drivers/i2c/busses/i2c-designware-core.h
+++ b/drivers/i2c/busses/i2c-designware-core.h
@@ -226,6 +226,7 @@
* @disable: function to disable the controller
* @disable_int: function to disable all interrupts
* @init: function to initialize the I2C hardware
+ * @mode: operation mode - DW_IC_MASTER or DW_IC_SLAVE
*
* HCNT and LCNT parameters can be used if the platform knows more accurate
* values than the one computed based only on the input clock frequency.
@@ -280,6 +281,7 @@ struct dw_i2c_dev {
void (*disable)(struct dw_i2c_dev *dev);
void (*disable_int)(struct dw_i2c_dev *dev);
int (*init)(struct dw_i2c_dev *dev);
+ int mode;
};
#define ACCESS_SWAP 0x00000001
diff --git a/drivers/i2c/busses/i2c-designware-platdrv.c b/drivers/i2c/busses/i2c-designware-platdrv.c
index 96c04a4475d2..ff31281554ad 100644
--- a/drivers/i2c/busses/i2c-designware-platdrv.c
+++ b/drivers/i2c/busses/i2c-designware-platdrv.c
@@ -1,5 +1,5 @@
/*
- * Synopsys DesignWare I2C adapter driver (master only).
+ * Synopsys DesignWare I2C adapter driver.
*
* Based on the TI DAVINCI I2C adapter driver.
*
@@ -157,9 +157,13 @@ static inline int dw_i2c_acpi_configure(struct platform_device *pdev)
static void i2c_dw_configure_master(struct dw_i2c_dev *dev)
{
+ dev->functionality = I2C_FUNC_10BIT_ADDR | DW_IC_DEFAULT_FUNCTIONALITY;
+
dev->master_cfg = DW_IC_CON_MASTER | DW_IC_CON_SLAVE_DISABLE |
DW_IC_CON_RESTART_EN;
+ dev->mode = DW_IC_MASTER;
+
switch (dev->clk_freq) {
case 100000:
dev->master_cfg |= DW_IC_CON_SPEED_STD;
@@ -172,6 +176,28 @@ static void i2c_dw_configure_master(struct dw_i2c_dev *dev)
}
}
+static void i2c_dw_configure_slave(struct dw_i2c_dev *dev)
+{
+ dev->functionality = I2C_FUNC_SLAVE | DW_IC_DEFAULT_FUNCTIONALITY;
+
+ dev->slave_cfg = DW_IC_CON_RX_FIFO_FULL_HLD_CTRL |
+ DW_IC_CON_RESTART_EN | DW_IC_CON_STOP_DET_IFADDRESSED |
+ DW_IC_CON_SPEED_FAST;
+
+ dev->mode = DW_IC_SLAVE;
+
+ switch (dev->clk_freq) {
+ case 100000:
+ dev->slave_cfg |= DW_IC_CON_SPEED_STD;
+ break;
+ case 3400000:
+ dev->slave_cfg |= DW_IC_CON_SPEED_HIGH;
+ break;
+ default:
+ dev->slave_cfg |= DW_IC_CON_SPEED_FAST;
+ }
+}
+
static int i2c_dw_plat_prepare_clk(struct dw_i2c_dev *i_dev, bool prepare)
{
if (IS_ERR(i_dev->clk))
@@ -285,9 +311,10 @@ static int dw_i2c_plat_probe(struct platform_device *pdev)
if (ret)
goto exit_reset;
- dev->functionality = I2C_FUNC_10BIT_ADDR | DW_IC_DEFAULT_FUNCTIONALITY;
-
- i2c_dw_configure_master(dev);
+ if (i2c_detect_slave_mode(&pdev->dev))
+ i2c_dw_configure_slave(dev);
+ else
+ i2c_dw_configure_master(dev);
dev->clk = devm_clk_get(&pdev->dev, NULL);
if (!i2c_dw_plat_prepare_clk(dev, true)) {
@@ -316,7 +343,11 @@ static int dw_i2c_plat_probe(struct platform_device *pdev)
pm_runtime_enable(&pdev->dev);
}
- ret = i2c_dw_probe(dev);
+ if (dev->mode == DW_IC_SLAVE)
+ ret = i2c_dw_probe_slave(dev);
+ else
+ ret = i2c_dw_probe(dev);
+
if (ret)
goto exit_probe;
--
2.11.0
^ permalink raw reply related
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox