All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 1/4] w1: ds1wm: Fix check for resource size
@ 2022-06-30 11:26 Julian Haller
  2022-06-30 11:26 ` [PATCH 2/4] w1: ds1wm: Add device tree support Julian Haller
                   ` (2 more replies)
  0 siblings, 3 replies; 4+ messages in thread
From: Julian Haller @ 2022-06-30 11:26 UTC (permalink / raw)
  To: linux-kernel; +Cc: julian.haller, zbr

From: Julian Haller <julian.haller@philips.com>

Commit 242b476f821b ("w1: ds1wm: fix register offset (bus shift)
calculation") introduced a check for the minimum resource size to span
at least 8 registers. However, the DS1WM only has 6 registers:

DS1WM_CMD       0x00    /* R/W 4 bits command */
DS1WM_DATA      0x01    /* R/W 8 bits, transmit/receive buffer */
DS1WM_INT       0x02    /* R/W interrupt status */
DS1WM_INT_EN    0x03    /* R/W interrupt enable */
DS1WM_CLKDIV    0x04    /* R/W 5 bits of divisor and pre-scale */
DS1WM_CNTRL     0x05    /* R/W master control register */

This causes the probe to fail incorrectly when the actual resource size of
6 is specified instead of 8.

Fixes: 242b476f821b ("w1: ds1wm: fix register offset (bus shift) calculation")
Signed-off-by: Julian Haller <julian.haller@philips.com>
---
 drivers/w1/masters/ds1wm.c | 7 +++----
 1 file changed, 3 insertions(+), 4 deletions(-)

diff --git a/drivers/w1/masters/ds1wm.c b/drivers/w1/masters/ds1wm.c
index f661695fb589..0ecb14772f30 100644
--- a/drivers/w1/masters/ds1wm.c
+++ b/drivers/w1/masters/ds1wm.c
@@ -544,13 +544,12 @@ static int ds1wm_probe(struct platform_device *pdev)
 		return -EINVAL;
 	}
 
-	ds1wm_data->bus_shift = plat->bus_shift;
-	/* make sure resource has space for 8 registers */
-	if ((8 << ds1wm_data->bus_shift) > resource_size(res)) {
+	/* make sure resource has space for 6 registers */
+	if ((6 << ds1wm_data->bus_shift) > resource_size(res)) {
 		dev_err(&ds1wm_data->pdev->dev,
 			"memory resource size %d to small, should be %d\n",
 			(int)resource_size(res),
-			8 << ds1wm_data->bus_shift);
+			6 << ds1wm_data->bus_shift);
 		return -EINVAL;
 	}
 
-- 
2.25.1


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

* [PATCH 2/4] w1: ds1wm: Add device tree support
  2022-06-30 11:26 [PATCH 1/4] w1: ds1wm: Fix check for resource size Julian Haller
