diff options
Diffstat (limited to 'drivers/w1/masters')
-rw-r--r-- | drivers/w1/masters/Kconfig | 11 | ||||
-rw-r--r-- | drivers/w1/masters/Makefile | 1 | ||||
-rw-r--r-- | drivers/w1/masters/amd_axi_w1.c | 396 | ||||
-rw-r--r-- | drivers/w1/masters/ds2490.c | 25 | ||||
-rw-r--r-- | drivers/w1/masters/w1-gpio.c | 118 |
5 files changed, 471 insertions, 80 deletions
diff --git a/drivers/w1/masters/Kconfig b/drivers/w1/masters/Kconfig index ad31657328..513c0b1143 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 diff --git a/drivers/w1/masters/Makefile b/drivers/w1/masters/Makefile index c5d85a827e..6c5a21f9b8 100644 --- a/drivers/w1/masters/Makefile +++ b/drivers/w1/masters/Makefile @@ -3,6 +3,7 @@ # 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 diff --git a/drivers/w1/masters/amd_axi_w1.c b/drivers/w1/masters/amd_axi_w1.c new file mode 100644 index 0000000000..4d3a68ca92 --- /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_new = 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/ds2490.c b/drivers/w1/masters/ds2490.c index 5f5b97e247..e1cac0730c 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 */ @@ -614,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); @@ -640,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; diff --git a/drivers/w1/masters/w1-gpio.c b/drivers/w1/masters/w1-gpio.c index e45acb6d91..05c67038ed 100644 --- a/drivers/w1/masters/w1-gpio.c +++ b/drivers/w1/masters/w1-gpio.c @@ -9,7 +9,6 @@ #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> @@ -18,27 +17,33 @@ #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,16 +51,16 @@ 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) @@ -69,58 +74,48 @@ MODULE_DEVICE_TABLE(of, w1_gpio_dt_ids); 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_property_present(np, "linux,open-drain")) - 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 (of_property_present(np, "linux,open-drain")) + gflags = GPIOD_OUT_LOW; master = devm_kzalloc(dev, sizeof(struct w1_bus_master), GFP_KERNEL); if (!master) return -ENOMEM; - pdata->gpiod = devm_gpiod_get_index(dev, NULL, 0, gflags); - if (IS_ERR(pdata->gpiod)) { + ddata->gpiod = devm_gpiod_get_index(dev, NULL, 0, gflags); + if (IS_ERR(ddata->gpiod)) { dev_err(dev, "gpio_request (pin) failed\n"); - return PTR_ERR(pdata->gpiod); + return PTR_ERR(ddata->gpiod); } - pdata->pullup_gpiod = + ddata->pullup_gpiod = devm_gpiod_get_index_optional(dev, NULL, 1, GPIOD_OUT_LOW); - if (IS_ERR(pdata->pullup_gpiod)) { + if (IS_ERR(ddata->pullup_gpiod)) { dev_err(dev, "gpio_request_one " "(ext_pullup_enable_pin) failed\n"); - return PTR_ERR(pdata->pullup_gpiod); + return PTR_ERR(ddata->pullup_gpiod); } - 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; /* @@ -138,11 +133,8 @@ static int w1_gpio_probe(struct platform_device *pdev) return err; } - if (pdata->enable_external_pullup) - pdata->enable_external_pullup(1); - - if (pdata->pullup_gpiod) - gpiod_set_value(pdata->pullup_gpiod, 1); + if (ddata->pullup_gpiod) + gpiod_set_value(ddata->pullup_gpiod, 1); platform_set_drvdata(pdev, master); @@ -152,45 +144,19 @@ static int w1_gpio_probe(struct platform_device *pdev) static int 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); + if (ddata->pullup_gpiod) + 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 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), }, .probe = w1_gpio_probe, |