summaryrefslogtreecommitdiff
path: root/drivers/w1
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/w1')
-rw-r--r--drivers/w1/masters/Kconfig30
-rw-r--r--drivers/w1/masters/Makefile3
-rw-r--r--drivers/w1/masters/amd_axi_w1.c396
-rw-r--r--drivers/w1/masters/ds1wm.c675
-rw-r--r--drivers/w1/masters/ds2482.c40
-rw-r--r--drivers/w1/masters/ds2490.c38
-rw-r--r--drivers/w1/masters/matrox_w1.c26
-rw-r--r--drivers/w1/masters/mxc_w1.c4
-rw-r--r--drivers/w1/masters/omap_hdq.c23
-rw-r--r--drivers/w1/masters/sgi_w1.c6
-rw-r--r--drivers/w1/masters/w1-gpio.c168
-rw-r--r--drivers/w1/masters/w1-uart.c415
-rw-r--r--drivers/w1/slaves/Kconfig4
-rw-r--r--drivers/w1/slaves/w1_ds2406.c37
-rw-r--r--drivers/w1/slaves/w1_ds2408.c52
-rw-r--r--drivers/w1/slaves/w1_ds2413.c18
-rw-r--r--drivers/w1/slaves/w1_ds2430.c8
-rw-r--r--drivers/w1/slaves/w1_ds2431.c8
-rw-r--r--drivers/w1/slaves/w1_ds2433.c187
-rw-r--r--drivers/w1/slaves/w1_ds2438.c34
-rw-r--r--drivers/w1/slaves/w1_ds250x.c1
-rw-r--r--drivers/w1/slaves/w1_ds2780.c7
-rw-r--r--drivers/w1/slaves/w1_ds2781.c7
-rw-r--r--drivers/w1/slaves/w1_ds2805.c8
-rw-r--r--drivers/w1/slaves/w1_ds28e04.c37
-rw-r--r--drivers/w1/slaves/w1_ds28e17.c14
-rw-r--r--drivers/w1/slaves/w1_therm.c49
-rw-r--r--drivers/w1/w1.c95
-rw-r--r--drivers/w1/w1_int.c6
-rw-r--r--drivers/w1/w1_netlink.c48
30 files changed, 1309 insertions, 1135 deletions
diff --git a/drivers/w1/masters/Kconfig b/drivers/w1/masters/Kconfig
index 24b9a8e05f64..e6049a75b35b 100644
--- a/drivers/w1/masters/Kconfig
+++ b/drivers/w1/masters/Kconfig
@@ -5,6 +5,17 @@
menu "1-wire Bus Masters"
+config W1_MASTER_AMD_AXI
+ tristate "AMD AXI 1-wire bus host"
+ help
+ Say Y here is you want to support the AMD AXI 1-wire IP core.
+ This driver makes use of the programmable logic IP to perform
+ correctly timed 1 wire transactions without relying on GPIO timing
+ through the kernel.
+
+ This driver can also be built as a module. If so, the module will be
+ called amd_w1_axi.
+
config W1_MASTER_MATROX
tristate "Matrox G400 transport layer for 1-wire"
depends on PCI
@@ -41,13 +52,6 @@ config W1_MASTER_MXC
help
Say Y here to enable MXC 1-wire host
-config W1_MASTER_DS1WM
- tristate "Maxim DS1WM 1-wire busmaster"
- help
- Say Y here to enable the DS1WM 1-wire driver, such as that
- in HP iPAQ devices like h5xxx, h2200, and ASIC3-based like
- hx4700.
-
config W1_MASTER_GPIO
tristate "GPIO 1-wire busmaster"
depends on GPIOLIB || COMPILE_TEST
@@ -60,7 +64,7 @@ config W1_MASTER_GPIO
config HDQ_MASTER_OMAP
tristate "OMAP HDQ driver"
- depends on ARCH_OMAP
+ depends on ARCH_OMAP || COMPILE_TEST
help
Say Y here if you want support for the 1-wire or HDQ Interface
on an OMAP processor.
@@ -74,5 +78,15 @@ config W1_MASTER_SGI
This support is also available as a module. If so, the module
will be called sgi_w1.
+config W1_MASTER_UART
+ tristate "UART 1-wire driver"
+ depends on SERIAL_DEV_BUS
+ help
+ Say Y here if you want to communicate with your 1-wire devices using
+ UART interface.
+
+ This support is also available as a module. If so, the module
+ will be called w1-uart.
+
endmenu
diff --git a/drivers/w1/masters/Makefile b/drivers/w1/masters/Makefile
index dae629b7ab49..227f80987e69 100644
--- a/drivers/w1/masters/Makefile
+++ b/drivers/w1/masters/Makefile
@@ -3,12 +3,13 @@
# Makefile for 1-wire bus master drivers.
#
+obj-$(CONFIG_W1_MASTER_AMD_AXI) += amd_axi_w1.o
obj-$(CONFIG_W1_MASTER_MATROX) += matrox_w1.o
obj-$(CONFIG_W1_MASTER_DS2490) += ds2490.o
obj-$(CONFIG_W1_MASTER_DS2482) += ds2482.o
obj-$(CONFIG_W1_MASTER_MXC) += mxc_w1.o
-obj-$(CONFIG_W1_MASTER_DS1WM) += ds1wm.o
obj-$(CONFIG_W1_MASTER_GPIO) += w1-gpio.o
obj-$(CONFIG_HDQ_MASTER_OMAP) += omap_hdq.o
obj-$(CONFIG_W1_MASTER_SGI) += sgi_w1.o
+obj-$(CONFIG_W1_MASTER_UART) += w1-uart.o
diff --git a/drivers/w1/masters/amd_axi_w1.c b/drivers/w1/masters/amd_axi_w1.c
new file mode 100644
index 000000000000..5da8b8d86811
--- /dev/null
+++ b/drivers/w1/masters/amd_axi_w1.c
@@ -0,0 +1,396 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * amd_axi_w1 - AMD 1Wire programmable logic bus host driver
+ *
+ * Copyright (C) 2022-2023 Advanced Micro Devices, Inc. All Rights Reserved.
+ */
+
+#include <linux/atomic.h>
+#include <linux/bitfield.h>
+#include <linux/clk.h>
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/jiffies.h>
+#include <linux/kernel.h>
+#include <linux/mod_devicetable.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/types.h>
+#include <linux/wait.h>
+
+#include <linux/w1.h>
+
+/* 1-wire AMD IP definition */
+#define AXIW1_IPID 0x10ee4453
+/* Registers offset */
+#define AXIW1_INST_REG 0x0
+#define AXIW1_CTRL_REG 0x4
+#define AXIW1_IRQE_REG 0x8
+#define AXIW1_STAT_REG 0xC
+#define AXIW1_DATA_REG 0x10
+#define AXIW1_IPVER_REG 0x18
+#define AXIW1_IPID_REG 0x1C
+/* Instructions */
+#define AXIW1_INITPRES 0x0800
+#define AXIW1_READBIT 0x0C00
+#define AXIW1_WRITEBIT 0x0E00
+#define AXIW1_READBYTE 0x0D00
+#define AXIW1_WRITEBYTE 0x0F00
+/* Status flag masks */
+#define AXIW1_DONE BIT(0)
+#define AXIW1_READY BIT(4)
+#define AXIW1_PRESENCE BIT(31)
+#define AXIW1_MAJORVER_MASK GENMASK(23, 8)
+#define AXIW1_MINORVER_MASK GENMASK(7, 0)
+/* Control flag */
+#define AXIW1_GO BIT(0)
+#define AXI_CLEAR 0
+#define AXI_RESET BIT(31)
+#define AXIW1_READDATA BIT(0)
+/* Interrupt Enable */
+#define AXIW1_READY_IRQ_EN BIT(4)
+#define AXIW1_DONE_IRQ_EN BIT(0)
+
+#define AXIW1_TIMEOUT msecs_to_jiffies(100)
+
+#define DRIVER_NAME "amd_axi_w1"
+
+struct amd_axi_w1_local {
+ struct device *dev;
+ void __iomem *base_addr;
+ int irq;
+ atomic_t flag; /* Set on IRQ, cleared once serviced */
+ wait_queue_head_t wait_queue;
+ struct w1_bus_master bus_host;
+};
+
+/**
+ * amd_axi_w1_wait_irq_interruptible_timeout() - Wait for IRQ with timeout.
+ *
+ * @amd_axi_w1_local: Pointer to device structure
+ * @IRQ: IRQ channel to wait on
+ *
+ * Return: %0 - OK, %-EINTR - Interrupted, %-EBUSY - Timed out
+ */
+static int amd_axi_w1_wait_irq_interruptible_timeout(struct amd_axi_w1_local *amd_axi_w1_local,
+ u32 IRQ)
+{
+ int ret;
+
+ /* Enable the IRQ requested and wait for flag to indicate it's been triggered */
+ iowrite32(IRQ, amd_axi_w1_local->base_addr + AXIW1_IRQE_REG);
+ ret = wait_event_interruptible_timeout(amd_axi_w1_local->wait_queue,
+ atomic_read(&amd_axi_w1_local->flag) != 0,
+ AXIW1_TIMEOUT);
+ if (ret < 0) {
+ dev_err(amd_axi_w1_local->dev, "Wait IRQ Interrupted\n");
+ return -EINTR;
+ }
+
+ if (!ret) {
+ dev_err(amd_axi_w1_local->dev, "Wait IRQ Timeout\n");
+ return -EBUSY;
+ }
+
+ atomic_set(&amd_axi_w1_local->flag, 0);
+ return 0;
+}
+
+/**
+ * amd_axi_w1_touch_bit() - Performs the touch-bit function - write a 0 or 1 and reads the level.
+ *
+ * @data: Pointer to device structure
+ * @bit: The level to write
+ *
+ * Return: The level read
+ */
+static u8 amd_axi_w1_touch_bit(void *data, u8 bit)
+{
+ struct amd_axi_w1_local *amd_axi_w1_local = data;
+ u8 val = 0;
+ int rc;
+
+ /* Wait for READY signal to be 1 to ensure 1-wire IP is ready */
+ while ((ioread32(amd_axi_w1_local->base_addr + AXIW1_STAT_REG) & AXIW1_READY) == 0) {
+ rc = amd_axi_w1_wait_irq_interruptible_timeout(amd_axi_w1_local,
+ AXIW1_READY_IRQ_EN);
+ if (rc < 0)
+ return 1; /* Callee doesn't test for error. Return inactive bus state */
+ }
+
+ if (bit)
+ /* Read. Write read Bit command in register 0 */
+ iowrite32(AXIW1_READBIT, amd_axi_w1_local->base_addr + AXIW1_INST_REG);
+ else
+ /* Write. Write tx Bit command in instruction register with bit to transmit */
+ iowrite32(AXIW1_WRITEBIT + (bit & 0x01),
+ amd_axi_w1_local->base_addr + AXIW1_INST_REG);
+
+ /* Write Go signal and clear control reset signal in control register */
+ iowrite32(AXIW1_GO, amd_axi_w1_local->base_addr + AXIW1_CTRL_REG);
+
+ /* Wait for done signal to be 1 */
+ while ((ioread32(amd_axi_w1_local->base_addr + AXIW1_STAT_REG) & AXIW1_DONE) != 1) {
+ rc = amd_axi_w1_wait_irq_interruptible_timeout(amd_axi_w1_local, AXIW1_DONE_IRQ_EN);
+ if (rc < 0)
+ return 1; /* Callee doesn't test for error. Return inactive bus state */
+ }
+
+ /* If read, Retrieve data from register */
+ if (bit)
+ val = (u8)(ioread32(amd_axi_w1_local->base_addr + AXIW1_DATA_REG) & AXIW1_READDATA);
+
+ /* Clear Go signal in register 1 */
+ iowrite32(AXI_CLEAR, amd_axi_w1_local->base_addr + AXIW1_CTRL_REG);
+
+ return val;
+}
+
+/**
+ * amd_axi_w1_read_byte - Performs the read byte function.
+ *
+ * @data: Pointer to device structure
+ * Return: The value read
+ */
+static u8 amd_axi_w1_read_byte(void *data)
+{
+ struct amd_axi_w1_local *amd_axi_w1_local = data;
+ u8 val = 0;
+ int rc;
+
+ /* Wait for READY signal to be 1 to ensure 1-wire IP is ready */
+ while ((ioread32(amd_axi_w1_local->base_addr + AXIW1_STAT_REG) & AXIW1_READY) == 0) {
+ rc = amd_axi_w1_wait_irq_interruptible_timeout(amd_axi_w1_local,
+ AXIW1_READY_IRQ_EN);
+ if (rc < 0)
+ return 0xFF; /* Return inactive bus state */
+ }
+
+ /* Write read Byte command in instruction register*/
+ iowrite32(AXIW1_READBYTE, amd_axi_w1_local->base_addr + AXIW1_INST_REG);
+
+ /* Write Go signal and clear control reset signal in control register */
+ iowrite32(AXIW1_GO, amd_axi_w1_local->base_addr + AXIW1_CTRL_REG);
+
+ /* Wait for done signal to be 1 */
+ while ((ioread32(amd_axi_w1_local->base_addr + AXIW1_STAT_REG) & AXIW1_DONE) != 1) {
+ rc = amd_axi_w1_wait_irq_interruptible_timeout(amd_axi_w1_local, AXIW1_DONE_IRQ_EN);
+ if (rc < 0)
+ return 0xFF; /* Return inactive bus state */
+ }
+
+ /* Retrieve LSB bit in data register to get RX byte */
+ val = (u8)(ioread32(amd_axi_w1_local->base_addr + AXIW1_DATA_REG) & 0x000000FF);
+
+ /* Clear Go signal in control register */
+ iowrite32(AXI_CLEAR, amd_axi_w1_local->base_addr + AXIW1_CTRL_REG);
+
+ return val;
+}
+
+/**
+ * amd_axi_w1_write_byte - Performs the write byte function.
+ *
+ * @data: The ds2482 channel pointer
+ * @val: The value to write
+ */
+static void amd_axi_w1_write_byte(void *data, u8 val)
+{
+ struct amd_axi_w1_local *amd_axi_w1_local = data;
+ int rc;
+
+ /* Wait for READY signal to be 1 to ensure 1-wire IP is ready */
+ while ((ioread32(amd_axi_w1_local->base_addr + AXIW1_STAT_REG) & AXIW1_READY) == 0) {
+ rc = amd_axi_w1_wait_irq_interruptible_timeout(amd_axi_w1_local,
+ AXIW1_READY_IRQ_EN);
+ if (rc < 0)
+ return;
+ }
+
+ /* Write tx Byte command in instruction register with bit to transmit */
+ iowrite32(AXIW1_WRITEBYTE + val, amd_axi_w1_local->base_addr + AXIW1_INST_REG);
+
+ /* Write Go signal and clear control reset signal in register 1 */
+ iowrite32(AXIW1_GO, amd_axi_w1_local->base_addr + AXIW1_CTRL_REG);
+
+ /* Wait for done signal to be 1 */
+ while ((ioread32(amd_axi_w1_local->base_addr + AXIW1_STAT_REG) & AXIW1_DONE) != 1) {
+ rc = amd_axi_w1_wait_irq_interruptible_timeout(amd_axi_w1_local,
+ AXIW1_DONE_IRQ_EN);
+ if (rc < 0)
+ return;
+ }
+
+ /* Clear Go signal in control register */
+ iowrite32(AXI_CLEAR, amd_axi_w1_local->base_addr + AXIW1_CTRL_REG);
+}
+
+/**
+ * amd_axi_w1_reset_bus() - Issues a reset bus sequence.
+ *
+ * @data: the bus host data struct
+ * Return: 0=Device present, 1=No device present or error
+ */
+static u8 amd_axi_w1_reset_bus(void *data)
+{
+ struct amd_axi_w1_local *amd_axi_w1_local = data;
+ u8 val = 0;
+ int rc;
+
+ /* Reset 1-wire Axi IP */
+ iowrite32(AXI_RESET, amd_axi_w1_local->base_addr + AXIW1_CTRL_REG);
+
+ /* Wait for READY signal to be 1 to ensure 1-wire IP is ready */
+ while ((ioread32(amd_axi_w1_local->base_addr + AXIW1_STAT_REG) & AXIW1_READY) == 0) {
+ rc = amd_axi_w1_wait_irq_interruptible_timeout(amd_axi_w1_local,
+ AXIW1_READY_IRQ_EN);
+ if (rc < 0)
+ return 1; /* Something went wrong with the hardware */
+ }
+ /* Write Initialization command in instruction register */
+ iowrite32(AXIW1_INITPRES, amd_axi_w1_local->base_addr + AXIW1_INST_REG);
+
+ /* Write Go signal and clear control reset signal in register 1 */
+ iowrite32(AXIW1_GO, amd_axi_w1_local->base_addr + AXIW1_CTRL_REG);
+
+ /* Wait for done signal to be 1 */
+ while ((ioread32(amd_axi_w1_local->base_addr + AXIW1_STAT_REG) & AXIW1_DONE) != 1) {
+ rc = amd_axi_w1_wait_irq_interruptible_timeout(amd_axi_w1_local, AXIW1_DONE_IRQ_EN);
+ if (rc < 0)
+ return 1; /* Something went wrong with the hardware */
+ }
+ /* Retrieve MSB bit in status register to get failure bit */
+ if ((ioread32(amd_axi_w1_local->base_addr + AXIW1_STAT_REG) & AXIW1_PRESENCE) != 0)
+ val = 1;
+
+ /* Clear Go signal in control register */
+ iowrite32(AXI_CLEAR, amd_axi_w1_local->base_addr + AXIW1_CTRL_REG);
+
+ return val;
+}
+
+/* Reset the 1-wire AXI IP. Put the IP in reset state and clear registers */
+static void amd_axi_w1_reset(struct amd_axi_w1_local *amd_axi_w1_local)
+{
+ iowrite32(AXI_RESET, amd_axi_w1_local->base_addr + AXIW1_CTRL_REG);
+ iowrite32(AXI_CLEAR, amd_axi_w1_local->base_addr + AXIW1_INST_REG);
+ iowrite32(AXI_CLEAR, amd_axi_w1_local->base_addr + AXIW1_IRQE_REG);
+ iowrite32(AXI_CLEAR, amd_axi_w1_local->base_addr + AXIW1_STAT_REG);
+ iowrite32(AXI_CLEAR, amd_axi_w1_local->base_addr + AXIW1_DATA_REG);
+}
+
+static irqreturn_t amd_axi_w1_irq(int irq, void *lp)
+{
+ struct amd_axi_w1_local *amd_axi_w1_local = lp;
+
+ /* Reset interrupt trigger */
+ iowrite32(AXI_CLEAR, amd_axi_w1_local->base_addr + AXIW1_IRQE_REG);
+
+ atomic_set(&amd_axi_w1_local->flag, 1);
+ wake_up_interruptible(&amd_axi_w1_local->wait_queue);
+
+ return IRQ_HANDLED;
+}
+
+static int amd_axi_w1_probe(struct platform_device *pdev)
+{
+ struct device *dev = &pdev->dev;
+ struct amd_axi_w1_local *lp;
+ struct clk *clk;
+ u32 ver_major, ver_minor;
+ int val, rc = 0;
+
+ lp = devm_kzalloc(dev, sizeof(*lp), GFP_KERNEL);
+ if (!lp)
+ return -ENOMEM;
+
+ lp->dev = dev;
+ lp->base_addr = devm_platform_ioremap_resource(pdev, 0);
+ if (IS_ERR(lp->base_addr))
+ return PTR_ERR(lp->base_addr);
+
+ lp->irq = platform_get_irq(pdev, 0);
+ if (lp->irq < 0)
+ return lp->irq;
+
+ rc = devm_request_irq(dev, lp->irq, &amd_axi_w1_irq, IRQF_TRIGGER_HIGH, DRIVER_NAME, lp);
+ if (rc)
+ return rc;
+
+ /* Initialize wait queue and flag */
+ init_waitqueue_head(&lp->wait_queue);
+
+ clk = devm_clk_get_enabled(dev, NULL);
+ if (IS_ERR(clk))
+ return PTR_ERR(clk);
+
+ /* Verify IP presence in HW */
+ if (ioread32(lp->base_addr + AXIW1_IPID_REG) != AXIW1_IPID) {
+ dev_err(dev, "AMD 1-wire IP not detected in hardware\n");
+ return -ENODEV;
+ }
+
+ /*
+ * Allow for future driver expansion supporting new hardware features
+ * This driver currently only supports hardware 1.x, but include logic
+ * to detect if a potentially incompatible future version is used
+ * by reading major version ID. It is highly undesirable for new IP versions
+ * to break the API, but this code will at least allow for graceful failure
+ * should that happen. Future new features can be enabled by hardware
+ * incrementing the minor version and augmenting the driver to detect capability
+ * using the minor version number
+ */
+ val = ioread32(lp->base_addr + AXIW1_IPVER_REG);
+ ver_major = FIELD_GET(AXIW1_MAJORVER_MASK, val);
+ ver_minor = FIELD_GET(AXIW1_MINORVER_MASK, val);
+
+ if (ver_major != 1) {
+ dev_err(dev, "AMD AXI W1 host version %u.%u is not supported by this driver",
+ ver_major, ver_minor);
+ return -ENODEV;
+ }
+
+ lp->bus_host.data = lp;
+ lp->bus_host.touch_bit = amd_axi_w1_touch_bit;
+ lp->bus_host.read_byte = amd_axi_w1_read_byte;
+ lp->bus_host.write_byte = amd_axi_w1_write_byte;
+ lp->bus_host.reset_bus = amd_axi_w1_reset_bus;
+
+ amd_axi_w1_reset(lp);
+
+ platform_set_drvdata(pdev, lp);
+ rc = w1_add_master_device(&lp->bus_host);
+ if (rc) {
+ dev_err(dev, "Could not add host device\n");
+ return rc;
+ }
+
+ return 0;
+}
+
+static void amd_axi_w1_remove(struct platform_device *pdev)
+{
+ struct amd_axi_w1_local *lp = platform_get_drvdata(pdev);
+
+ w1_remove_master_device(&lp->bus_host);
+}
+
+static const struct of_device_id amd_axi_w1_of_match[] = {
+ { .compatible = "amd,axi-1wire-host" },
+ { /* end of list */ },
+};
+MODULE_DEVICE_TABLE(of, amd_axi_w1_of_match);
+
+static struct platform_driver amd_axi_w1_driver = {
+ .probe = amd_axi_w1_probe,
+ .remove = amd_axi_w1_remove,
+ .driver = {
+ .name = DRIVER_NAME,
+ .of_match_table = amd_axi_w1_of_match,
+ },
+};
+module_platform_driver(amd_axi_w1_driver);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Kris Chaplin <kris.chaplin@amd.com>");
+MODULE_DESCRIPTION("Driver for AMD AXI 1 Wire IP core");
diff --git a/drivers/w1/masters/ds1wm.c b/drivers/w1/masters/ds1wm.c
deleted file mode 100644
index f661695fb589..000000000000
--- a/drivers/w1/masters/ds1wm.c
+++ /dev/null
@@ -1,675 +0,0 @@
-/*
- * 1-wire busmaster driver for DS1WM and ASICs with embedded DS1WMs
- * such as HP iPAQs (including h5xxx, h2200, and devices with ASIC3
- * like hx4700).
- *
- * Copyright (c) 2004-2005, Szabolcs Gyurko <szabolcs.gyurko@tlt.hu>
- * Copyright (c) 2004-2007, Matt Reimer <mreimer@vpop.net>
- *
- * Use consistent with the GNU GPL is permitted,
- * provided that this copyright notice is
- * preserved in its entirety in all copies and derived works.
- */
-
-#include <linux/module.h>
-#include <linux/interrupt.h>
-#include <linux/io.h>
-#include <linux/irq.h>
-#include <linux/pm.h>
-#include <linux/platform_device.h>
-#include <linux/err.h>
-#include <linux/delay.h>
-#include <linux/mfd/core.h>
-#include <linux/mfd/ds1wm.h>
-#include <linux/slab.h>
-
-#include <asm/io.h>
-
-#include <linux/w1.h>
-
-
-#define DS1WM_CMD 0x00 /* R/W 4 bits command */
-#define DS1WM_DATA 0x01 /* R/W 8 bits, transmit/receive buffer */
-#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_CMD_1W_RESET (1 << 0) /* force reset on 1-wire bus */
-#define DS1WM_CMD_SRA (1 << 1) /* enable Search ROM accelerator mode */
-#define DS1WM_CMD_DQ_OUTPUT (1 << 2) /* write only - forces bus low */
-#define DS1WM_CMD_DQ_INPUT (1 << 3) /* read only - reflects state of bus */
-#define DS1WM_CMD_RST (1 << 5) /* software reset */
-#define DS1WM_CMD_OD (1 << 7) /* overdrive */
-
-#define DS1WM_INT_PD (1 << 0) /* presence detect */
-#define DS1WM_INT_PDR (1 << 1) /* presence detect result */
-#define DS1WM_INT_TBE (1 << 2) /* tx buffer empty */
-#define DS1WM_INT_TSRE (1 << 3) /* tx shift register empty */
-#define DS1WM_INT_RBF (1 << 4) /* rx buffer full */
-#define DS1WM_INT_RSRF (1 << 5) /* rx shift register full */
-
-#define DS1WM_INTEN_EPD (1 << 0) /* enable presence detect int */
-#define DS1WM_INTEN_IAS (1 << 1) /* INTR active state */
-#define DS1WM_INTEN_ETBE (1 << 2) /* enable tx buffer empty int */
-#define DS1WM_INTEN_ETMT (1 << 3) /* enable tx shift register empty int */
-#define DS1WM_INTEN_ERBF (1 << 4) /* enable rx buffer full int */
-#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_INTEN_NOT_IAS (~DS1WM_INTEN_IAS) /* all but INTR active state */
-
-#define DS1WM_TIMEOUT (HZ * 5)
-
-static struct {
- unsigned long freq;
- unsigned long divisor;
-} freq[] = {
- { 1000000, 0x80 },
- { 2000000, 0x84 },
- { 3000000, 0x81 },
- { 4000000, 0x88 },
- { 5000000, 0x82 },
- { 6000000, 0x85 },
- { 7000000, 0x83 },
- { 8000000, 0x8c },
- { 10000000, 0x86 },
- { 12000000, 0x89 },
- { 14000000, 0x87 },
- { 16000000, 0x90 },
- { 20000000, 0x8a },
- { 24000000, 0x8d },
- { 28000000, 0x8b },
- { 32000000, 0x94 },
- { 40000000, 0x8e },
- { 48000000, 0x91 },
- { 56000000, 0x8f },
- { 64000000, 0x98 },
- { 80000000, 0x92 },
- { 96000000, 0x95 },
- { 112000000, 0x93 },
- { 128000000, 0x9c },
-/* you can continue this table, consult the OPERATION - CLOCK DIVISOR
- section of the ds1wm spec sheet. */
-};
-
-struct ds1wm_data {
- void __iomem *map;
- unsigned int bus_shift; /* # of shifts to calc register offsets */
- bool is_hw_big_endian;
- struct platform_device *pdev;
- const struct mfd_cell *cell;
- int irq;
- int slave_present;
- void *reset_complete;
- void *read_complete;
- void *write_complete;
- int read_error;
- /* last byte received */
- u8 read_byte;
- /* byte to write that makes all intr disabled, */
- /* considering active_state (IAS) (optimization) */
- u8 int_en_reg_none;
- unsigned int reset_recover_delay; /* see ds1wm.h */
-};
-
-static inline void ds1wm_write_register(struct ds1wm_data *ds1wm_data, u32 reg,
- u8 val)
-{
- if (ds1wm_data->is_hw_big_endian) {
- switch (ds1wm_data->bus_shift) {
- case 0:
- iowrite8(val, ds1wm_data->map + (reg << 0));
- break;
- case 1:
- iowrite16be((u16)val, ds1wm_data->map + (reg << 1));
- break;
- case 2:
- iowrite32be((u32)val, ds1wm_data->map + (reg << 2));
- break;
- }
- } else {
- switch (ds1wm_data->bus_shift) {
- case 0:
- iowrite8(val, ds1wm_data->map + (reg << 0));
- break;
- case 1:
- iowrite16((u16)val, ds1wm_data->map + (reg << 1));
- break;
- case 2:
- iowrite32((u32)val, ds1wm_data->map + (reg << 2));
- break;
- }
- }
-}
-
-static inline u8 ds1wm_read_register(struct ds1wm_data *ds1wm_data, u32 reg)
-{
- u32 val = 0;
-
- if (ds1wm_data->is_hw_big_endian) {
- switch (ds1wm_data->bus_shift) {
- case 0:
- val = ioread8(ds1wm_data->map + (reg << 0));
- break;
- case 1:
- val = ioread16be(ds1wm_data->map + (reg << 1));
- break;
- case 2:
- val = ioread32be(ds1wm_data->map + (reg << 2));
- break;
- }
- } else {
- switch (ds1wm_data->bus_shift) {
- case 0:
- val = ioread8(ds1wm_data->map + (reg << 0));
- break;
- case 1:
- val = ioread16(ds1wm_data->map + (reg << 1));
- break;
- case 2:
- val = ioread32(ds1wm_data->map + (reg << 2));
- break;
- }
- }
- dev_dbg(&ds1wm_data->pdev->dev,
- "ds1wm_read_register reg: %d, 32 bit val:%x\n", reg, val);
- return (u8)val;
-}
-
-
-static irqreturn_t ds1wm_isr(int isr, void *data)
-{
- struct ds1wm_data *ds1wm_data = data;
- u8 intr;
- u8 inten = ds1wm_read_register(ds1wm_data, DS1WM_INT_EN);
- /* if no bits are set in int enable register (except the IAS)
- than go no further, reading the regs below has side effects */
- if (!(inten & DS1WM_INTEN_NOT_IAS))
- return IRQ_NONE;
-
- ds1wm_write_register(ds1wm_data,
- DS1WM_INT_EN, ds1wm_data->int_en_reg_none);
-
- /* this read action clears the INTR and certain flags in ds1wm */
- intr = ds1wm_read_register(ds1wm_data, DS1WM_INT);
-
- ds1wm_data->slave_present = (intr & DS1WM_INT_PDR) ? 0 : 1;
-
- if ((intr & DS1WM_INT_TSRE) && ds1wm_data->write_complete) {
- inten &= ~DS1WM_INTEN_ETMT;
- complete(ds1wm_data->write_complete);
- }
- if (intr & DS1WM_INT_RBF) {
- /* this read clears the RBF flag */
- ds1wm_data->read_byte = ds1wm_read_register(ds1wm_data,
- DS1WM_DATA);
- inten &= ~DS1WM_INTEN_ERBF;
- if (ds1wm_data->read_complete)
- complete(ds1wm_data->read_complete);
- }
- if ((intr & DS1WM_INT_PD) && ds1wm_data->reset_complete) {
- inten &= ~DS1WM_INTEN_EPD;
- complete(ds1wm_data->reset_complete);
- }
-
- ds1wm_write_register(ds1wm_data, DS1WM_INT_EN, inten);
- return IRQ_HANDLED;
-}
-
-static int ds1wm_reset(struct ds1wm_data *ds1wm_data)
-{
- unsigned long timeleft;
- DECLARE_COMPLETION_ONSTACK(reset_done);
-
- ds1wm_data->reset_complete = &reset_done;
-
- /* enable Presence detect only */
- ds1wm_write_register(ds1wm_data, DS1WM_INT_EN, DS1WM_INTEN_EPD |
- ds1wm_data->int_en_reg_none);
-
- ds1wm_write_register(ds1wm_data, DS1WM_CMD, DS1WM_CMD_1W_RESET);
-
- timeleft = wait_for_completion_timeout(&reset_done, DS1WM_TIMEOUT);
- ds1wm_data->reset_complete = NULL;
- if (!timeleft) {
- dev_err(&ds1wm_data->pdev->dev, "reset failed, timed out\n");
- return 1;
- }
-
- if (!ds1wm_data->slave_present) {
- dev_dbg(&ds1wm_data->pdev->dev, "reset: no devices found\n");
- return 1;
- }
-
- if (ds1wm_data->reset_recover_delay)
- msleep(ds1wm_data->reset_recover_delay);
-
- return 0;
-}
-
-static int ds1wm_write(struct ds1wm_data *ds1wm_data, u8 data)
-{
- unsigned long timeleft;
- DECLARE_COMPLETION_ONSTACK(write_done);
- ds1wm_data->write_complete = &write_done;
-
- ds1wm_write_register(ds1wm_data, DS1WM_INT_EN,
- ds1wm_data->int_en_reg_none | DS1WM_INTEN_ETMT);
-
- ds1wm_write_register(ds1wm_data, DS1WM_DATA, data);
-
- timeleft = wait_for_completion_timeout(&write_done, DS1WM_TIMEOUT);
-
- ds1wm_data->write_complete = NULL;
- if (!timeleft) {
- dev_err(&ds1wm_data->pdev->dev, "write failed, timed out\n");
- return -ETIMEDOUT;
- }
-
- return 0;
-}
-
-static u8 ds1wm_read(struct ds1wm_data *ds1wm_data, unsigned char write_data)
-{
- unsigned long timeleft;
- u8 intEnable = DS1WM_INTEN_ERBF | ds1wm_data->int_en_reg_none;
- DECLARE_COMPLETION_ONSTACK(read_done);
-
- ds1wm_read_register(ds1wm_data, DS1WM_DATA);
-
- ds1wm_data->read_complete = &read_done;
- ds1wm_write_register(ds1wm_data, DS1WM_INT_EN, intEnable);
-
- ds1wm_write_register(ds1wm_data, DS1WM_DATA, write_data);
- timeleft = wait_for_completion_timeout(&read_done, DS1WM_TIMEOUT);
-
- ds1wm_data->read_complete = NULL;
- if (!timeleft) {
- dev_err(&ds1wm_data->pdev->dev, "read failed, timed out\n");
- ds1wm_data->read_error = -ETIMEDOUT;
- return 0xFF;
- }
- ds1wm_data->read_error = 0;
- return ds1wm_data->read_byte;
-}
-
-static int ds1wm_find_divisor(int gclk)
-{
- int i;
-
- for (i = ARRAY_SIZE(freq)-1; i >= 0; --i)
- if (gclk >= freq[i].freq)
- return freq[i].divisor;
-
- return 0;
-}
-
-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)
- 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);
- if (divisor == 0) {
- dev_err(dev, "no suitable divisor for %dHz clock\n",
- plat->clock_rate);
- return;
- }
- ds1wm_write_register(ds1wm_data, DS1WM_CLKDIV, divisor);
-
- /* Let the w1 clock stabilize. */
- msleep(1);
-
- ds1wm_reset(ds1wm_data);
-}
-
-static void ds1wm_down(struct ds1wm_data *ds1wm_data)
-{
- ds1wm_reset(ds1wm_data);
-
- /* Disable interrupts. */
- ds1wm_write_register(ds1wm_data, DS1WM_INT_EN,
- ds1wm_data->int_en_reg_none);
-
- if (ds1wm_data->cell->disable)
- ds1wm_data->cell->disable(ds1wm_data->pdev);
-}
-
-/* --------------------------------------------------------------------- */
-/* w1 methods */
-
-static u8 ds1wm_read_byte(void *data)
-{
- struct ds1wm_data *ds1wm_data = data;
-
- return ds1wm_read(ds1wm_data, 0xff);
-}
-
-static void ds1wm_write_byte(void *data, u8 byte)
-{
- struct ds1wm_data *ds1wm_data = data;
-
- ds1wm_write(ds1wm_data, byte);
-}
-
-static u8 ds1wm_reset_bus(void *data)
-{
- struct ds1wm_data *ds1wm_data = data;
-
- ds1wm_reset(ds1wm_data);
-
- return 0;
-}
-
-static void ds1wm_search(void *data, struct w1_master *master_dev,
- u8 search_type, w1_slave_found_callback slave_found)
-{
- struct ds1wm_data *ds1wm_data = data;
- int i;
- int ms_discrep_bit = -1;
- u64 r = 0; /* holds the progress of the search */
- u64 r_prime, d;
- unsigned slaves_found = 0;
- unsigned int pass = 0;
-
- dev_dbg(&ds1wm_data->pdev->dev, "search begin\n");
- while (true) {
- ++pass;
- if (pass > 100) {
- dev_dbg(&ds1wm_data->pdev->dev,
- "too many attempts (100), search aborted\n");
- return;
- }
-
- mutex_lock(&master_dev->bus_mutex);
- if (ds1wm_reset(ds1wm_data)) {
- mutex_unlock(&master_dev->bus_mutex);
- dev_dbg(&ds1wm_data->pdev->dev,
- "pass: %d reset error (or no slaves)\n", pass);
- break;
- }
-
- dev_dbg(&ds1wm_data->pdev->dev,
- "pass: %d r : %0#18llx writing SEARCH_ROM\n", pass, r);
- ds1wm_write(ds1wm_data, search_type);
- dev_dbg(&ds1wm_data->pdev->dev,
- "pass: %d entering ASM\n", pass);
- ds1wm_write_register(ds1wm_data, DS1WM_CMD, DS1WM_CMD_SRA);
- dev_dbg(&ds1wm_data->pdev->dev,
- "pass: %d beginning nibble loop\n", pass);
-
- r_prime = 0;
- d = 0;
- /* we work one nibble at a time */
- /* each nibble is interleaved to form a byte */
- for (i = 0; i < 16; i++) {
-
- unsigned char resp, _r, _r_prime, _d;
-
- _r = (r >> (4*i)) & 0xf;
- _r = ((_r & 0x1) << 1) |
- ((_r & 0x2) << 2) |
- ((_r & 0x4) << 3) |
- ((_r & 0x8) << 4);
-
- /* writes _r, then reads back: */
- resp = ds1wm_read(ds1wm_data, _r);
-
- if (ds1wm_data->read_error) {
- dev_err(&ds1wm_data->pdev->dev,
- "pass: %d nibble: %d read error\n", pass, i);
- break;
- }
-
- _r_prime = ((resp & 0x02) >> 1) |
- ((resp & 0x08) >> 2) |
- ((resp & 0x20) >> 3) |
- ((resp & 0x80) >> 4);
-
- _d = ((resp & 0x01) >> 0) |
- ((resp & 0x04) >> 1) |
- ((resp & 0x10) >> 2) |
- ((resp & 0x40) >> 3);
-
- r_prime |= (unsigned long long) _r_prime << (i * 4);
- d |= (unsigned long long) _d << (i * 4);
-
- }
- if (ds1wm_data->read_error) {
- mutex_unlock(&master_dev->bus_mutex);
- dev_err(&ds1wm_data->pdev->dev,
- "pass: %d read error, retrying\n", pass);
- break;
- }
- dev_dbg(&ds1wm_data->pdev->dev,
- "pass: %d r\': %0#18llx d:%0#18llx\n",
- pass, r_prime, d);
- dev_dbg(&ds1wm_data->pdev->dev,
- "pass: %d nibble loop complete, exiting ASM\n", pass);
- ds1wm_write_register(ds1wm_data, DS1WM_CMD, ~DS1WM_CMD_SRA);
- dev_dbg(&ds1wm_data->pdev->dev,
- "pass: %d resetting bus\n", pass);
- ds1wm_reset(ds1wm_data);
- mutex_unlock(&master_dev->bus_mutex);
- if ((r_prime & ((u64)1 << 63)) && (d & ((u64)1 << 63))) {
- dev_err(&ds1wm_data->pdev->dev,
- "pass: %d bus error, retrying\n", pass);
- continue; /* start over */
- }
-
-
- dev_dbg(&ds1wm_data->pdev->dev,
- "pass: %d found %0#18llx\n", pass, r_prime);
- slave_found(master_dev, r_prime);
- ++slaves_found;
- dev_dbg(&ds1wm_data->pdev->dev,
- "pass: %d complete, preparing next pass\n", pass);
-
- /* any discrepency found which we already choose the
- '1' branch is now is now irrelevant we reveal the
- next branch with this: */
- d &= ~r;
- /* find last bit set, i.e. the most signif. bit set */
- ms_discrep_bit = fls64(d) - 1;
- dev_dbg(&ds1wm_data->pdev->dev,
- "pass: %d new d:%0#18llx MS discrep bit:%d\n",
- pass, d, ms_discrep_bit);
-
- /* prev_ms_discrep_bit = ms_discrep_bit;
- prepare for next ROM search: */
- if (ms_discrep_bit == -1)
- break;
-
- r = (r & ~(~0ull << (ms_discrep_bit))) | 1 << ms_discrep_bit;
- } /* end while true */
- dev_dbg(&ds1wm_data->pdev->dev,
- "pass: %d total: %d search done ms d bit pos: %d\n", pass,
- slaves_found, ms_discrep_bit);
-}
-
-/* --------------------------------------------------------------------- */
-
-static struct w1_bus_master ds1wm_master = {
- .read_byte = ds1wm_read_byte,
- .write_byte = ds1wm_write_byte,
- .reset_bus = ds1wm_reset_bus,
- .search = ds1wm_search,
-};
-
-static int ds1wm_probe(struct platform_device *pdev)
-{
- struct ds1wm_data *ds1wm_data;
- struct ds1wm_driver_data *plat;
- struct resource *res;
- int ret;
- u8 inten;
-
- if (!pdev)
- return -ENODEV;
-
- ds1wm_data = devm_kzalloc(&pdev->dev, sizeof(*ds1wm_data), GFP_KERNEL);
- if (!ds1wm_data)
- return -ENOMEM;
-
- platform_set_drvdata(pdev, ds1wm_data);
-
- res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- if (!res)
- return -ENXIO;
- ds1wm_data->map = devm_ioremap(&pdev->dev, res->start,
- resource_size(res));
- if (!ds1wm_data->map)
- 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;
-
- /* how many bits to shift register number to get register offset */
- if (plat->bus_shift > 2) {
- dev_err(&ds1wm_data->pdev->dev,
- "illegal bus shift %d, not written",
- ds1wm_data->bus_shift);
- 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)) {
- 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);
- 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);
- ds1wm_write_register(ds1wm_data,
- DS1WM_INT_EN, ds1wm_data->int_en_reg_none);
-
- if (res->flags & IORESOURCE_IRQ_HIGHEDGE)
- irq_set_irq_type(ds1wm_data->irq, IRQ_TYPE_EDGE_RISING);
- if (res->flags & IORESOURCE_IRQ_LOWEDGE)
- irq_set_irq_type(ds1wm_data->irq, IRQ_TYPE_EDGE_FALLING);
- if (res->flags & IORESOURCE_IRQ_HIGHLEVEL)
- irq_set_irq_type(ds1wm_data->irq, IRQ_TYPE_LEVEL_HIGH);
- if (res->flags & IORESOURCE_IRQ_LOWLEVEL)
- irq_set_irq_type(ds1wm_data->irq, IRQ_TYPE_LEVEL_LOW);
-
- ret = devm_request_irq(&pdev->dev, ds1wm_data->irq, ds1wm_isr,
- IRQF_SHARED, "ds1wm", ds1wm_data);
- if (ret) {
- dev_err(&ds1wm_data->pdev->dev,
- "devm_request_irq %d failed with errno %d\n",
- ds1wm_data->irq,
- ret);
-
- return ret;
- }
-
- ds1wm_up(ds1wm_data);
-
- ds1wm_master.data = (void *)ds1wm_data;
-
- ret = w1_add_master_device(&ds1wm_master);
- if (ret)
- goto err;
-
- dev_dbg(&ds1wm_data->pdev->dev,
- "ds1wm: probe successful, IAS: %d, rec.delay: %d, clockrate: %d, bus-shift: %d, is Hw Big Endian: %d\n",
- plat->active_high,
- plat->reset_recover_delay,
- plat->clock_rate,
- ds1wm_data->bus_shift,
- ds1wm_data->is_hw_big_endian);
- return 0;
-
-err:
- ds1wm_down(ds1wm_data);
-
- return ret;
-}
-
-#ifdef CONFIG_PM
-static int ds1wm_suspend(struct platform_device *pdev, pm_message_t state)
-{
- struct ds1wm_data *ds1wm_data = platform_get_drvdata(pdev);
-
- ds1wm_down(ds1wm_data);
-
- return 0;
-}
-
-static int ds1wm_resume(struct platform_device *pdev)
-{
- struct ds1wm_data *ds1wm_data = platform_get_drvdata(pdev);
-
- ds1wm_up(ds1wm_data);
-
- return 0;
-}
-#else
-#define ds1wm_suspend NULL
-#define ds1wm_resume NULL
-#endif
-
-static int ds1wm_remove(struct platform_device *pdev)
-{
- struct ds1wm_data *ds1wm_data = platform_get_drvdata(pdev);
-
- w1_remove_master_device(&ds1wm_master);
- ds1wm_down(ds1wm_data);
-
- return 0;
-}
-
-static struct platform_driver ds1wm_driver = {
- .driver = {
- .name = "ds1wm",
- },
- .probe = ds1wm_probe,
- .remove = ds1wm_remove,
- .suspend = ds1wm_suspend,
- .resume = ds1wm_resume
-};
-
-static int __init ds1wm_init(void)
-{
- pr_info("DS1WM w1 busmaster driver - (c) 2004 Szabolcs Gyurko\n");
- return platform_driver_register(&ds1wm_driver);
-}
-
-static void __exit ds1wm_exit(void)
-{
- platform_driver_unregister(&ds1wm_driver);
-}
-
-module_init(ds1wm_init);
-module_exit(ds1wm_exit);
-
-MODULE_LICENSE("GPL");
-MODULE_AUTHOR("Szabolcs Gyurko <szabolcs.gyurko@tlt.hu>, "
- "Matt Reimer <mreimer@vpop.net>,"
- "Jean-Francois Dagenais <dagenaisj@sonatest.com>");
-MODULE_DESCRIPTION("DS1WM w1 busmaster driver");
diff --git a/drivers/w1/masters/ds2482.c b/drivers/w1/masters/ds2482.c
index 62c44616d8a9..e2a568c9a43a 100644
--- a/drivers/w1/masters/ds2482.c
+++ b/drivers/w1/masters/ds2482.c
@@ -7,7 +7,7 @@
* It is a I2C to 1-wire bridge.
* There are two variations: -100 and -800, which have 1 or 8 1-wire ports.
* The complete datasheet can be obtained from MAXIM's website at:
- * http://www.maxim-ic.com/quick_view2.cfm/qv_pk/4382
+ * https://www.analog.com/en/products/ds2482-100.html
*/
#include <linux/module.h>
@@ -15,7 +15,7 @@
#include <linux/slab.h>
#include <linux/i2c.h>
#include <linux/delay.h>
-#include <asm/delay.h>
+#include <linux/regulator/consumer.h>
#include <linux/w1.h>
@@ -36,7 +36,7 @@ MODULE_PARM_DESC(active_pullup, "Active pullup (apply to all buses): " \
/* extra configurations - e.g. 1WS */
static int extra_config;
-module_param(extra_config, int, S_IRUGO | S_IWUSR);
+module_param(extra_config, int, 0644);
MODULE_PARM_DESC(extra_config, "Extra Configuration settings 1=APU,2=PPM,3=SPU,8=1WS");
/*
@@ -78,10 +78,8 @@ MODULE_PARM_DESC(extra_config, "Extra Configuration settings 1=APU,2=PPM,3=SPU,8
* To set the channel, write the value at the index of the channel.
* Read and compare against the corresponding value to verify the change.
*/
-static const u8 ds2482_chan_wr[8] =
- { 0xF0, 0xE1, 0xD2, 0xC3, 0xB4, 0xA5, 0x96, 0x87 };
-static const u8 ds2482_chan_rd[8] =
- { 0xB8, 0xB1, 0xAA, 0xA3, 0x9C, 0x95, 0x8E, 0x87 };
+static const u8 ds2482_chan_wr[8] = { 0xF0, 0xE1, 0xD2, 0xC3, 0xB4, 0xA5, 0x96, 0x87 };
+static const u8 ds2482_chan_rd[8] = { 0xB8, 0xB1, 0xAA, 0xA3, 0x9C, 0x95, 0x8E, 0x87 };
/*
@@ -442,23 +440,26 @@ static u8 ds2482_w1_set_pullup(void *data, int delay)
}
-static int ds2482_probe(struct i2c_client *client,
- const struct i2c_device_id *id)
+static int ds2482_probe(struct i2c_client *client)
{
struct ds2482_data *data;
int err = -ENODEV;
int temp1;
int idx;
+ int ret;
if (!i2c_check_functionality(client->adapter,
I2C_FUNC_SMBUS_WRITE_BYTE_DATA |
I2C_FUNC_SMBUS_BYTE))
return -ENODEV;
- if (!(data = kzalloc(sizeof(struct ds2482_data), GFP_KERNEL))) {
- err = -ENOMEM;
- goto exit;
- }
+ data = devm_kzalloc(&client->dev, sizeof(struct ds2482_data), GFP_KERNEL);
+ if (!data)
+ return -ENOMEM;
+
+ ret = devm_regulator_get_enable(&client->dev, "vcc");
+ if (ret)
+ return dev_err_probe(&client->dev, ret, "Failed to enable regulator\n");
data->client = client;
i2c_set_clientdata(client, data);
@@ -466,7 +467,7 @@ static int ds2482_probe(struct i2c_client *client,
/* Reset the device (sets the read_ptr to status) */
if (ds2482_send_cmd(data, DS2482_CMD_RESET) < 0) {
dev_warn(&client->dev, "DS2482 reset failed.\n");
- goto exit_free;
+ return err;
}
/* Sleep at least 525ns to allow the reset to complete */
@@ -477,7 +478,7 @@ static int ds2482_probe(struct i2c_client *client,
if (temp1 != (DS2482_REG_STS_LL | DS2482_REG_STS_RST)) {
dev_warn(&client->dev, "DS2482 reset status "
"0x%02X - not a DS2482\n", temp1);
- goto exit_free;
+ return err;
}
/* Detect the 8-port version */
@@ -519,9 +520,6 @@ exit_w1_remove:
if (data->w1_ch[idx].pdev != NULL)
w1_remove_master_device(&data->w1_ch[idx].w1_bm);
}
-exit_free:
- kfree(data);
-exit:
return err;
}
@@ -535,16 +533,14 @@ static void ds2482_remove(struct i2c_client *client)
if (data->w1_ch[idx].pdev != NULL)
w1_remove_master_device(&data->w1_ch[idx].w1_bm);
}
-
- /* Free the memory */
- kfree(data);
}
/*
* Driver data (common to all clients)
*/
static const struct i2c_device_id ds2482_id[] = {
- { "ds2482", 0 },
+ { "ds2482" },
+ { "ds2484" },
{ }
};
MODULE_DEVICE_TABLE(i2c, ds2482_id);
diff --git a/drivers/w1/masters/ds2490.c b/drivers/w1/masters/ds2490.c
index 0eb560fc0153..e1cac0730cbb 100644
--- a/drivers/w1/masters/ds2490.c
+++ b/drivers/w1/masters/ds2490.c
@@ -98,6 +98,8 @@
#define ST_EPOF 0x80
/* Status transfer size, 16 bytes status, 16 byte result flags */
#define ST_SIZE 0x20
+/* 1-wire data i/o fifo size, 128 bytes */
+#define FIFO_SIZE 0x80
/* Result Register flags */
#define RR_DETECT 0xA5 /* New device detected */
@@ -304,6 +306,7 @@ static void ds_reset_device(struct ds_device *dev)
if (dev->spu_sleep) {
/* lower 4 bits are 0, see ds_set_pullup */
u8 del = dev->spu_sleep>>4;
+
if (ds_send_control(dev, COMM_SET_DURATION | COMM_IM, del))
dev_err(&dev->udev->dev,
"%s: Error setting duration\n", __func__);
@@ -613,14 +616,11 @@ static int ds_read_byte(struct ds_device *dev, u8 *byte)
return 0;
}
-static int ds_read_block(struct ds_device *dev, u8 *buf, int len)
+static int read_block_chunk(struct ds_device *dev, u8 *buf, int len)
{
struct ds_status st;
int err;
- if (len > 64*1024)
- return -E2BIG;
-
memset(buf, 0xFF, len);
err = ds_send_data(dev, buf, len);
@@ -639,6 +639,24 @@ static int ds_read_block(struct ds_device *dev, u8 *buf, int len)
return err;
}
+static int ds_read_block(struct ds_device *dev, u8 *buf, int len)
+{
+ int err, to_read, rem = len;
+
+ if (len > 64 * 1024)
+ return -E2BIG;
+
+ do {
+ to_read = rem <= FIFO_SIZE ? rem : FIFO_SIZE;
+ err = read_block_chunk(dev, &buf[len - rem], to_read);
+ if (err < 0)
+ return err;
+ rem -= to_read;
+ } while (rem);
+
+ return err;
+}
+
static int ds_write_block(struct ds_device *dev, u8 *buf, int len)
{
int err;
@@ -731,7 +749,8 @@ static void ds9490r_search(void *data, struct w1_master *master,
break;
if (st.data_in_buffer_status) {
- /* Bulk in can receive partial ids, but when it does
+ /*
+ * Bulk in can receive partial ids, but when it does
* they fail crc and will be discarded anyway.
* That has only been seen when status in buffer
* is 0 and bulk is read anyway, so don't read
@@ -743,8 +762,10 @@ static void ds9490r_search(void *data, struct w1_master *master,
break;
for (i = 0; i < err/8; ++i) {
found_ids[found++] = buf[i];
- /* can't know if there will be a discrepancy
- * value after until the next id */
+ /*
+ * can't know if there will be a discrepancy
+ * value after until the next id
+ */
if (found == search_limit) {
master->search_id = buf[i];
break;
@@ -760,7 +781,8 @@ static void ds9490r_search(void *data, struct w1_master *master,
if (found <= search_limit) {
master->search_id = 0;
} else if (!test_bit(W1_WARN_MAX_COUNT, &master->flags)) {
- /* Only max_slave_count will be scanned in a search,
+ /*
+ * Only max_slave_count will be scanned in a search,
* but it will start where it left off next search
* until all ids are identified and then it will start
* over. A continued search will report the previous
diff --git a/drivers/w1/masters/matrox_w1.c b/drivers/w1/masters/matrox_w1.c
index ee716c715710..146fa7c6e74e 100644
--- a/drivers/w1/masters/matrox_w1.c
+++ b/drivers/w1/masters/matrox_w1.c
@@ -7,7 +7,7 @@
#include <asm/types.h>
#include <linux/atomic.h>
-#include <asm/io.h>
+#include <linux/io.h>
#include <linux/delay.h>
#include <linux/kernel.h>
@@ -39,8 +39,7 @@
#define MATROX_GET_DATA 0x2B
#define MATROX_CURSOR_CTL 0x06
-struct matrox_device
-{
+struct matrox_device {
void __iomem *base_addr;
void __iomem *port_index;
void __iomem *port_data;
@@ -48,7 +47,6 @@ struct matrox_device
unsigned long phys_addr;
void __iomem *virt_addr;
- unsigned long found;
struct w1_bus_master *bus_master;
};
@@ -64,7 +62,7 @@ struct matrox_device
*
* Port mapping.
*/
-static __inline__ u8 matrox_w1_read_reg(struct matrox_device *dev, u8 reg)
+static inline u8 matrox_w1_read_reg(struct matrox_device *dev, u8 reg)
{
u8 ret;
@@ -75,7 +73,7 @@ static __inline__ u8 matrox_w1_read_reg(struct matrox_device *dev, u8 reg)
return ret;
}
-static __inline__ void matrox_w1_write_reg(struct matrox_device *dev, u8 reg, u8 val)
+static inline void matrox_w1_write_reg(struct matrox_device *dev, u8 reg, u8 val)
{
writeb(reg, dev->port_index);
writeb(val, dev->port_data);
@@ -123,13 +121,8 @@ static int matrox_w1_probe(struct pci_dev *pdev, const struct pci_device_id *ent
dev = kzalloc(sizeof(struct matrox_device) +
sizeof(struct w1_bus_master), GFP_KERNEL);
- if (!dev) {
- dev_err(&pdev->dev,
- "%s: Failed to create new matrox_device object.\n",
- __func__);
+ if (!dev)
return -ENOMEM;
- }
-
dev->bus_master = (struct w1_bus_master *)(dev + 1);
@@ -164,8 +157,6 @@ static int matrox_w1_probe(struct pci_dev *pdev, const struct pci_device_id *ent
pci_set_drvdata(pdev, dev);
- dev->found = 1;
-
dev_info(&pdev->dev, "Matrox G400 GPIO transport layer for 1-wire.\n");
return 0;
@@ -182,10 +173,9 @@ static void matrox_w1_remove(struct pci_dev *pdev)
{
struct matrox_device *dev = pci_get_drvdata(pdev);
- if (dev->found) {
- w1_remove_master_device(dev->bus_master);
- iounmap(dev->virt_addr);
- }
+ w1_remove_master_device(dev->bus_master);
+ iounmap(dev->virt_addr);
+
kfree(dev);
}
diff --git a/drivers/w1/masters/mxc_w1.c b/drivers/w1/masters/mxc_w1.c
index 090cbbf9e1e2..30a190ce4298 100644
--- a/drivers/w1/masters/mxc_w1.c
+++ b/drivers/w1/masters/mxc_w1.c
@@ -151,15 +151,13 @@ out_disable_clk:
/*
* disassociate the w1 device from the driver
*/
-static int mxc_w1_remove(struct platform_device *pdev)
+static void mxc_w1_remove(struct platform_device *pdev)
{
struct mxc_w1_device *mdev = platform_get_drvdata(pdev);
w1_remove_master_device(&mdev->bus_master);
clk_disable_unprepare(mdev->clk);
-
- return 0;
}
static const struct of_device_id mxc_w1_dt_ids[] = {
diff --git a/drivers/w1/masters/omap_hdq.c b/drivers/w1/masters/omap_hdq.c
index bf2ec59c1f9d..d13db3396570 100644
--- a/drivers/w1/masters/omap_hdq.c
+++ b/drivers/w1/masters/omap_hdq.c
@@ -1,12 +1,6 @@
+// SPDX-License-Identifier: GPL-2.0-only
/*
- * drivers/w1/masters/omap_hdq.c
- *
* Copyright (C) 2007,2012 Texas Instruments, Inc.
- *
- * This file is licensed under the terms of the GNU General Public License
- * version 2. This program is licensed "as is" without any warranty of any
- * kind, whether express or implied.
- *
*/
#include <linux/kernel.h>
#include <linux/module.h>
@@ -48,7 +42,7 @@
static DECLARE_WAIT_QUEUE_HEAD(hdq_wait_queue);
static int w1_id;
-module_param(w1_id, int, S_IRUSR);
+module_param(w1_id, int, 0400);
MODULE_PARM_DESC(w1_id, "1-wire id for the slave detection in HDQ mode");
struct hdq_data {
@@ -451,7 +445,6 @@ static u8 omap_w1_triplet(void *_hdq, u8 bdir)
out:
mutex_unlock(&hdq_data->hdq_mutex);
rtn:
- pm_runtime_mark_last_busy(hdq_data->dev);
pm_runtime_put_autosuspend(hdq_data->dev);
return ret;
@@ -472,7 +465,6 @@ static u8 omap_w1_reset_bus(void *_hdq)
omap_hdq_break(hdq_data);
- pm_runtime_mark_last_busy(hdq_data->dev);
pm_runtime_put_autosuspend(hdq_data->dev);
return 0;
@@ -496,7 +488,6 @@ static u8 omap_w1_read_byte(void *_hdq)
if (ret)
val = -1;
- pm_runtime_mark_last_busy(hdq_data->dev);
pm_runtime_put_autosuspend(hdq_data->dev);
return val;
@@ -531,7 +522,6 @@ static void omap_w1_write_byte(void *_hdq, u8 byte)
}
out_err:
- pm_runtime_mark_last_busy(hdq_data->dev);
pm_runtime_put_autosuspend(hdq_data->dev);
}
@@ -579,10 +569,8 @@ static int omap_hdq_probe(struct platform_device *pdev)
const char *mode;
hdq_data = devm_kzalloc(dev, sizeof(*hdq_data), GFP_KERNEL);
- if (!hdq_data) {
- dev_dbg(&pdev->dev, "unable to allocate memory\n");
+ if (!hdq_data)
return -ENOMEM;
- }
hdq_data->dev = dev;
platform_set_drvdata(pdev, hdq_data);
@@ -633,7 +621,6 @@ static int omap_hdq_probe(struct platform_device *pdev)
omap_hdq_break(hdq_data);
- pm_runtime_mark_last_busy(&pdev->dev);
pm_runtime_put_autosuspend(&pdev->dev);
omap_w1_master.data = hdq_data;
@@ -655,7 +642,7 @@ err_w1:
return ret;
}
-static int omap_hdq_remove(struct platform_device *pdev)
+static void omap_hdq_remove(struct platform_device *pdev)
{
int active;
@@ -669,8 +656,6 @@ static int omap_hdq_remove(struct platform_device *pdev)
if (active >= 0)
pm_runtime_put_sync(&pdev->dev);
pm_runtime_disable(&pdev->dev);
-
- return 0;
}
static const struct of_device_id omap_hdq_dt_ids[] = {
diff --git a/drivers/w1/masters/sgi_w1.c b/drivers/w1/masters/sgi_w1.c
index e8c7fa68d3cc..af6b1186b763 100644
--- a/drivers/w1/masters/sgi_w1.c
+++ b/drivers/w1/masters/sgi_w1.c
@@ -93,7 +93,7 @@ static int sgi_w1_probe(struct platform_device *pdev)
pdata = dev_get_platdata(&pdev->dev);
if (pdata) {
- strlcpy(sdev->dev_id, pdata->dev_id, sizeof(sdev->dev_id));
+ strscpy(sdev->dev_id, pdata->dev_id, sizeof(sdev->dev_id));
sdev->bus_master.dev_id = sdev->dev_id;
}
@@ -105,13 +105,11 @@ static int sgi_w1_probe(struct platform_device *pdev)
/*
* disassociate the w1 device from the driver
*/
-static int sgi_w1_remove(struct platform_device *pdev)
+static void sgi_w1_remove(struct platform_device *pdev)
{
struct sgi_w1_device *sdev = platform_get_drvdata(pdev);
w1_remove_master_device(&sdev->bus_master);
-
- return 0;
}
static struct platform_driver sgi_w1_driver = {
diff --git a/drivers/w1/masters/w1-gpio.c b/drivers/w1/masters/w1-gpio.c
index d4632aace402..a579f95be8f1 100644
--- a/drivers/w1/masters/w1-gpio.c
+++ b/drivers/w1/masters/w1-gpio.c
@@ -5,40 +5,45 @@
* Copyright (C) 2007 Ville Syrjala <syrjala@sci.fi>
*/
-#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/device.h>
+#include <linux/err.h>
+#include <linux/gpio/consumer.h>
+#include <linux/mod_devicetable.h>
#include <linux/module.h>
#include <linux/platform_device.h>
-#include <linux/slab.h>
-#include <linux/w1-gpio.h>
-#include <linux/gpio/consumer.h>
-#include <linux/of_platform.h>
-#include <linux/err.h>
-#include <linux/of.h>
-#include <linux/delay.h>
+#include <linux/property.h>
+#include <linux/types.h>
#include <linux/w1.h>
+struct w1_gpio_ddata {
+ struct gpio_desc *gpiod;
+ struct gpio_desc *pullup_gpiod;
+ unsigned int pullup_duration;
+};
+
static u8 w1_gpio_set_pullup(void *data, int delay)
{
- struct w1_gpio_platform_data *pdata = data;
+ struct w1_gpio_ddata *ddata = data;
if (delay) {
- pdata->pullup_duration = delay;
+ ddata->pullup_duration = delay;
} else {
- if (pdata->pullup_duration) {
+ if (ddata->pullup_duration) {
/*
* This will OVERRIDE open drain emulation and force-pull
* the line high for some time.
*/
- gpiod_set_raw_value(pdata->gpiod, 1);
- msleep(pdata->pullup_duration);
+ gpiod_set_raw_value(ddata->gpiod, 1);
+ msleep(ddata->pullup_duration);
/*
* This will simply set the line as input since we are doing
* open drain emulation in the GPIO library.
*/
- gpiod_set_value(pdata->gpiod, 1);
+ gpiod_set_value(ddata->gpiod, 1);
}
- pdata->pullup_duration = 0;
+ ddata->pullup_duration = 0;
}
return 0;
@@ -46,83 +51,57 @@ static u8 w1_gpio_set_pullup(void *data, int delay)
static void w1_gpio_write_bit(void *data, u8 bit)
{
- struct w1_gpio_platform_data *pdata = data;
+ struct w1_gpio_ddata *ddata = data;
- gpiod_set_value(pdata->gpiod, bit);
+ gpiod_set_value(ddata->gpiod, bit);
}
static u8 w1_gpio_read_bit(void *data)
{
- struct w1_gpio_platform_data *pdata = data;
+ struct w1_gpio_ddata *ddata = data;
- return gpiod_get_value(pdata->gpiod) ? 1 : 0;
+ return gpiod_get_value(ddata->gpiod) ? 1 : 0;
}
-#if defined(CONFIG_OF)
-static const struct of_device_id w1_gpio_dt_ids[] = {
- { .compatible = "w1-gpio" },
- {}
-};
-MODULE_DEVICE_TABLE(of, w1_gpio_dt_ids);
-#endif
-
static int w1_gpio_probe(struct platform_device *pdev)
{
struct w1_bus_master *master;
- struct w1_gpio_platform_data *pdata;
+ struct w1_gpio_ddata *ddata;
struct device *dev = &pdev->dev;
- struct device_node *np = dev->of_node;
/* Enforce open drain mode by default */
enum gpiod_flags gflags = GPIOD_OUT_LOW_OPEN_DRAIN;
int err;
- if (of_have_populated_dt()) {
- pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL);
- if (!pdata)
- return -ENOMEM;
-
- /*
- * This parameter means that something else than the gpiolib has
- * already set the line into open drain mode, so we should just
- * driver it high/low like we are in full control of the line and
- * open drain will happen transparently.
- */
- if (of_get_property(np, "linux,open-drain", NULL))
- gflags = GPIOD_OUT_LOW;
-
- pdev->dev.platform_data = pdata;
- }
- pdata = dev_get_platdata(dev);
+ ddata = devm_kzalloc(&pdev->dev, sizeof(*ddata), GFP_KERNEL);
+ if (!ddata)
+ return -ENOMEM;
- if (!pdata) {
- dev_err(dev, "No configuration data\n");
- return -ENXIO;
- }
+ /*
+ * This parameter means that something else than the gpiolib has
+ * already set the line into open drain mode, so we should just
+ * driver it high/low like we are in full control of the line and
+ * open drain will happen transparently.
+ */
+ if (device_property_present(dev, "linux,open-drain"))
+ gflags = GPIOD_OUT_LOW;
- master = devm_kzalloc(dev, sizeof(struct w1_bus_master),
- GFP_KERNEL);
- if (!master) {
- dev_err(dev, "Out of memory\n");
+ master = devm_kzalloc(dev, sizeof(*master), GFP_KERNEL);
+ if (!master)
return -ENOMEM;
- }
- pdata->gpiod = devm_gpiod_get_index(dev, NULL, 0, gflags);
- if (IS_ERR(pdata->gpiod)) {
- dev_err(dev, "gpio_request (pin) failed\n");
- return PTR_ERR(pdata->gpiod);
- }
+ ddata->gpiod = devm_gpiod_get_index(dev, NULL, 0, gflags);
+ if (IS_ERR(ddata->gpiod))
+ return dev_err_probe(dev, PTR_ERR(ddata->gpiod), "gpio_request (pin) failed\n");
- pdata->pullup_gpiod =
+ ddata->pullup_gpiod =
devm_gpiod_get_index_optional(dev, NULL, 1, GPIOD_OUT_LOW);
- if (IS_ERR(pdata->pullup_gpiod)) {
- dev_err(dev, "gpio_request_one "
- "(ext_pullup_enable_pin) failed\n");
- return PTR_ERR(pdata->pullup_gpiod);
- }
+ if (IS_ERR(ddata->pullup_gpiod))
+ return dev_err_probe(dev, PTR_ERR(ddata->pullup_gpiod),
+ "gpio_request (ext_pullup_enable_pin) failed\n");
- master->data = pdata;
+ master->data = ddata;
master->read_bit = w1_gpio_read_bit;
- gpiod_direction_output(pdata->gpiod, 1);
+ gpiod_direction_output(ddata->gpiod, 1);
master->write_bit = w1_gpio_write_bit;
/*
@@ -135,65 +114,36 @@ static int w1_gpio_probe(struct platform_device *pdev)
master->set_pullup = w1_gpio_set_pullup;
err = w1_add_master_device(master);
- if (err) {
- dev_err(dev, "w1_add_master device failed\n");
- return err;
- }
-
- if (pdata->enable_external_pullup)
- pdata->enable_external_pullup(1);
+ if (err)
+ return dev_err_probe(dev, err, "w1_add_master device failed\n");
- if (pdata->pullup_gpiod)
- gpiod_set_value(pdata->pullup_gpiod, 1);
+ gpiod_set_value(ddata->pullup_gpiod, 1);
platform_set_drvdata(pdev, master);
return 0;
}
-static int w1_gpio_remove(struct platform_device *pdev)
+static void w1_gpio_remove(struct platform_device *pdev)
{
struct w1_bus_master *master = platform_get_drvdata(pdev);
- struct w1_gpio_platform_data *pdata = dev_get_platdata(&pdev->dev);
-
- if (pdata->enable_external_pullup)
- pdata->enable_external_pullup(0);
+ struct w1_gpio_ddata *ddata = master->data;
- if (pdata->pullup_gpiod)
- gpiod_set_value(pdata->pullup_gpiod, 0);
+ gpiod_set_value(ddata->pullup_gpiod, 0);
w1_remove_master_device(master);
-
- return 0;
-}
-
-static int __maybe_unused w1_gpio_suspend(struct device *dev)
-{
- struct w1_gpio_platform_data *pdata = dev_get_platdata(dev);
-
- if (pdata->enable_external_pullup)
- pdata->enable_external_pullup(0);
-
- return 0;
}
-static int __maybe_unused w1_gpio_resume(struct device *dev)
-{
- struct w1_gpio_platform_data *pdata = dev_get_platdata(dev);
-
- if (pdata->enable_external_pullup)
- pdata->enable_external_pullup(1);
-
- return 0;
-}
-
-static SIMPLE_DEV_PM_OPS(w1_gpio_pm_ops, w1_gpio_suspend, w1_gpio_resume);
+static const struct of_device_id w1_gpio_dt_ids[] = {
+ { .compatible = "w1-gpio" },
+ {}
+};
+MODULE_DEVICE_TABLE(of, w1_gpio_dt_ids);
static struct platform_driver w1_gpio_driver = {
.driver = {
.name = "w1-gpio",
- .pm = &w1_gpio_pm_ops,
- .of_match_table = of_match_ptr(w1_gpio_dt_ids),
+ .of_match_table = w1_gpio_dt_ids,
},
.probe = w1_gpio_probe,
.remove = w1_gpio_remove,
diff --git a/drivers/w1/masters/w1-uart.c b/drivers/w1/masters/w1-uart.c
new file mode 100644
index 000000000000..c87eea347806
--- /dev/null
+++ b/drivers/w1/masters/w1-uart.c
@@ -0,0 +1,415 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * w1-uart - UART 1-Wire bus driver
+ *
+ * Uses the UART interface (via Serial Device Bus) to create the 1-Wire
+ * timing patterns. Implements the following 1-Wire master interface:
+ *
+ * - reset_bus: requests baud-rate 9600
+ *
+ * - touch_bit: requests baud-rate 115200
+ *
+ * Author: Christoph Winklhofer <cj.winklhofer@gmail.com>
+ */
+
+#include <linux/completion.h>
+#include <linux/delay.h>
+#include <linux/jiffies.h>
+#include <linux/module.h>
+#include <linux/mutex.h>
+#include <linux/of.h>
+#include <linux/serdev.h>
+#include <linux/w1.h>
+
+/* UART packet contains start and stop bit */
+#define W1_UART_BITS_PER_PACKET (BITS_PER_BYTE + 2)
+
+/* Timeout to wait for completion of serdev-receive */
+#define W1_UART_TIMEOUT msecs_to_jiffies(500)
+
+/**
+ * struct w1_uart_config - configuration for 1-Wire operation
+ * @baudrate: baud-rate returned from serdev
+ * @delay_us: delay to complete a 1-Wire cycle (in us)
+ * @tx_byte: byte to generate 1-Wire timing pattern
+ */
+struct w1_uart_config {
+ unsigned int baudrate;
+ unsigned int delay_us;
+ u8 tx_byte;
+};
+
+/**
+ * struct w1_uart_device - 1-Wire UART device structure
+ * @serdev: serial device
+ * @bus: w1-bus master
+ * @cfg_reset: config for 1-Wire reset
+ * @cfg_touch_0: config for 1-Wire write-0 cycle
+ * @cfg_touch_1: config for 1-Wire write-1 and read cycle
+ * @rx_byte_received: completion for serdev receive
+ * @rx_mutex: mutex to protect rx_err and rx_byte
+ * @rx_err: indicates an error in serdev-receive
+ * @rx_byte: result byte from serdev-receive
+ */
+struct w1_uart_device {
+ struct serdev_device *serdev;
+ struct w1_bus_master bus;
+
+ struct w1_uart_config cfg_reset;
+ struct w1_uart_config cfg_touch_0;
+ struct w1_uart_config cfg_touch_1;
+
+ struct completion rx_byte_received;
+ /*
+ * protect rx_err and rx_byte from concurrent access in
+ * w1-callbacks and serdev-receive.
+ */
+ struct mutex rx_mutex;
+ int rx_err;
+ u8 rx_byte;
+};
+
+/**
+ * struct w1_uart_limits - limits for 1-Wire operations
+ * @baudrate: Requested baud-rate to create 1-Wire timing pattern
+ * @bit_min_us: minimum time for a bit (in us)
+ * @bit_max_us: maximum time for a bit (in us)
+ * @sample_us: timespan to sample 1-Wire response
+ * @cycle_us: duration of the 1-Wire cycle
+ */
+struct w1_uart_limits {
+ unsigned int baudrate;
+ unsigned int bit_min_us;
+ unsigned int bit_max_us;
+ unsigned int sample_us;
+ unsigned int cycle_us;
+};
+
+static inline unsigned int baud_to_bit_ns(unsigned int baud)
+{
+ return NSEC_PER_SEC / baud;
+}
+
+static inline unsigned int to_ns(unsigned int us)
+{
+ return us * NSEC_PER_USEC;
+}
+
+/*
+ * Set baud-rate, delay and tx-byte to create a 1-Wire pulse and adapt
+ * the tx-byte according to the actual baud-rate.
+ *
+ * Reject when:
+ * - time for a bit outside min/max range
+ * - a 1-Wire response is not detectable for sent byte
+ */
+static int w1_uart_set_config(struct serdev_device *serdev,
+ const struct w1_uart_limits *limits,
+ struct w1_uart_config *w1cfg)
+{
+ unsigned int packet_ns;
+ unsigned int bits_low;
+ unsigned int bit_ns;
+ unsigned int low_ns;
+
+ w1cfg->baudrate = serdev_device_set_baudrate(serdev, limits->baudrate);
+ if (w1cfg->baudrate == 0)
+ return -EINVAL;
+
+ /* Compute in nanoseconds for accuracy */
+ bit_ns = baud_to_bit_ns(w1cfg->baudrate);
+ bits_low = to_ns(limits->bit_min_us) / bit_ns;
+ /* start bit is always low */
+ low_ns = bit_ns * (bits_low + 1);
+
+ if (low_ns < to_ns(limits->bit_min_us))
+ return -EINVAL;
+
+ if (low_ns > to_ns(limits->bit_max_us))
+ return -EINVAL;
+
+ /* 1-Wire response detectable for sent byte */
+ if (limits->sample_us > 0 &&
+ bit_ns * BITS_PER_BYTE < low_ns + to_ns(limits->sample_us))
+ return -EINVAL;
+
+ /* delay: 1-Wire cycle takes longer than the UART packet */
+ packet_ns = bit_ns * W1_UART_BITS_PER_PACKET;
+ w1cfg->delay_us = 0;
+ if (to_ns(limits->cycle_us) > packet_ns)
+ w1cfg->delay_us =
+ (to_ns(limits->cycle_us) - packet_ns) / NSEC_PER_USEC;
+
+ /* byte to create 1-Wire pulse */
+ w1cfg->tx_byte = 0xff << bits_low;
+
+ return 0;
+}
+
+/*
+ * Configuration for reset and presence detect
+ * - bit_min_us is 480us, add margin and use 485us
+ * - limits for sample time 60us-75us, use 65us
+ */
+static int w1_uart_set_config_reset(struct w1_uart_device *w1dev)
+{
+ struct serdev_device *serdev = w1dev->serdev;
+ struct device_node *np = serdev->dev.of_node;
+
+ struct w1_uart_limits limits = { .baudrate = 9600,
+ .bit_min_us = 485,
+ .bit_max_us = 640,
+ .sample_us = 65,
+ .cycle_us = 960 };
+
+ of_property_read_u32(np, "reset-bps", &limits.baudrate);
+
+ return w1_uart_set_config(serdev, &limits, &w1dev->cfg_reset);
+}
+
+/*
+ * Configuration for write-0 cycle (touch bit 0)
+ * - bit_min_us is 60us, add margin and use 65us
+ * - no sampling required, sample_us = 0
+ */
+static int w1_uart_set_config_touch_0(struct w1_uart_device *w1dev)
+{
+ struct serdev_device *serdev = w1dev->serdev;
+ struct device_node *np = serdev->dev.of_node;
+
+ struct w1_uart_limits limits = { .baudrate = 115200,
+ .bit_min_us = 65,
+ .bit_max_us = 120,
+ .sample_us = 0,
+ .cycle_us = 70 };
+
+ of_property_read_u32(np, "write-0-bps", &limits.baudrate);
+
+ return w1_uart_set_config(serdev, &limits, &w1dev->cfg_touch_0);
+}
+
+/*
+ * Configuration for write-1 and read cycle (touch bit 1)
+ * - bit_min_us is 5us, add margin and use 6us
+ * - limits for sample time 5us-15us, use 15us
+ */
+static int w1_uart_set_config_touch_1(struct w1_uart_device *w1dev)
+{
+ struct serdev_device *serdev = w1dev->serdev;
+ struct device_node *np = serdev->dev.of_node;
+
+ struct w1_uart_limits limits = { .baudrate = 115200,
+ .bit_min_us = 6,
+ .bit_max_us = 15,
+ .sample_us = 15,
+ .cycle_us = 70 };
+
+ of_property_read_u32(np, "write-1-bps", &limits.baudrate);
+
+ return w1_uart_set_config(serdev, &limits, &w1dev->cfg_touch_1);
+}
+
+/*
+ * Configure and open the serial device
+ */
+static int w1_uart_serdev_open(struct w1_uart_device *w1dev)
+{
+ struct serdev_device *serdev = w1dev->serdev;
+ struct device *dev = &serdev->dev;
+ int ret;
+
+ ret = devm_serdev_device_open(dev, serdev);
+ if (ret < 0)
+ return ret;
+
+ ret = serdev_device_set_parity(serdev, SERDEV_PARITY_NONE);
+ if (ret < 0) {
+ dev_err(dev, "set parity failed\n");
+ return ret;
+ }
+
+ ret = w1_uart_set_config_reset(w1dev);
+ if (ret < 0) {
+ dev_err(dev, "config for reset failed\n");
+ return ret;
+ }
+
+ ret = w1_uart_set_config_touch_0(w1dev);
+ if (ret < 0) {
+ dev_err(dev, "config for touch-0 failed\n");
+ return ret;
+ }
+
+ ret = w1_uart_set_config_touch_1(w1dev);
+ if (ret < 0) {
+ dev_err(dev, "config for touch-1 failed\n");
+ return ret;
+ }
+
+ serdev_device_set_flow_control(serdev, false);
+
+ return 0;
+}
+
+/*
+ * Send one byte (tx_byte) and read one byte (rx_byte) via serdev.
+ */
+static int w1_uart_serdev_tx_rx(struct w1_uart_device *w1dev,
+ const struct w1_uart_config *w1cfg, u8 *rx_byte)
+{
+ struct serdev_device *serdev = w1dev->serdev;
+ int ret;
+
+ serdev_device_write_flush(serdev);
+ serdev_device_set_baudrate(serdev, w1cfg->baudrate);
+
+ /* write and immediately read one byte */
+ reinit_completion(&w1dev->rx_byte_received);
+ ret = serdev_device_write_buf(serdev, &w1cfg->tx_byte, 1);
+ if (ret != 1)
+ return -EIO;
+ ret = wait_for_completion_interruptible_timeout(
+ &w1dev->rx_byte_received, W1_UART_TIMEOUT);
+ if (ret <= 0)
+ return -EIO;
+
+ /* locking could fail when serdev is unexpectedly receiving. */
+ if (!mutex_trylock(&w1dev->rx_mutex))
+ return -EIO;
+
+ ret = w1dev->rx_err;
+ if (ret == 0)
+ *rx_byte = w1dev->rx_byte;
+
+ mutex_unlock(&w1dev->rx_mutex);
+
+ if (w1cfg->delay_us > 0)
+ fsleep(w1cfg->delay_us);
+
+ return ret;
+}
+
+static size_t w1_uart_serdev_receive_buf(struct serdev_device *serdev,
+ const u8 *buf, size_t count)
+{
+ struct w1_uart_device *w1dev = serdev_device_get_drvdata(serdev);
+
+ mutex_lock(&w1dev->rx_mutex);
+
+ /* sent a single byte and receive one single byte */
+ if (count == 1) {
+ w1dev->rx_byte = buf[0];
+ w1dev->rx_err = 0;
+ } else {
+ w1dev->rx_err = -EIO;
+ }
+
+ mutex_unlock(&w1dev->rx_mutex);
+ complete(&w1dev->rx_byte_received);
+
+ return count;
+}
+
+static const struct serdev_device_ops w1_uart_serdev_ops = {
+ .receive_buf = w1_uart_serdev_receive_buf,
+ .write_wakeup = serdev_device_write_wakeup,
+};
+
+/*
+ * 1-wire reset and presence detect: A present slave will manipulate
+ * the received byte by pulling the 1-Wire low.
+ */
+static u8 w1_uart_reset_bus(void *data)
+{
+ struct w1_uart_device *w1dev = data;
+ const struct w1_uart_config *w1cfg = &w1dev->cfg_reset;
+ int ret;
+ u8 val;
+
+ ret = w1_uart_serdev_tx_rx(w1dev, w1cfg, &val);
+ if (ret < 0)
+ return -1;
+
+ /* Device present (0) or no device (1) */
+ return val != w1cfg->tx_byte ? 0 : 1;
+}
+
+/*
+ * 1-Wire read and write cycle: Only the read-0 manipulates the
+ * received byte, all others left the line untouched.
+ */
+static u8 w1_uart_touch_bit(void *data, u8 bit)
+{
+ struct w1_uart_device *w1dev = data;
+ const struct w1_uart_config *w1cfg = bit ? &w1dev->cfg_touch_1 :
+ &w1dev->cfg_touch_0;
+ int ret;
+ u8 val;
+
+ ret = w1_uart_serdev_tx_rx(w1dev, w1cfg, &val);
+
+ /* return inactive bus state on error */
+ if (ret < 0)
+ return 1;
+
+ return val == w1cfg->tx_byte ? 1 : 0;
+}
+
+static int w1_uart_probe(struct serdev_device *serdev)
+{
+ struct device *dev = &serdev->dev;
+ struct w1_uart_device *w1dev;
+ int ret;
+
+ w1dev = devm_kzalloc(dev, sizeof(*w1dev), GFP_KERNEL);
+ if (!w1dev)
+ return -ENOMEM;
+ w1dev->bus.data = w1dev;
+ w1dev->bus.reset_bus = w1_uart_reset_bus;
+ w1dev->bus.touch_bit = w1_uart_touch_bit;
+ w1dev->serdev = serdev;
+
+ init_completion(&w1dev->rx_byte_received);
+ mutex_init(&w1dev->rx_mutex);
+
+ serdev_device_set_drvdata(serdev, w1dev);
+ serdev_device_set_client_ops(serdev, &w1_uart_serdev_ops);
+ ret = w1_uart_serdev_open(w1dev);
+ if (ret < 0)
+ return ret;
+
+ return w1_add_master_device(&w1dev->bus);
+}
+
+static void w1_uart_remove(struct serdev_device *serdev)
+{
+ struct w1_uart_device *w1dev = serdev_device_get_drvdata(serdev);
+
+ /*
+ * Waits until w1-uart callbacks are finished, serdev is closed
+ * and its device data released automatically by devres (waits
+ * until serdev-receive is finished).
+ */
+ w1_remove_master_device(&w1dev->bus);
+}
+
+static const struct of_device_id w1_uart_of_match[] = {
+ { .compatible = "w1-uart" },
+ {},
+};
+MODULE_DEVICE_TABLE(of, w1_uart_of_match);
+
+static struct serdev_device_driver w1_uart_driver = {
+ .driver = {
+ .name = "w1-uart",
+ .of_match_table = w1_uart_of_match,
+ },
+ .probe = w1_uart_probe,
+ .remove = w1_uart_remove,
+};
+
+module_serdev_device_driver(w1_uart_driver);
+
+MODULE_DESCRIPTION("UART w1 bus driver");
+MODULE_AUTHOR("Christoph Winklhofer <cj.winklhofer@gmail.com>");
+MODULE_LICENSE("GPL");
diff --git a/drivers/w1/slaves/Kconfig b/drivers/w1/slaves/Kconfig
index 687753889c34..32b8a757744e 100644
--- a/drivers/w1/slaves/Kconfig
+++ b/drivers/w1/slaves/Kconfig
@@ -71,8 +71,8 @@ config W1_SLAVE_DS2805
help
Say Y here if you want to use a 1-wire
is a 112-byte user-programmable EEPROM is
- organized as 7 pages of 16 bytes each with 64bit
- unique number. Requires OverDrive Speed to talk to.
+ organized as 7 pages of 16 bytes each with 64bit
+ unique number. Requires OverDrive Speed to talk to.
config W1_SLAVE_DS2430
tristate "256b EEPROM family support (DS2430)"
diff --git a/drivers/w1/slaves/w1_ds2406.c b/drivers/w1/slaves/w1_ds2406.c
index 6c269af73c80..efb2e784f8d7 100644
--- a/drivers/w1/slaves/w1_ds2406.c
+++ b/drivers/w1/slaves/w1_ds2406.c
@@ -24,14 +24,12 @@
static ssize_t w1_f12_read_state(
struct file *filp, struct kobject *kobj,
- struct bin_attribute *bin_attr,
+ const struct bin_attribute *bin_attr,
char *buf, loff_t off, size_t count)
{
- u8 w1_buf[6]={W1_F12_FUNC_READ_STATUS, 7, 0, 0, 0, 0};
+ u8 w1_buf[6] = {W1_F12_FUNC_READ_STATUS, 7, 0, 0, 0, 0};
struct w1_slave *sl = kobj_to_w1_slave(kobj);
- u16 crc=0;
- int i;
- ssize_t rtnval=1;
+ ssize_t rtnval = 1;
if (off != 0)
return 0;
@@ -47,12 +45,10 @@ static ssize_t w1_f12_read_state(
w1_write_block(sl->master, w1_buf, 3);
w1_read_block(sl->master, w1_buf+3, 3);
- for (i=0; i<6; i++)
- crc=crc16_byte(crc, w1_buf[i]);
- if (crc==0xb001) /* good read? */
- *buf=((w1_buf[3]>>5)&3)|0x30;
+ if (crc16(0, w1_buf, sizeof(w1_buf)) == 0xb001) /* good read? */
+ *buf = ((w1_buf[3]>>5)&3)|0x30;
else
- rtnval=-EIO;
+ rtnval = -EIO;
mutex_unlock(&sl->master->bus_mutex);
@@ -61,14 +57,12 @@ static ssize_t w1_f12_read_state(
static ssize_t w1_f12_write_output(
struct file *filp, struct kobject *kobj,
- struct bin_attribute *bin_attr,
+ const struct bin_attribute *bin_attr,
char *buf, loff_t off, size_t count)
{
struct w1_slave *sl = kobj_to_w1_slave(kobj);
- u8 w1_buf[6]={W1_F12_FUNC_WRITE_STATUS, 7, 0, 0, 0, 0};
- u16 crc=0;
- int i;
- ssize_t rtnval=1;
+ u8 w1_buf[6] = {W1_F12_FUNC_WRITE_STATUS, 7, 0, 0, 0, 0};
+ ssize_t rtnval = 1;
if (count != 1 || off != 0)
return -EFAULT;
@@ -83,23 +77,21 @@ static ssize_t w1_f12_write_output(
w1_buf[3] = (((*buf)&3)<<5)|0x1F;
w1_write_block(sl->master, w1_buf, 4);
w1_read_block(sl->master, w1_buf+4, 2);
- for (i=0; i<6; i++)
- crc=crc16_byte(crc, w1_buf[i]);
- if (crc==0xb001) /* good read? */
+ if (crc16(0, w1_buf, sizeof(w1_buf)) == 0xb001) /* good read? */
w1_write_8(sl->master, 0xFF);
else
- rtnval=-EIO;
+ rtnval = -EIO;
mutex_unlock(&sl->master->bus_mutex);
return rtnval;
}
#define NB_SYSFS_BIN_FILES 2
-static struct bin_attribute w1_f12_sysfs_bin_files[NB_SYSFS_BIN_FILES] = {
+static const struct bin_attribute w1_f12_sysfs_bin_files[NB_SYSFS_BIN_FILES] = {
{
.attr = {
.name = "state",
- .mode = S_IRUGO,
+ .mode = 0444,
},
.size = 1,
.read = w1_f12_read_state,
@@ -107,7 +99,7 @@ static struct bin_attribute w1_f12_sysfs_bin_files[NB_SYSFS_BIN_FILES] = {
{
.attr = {
.name = "output",
- .mode = S_IRUGO | S_IWUSR | S_IWGRP,
+ .mode = 0664,
},
.size = 1,
.write = w1_f12_write_output,
@@ -133,6 +125,7 @@ static int w1_f12_add_slave(struct w1_slave *sl)
static void w1_f12_remove_slave(struct w1_slave *sl)
{
int i;
+
for (i = NB_SYSFS_BIN_FILES - 1; i >= 0; --i)
sysfs_remove_bin_file(&sl->dev.kobj,
&(w1_f12_sysfs_bin_files[i]));
diff --git a/drivers/w1/slaves/w1_ds2408.c b/drivers/w1/slaves/w1_ds2408.c
index ad102c577122..30d1d574d2e5 100644
--- a/drivers/w1/slaves/w1_ds2408.c
+++ b/drivers/w1/slaves/w1_ds2408.c
@@ -35,12 +35,12 @@
#define W1_F29_SUCCESS_CONFIRM_BYTE 0xAA
-static int _read_reg(struct w1_slave *sl, u8 address, unsigned char* buf)
+static int _read_reg(struct w1_slave *sl, u8 address, unsigned char *buf)
{
u8 wrbuf[3];
- dev_dbg(&sl->dev,
- "Reading with slave: %p, reg addr: %0#4x, buff addr: %p",
- sl, (unsigned int)address, buf);
+
+ dev_dbg(&sl->dev, "Reading with slave: %p, reg addr: %0#4x, buff addr: %p",
+ sl, (unsigned int)address, buf);
if (!buf)
return -EINVAL;
@@ -65,8 +65,8 @@ static int _read_reg(struct w1_slave *sl, u8 address, unsigned char* buf)
}
static ssize_t state_read(struct file *filp, struct kobject *kobj,
- struct bin_attribute *bin_attr, char *buf, loff_t off,
- size_t count)
+ const struct bin_attribute *bin_attr, char *buf,
+ loff_t off, size_t count)
{
dev_dbg(&kobj_to_w1_slave(kobj)->dev,
"Reading %s kobj: %p, off: %0#10x, count: %zu, buff addr: %p",
@@ -77,7 +77,7 @@ static ssize_t state_read(struct file *filp, struct kobject *kobj,
}
static ssize_t output_read(struct file *filp, struct kobject *kobj,
- struct bin_attribute *bin_attr, char *buf,
+ const struct bin_attribute *bin_attr, char *buf,
loff_t off, size_t count)
{
dev_dbg(&kobj_to_w1_slave(kobj)->dev,
@@ -90,7 +90,7 @@ static ssize_t output_read(struct file *filp, struct kobject *kobj,
}
static ssize_t activity_read(struct file *filp, struct kobject *kobj,
- struct bin_attribute *bin_attr, char *buf,
+ const struct bin_attribute *bin_attr, char *buf,
loff_t off, size_t count)
{
dev_dbg(&kobj_to_w1_slave(kobj)->dev,
@@ -103,8 +103,8 @@ static ssize_t activity_read(struct file *filp, struct kobject *kobj,
}
static ssize_t cond_search_mask_read(struct file *filp, struct kobject *kobj,
- struct bin_attribute *bin_attr, char *buf,
- loff_t off, size_t count)
+ const struct bin_attribute *bin_attr,
+ char *buf, loff_t off, size_t count)
{
dev_dbg(&kobj_to_w1_slave(kobj)->dev,
"Reading %s kobj: %p, off: %0#10x, count: %zu, buff addr: %p",
@@ -117,7 +117,7 @@ static ssize_t cond_search_mask_read(struct file *filp, struct kobject *kobj,
static ssize_t cond_search_polarity_read(struct file *filp,
struct kobject *kobj,
- struct bin_attribute *bin_attr,
+ const struct bin_attribute *bin_attr,
char *buf, loff_t off, size_t count)
{
if (count != 1 || off != 0)
@@ -127,8 +127,8 @@ static ssize_t cond_search_polarity_read(struct file *filp,
}
static ssize_t status_control_read(struct file *filp, struct kobject *kobj,
- struct bin_attribute *bin_attr, char *buf,
- loff_t off, size_t count)
+ const struct bin_attribute *bin_attr,
+ char *buf, loff_t off, size_t count)
{
if (count != 1 || off != 0)
return -EFAULT;
@@ -160,7 +160,7 @@ static bool optional_read_back_valid(struct w1_slave *sl, u8 expected)
#endif
static ssize_t output_write(struct file *filp, struct kobject *kobj,
- struct bin_attribute *bin_attr, char *buf,
+ const struct bin_attribute *bin_attr, char *buf,
loff_t off, size_t count)
{
struct w1_slave *sl = kobj_to_w1_slave(kobj);
@@ -206,11 +206,11 @@ out:
}
-/**
+/*
* Writing to the activity file resets the activity latches.
*/
static ssize_t activity_write(struct file *filp, struct kobject *kobj,
- struct bin_attribute *bin_attr, char *buf,
+ const struct bin_attribute *bin_attr, char *buf,
loff_t off, size_t count)
{
struct w1_slave *sl = kobj_to_w1_slave(kobj);
@@ -240,8 +240,8 @@ error:
}
static ssize_t status_control_write(struct file *filp, struct kobject *kobj,
- struct bin_attribute *bin_attr, char *buf,
- loff_t off, size_t count)
+ const struct bin_attribute *bin_attr,
+ char *buf, loff_t off, size_t count)
{
struct w1_slave *sl = kobj_to_w1_slave(kobj);
u8 w1_buf[4];
@@ -292,7 +292,7 @@ static int w1_f29_disable_test_mode(struct w1_slave *sl)
{
int res;
u8 magic[10] = {0x96, };
- u64 rn = le64_to_cpu(*((u64*)&sl->reg_num));
+ u64 rn = le64_to_cpu(*((u64 *)&sl->reg_num));
memcpy(&magic[1], &rn, 8);
magic[9] = 0x3C;
@@ -310,14 +310,14 @@ out:
return res;
}
-static BIN_ATTR_RO(state, 1);
-static BIN_ATTR_RW(output, 1);
-static BIN_ATTR_RW(activity, 1);
-static BIN_ATTR_RO(cond_search_mask, 1);
-static BIN_ATTR_RO(cond_search_polarity, 1);
-static BIN_ATTR_RW(status_control, 1);
+static const BIN_ATTR_RO(state, 1);
+static const BIN_ATTR_RW(output, 1);
+static const BIN_ATTR_RW(activity, 1);
+static const BIN_ATTR_RO(cond_search_mask, 1);
+static const BIN_ATTR_RO(cond_search_polarity, 1);
+static const BIN_ATTR_RW(status_control, 1);
-static struct bin_attribute *w1_f29_bin_attrs[] = {
+static const struct bin_attribute *const w1_f29_bin_attrs[] = {
&bin_attr_state,
&bin_attr_output,
&bin_attr_activity,
diff --git a/drivers/w1/slaves/w1_ds2413.c b/drivers/w1/slaves/w1_ds2413.c
index c8cfac555b48..94d3cd2a0ec9 100644
--- a/drivers/w1/slaves/w1_ds2413.c
+++ b/drivers/w1/slaves/w1_ds2413.c
@@ -25,8 +25,8 @@
#define W1_F3A_INVALID_PIO_STATE 0xFF
static ssize_t state_read(struct file *filp, struct kobject *kobj,
- struct bin_attribute *bin_attr, char *buf, loff_t off,
- size_t count)
+ const struct bin_attribute *bin_attr, char *buf,
+ loff_t off, size_t count)
{
struct w1_slave *sl = kobj_to_w1_slave(kobj);
unsigned int retries = W1_F3A_RETRIES;
@@ -78,10 +78,10 @@ out:
return bytes_read;
}
-static BIN_ATTR_RO(state, 1);
+static const BIN_ATTR_RO(state, 1);
static ssize_t output_write(struct file *filp, struct kobject *kobj,
- struct bin_attribute *bin_attr, char *buf,
+ const struct bin_attribute *bin_attr, char *buf,
loff_t off, size_t count)
{
struct w1_slave *sl = kobj_to_w1_slave(kobj);
@@ -99,8 +99,10 @@ static ssize_t output_write(struct file *filp, struct kobject *kobj,
if (w1_reset_select_slave(sl))
goto out;
- /* according to the DS2413 datasheet the most significant 6 bits
- should be set to "1"s, so do it now */
+ /*
+ * according to the DS2413 datasheet the most significant 6 bits
+ * should be set to "1"s, so do it now
+ */
*buf = *buf | 0xFC;
while (retries--) {
@@ -126,9 +128,9 @@ out:
return bytes_written;
}
-static BIN_ATTR(output, S_IRUGO | S_IWUSR | S_IWGRP, NULL, output_write, 1);
+static const BIN_ATTR(output, 0664, NULL, output_write, 1);
-static struct bin_attribute *w1_f3a_bin_attrs[] = {
+static const struct bin_attribute *const w1_f3a_bin_attrs[] = {
&bin_attr_state,
&bin_attr_output,
NULL,
diff --git a/drivers/w1/slaves/w1_ds2430.c b/drivers/w1/slaves/w1_ds2430.c
index 0ea7d779d17a..3d8c2b238aed 100644
--- a/drivers/w1/slaves/w1_ds2430.c
+++ b/drivers/w1/slaves/w1_ds2430.c
@@ -95,7 +95,7 @@ static int w1_f14_readblock(struct w1_slave *sl, int off, int count, char *buf)
}
static ssize_t eeprom_read(struct file *filp, struct kobject *kobj,
- struct bin_attribute *bin_attr, char *buf,
+ const struct bin_attribute *bin_attr, char *buf,
loff_t off, size_t count)
{
struct w1_slave *sl = kobj_to_w1_slave(kobj);
@@ -202,7 +202,7 @@ retry:
}
static ssize_t eeprom_write(struct file *filp, struct kobject *kobj,
- struct bin_attribute *bin_attr, char *buf,
+ const struct bin_attribute *bin_attr, char *buf,
loff_t off, size_t count)
{
struct w1_slave *sl = kobj_to_w1_slave(kobj);
@@ -263,9 +263,9 @@ out_up:
return count;
}
-static BIN_ATTR_RW(eeprom, W1_F14_EEPROM_SIZE);
+static const BIN_ATTR_RW(eeprom, W1_F14_EEPROM_SIZE);
-static struct bin_attribute *w1_f14_bin_attrs[] = {
+static const struct bin_attribute *const w1_f14_bin_attrs[] = {
&bin_attr_eeprom,
NULL,
};
diff --git a/drivers/w1/slaves/w1_ds2431.c b/drivers/w1/slaves/w1_ds2431.c
index 6856b1c29e17..5749880b67c5 100644
--- a/drivers/w1/slaves/w1_ds2431.c
+++ b/drivers/w1/slaves/w1_ds2431.c
@@ -95,7 +95,7 @@ static int w1_f2d_readblock(struct w1_slave *sl, int off, int count, char *buf)
}
static ssize_t eeprom_read(struct file *filp, struct kobject *kobj,
- struct bin_attribute *bin_attr, char *buf,
+ const struct bin_attribute *bin_attr, char *buf,
loff_t off, size_t count)
{
struct w1_slave *sl = kobj_to_w1_slave(kobj);
@@ -201,7 +201,7 @@ retry:
}
static ssize_t eeprom_write(struct file *filp, struct kobject *kobj,
- struct bin_attribute *bin_attr, char *buf,
+ const struct bin_attribute *bin_attr, char *buf,
loff_t off, size_t count)
{
struct w1_slave *sl = kobj_to_w1_slave(kobj);
@@ -262,9 +262,9 @@ out_up:
return count;
}
-static BIN_ATTR_RW(eeprom, W1_F2D_EEPROM_SIZE);
+static const BIN_ATTR_RW(eeprom, W1_F2D_EEPROM_SIZE);
-static struct bin_attribute *w1_f2d_bin_attrs[] = {
+static const struct bin_attribute *const w1_f2d_bin_attrs[] = {
&bin_attr_eeprom,
NULL,
};
diff --git a/drivers/w1/slaves/w1_ds2433.c b/drivers/w1/slaves/w1_ds2433.c
index 0f72df15a024..3371d804dc6c 100644
--- a/drivers/w1/slaves/w1_ds2433.c
+++ b/drivers/w1/slaves/w1_ds2433.c
@@ -1,8 +1,9 @@
// SPDX-License-Identifier: GPL-2.0-only
/*
- * w1_ds2433.c - w1 family 23 (DS2433) driver
+ * w1_ds2433.c - w1 family 23 (DS2433) & 43 (DS28EC20) eeprom driver
*
* Copyright (c) 2005 Ben Gardner <bgardner@wabtec.com>
+ * Copyright (c) 2023 Marc Ferland <marc.ferland@sonatest.com>
*/
#include <linux/kernel.h>
@@ -23,26 +24,48 @@
#include <linux/w1.h>
#define W1_EEPROM_DS2433 0x23
+#define W1_EEPROM_DS28EC20 0x43
+
+#define W1_EEPROM_DS2433_SIZE 512
+#define W1_EEPROM_DS28EC20_SIZE 2560
-#define W1_EEPROM_SIZE 512
-#define W1_PAGE_COUNT 16
#define W1_PAGE_SIZE 32
#define W1_PAGE_BITS 5
#define W1_PAGE_MASK 0x1F
-
-#define W1_F23_TIME 300
+#define W1_VALIDCRC_MAX 96
#define W1_F23_READ_EEPROM 0xF0
#define W1_F23_WRITE_SCRATCH 0x0F
#define W1_F23_READ_SCRATCH 0xAA
#define W1_F23_COPY_SCRATCH 0x55
+struct ds2433_config {
+ size_t eeprom_size; /* eeprom size in bytes */
+ unsigned int page_count; /* number of 256 bits pages */
+ unsigned int tprog; /* time in ms for page programming */
+};
+
+static const struct ds2433_config config_f23 = {
+ .eeprom_size = W1_EEPROM_DS2433_SIZE,
+ .page_count = 16,
+ .tprog = 5,
+};
+
+static const struct ds2433_config config_f43 = {
+ .eeprom_size = W1_EEPROM_DS28EC20_SIZE,
+ .page_count = 80,
+ .tprog = 10,
+};
+
struct w1_f23_data {
- u8 memory[W1_EEPROM_SIZE];
- u32 validcrc;
+#ifdef CONFIG_W1_SLAVE_DS2433_CRC
+ u8 *memory;
+ DECLARE_BITMAP(validcrc, W1_VALIDCRC_MAX);
+#endif
+ const struct ds2433_config *cfg;
};
-/**
+/*
* Check the file size bounds and adjusts count as needed.
* This would not be needed if the file size didn't reset to 0 after a write.
*/
@@ -64,11 +87,11 @@ static int w1_f23_refresh_block(struct w1_slave *sl, struct w1_f23_data *data,
u8 wrbuf[3];
int off = block * W1_PAGE_SIZE;
- if (data->validcrc & (1 << block))
+ if (test_bit(block, data->validcrc))
return 0;
if (w1_reset_select_slave(sl)) {
- data->validcrc = 0;
+ bitmap_zero(data->validcrc, data->cfg->page_count);
return -EIO;
}
@@ -80,14 +103,14 @@ static int w1_f23_refresh_block(struct w1_slave *sl, struct w1_f23_data *data,
/* cache the block if the CRC is valid */
if (crc16(CRC16_INIT, &data->memory[off], W1_PAGE_SIZE) == CRC16_VALID)
- data->validcrc |= (1 << block);
+ set_bit(block, data->validcrc);
return 0;
}
#endif /* CONFIG_W1_SLAVE_DS2433_CRC */
static ssize_t eeprom_read(struct file *filp, struct kobject *kobj,
- struct bin_attribute *bin_attr, char *buf,
+ const struct bin_attribute *bin_attr, char *buf,
loff_t off, size_t count)
{
struct w1_slave *sl = kobj_to_w1_slave(kobj);
@@ -98,7 +121,8 @@ static ssize_t eeprom_read(struct file *filp, struct kobject *kobj,
u8 wrbuf[3];
#endif
- if ((count = w1_f23_fix_count(off, count, W1_EEPROM_SIZE)) == 0)
+ count = w1_f23_fix_count(off, count, bin_attr->size);
+ if (!count)
return 0;
mutex_lock(&sl->master->bus_mutex);
@@ -115,7 +139,7 @@ static ssize_t eeprom_read(struct file *filp, struct kobject *kobj,
}
memcpy(buf, &data->memory[off], count);
-#else /* CONFIG_W1_SLAVE_DS2433_CRC */
+#else /* CONFIG_W1_SLAVE_DS2433_CRC */
/* read directly from the EEPROM */
if (w1_reset_select_slave(sl)) {
@@ -138,22 +162,21 @@ out_up:
}
/**
- * Writes to the scratchpad and reads it back for verification.
+ * w1_f23_write() - Writes to the scratchpad and reads it back for verification.
+ * @sl: The slave structure
+ * @addr: Address for the write
+ * @len: length must be <= (W1_PAGE_SIZE - (addr & W1_PAGE_MASK))
+ * @data: The data to write
+ *
* Then copies the scratchpad to EEPROM.
* The data must be on one page.
* The master must be locked.
*
- * @param sl The slave structure
- * @param addr Address for the write
- * @param len length must be <= (W1_PAGE_SIZE - (addr & W1_PAGE_MASK))
- * @param data The data to write
- * @return 0=Success -1=failure
+ * Return: 0=Success, -1=failure
*/
static int w1_f23_write(struct w1_slave *sl, int addr, int len, const u8 *data)
{
-#ifdef CONFIG_W1_SLAVE_DS2433_CRC
struct w1_f23_data *f23 = sl->family_data;
-#endif
u8 wrbuf[4];
u8 rdbuf[W1_PAGE_SIZE + 3];
u8 es = (addr + len - 1) & 0x1f;
@@ -189,25 +212,26 @@ static int w1_f23_write(struct w1_slave *sl, int addr, int len, const u8 *data)
wrbuf[3] = es;
w1_write_block(sl->master, wrbuf, 4);
- /* Sleep for 5 ms to wait for the write to complete */
- msleep(5);
+ /* Sleep for tprog ms to wait for the write to complete */
+ msleep(f23->cfg->tprog);
/* Reset the bus to wake up the EEPROM (this may not be needed) */
w1_reset_bus(sl->master);
#ifdef CONFIG_W1_SLAVE_DS2433_CRC
- f23->validcrc &= ~(1 << (addr >> W1_PAGE_BITS));
+ clear_bit(addr >> W1_PAGE_BITS, f23->validcrc);
#endif
return 0;
}
static ssize_t eeprom_write(struct file *filp, struct kobject *kobj,
- struct bin_attribute *bin_attr, char *buf,
+ const struct bin_attribute *bin_attr, char *buf,
loff_t off, size_t count)
{
struct w1_slave *sl = kobj_to_w1_slave(kobj);
int addr, len, idx;
- if ((count = w1_f23_fix_count(off, count, W1_EEPROM_SIZE)) == 0)
+ count = w1_f23_fix_count(off, count, bin_attr->size);
+ if (!count)
return 0;
#ifdef CONFIG_W1_SLAVE_DS2433_CRC
@@ -250,10 +274,22 @@ out_up:
return count;
}
-static BIN_ATTR_RW(eeprom, W1_EEPROM_SIZE);
+static const struct bin_attribute bin_attr_f23_eeprom = {
+ .attr = { .name = "eeprom", .mode = 0644 },
+ .read = eeprom_read,
+ .write = eeprom_write,
+ .size = W1_EEPROM_DS2433_SIZE,
+};
+
+static const struct bin_attribute bin_attr_f43_eeprom = {
+ .attr = { .name = "eeprom", .mode = 0644 },
+ .read = eeprom_read,
+ .write = eeprom_write,
+ .size = W1_EEPROM_DS28EC20_SIZE,
+};
-static struct bin_attribute *w1_f23_bin_attributes[] = {
- &bin_attr_eeprom,
+static const struct bin_attribute *const w1_f23_bin_attributes[] = {
+ &bin_attr_f23_eeprom,
NULL,
};
@@ -266,26 +302,63 @@ static const struct attribute_group *w1_f23_groups[] = {
NULL,
};
+static const struct bin_attribute *const w1_f43_bin_attributes[] = {
+ &bin_attr_f43_eeprom,
+ NULL,
+};
+
+static const struct attribute_group w1_f43_group = {
+ .bin_attrs = w1_f43_bin_attributes,
+};
+
+static const struct attribute_group *w1_f43_groups[] = {
+ &w1_f43_group,
+ NULL,
+};
+
static int w1_f23_add_slave(struct w1_slave *sl)
{
-#ifdef CONFIG_W1_SLAVE_DS2433_CRC
struct w1_f23_data *data;
data = kzalloc(sizeof(struct w1_f23_data), GFP_KERNEL);
if (!data)
return -ENOMEM;
+
+ switch (sl->family->fid) {
+ case W1_EEPROM_DS2433:
+ data->cfg = &config_f23;
+ break;
+ case W1_EEPROM_DS28EC20:
+ data->cfg = &config_f43;
+ break;
+ }
+
+#ifdef CONFIG_W1_SLAVE_DS2433_CRC
+ if (data->cfg->page_count > W1_VALIDCRC_MAX) {
+ dev_err(&sl->dev, "page count too big for crc bitmap\n");
+ kfree(data);
+ return -EINVAL;
+ }
+ data->memory = kzalloc(data->cfg->eeprom_size, GFP_KERNEL);
+ if (!data->memory) {
+ kfree(data);
+ return -ENOMEM;
+ }
+ bitmap_zero(data->validcrc, data->cfg->page_count);
+#endif /* CONFIG_W1_SLAVE_DS2433_CRC */
sl->family_data = data;
-#endif /* CONFIG_W1_SLAVE_DS2433_CRC */
return 0;
}
static void w1_f23_remove_slave(struct w1_slave *sl)
{
-#ifdef CONFIG_W1_SLAVE_DS2433_CRC
- kfree(sl->family_data);
+ struct w1_f23_data *data = sl->family_data;
sl->family_data = NULL;
-#endif /* CONFIG_W1_SLAVE_DS2433_CRC */
+#ifdef CONFIG_W1_SLAVE_DS2433_CRC
+ kfree(data->memory);
+#endif /* CONFIG_W1_SLAVE_DS2433_CRC */
+ kfree(data);
}
static const struct w1_family_ops w1_f23_fops = {
@@ -294,13 +367,53 @@ static const struct w1_family_ops w1_f23_fops = {
.groups = w1_f23_groups,
};
+static const struct w1_family_ops w1_f43_fops = {
+ .add_slave = w1_f23_add_slave,
+ .remove_slave = w1_f23_remove_slave,
+ .groups = w1_f43_groups,
+};
+
static struct w1_family w1_family_23 = {
.fid = W1_EEPROM_DS2433,
.fops = &w1_f23_fops,
};
-module_w1_family(w1_family_23);
+
+static struct w1_family w1_family_43 = {
+ .fid = W1_EEPROM_DS28EC20,
+ .fops = &w1_f43_fops,
+};
+
+static int __init w1_ds2433_init(void)
+{
+ int err;
+
+ err = w1_register_family(&w1_family_23);
+ if (err)
+ return err;
+
+ err = w1_register_family(&w1_family_43);
+ if (err)
+ goto err_43;
+
+ return 0;
+
+err_43:
+ w1_unregister_family(&w1_family_23);
+ return err;
+}
+
+static void __exit w1_ds2433_exit(void)
+{
+ w1_unregister_family(&w1_family_23);
+ w1_unregister_family(&w1_family_43);
+}
+
+module_init(w1_ds2433_init);
+module_exit(w1_ds2433_exit);
MODULE_AUTHOR("Ben Gardner <bgardner@wabtec.com>");
-MODULE_DESCRIPTION("w1 family 23 driver for DS2433, 4kb EEPROM");
+MODULE_AUTHOR("Marc Ferland <marc.ferland@sonatest.com>");
+MODULE_DESCRIPTION("w1 family 23/43 driver for DS2433 (4kb) and DS28EC20 (20kb)");
MODULE_LICENSE("GPL");
MODULE_ALIAS("w1-family-" __stringify(W1_EEPROM_DS2433));
+MODULE_ALIAS("w1-family-" __stringify(W1_EEPROM_DS28EC20));
diff --git a/drivers/w1/slaves/w1_ds2438.c b/drivers/w1/slaves/w1_ds2438.c
index ca64f99c8f3d..86860f727e96 100644
--- a/drivers/w1/slaves/w1_ds2438.c
+++ b/drivers/w1/slaves/w1_ds2438.c
@@ -66,8 +66,6 @@ static int w1_ds2438_get_page(struct w1_slave *sl, int pageno, u8 *buf)
size_t count;
while (retries--) {
- crc = 0;
-
if (w1_reset_select_slave(sl))
continue;
w1_buf[0] = W1_DS2438_RECALL_MEMORY;
@@ -290,7 +288,7 @@ static int w1_ds2438_get_current(struct w1_slave *sl, int16_t *voltage)
}
static ssize_t iad_write(struct file *filp, struct kobject *kobj,
- struct bin_attribute *bin_attr, char *buf,
+ const struct bin_attribute *bin_attr, char *buf,
loff_t off, size_t count)
{
struct w1_slave *sl = kobj_to_w1_slave(kobj);
@@ -312,7 +310,7 @@ static ssize_t iad_write(struct file *filp, struct kobject *kobj,
}
static ssize_t iad_read(struct file *filp, struct kobject *kobj,
- struct bin_attribute *bin_attr, char *buf,
+ const struct bin_attribute *bin_attr, char *buf,
loff_t off, size_t count)
{
struct w1_slave *sl = kobj_to_w1_slave(kobj);
@@ -333,7 +331,7 @@ static ssize_t iad_read(struct file *filp, struct kobject *kobj,
}
static ssize_t page0_read(struct file *filp, struct kobject *kobj,
- struct bin_attribute *bin_attr, char *buf,
+ const struct bin_attribute *bin_attr, char *buf,
loff_t off, size_t count)
{
struct w1_slave *sl = kobj_to_w1_slave(kobj);
@@ -363,7 +361,7 @@ static ssize_t page0_read(struct file *filp, struct kobject *kobj,
}
static ssize_t page1_read(struct file *filp, struct kobject *kobj,
- struct bin_attribute *bin_attr, char *buf,
+ const struct bin_attribute *bin_attr, char *buf,
loff_t off, size_t count)
{
struct w1_slave *sl = kobj_to_w1_slave(kobj);
@@ -393,7 +391,7 @@ static ssize_t page1_read(struct file *filp, struct kobject *kobj,
}
static ssize_t offset_write(struct file *filp, struct kobject *kobj,
- struct bin_attribute *bin_attr, char *buf,
+ const struct bin_attribute *bin_attr, char *buf,
loff_t off, size_t count)
{
struct w1_slave *sl = kobj_to_w1_slave(kobj);
@@ -412,7 +410,7 @@ static ssize_t offset_write(struct file *filp, struct kobject *kobj,
}
static ssize_t temperature_read(struct file *filp, struct kobject *kobj,
- struct bin_attribute *bin_attr, char *buf,
+ const struct bin_attribute *bin_attr, char *buf,
loff_t off, size_t count)
{
struct w1_slave *sl = kobj_to_w1_slave(kobj);
@@ -433,7 +431,7 @@ static ssize_t temperature_read(struct file *filp, struct kobject *kobj,
}
static ssize_t vad_read(struct file *filp, struct kobject *kobj,
- struct bin_attribute *bin_attr, char *buf,
+ const struct bin_attribute *bin_attr, char *buf,
loff_t off, size_t count)
{
struct w1_slave *sl = kobj_to_w1_slave(kobj);
@@ -454,7 +452,7 @@ static ssize_t vad_read(struct file *filp, struct kobject *kobj,
}
static ssize_t vdd_read(struct file *filp, struct kobject *kobj,
- struct bin_attribute *bin_attr, char *buf,
+ const struct bin_attribute *bin_attr, char *buf,
loff_t off, size_t count)
{
struct w1_slave *sl = kobj_to_w1_slave(kobj);
@@ -474,15 +472,15 @@ static ssize_t vdd_read(struct file *filp, struct kobject *kobj,
return ret;
}
-static BIN_ATTR_RW(iad, 0);
-static BIN_ATTR_RO(page0, DS2438_PAGE_SIZE);
-static BIN_ATTR_RO(page1, DS2438_PAGE_SIZE);
-static BIN_ATTR_WO(offset, 2);
-static BIN_ATTR_RO(temperature, 0/* real length varies */);
-static BIN_ATTR_RO(vad, 0/* real length varies */);
-static BIN_ATTR_RO(vdd, 0/* real length varies */);
+static const BIN_ATTR_RW(iad, 0);
+static const BIN_ATTR_RO(page0, DS2438_PAGE_SIZE);
+static const BIN_ATTR_RO(page1, DS2438_PAGE_SIZE);
+static const BIN_ATTR_WO(offset, 2);
+static const BIN_ATTR_RO(temperature, 0/* real length varies */);
+static const BIN_ATTR_RO(vad, 0/* real length varies */);
+static const BIN_ATTR_RO(vdd, 0/* real length varies */);
-static struct bin_attribute *w1_ds2438_bin_attrs[] = {
+static const struct bin_attribute *const w1_ds2438_bin_attrs[] = {
&bin_attr_iad,
&bin_attr_page0,
&bin_attr_page1,
diff --git a/drivers/w1/slaves/w1_ds250x.c b/drivers/w1/slaves/w1_ds250x.c
index 7592c7050d1d..cb426f7dd23d 100644
--- a/drivers/w1/slaves/w1_ds250x.c
+++ b/drivers/w1/slaves/w1_ds250x.c
@@ -168,6 +168,7 @@ static int w1_eprom_add_slave(struct w1_slave *sl)
struct nvmem_device *nvmem;
struct nvmem_config nvmem_cfg = {
.dev = &sl->dev,
+ .add_legacy_fixed_of_cells = true,
.reg_read = w1_nvmem_read,
.type = NVMEM_TYPE_OTP,
.read_only = true,
diff --git a/drivers/w1/slaves/w1_ds2780.c b/drivers/w1/slaves/w1_ds2780.c
index 9dcb5a54f7fc..889a6099c314 100644
--- a/drivers/w1/slaves/w1_ds2780.c
+++ b/drivers/w1/slaves/w1_ds2780.c
@@ -87,16 +87,17 @@ int w1_ds2780_eeprom_cmd(struct device *dev, int addr, int cmd)
EXPORT_SYMBOL(w1_ds2780_eeprom_cmd);
static ssize_t w1_slave_read(struct file *filp, struct kobject *kobj,
- struct bin_attribute *bin_attr, char *buf,
+ const struct bin_attribute *bin_attr, char *buf,
loff_t off, size_t count)
{
struct device *dev = kobj_to_dev(kobj);
+
return w1_ds2780_io(dev, buf, off, count, 0);
}
-static BIN_ATTR_RO(w1_slave, DS2780_DATA_SIZE);
+static const BIN_ATTR_RO(w1_slave, DS2780_DATA_SIZE);
-static struct bin_attribute *w1_ds2780_bin_attrs[] = {
+static const struct bin_attribute *const w1_ds2780_bin_attrs[] = {
&bin_attr_w1_slave,
NULL,
};
diff --git a/drivers/w1/slaves/w1_ds2781.c b/drivers/w1/slaves/w1_ds2781.c
index 2cb7c020b607..88f3abd5cd4b 100644
--- a/drivers/w1/slaves/w1_ds2781.c
+++ b/drivers/w1/slaves/w1_ds2781.c
@@ -84,16 +84,17 @@ int w1_ds2781_eeprom_cmd(struct device *dev, int addr, int cmd)
EXPORT_SYMBOL(w1_ds2781_eeprom_cmd);
static ssize_t w1_slave_read(struct file *filp, struct kobject *kobj,
- struct bin_attribute *bin_attr, char *buf,
+ const struct bin_attribute *bin_attr, char *buf,
loff_t off, size_t count)
{
struct device *dev = kobj_to_dev(kobj);
+
return w1_ds2781_io(dev, buf, off, count, 0);
}
-static BIN_ATTR_RO(w1_slave, DS2781_DATA_SIZE);
+static const BIN_ATTR_RO(w1_slave, DS2781_DATA_SIZE);
-static struct bin_attribute *w1_ds2781_bin_attrs[] = {
+static const struct bin_attribute *const w1_ds2781_bin_attrs[] = {
&bin_attr_w1_slave,
NULL,
};
diff --git a/drivers/w1/slaves/w1_ds2805.c b/drivers/w1/slaves/w1_ds2805.c
index 6b5d12ba1b65..9c86b7985d0b 100644
--- a/drivers/w1/slaves/w1_ds2805.c
+++ b/drivers/w1/slaves/w1_ds2805.c
@@ -92,7 +92,7 @@ static int w1_f0d_readblock(struct w1_slave *sl, int off, int count, char *buf)
}
static ssize_t w1_f0d_read_bin(struct file *filp, struct kobject *kobj,
- struct bin_attribute *bin_attr,
+ const struct bin_attribute *bin_attr,
char *buf, loff_t off, size_t count)
{
struct w1_slave *sl = kobj_to_w1_slave(kobj);
@@ -200,7 +200,7 @@ retry:
}
static ssize_t w1_f0d_write_bin(struct file *filp, struct kobject *kobj,
- struct bin_attribute *bin_attr,
+ const struct bin_attribute *bin_attr,
char *buf, loff_t off, size_t count)
{
struct w1_slave *sl = kobj_to_w1_slave(kobj);
@@ -261,10 +261,10 @@ out_up:
return count;
}
-static struct bin_attribute w1_f0d_bin_attr = {
+static const struct bin_attribute w1_f0d_bin_attr = {
.attr = {
.name = "eeprom",
- .mode = S_IRUGO | S_IWUSR,
+ .mode = 0644,
},
.size = W1_F0D_EEPROM_SIZE,
.read = w1_f0d_read_bin,
diff --git a/drivers/w1/slaves/w1_ds28e04.c b/drivers/w1/slaves/w1_ds28e04.c
index 6cef6e2edb89..c577b5973032 100644
--- a/drivers/w1/slaves/w1_ds28e04.c
+++ b/drivers/w1/slaves/w1_ds28e04.c
@@ -53,7 +53,7 @@ struct w1_f1C_data {
u32 validcrc;
};
-/**
+/*
* Check the file size bounds and adjusts count as needed.
* This would not be needed if the file size didn't reset to 0 after a write.
*/
@@ -112,7 +112,7 @@ static int w1_f1C_read(struct w1_slave *sl, int addr, int len, char *data)
}
static ssize_t eeprom_read(struct file *filp, struct kobject *kobj,
- struct bin_attribute *bin_attr, char *buf,
+ const struct bin_attribute *bin_attr, char *buf,
loff_t off, size_t count)
{
struct w1_slave *sl = kobj_to_w1_slave(kobj);
@@ -146,16 +146,17 @@ out_up:
}
/**
- * Writes to the scratchpad and reads it back for verification.
+ * w1_f1C_write() - Writes to the scratchpad and reads it back for verification.
+ * @sl: The slave structure
+ * @addr: Address for the write
+ * @len: length must be <= (W1_PAGE_SIZE - (addr & W1_PAGE_MASK))
+ * @data: The data to write
+ *
* Then copies the scratchpad to EEPROM.
* The data must be on one page.
* The master must be locked.
*
- * @param sl The slave structure
- * @param addr Address for the write
- * @param len length must be <= (W1_PAGE_SIZE - (addr & W1_PAGE_MASK))
- * @param data The data to write
- * @return 0=Success -1=failure
+ * Return: 0=Success, -1=failure
*/
static int w1_f1C_write(struct w1_slave *sl, int addr, int len, const u8 *data)
{
@@ -197,8 +198,10 @@ static int w1_f1C_write(struct w1_slave *sl, int addr, int len, const u8 *data)
wrbuf[3] = es;
for (i = 0; i < sizeof(wrbuf); ++i) {
- /* issue 10ms strong pullup (or delay) on the last byte
- for writing the data from the scratchpad to EEPROM */
+ /*
+ * issue 10ms strong pullup (or delay) on the last byte
+ * for writing the data from the scratchpad to EEPROM
+ */
if (w1_strong_pullup && i == sizeof(wrbuf)-1)
w1_next_pullup(sl->master, tm);
@@ -220,7 +223,7 @@ static int w1_f1C_write(struct w1_slave *sl, int addr, int len, const u8 *data)
}
static ssize_t eeprom_write(struct file *filp, struct kobject *kobj,
- struct bin_attribute *bin_attr, char *buf,
+ const struct bin_attribute *bin_attr, char *buf,
loff_t off, size_t count)
{
@@ -273,10 +276,10 @@ out_up:
return count;
}
-static BIN_ATTR_RW(eeprom, W1_EEPROM_SIZE);
+static const BIN_ATTR_RW(eeprom, W1_EEPROM_SIZE);
static ssize_t pio_read(struct file *filp, struct kobject *kobj,
- struct bin_attribute *bin_attr, char *buf, loff_t off,
+ const struct bin_attribute *bin_attr, char *buf, loff_t off,
size_t count)
{
@@ -295,8 +298,8 @@ static ssize_t pio_read(struct file *filp, struct kobject *kobj,
}
static ssize_t pio_write(struct file *filp, struct kobject *kobj,
- struct bin_attribute *bin_attr, char *buf, loff_t off,
- size_t count)
+ const struct bin_attribute *bin_attr, char *buf,
+ loff_t off, size_t count)
{
struct w1_slave *sl = kobj_to_w1_slave(kobj);
@@ -334,7 +337,7 @@ static ssize_t pio_write(struct file *filp, struct kobject *kobj,
return count;
}
-static BIN_ATTR_RW(pio, 1);
+static const BIN_ATTR_RW(pio, 1);
static ssize_t crccheck_show(struct device *dev, struct device_attribute *attr,
char *buf)
@@ -360,7 +363,7 @@ static struct attribute *w1_f1C_attrs[] = {
NULL,
};
-static struct bin_attribute *w1_f1C_bin_attrs[] = {
+static const struct bin_attribute *const w1_f1C_bin_attrs[] = {
&bin_attr_eeprom,
&bin_attr_pio,
NULL,
diff --git a/drivers/w1/slaves/w1_ds28e17.c b/drivers/w1/slaves/w1_ds28e17.c
index aed10b72fc99..e53bc41bde3c 100644
--- a/drivers/w1/slaves/w1_ds28e17.c
+++ b/drivers/w1/slaves/w1_ds28e17.c
@@ -31,12 +31,12 @@ MODULE_ALIAS("w1-family-" __stringify(W1_FAMILY_DS28E17));
/* Default I2C speed to be set when a DS28E17 is detected. */
static int i2c_speed = 100;
-module_param_named(speed, i2c_speed, int, (S_IRUSR | S_IWUSR));
+module_param_named(speed, i2c_speed, int, 0600);
MODULE_PARM_DESC(speed, "Default I2C speed to be set when a DS28E17 is detected");
/* Default I2C stretch value to be set when a DS28E17 is detected. */
static char i2c_stretch = 1;
-module_param_named(stretch, i2c_stretch, byte, (S_IRUSR | S_IWUSR));
+module_param_named(stretch, i2c_stretch, byte, 0600);
MODULE_PARM_DESC(stretch, "Default I2C stretch value to be set when a DS28E17 is detected");
/* DS28E17 device command codes. */
@@ -59,7 +59,7 @@ MODULE_PARM_DESC(stretch, "Default I2C stretch value to be set when a DS28E17 is
/*
* Maximum number of I2C bytes to transfer within one CRC16 protected onewire
* command.
- * */
+ */
#define W1_F19_WRITE_DATA_LIMIT 255
/* Maximum number of I2C bytes to read with one onewire command. */
@@ -583,7 +583,7 @@ static ssize_t speed_show(struct device *dev, struct device_attribute *attr,
return result;
/* Return current speed value. */
- return sprintf(buf, "%d\n", result);
+ return sysfs_emit(buf, "%d\n", result);
}
static ssize_t speed_store(struct device *dev, struct device_attribute *attr,
@@ -633,7 +633,7 @@ static ssize_t stretch_show(struct device *dev, struct device_attribute *attr,
struct w1_f19_data *data = sl->family_data;
/* Return current stretch value. */
- return sprintf(buf, "%d\n", data->stretch);
+ return sysfs_emit(buf, "%d\n", data->stretch);
}
static ssize_t stretch_store(struct device *dev, struct device_attribute *attr,
@@ -719,8 +719,8 @@ static int w1_f19_add_slave(struct w1_slave *sl)
data->adapter.owner = THIS_MODULE;
data->adapter.algo = &w1_f19_i2c_algorithm;
data->adapter.algo_data = sl;
- strcpy(data->adapter.name, "w1-");
- strcat(data->adapter.name, sl->name);
+ scnprintf(data->adapter.name, sizeof(data->adapter.name), "w1-%s",
+ sl->name);
data->adapter.dev.parent = &sl->dev;
data->adapter.quirks = &w1_f19_i2c_adapter_quirks;
diff --git a/drivers/w1/slaves/w1_therm.c b/drivers/w1/slaves/w1_therm.c
index 067692626cf0..9ccedb3264fb 100644
--- a/drivers/w1/slaves/w1_therm.c
+++ b/drivers/w1/slaves/w1_therm.c
@@ -284,7 +284,7 @@ static int read_powermode(struct w1_slave *sl);
* trigger_bulk_read() - function to trigger a bulk read on the bus
* @dev_master: the device master of the bus
*
- * Send a SKIP ROM follow by a CONVERT T commmand on the bus.
+ * Send a SKIP ROM follow by a CONVERT T command on the bus.
* It also set the status flag in each slave &struct w1_therm_family_data
* to signal that a conversion is in progress.
*
@@ -444,18 +444,8 @@ static int w1_read(struct device *dev, enum hwmon_sensor_types type,
}
}
-static const u32 w1_temp_config[] = {
- HWMON_T_INPUT,
- 0
-};
-
-static const struct hwmon_channel_info w1_temp = {
- .type = hwmon_temp,
- .config = w1_temp_config,
-};
-
-static const struct hwmon_channel_info *w1_info[] = {
- &w1_temp,
+static const struct hwmon_channel_info * const w1_info[] = {
+ HWMON_CHANNEL_INFO(temp, HWMON_T_INPUT),
NULL
};
@@ -1159,29 +1149,26 @@ static int convert_t(struct w1_slave *sl, struct therm_info *info)
w1_write_8(dev_master, W1_CONVERT_TEMP);
- if (strong_pullup) { /*some device need pullup */
+ if (SLAVE_FEATURES(sl) & W1_THERM_POLL_COMPLETION) {
+ ret = w1_poll_completion(dev_master, W1_POLL_CONVERT_TEMP);
+ if (ret) {
+ dev_dbg(&sl->dev, "%s: Timeout\n", __func__);
+ goto mt_unlock;
+ }
+ mutex_unlock(&dev_master->bus_mutex);
+ } else if (!strong_pullup) { /*no device need pullup */
sleep_rem = msleep_interruptible(t_conv);
if (sleep_rem != 0) {
ret = -EINTR;
goto mt_unlock;
}
mutex_unlock(&dev_master->bus_mutex);
- } else { /*no device need pullup */
- if (SLAVE_FEATURES(sl) & W1_THERM_POLL_COMPLETION) {
- ret = w1_poll_completion(dev_master, W1_POLL_CONVERT_TEMP);
- if (ret) {
- dev_dbg(&sl->dev, "%s: Timeout\n", __func__);
- goto mt_unlock;
- }
- mutex_unlock(&dev_master->bus_mutex);
- } else {
- /* Fixed delay */
- mutex_unlock(&dev_master->bus_mutex);
- sleep_rem = msleep_interruptible(t_conv);
- if (sleep_rem != 0) {
- ret = -EINTR;
- goto dec_refcnt;
- }
+ } else { /*some device need pullup */
+ mutex_unlock(&dev_master->bus_mutex);
+ sleep_rem = msleep_interruptible(t_conv);
+ if (sleep_rem != 0) {
+ ret = -EINTR;
+ goto dec_refcnt;
}
}
ret = read_scratchpad(sl, info);
@@ -1515,7 +1502,7 @@ static int trigger_bulk_read(struct w1_master *dev_master)
if (bulk_read_support(sl)) {
int t_cur = conversion_time(sl);
- t_conv = t_cur > t_conv ? t_cur : t_conv;
+ t_conv = max(t_cur, t_conv);
strong_pullup = strong_pullup ||
(w1_strong_pullup == 2 ||
(!SLAVE_POWERMODE(sl) &&
diff --git a/drivers/w1/w1.c b/drivers/w1/w1.c
index 4a2ddf730a3a..002d2639aa12 100644
--- a/drivers/w1/w1.c
+++ b/drivers/w1/w1.c
@@ -32,7 +32,7 @@ static int w1_timeout = 10;
module_param_named(timeout, w1_timeout, int, 0);
MODULE_PARM_DESC(timeout, "time in seconds between automatic slave searches");
-static int w1_timeout_us = 0;
+static int w1_timeout_us;
module_param_named(timeout_us, w1_timeout_us, int, 0);
MODULE_PARM_DESC(timeout_us,
"time in microseconds between automatic slave searches");
@@ -58,11 +58,6 @@ MODULE_PARM_DESC(slave_ttl,
DEFINE_MUTEX(w1_mlock);
LIST_HEAD(w1_masters);
-static int w1_master_match(struct device *dev, struct device_driver *drv)
-{
- return 1;
-}
-
static int w1_master_probe(struct device *dev)
{
return -ENODEV;
@@ -91,7 +86,7 @@ static ssize_t name_show(struct device *dev, struct device_attribute *attr, char
{
struct w1_slave *sl = dev_to_w1_slave(dev);
- return sprintf(buf, "%s\n", sl->name);
+ return sysfs_emit(buf, "%s\n", sl->name);
}
static DEVICE_ATTR_RO(name);
@@ -116,7 +111,7 @@ ATTRIBUTE_GROUPS(w1_slave);
/* Default family */
static ssize_t rw_write(struct file *filp, struct kobject *kobj,
- struct bin_attribute *bin_attr, char *buf, loff_t off,
+ const struct bin_attribute *bin_attr, char *buf, loff_t off,
size_t count)
{
struct w1_slave *sl = kobj_to_w1_slave(kobj);
@@ -135,8 +130,8 @@ out_up:
}
static ssize_t rw_read(struct file *filp, struct kobject *kobj,
- struct bin_attribute *bin_attr, char *buf, loff_t off,
- size_t count)
+ const struct bin_attribute *bin_attr, char *buf,
+ loff_t off, size_t count)
{
struct w1_slave *sl = kobj_to_w1_slave(kobj);
@@ -146,9 +141,9 @@ static ssize_t rw_read(struct file *filp, struct kobject *kobj,
return count;
}
-static BIN_ATTR_RW(rw, PAGE_SIZE);
+static const BIN_ATTR_RW(rw, PAGE_SIZE);
-static struct bin_attribute *w1_slave_bin_attrs[] = {
+static const struct bin_attribute *const w1_slave_bin_attrs[] = {
&bin_attr_rw,
NULL,
};
@@ -170,11 +165,10 @@ static struct w1_family w1_default_family = {
.fops = &w1_default_fops,
};
-static int w1_uevent(struct device *dev, struct kobj_uevent_env *env);
+static int w1_uevent(const struct device *dev, struct kobj_uevent_env *env);
-static struct bus_type w1_bus_type = {
+static const struct bus_type w1_bus_type = {
.name = "w1",
- .match = w1_master_match,
.uevent = w1_uevent,
};
@@ -213,7 +207,7 @@ static ssize_t w1_master_attribute_show_name(struct device *dev, struct device_a
ssize_t count;
mutex_lock(&md->mutex);
- count = sprintf(buf, "%s\n", md->name);
+ count = sysfs_emit(buf, "%s\n", md->name);
mutex_unlock(&md->mutex);
return count;
@@ -249,7 +243,7 @@ static ssize_t w1_master_attribute_show_search(struct device *dev,
ssize_t count;
mutex_lock(&md->mutex);
- count = sprintf(buf, "%d\n", md->search_count);
+ count = sysfs_emit(buf, "%d\n", md->search_count);
mutex_unlock(&md->mutex);
return count;
@@ -282,7 +276,7 @@ static ssize_t w1_master_attribute_show_pullup(struct device *dev,
ssize_t count;
mutex_lock(&md->mutex);
- count = sprintf(buf, "%d\n", md->enable_pullup);
+ count = sysfs_emit(buf, "%d\n", md->enable_pullup);
mutex_unlock(&md->mutex);
return count;
@@ -294,24 +288,20 @@ static ssize_t w1_master_attribute_show_pointer(struct device *dev, struct devic
ssize_t count;
mutex_lock(&md->mutex);
- count = sprintf(buf, "0x%p\n", md->bus_master);
+ count = sysfs_emit(buf, "0x%p\n", md->bus_master);
mutex_unlock(&md->mutex);
return count;
}
static ssize_t w1_master_attribute_show_timeout(struct device *dev, struct device_attribute *attr, char *buf)
{
- ssize_t count;
- count = sprintf(buf, "%d\n", w1_timeout);
- return count;
+ return sysfs_emit(buf, "%d\n", w1_timeout);
}
static ssize_t w1_master_attribute_show_timeout_us(struct device *dev,
struct device_attribute *attr, char *buf)
{
- ssize_t count;
- count = sprintf(buf, "%d\n", w1_timeout_us);
- return count;
+ return sysfs_emit(buf, "%d\n", w1_timeout_us);
}
static ssize_t w1_master_attribute_store_max_slave_count(struct device *dev,
@@ -338,7 +328,7 @@ static ssize_t w1_master_attribute_show_max_slave_count(struct device *dev, stru
ssize_t count;
mutex_lock(&md->mutex);
- count = sprintf(buf, "%d\n", md->max_slave_count);
+ count = sysfs_emit(buf, "%d\n", md->max_slave_count);
mutex_unlock(&md->mutex);
return count;
}
@@ -349,7 +339,7 @@ static ssize_t w1_master_attribute_show_attempts(struct device *dev, struct devi
ssize_t count;
mutex_lock(&md->mutex);
- count = sprintf(buf, "%lu\n", md->attempts);
+ count = sysfs_emit(buf, "%lu\n", md->attempts);
mutex_unlock(&md->mutex);
return count;
}
@@ -360,7 +350,7 @@ static ssize_t w1_master_attribute_show_slave_count(struct device *dev, struct d
ssize_t count;
mutex_lock(&md->mutex);
- count = sprintf(buf, "%d\n", md->slave_count);
+ count = sysfs_emit(buf, "%d\n", md->slave_count);
mutex_unlock(&md->mutex);
return count;
}
@@ -501,7 +491,7 @@ static ssize_t w1_master_attribute_store_remove(struct device *dev,
struct w1_master *md = dev_to_w1_master(dev);
struct w1_reg_num rn;
struct w1_slave *sl;
- ssize_t result = count;
+ ssize_t result;
if (w1_atoreg_num(dev, buf, count, &rn))
return -EINVAL;
@@ -514,7 +504,7 @@ static ssize_t w1_master_attribute_store_remove(struct device *dev,
if (result == 0)
result = count;
} else {
- dev_info(dev, "Device %02x-%012llx doesn't exists\n", rn.family,
+ dev_info(dev, "Device %02x-%012llx doesn't exist\n", rn.family,
(unsigned long long)rn.id);
result = -EINVAL;
}
@@ -577,11 +567,11 @@ void w1_destroy_master_attributes(struct w1_master *master)
sysfs_remove_group(&master->dev.kobj, &w1_master_defattr_group);
}
-static int w1_uevent(struct device *dev, struct kobj_uevent_env *env)
+static int w1_uevent(const struct device *dev, struct kobj_uevent_env *env)
{
- struct w1_master *md = NULL;
- struct w1_slave *sl = NULL;
- char *event_owner, *name;
+ const struct w1_master *md = NULL;
+ const struct w1_slave *sl = NULL;
+ const char *event_owner, *name;
int err = 0;
if (dev->driver == &w1_master_driver) {
@@ -702,6 +692,7 @@ static int __w1_attach_slave_device(struct w1_slave *sl)
dev_err(&sl->dev,
"Device registration [%s] failed. err=%d\n",
dev_name(&sl->dev), err);
+ of_node_put(sl->dev.of_node);
put_device(&sl->dev);
return err;
}
@@ -830,49 +821,47 @@ int w1_slave_detach(struct w1_slave *sl)
struct w1_master *w1_search_master_id(u32 id)
{
- struct w1_master *dev;
- int found = 0;
+ struct w1_master *dev = NULL, *iter;
mutex_lock(&w1_mlock);
- list_for_each_entry(dev, &w1_masters, w1_master_entry) {
- if (dev->id == id) {
- found = 1;
- atomic_inc(&dev->refcnt);
+ list_for_each_entry(iter, &w1_masters, w1_master_entry) {
+ if (iter->id == id) {
+ dev = iter;
+ atomic_inc(&iter->refcnt);
break;
}
}
mutex_unlock(&w1_mlock);
- return (found)?dev:NULL;
+ return dev;
}
struct w1_slave *w1_search_slave(struct w1_reg_num *id)
{
struct w1_master *dev;
- struct w1_slave *sl = NULL;
- int found = 0;
+ struct w1_slave *sl = NULL, *iter;
mutex_lock(&w1_mlock);
list_for_each_entry(dev, &w1_masters, w1_master_entry) {
mutex_lock(&dev->list_mutex);
- list_for_each_entry(sl, &dev->slist, w1_slave_entry) {
- if (sl->reg_num.family == id->family &&
- sl->reg_num.id == id->id &&
- sl->reg_num.crc == id->crc) {
- found = 1;
+ list_for_each_entry(iter, &dev->slist, w1_slave_entry) {
+ if (iter->reg_num.family == id->family &&
+ iter->reg_num.id == id->id &&
+ iter->reg_num.crc == id->crc) {
+ sl = iter;
atomic_inc(&dev->refcnt);
- atomic_inc(&sl->refcnt);
+ atomic_inc(&iter->refcnt);
break;
}
}
mutex_unlock(&dev->list_mutex);
- if (found)
+ if (sl)
break;
}
mutex_unlock(&w1_mlock);
- return (found)?sl:NULL;
+ return sl;
}
void w1_reconnect_slaves(struct w1_family *f, int attach)
@@ -1263,10 +1252,10 @@ err_out_exit_init:
static void __exit w1_fini(void)
{
- struct w1_master *dev;
+ struct w1_master *dev, *n;
/* Set netlink removal messages and some cleanup */
- list_for_each_entry(dev, &w1_masters, w1_master_entry)
+ list_for_each_entry_safe(dev, n, &w1_masters, w1_master_entry)
__w1_remove_master_device(dev);
w1_fini_netlink();
diff --git a/drivers/w1/w1_int.c b/drivers/w1/w1_int.c
index 3a71c5eb2f83..19a0ea28e9f3 100644
--- a/drivers/w1/w1_int.c
+++ b/drivers/w1/w1_int.c
@@ -32,12 +32,8 @@ static struct w1_master *w1_alloc_dev(u32 id, int slave_count, int slave_ttl,
* We are in process context(kernel thread), so can sleep.
*/
dev = kzalloc(sizeof(struct w1_master) + sizeof(struct w1_bus_master), GFP_KERNEL);
- if (!dev) {
- pr_err("Failed to allocate %zd bytes for new w1 device.\n",
- sizeof(struct w1_master));
+ if (!dev)
return NULL;
- }
-
dev->bus_master = (struct w1_bus_master *)(dev + 1);
diff --git a/drivers/w1/w1_netlink.c b/drivers/w1/w1_netlink.c
index db110cc442b1..e6b59d921076 100644
--- a/drivers/w1/w1_netlink.c
+++ b/drivers/w1/w1_netlink.c
@@ -65,7 +65,8 @@ static void w1_unref_block(struct w1_cb_block *block)
u16 len = w1_reply_len(block);
if (len) {
cn_netlink_send_mult(block->first_cn, len,
- block->portid, 0, GFP_KERNEL);
+ block->portid, 0,
+ GFP_KERNEL, NULL, NULL);
}
kfree(block);
}
@@ -83,7 +84,8 @@ static void w1_reply_make_space(struct w1_cb_block *block, u16 space)
{
u16 len = w1_reply_len(block);
if (len + space >= block->maxlen) {
- cn_netlink_send_mult(block->first_cn, len, block->portid, 0, GFP_KERNEL);
+ cn_netlink_send_mult(block->first_cn, len, block->portid,
+ 0, GFP_KERNEL, NULL, NULL);
block->first_cn->len = 0;
block->cn = NULL;
block->msg = NULL;
@@ -192,16 +194,16 @@ static void w1_netlink_queue_status(struct w1_cb_block *block,
static void w1_netlink_send_error(struct cn_msg *cn, struct w1_netlink_msg *msg,
int portid, int error)
{
- struct {
- struct cn_msg cn;
- struct w1_netlink_msg msg;
- } packet;
- memcpy(&packet.cn, cn, sizeof(packet.cn));
- memcpy(&packet.msg, msg, sizeof(packet.msg));
- packet.cn.len = sizeof(packet.msg);
- packet.msg.len = 0;
- packet.msg.status = (u8)-error;
- cn_netlink_send(&packet.cn, portid, 0, GFP_KERNEL);
+ DEFINE_RAW_FLEX(struct cn_msg, packet, data,
+ sizeof(struct w1_netlink_msg));
+ struct w1_netlink_msg *pkt_msg = (struct w1_netlink_msg *)packet->data;
+
+ *packet = *cn;
+ *pkt_msg = *msg;
+ packet->len = sizeof(*pkt_msg);
+ pkt_msg->len = 0;
+ pkt_msg->status = (u8)-error;
+ cn_netlink_send(packet, portid, 0, GFP_KERNEL);
}
/**
@@ -213,22 +215,20 @@ static void w1_netlink_send_error(struct cn_msg *cn, struct w1_netlink_msg *msg,
*/
void w1_netlink_send(struct w1_master *dev, struct w1_netlink_msg *msg)
{
- struct {
- struct cn_msg cn;
- struct w1_netlink_msg msg;
- } packet;
- memset(&packet, 0, sizeof(packet));
+ DEFINE_RAW_FLEX(struct cn_msg, packet, data,
+ sizeof(struct w1_netlink_msg));
+ struct w1_netlink_msg *pkt_msg = (struct w1_netlink_msg *)packet->data;
- packet.cn.id.idx = CN_W1_IDX;
- packet.cn.id.val = CN_W1_VAL;
+ packet->id.idx = CN_W1_IDX;
+ packet->id.val = CN_W1_VAL;
- packet.cn.seq = dev->seq++;
- packet.cn.len = sizeof(*msg);
+ packet->seq = dev->seq++;
+ packet->len = sizeof(*msg);
- memcpy(&packet.msg, msg, sizeof(*msg));
- packet.msg.len = 0;
+ *pkt_msg = *msg;
+ pkt_msg->len = 0;
- cn_netlink_send(&packet.cn, 0, 0, GFP_KERNEL);
+ cn_netlink_send(packet, 0, 0, GFP_KERNEL);
}
static void w1_send_slave(struct w1_master *dev, u64 rn)