lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-Id: <20220630112651.2739425-2-julian.haller@bbl.ms.philips.com>
Date:   Thu, 30 Jun 2022 13:26:49 +0200
From:   Julian Haller <julian.haller@....ms.philips.com>
To:     linux-kernel@...r.kernel.org
Cc:     julian.haller@...lips.com, zbr@...emap.net
Subject: [PATCH 2/4] w1: ds1wm: Add device tree support

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

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

Signed-off-by: Julian Haller <julian.haller@...lips.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@....hu>, "
 	"Matt Reimer <mreimer@...p.net>,"
-- 
2.25.1

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