@ 2022-06-30 11:26 ` Julian Haller
  2022-06-30 11:26 ` [PATCH 3/4] w1: ds1wm: Add support for permanent strong pull-up Julian Haller
  2022-06-30 11:26 ` [PATCH 4/4] dt-bindings: w1: Add schema for Maxim DS1WM Julian Haller
  2 siblings, 0 replies; 4+ messages in thread
From: Julian Haller @ 2022-06-30 11:26 UTC (permalink / raw)
  To: linux-kernel; +Cc: julian.haller, zbr

From: Julian Haller <julian.haller@philips.com>

The ds1wm driver now supports both, initialization with platform_data
and initialization via device tree.

Signed-off-by: Julian Haller <julian.haller@philips.com>
---
 drivers/w1/masters/ds1wm.c | 122 +++++++++++++++++++++++++++++++------
 1 file changed, 102 insertions(+), 20 deletions(-)

diff --git a/drivers/w1/masters/ds1wm.c b/drivers/w1/masters/ds1wm.c
index 0ecb14772f30..a764b016758f 100644
--- a/drivers/w1/masters/ds1wm.c
+++ b/drivers/w1/masters/ds1wm.c
@@ -22,6 +22,9 @@
 #include <linux/mfd/core.h>
 #include <linux/mfd/ds1wm.h>
 #include <linux/slab.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/of_irq.h>
 
 #include <asm/io.h>
 
@@ -97,6 +100,7 @@ struct ds1wm_data {
 	void     __iomem *map;
 	unsigned int      bus_shift; /* # of shifts to calc register offsets */
 	bool      is_hw_big_endian;
+	unsigned long clock_rate;
 	struct platform_device *pdev;
 	const struct mfd_cell   *cell;
 	int      irq;
@@ -294,7 +298,7 @@ static u8 ds1wm_read(struct ds1wm_data *ds1wm_data, unsigned char write_data)
 	return ds1wm_data->read_byte;
 }
 
-static int ds1wm_find_divisor(int gclk)
+static int ds1wm_find_divisor(unsigned long gclk)
 {
 	int i;
 
@@ -309,17 +313,16 @@ static void ds1wm_up(struct ds1wm_data *ds1wm_data)
 {
 	int divisor;
 	struct device *dev = &ds1wm_data->pdev->dev;
-	struct ds1wm_driver_data *plat = dev_get_platdata(dev);
 
-	if (ds1wm_data->cell->enable)
+	if (ds1wm_data->cell && ds1wm_data->cell->enable)
 		ds1wm_data->cell->enable(ds1wm_data->pdev);
 
-	divisor = ds1wm_find_divisor(plat->clock_rate);
-	dev_dbg(dev, "found divisor 0x%x for clock %d\n",
-		divisor, plat->clock_rate);
+	divisor = ds1wm_find_divisor(ds1wm_data->clock_rate);
+	dev_dbg(dev, "found divisor 0x%x for clock %lu\n",
+		divisor, ds1wm_data->clock_rate);
 	if (divisor == 0) {
-		dev_err(dev, "no suitable divisor for %dHz clock\n",
-			plat->clock_rate);
+		dev_err(dev, "no suitable divisor for %luHz clock\n",
+			ds1wm_data->clock_rate);
 		return;
 	}
 	ds1wm_write_register(ds1wm_data, DS1WM_CLKDIV, divisor);
@@ -338,7 +341,7 @@ static void ds1wm_down(struct ds1wm_data *ds1wm_data)
 	ds1wm_write_register(ds1wm_data, DS1WM_INT_EN,
 		ds1wm_data->int_en_reg_none);
 
-	if (ds1wm_data->cell->disable)
+	if (ds1wm_data->cell && ds1wm_data->cell->disable)
 		ds1wm_data->cell->disable(ds1wm_data->pdev);
 }
 
@@ -529,15 +532,86 @@ static int ds1wm_probe(struct platform_device *pdev)
 		return -ENOMEM;
 
 	ds1wm_data->pdev = pdev;
-	ds1wm_data->cell = mfd_get_cell(pdev);
-	if (!ds1wm_data->cell)
-		return -ENODEV;
-	plat = dev_get_platdata(&pdev->dev);
-	if (!plat)
-		return -ENODEV;
+
+	if (pdev->dev.of_node) {
+		/* Using device tree */
+		struct device_node *node = pdev->dev.of_node;
+		uint32_t register_size;
+		uint32_t clock_rate;
+
+		ret = of_property_read_u32(node, "maxim,register-size",
+				&register_size);
+		if (ret) {
+			dev_err(&pdev->dev,
+				"Failed to read maxim,register-size from dtb\n");
+			return ret;
+		}
+
+		switch (register_size) {
+		case 1:
+			ds1wm_data->bus_shift = 0;
+			break;
+		case 2:
+			ds1wm_data->bus_shift = 1;
+			break;
+		case 4:
+			ds1wm_data->bus_shift = 2;
+			break;
+		default:
+			dev_err(&pdev->dev,
+				"Invalid value for maxim,register-size: %u\n",
+				register_size);
+			return -EINVAL;
+		}
+
+		ds1wm_data->is_hw_big_endian = of_property_read_bool(node,
+				"maxim,big-endian");
+
+		if (of_property_read_bool(node, "maxim,active-high"))
+			ds1wm_data->int_en_reg_none = DS1WM_INTEN_IAS;
+		else
+			ds1wm_data->int_en_reg_none = 0;
+
+		ret = of_property_read_u32(node, "maxim,reset-recover-delay",
+				&ds1wm_data->reset_recover_delay);
+		if (ret) {
+			dev_err(&pdev->dev,
+				"failed to read maxim,reset-recover-delay from dtb\n");
+			return ret;
+		}
+
+		ret = of_property_read_u32(node, "maxim,clock-rate",
+				&clock_rate);
+		if (ret) {
+			dev_err(&pdev->dev,
+				"failed to read maxim,clock-rate from dtb\n");
+			return ret;
+		}
+		ds1wm_data->clock_rate = clock_rate;
+
+		ds1wm_data->strong_pullup = of_property_read_bool(node,
+				"maxim,strong-pullup");
+	} else {
+		/* Using platform data */
+		ds1wm_data->cell = mfd_get_cell(pdev);
+		if (!ds1wm_data->cell)
+			return -ENODEV;
+		plat = dev_get_platdata(&pdev->dev);
+		if (!plat)
+			return -ENODEV;
+
+		ds1wm_data->bus_shift = plat->bus_shift;
+		ds1wm_data->is_hw_big_endian = plat->is_hw_big_endian;
+
+		ds1wm_data->int_en_reg_none =
+			(plat->active_high ? DS1WM_INTEN_IAS : 0);
+		ds1wm_data->reset_recover_delay = plat->reset_recover_delay;
+
+		ds1wm_data->clock_rate = plat->clock_rate;
+	}
 
 	/* how many bits to shift register number to get register offset */
-	if (plat->bus_shift > 2) {
+	if (ds1wm_data->bus_shift > 2) {
 		dev_err(&ds1wm_data->pdev->dev,
 			"illegal bus shift %d, not written",
 			ds1wm_data->bus_shift);
@@ -553,14 +627,10 @@ static int ds1wm_probe(struct platform_device *pdev)
 		return -EINVAL;
 	}
 
-	ds1wm_data->is_hw_big_endian = plat->is_hw_big_endian;
-
 	res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
 	if (!res)
 		return -ENXIO;
 	ds1wm_data->irq = res->start;
-	ds1wm_data->int_en_reg_none = (plat->active_high ? DS1WM_INTEN_IAS : 0);
-	ds1wm_data->reset_recover_delay = plat->reset_recover_delay;
 
 	/* Mask interrupts, set IAS before claiming interrupt */
 	inten = ds1wm_read_register(ds1wm_data, DS1WM_INT_EN);
@@ -643,9 +713,20 @@ static int ds1wm_remove(struct platform_device *pdev)
 	return 0;
 }
 
+static const struct of_device_id driver_of_ids[] = {
+	{
+		.compatible = "maxim,ds1wm",
+	},
+	{
+		/* sentinel */
+	}
+};
+
 static struct platform_driver ds1wm_driver = {
 	.driver   = {
 		.name = "ds1wm",
+		.owner = THIS_MODULE,
+		.of_match_table = driver_of_ids,
 	},
 	.probe    = ds1wm_probe,
 	.remove   = ds1wm_remove,
@@ -667,6 +748,7 @@ static void __exit ds1wm_exit(void)
 module_init(ds1wm_init);
 module_exit(ds1wm_exit);
 
+MODULE_DEVICE_TABLE(of, driver_of_ids);
 MODULE_LICENSE("GPL");
 MODULE_AUTHOR("Szabolcs Gyurko <szabolcs.gyurko@tlt.hu>, "
 	"Matt Reimer <mreimer@vpop.net>,"
-- 
2.25.1


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

* [PATCH 3/4] w1: ds1wm: Add support for permanent strong pull-up
  2022-06-30 11:26 [PATCH 1/4] w1: ds1wm: Fix check for resource size Julian Haller
  2022-06-30 11:26 ` [PATCH 2/4] w1: ds1wm: Add device tree support Julian Haller
