[PATCH 3/4] w1: ds1wm: Add support for permanent strong pull-up

From: Julian Haller
Date: Thu Jun 30 2022 - 07:27:07 EST


From: Julian Haller <julian.haller@xxxxxxxxxxx>

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

Signed-off-by: Julian Haller <julian.haller@xxxxxxxxxxx>
---
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