@ 2022-06-30 11:26 ` Julian Haller
  2022-06-30 11:26 ` [PATCH 4/4] dt-bindings: w1: Add schema for Maxim DS1WM Julian Haller
  2 siblings, 0 replies; 4+ messages in thread
From: Julian Haller @ 2022-06-30 11:26 UTC (permalink / raw)
  To: linux-kernel; +Cc: julian.haller, zbr

From: Julian Haller <julian.haller@philips.com>

Add support for enabling the strong pull-up, both via device tree and
platform data.

Signed-off-by: Julian Haller <julian.haller@philips.com>
---
 drivers/w1/masters/ds1wm.c | 38 +++++++++++++++++++++++++++++++++++---
 include/linux/mfd/ds1wm.h  |  2 ++
 2 files changed, 37 insertions(+), 3 deletions(-)

diff --git a/drivers/w1/masters/ds1wm.c b/drivers/w1/masters/ds1wm.c
index a764b016758f..5768430a536e 100644
--- a/drivers/w1/masters/ds1wm.c
+++ b/drivers/w1/masters/ds1wm.c
@@ -25,6 +25,7 @@
 #include <linux/of.h>
 #include <linux/of_address.h>
 #include <linux/of_irq.h>
+#include <linux/bitops.h>
 
 #include <asm/io.h>
 
@@ -36,7 +37,7 @@
 #define DS1WM_INT	0x02	/* R/W interrupt status */
 #define DS1WM_INT_EN	0x03	/* R/W interrupt enable */
 #define DS1WM_CLKDIV	0x04	/* R/W 5 bits of divisor and pre-scale */
-#define DS1WM_CNTRL	0x05	/* R/W master control register (not used yet) */
+#define DS1WM_CNTRL	0x05	/* R/W master control register */
 
 #define DS1WM_CMD_1W_RESET  (1 << 0)	/* force reset on 1-wire bus */
 #define DS1WM_CMD_SRA	    (1 << 1)	/* enable Search ROM accelerator mode */
@@ -60,6 +61,15 @@
 #define DS1WM_INTEN_ERSRF   (1 << 5)	/* enable rx shift register full int */
 #define DS1WM_INTEN_DQO	    (1 << 6)	/* enable direct bus driving ops */
 
+#define DS1WM_CNTRL_LLM     BIT(0)	/* long line mode */
+#define DS1WM_CNTRL_PPM     BIT(1)	/* presence pulse masking */
+#define DS1WM_CNTRL_EN_FOW  BIT(2)	/* enable force 1 wire command */
+#define DS1WM_CNTRL_STPEN   BIT(3)	/* active pullup enable */
+#define DS1WM_CNTRL_STP_SPLY BIT(4)	/* strong pullup power delivery */
+#define DS1WM_CNTRL_BIT_CTL BIT(5)	/* bit control */
+#define DS1WM_CNTRL_OD      BIT(6)	/* overdrive speed */
+
+
 #define DS1WM_INTEN_NOT_IAS (~DS1WM_INTEN_IAS)	/* all but INTR active state */
 
 #define DS1WM_TIMEOUT (HZ * 5)
@@ -115,6 +125,8 @@ struct ds1wm_data {
 	/* considering active_state (IAS) (optimization) */
 	u8       int_en_reg_none;
 	unsigned int reset_recover_delay; /* see ds1wm.h */
+	bool     strong_pullup_enable;
+	bool     strong_pullup_supply;
 };
 
 static inline void ds1wm_write_register(struct ds1wm_data *ds1wm_data, u32 reg,
@@ -313,6 +325,7 @@ static void ds1wm_up(struct ds1wm_data *ds1wm_data)
 {
 	int divisor;
 	struct device *dev = &ds1wm_data->pdev->dev;
+	u8 cntrl;
 
 	if (ds1wm_data->cell && ds1wm_data->cell->enable)
 		ds1wm_data->cell->enable(ds1wm_data->pdev);
@@ -330,6 +343,20 @@ static void ds1wm_up(struct ds1wm_data *ds1wm_data)
 	/* Let the w1 clock stabilize. */
 	msleep(1);
 
+	/* Set strong pullup */
+	cntrl = ds1wm_read_register(ds1wm_data, DS1WM_CNTRL);
+	if (ds1wm_data->strong_pullup_enable) {
+		cntrl |= DS1WM_CNTRL_STPEN;
+		if (ds1wm_data->strong_pullup_supply)
+			cntrl |= DS1WM_CNTRL_STP_SPLY;
+		else
+			cntrl &= ~DS1WM_CNTRL_STP_SPLY;
+	} else {
+		cntrl &= ~DS1WM_CNTRL_STPEN;
+		cntrl &= ~DS1WM_CNTRL_STP_SPLY;
+	}
+	ds1wm_write_register(ds1wm_data, DS1WM_CNTRL, cntrl);
+
 	ds1wm_reset(ds1wm_data);
 }
 
@@ -589,8 +616,10 @@ static int ds1wm_probe(struct platform_device *pdev)
 		}
 		ds1wm_data->clock_rate = clock_rate;
 
-		ds1wm_data->strong_pullup = of_property_read_bool(node,
-				"maxim,strong-pullup");
+		ds1wm_data->strong_pullup_enable = of_property_read_bool(node,
+				"maxim,strong-pullup-enable");
+		ds1wm_data->strong_pullup_supply = of_property_read_bool(node,
+				"maxim,strong-pullup-supply");
 	} else {
 		/* Using platform data */
 		ds1wm_data->cell = mfd_get_cell(pdev);
@@ -608,6 +637,9 @@ static int ds1wm_probe(struct platform_device *pdev)
 		ds1wm_data->reset_recover_delay = plat->reset_recover_delay;
 
 		ds1wm_data->clock_rate = plat->clock_rate;
+
+		ds1wm_data->strong_pullup_enable = plat->strong_pullup_enable;
+		ds1wm_data->strong_pullup_supply = plat->strong_pullup_supply;
 	}
 
 	/* how many bits to shift register number to get register offset */
diff --git a/include/linux/mfd/ds1wm.h b/include/linux/mfd/ds1wm.h
index 43dfca1c9702..dd9285ea507b 100644
--- a/include/linux/mfd/ds1wm.h
+++ b/include/linux/mfd/ds1wm.h
@@ -26,4 +26,6 @@ struct ds1wm_driver_data {
 	 * Only 0,1,2 allowed for 8,16 or 32 bit bus width respectively
 	 */
 	unsigned int bus_shift;
+	bool strong_pullup_enable;
+	bool strong_pullup_supply;
 };
-- 
2.25.1


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

* [PATCH 4/4] dt-bindings: w1: Add schema for Maxim DS1WM
  2022-06-30 11:26 [PATCH 1/4] w1: ds1wm: Fix check for resource size Julian Haller
  2022-06-30 11:26 ` [PATCH 2/4] w1: ds1wm: Add device tree support Julian Haller
  2022-06-30 11:26 ` [PATCH 3/4] w1: ds1wm: Add support for permanent strong pull-up Julian Haller
@ 2022-06-30 11:26 ` Julian Haller
  2 siblings, 0 replies; 4+ messages in thread
From: Julian Haller @ 2022-06-30 11:26 UTC (permalink / raw)
  To: linux-kernel; +Cc: julian.haller, zbr

From: Julian Haller <julian.haller@philips.com>

The Maxim DS1WM is a synthesizable 1-Wire Bus Master for usage in
custom ASIC and FPGA designs. The datatsheet can be found under
https://datasheets.maximintegrated.com/en/ds/DS1WM.pdf

Signed-off-by: Julian Haller <julian.haller@philips.com>
---
 .../devicetree/bindings/w1/maxim,ds1wm.yaml   | 102 ++++++++++++++++++
 1 file changed, 102 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/w1/maxim,ds1wm.yaml

diff --git a/Documentation/devicetree/bindings/w1/maxim,ds1wm.yaml b/Documentation/devicetree/bindings/w1/maxim,ds1wm.yaml
new file mode 100644
index 000000000000..c3f57ff2fdde
--- /dev/null
+++ b/Documentation/devicetree/bindings/w1/maxim,ds1wm.yaml
@@ -0,0 +1,102 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/w1/maxim,ds1wm.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Maxim DS1WM One wire bus master controller Binding
+
+maintainers:
+  - Evgeniy Polyakov <zbr@ioremap.net>
+
+description: |
+  This document describes bindings which can be used to
+  describe DS1WM devices in a device tree. The DS1WM is a synthesizable 1-Wire
+  Bus Master for usage in custom ASIC and FPGA designs.
+
+  The datatsheet can be found under
+  https://datasheets.maximintegrated.com/en/ds/DS1WM.pdf
+
+properties:
+  $nodename:
+    pattern: "^w1(@.*|-[0-9a-f])*$"
+
+  reg:
+    maxItems: 1
+
+  interrupts:
+    maxItems: 1
+
+  compatible:
+    const: maxim,ds1wm
+
+  maxim,clock-rate:
+    $ref: /schemas/types.yaml#/definitions/uint32
+    description:
+      DS1WM input clock rate.
+
+  maxim,active-high:
+    $ref: /schemas/types.yaml#/definitions/flag
+    description:
+      When set, INTR pin is active high. Defaults to active low.
+
+  maxim,register-size:
+    $ref: /schemas/types.yaml#/definitions/uint32
+    description:
+      DS1WM register size in bytes.
+    oneOf:
+      - enum: [1, 2, 4]
+
+  maxim,reset-recover-delay:
+    $ref: /schemas/types.yaml#/definitions/uint32
+    description:
+      Amount of time to sleep following a reset pulse (in milliseconds). Zero
+      should work if your bus devices recover time respects the 1-wire spec
+      since the ds1wm implements the precise timings of a reset pulse/presence
+      detect sequence.
+
+  maxim,big-endian:
+    $ref: /schemas/types.yaml#/definitions/flag
+    description:
+      Set if DS1WM hardware is of type big-endian. Defaults to little-endian.
+
+  maxim,strong-pullup-enable:
+    $ref: /schemas/types.yaml#/definitions/flag
+    description:
+      Enables the strong pull-up output enable (STPZ) pin’s functionality which
+      allows an external strong pull-up any time the master is not pulling the
+      line low or waiting to read a value from a slave device. This
+      functionality is used for meeting the recovery time requirement in
+      Overdrive mode and long-line standard communications.
+
+  maxim,strong-pullup-supply:
+    $ref: /schemas/types.yaml#/definitions/flag
+    description:
+      Enables the STPZ output while the master is in an IDLE state. This will
+      provide a stiff supply to devices requiring high current during
+      operations. Requires maxim,strong-pullup-enable.
+
+required:
+  - compatible
+  - reg
+  - interrupts
+  - maxim,register-size
+  - maxim,reset-recover-delay
+  - maxim,clock-rate
+
+additionalProperties: false
+
+examples:
+  - |
+    w1@4200 {
+        compatible = "maxim,ds1wm";
+        reg = <0x4200 0x24>;
+        interrupts = <10>;
+        maxim,register-size = <4>;
+        maxim,reset-recover-delay = <2>;
+        maxim,clock-rate = <100000000>;
+        maxim,strong-pullup;
+        maxim,big-endian;
+        maxim,active-high;
+    };
+...
-- 
2.25.1


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

end of thread, other threads:[~2022-06-30 11:27 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-06-30 11:26 [PATCH 1/4] w1: ds1wm: Fix check for resource size Julian Haller
2022-06-30 11:26 ` [PATCH 2/4] w1: ds1wm: Add device tree support Julian Haller
2022-06-30 11:26 ` [PATCH 3/4] w1: ds1wm: Add support for permanent strong pull-up Julian Haller
2022-06-30 11:26 ` [PATCH 4/4] dt-bindings: w1: Add schema for Maxim DS1WM Julian Haller

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