From patchwork Wed Nov 14 09:52:40 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Chris Coffey X-Patchwork-Id: 10682301 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 7E5F213B5 for ; Wed, 14 Nov 2018 09:52:57 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 6F9B52B056 for ; Wed, 14 Nov 2018 09:52:57 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 625A52B05C; Wed, 14 Nov 2018 09:52:57 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-7.7 required=2.0 tests=BAYES_00,DKIM_INVALID, DKIM_SIGNED,MAILING_LIST_MULTI,RCVD_IN_DNSWL_HI autolearn=ham version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id EF4502B056 for ; Wed, 14 Nov 2018 09:52:56 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1732413AbeKNTz1 (ORCPT ); Wed, 14 Nov 2018 14:55:27 -0500 Received: from mail.babblebit.net ([37.139.8.208]:47078 "EHLO mail.babblebit.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1727558AbeKNTz1 (ORCPT ); Wed, 14 Nov 2018 14:55:27 -0500 Received: from localhost.localdomain (80-44-164-194.dynamic.dsl.as9105.com [80.44.164.194]) by mail.babblebit.net (Postfix) with ESMTPSA id 081B7209D6; Wed, 14 Nov 2018 09:52:54 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=simple/simple; d=babblebit.net; s=mail; t=1542189174; bh=k1sA0CHc32V1PQGxiTc2/z8OpnFP7VjmpBgmAtrjoIE=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=W7dnB6EBEIE+demzhNS25Ro291e1VTIXv62tuD933IVdTXcj0eRJD1sRnzivF/pN/ ppOxJcvxBoKfXFu5PqeMfVeWDqPKYQq6BS9A+8gSD7fJSwOpcFklNAKEpl/n+l4MUP lJhJtgCffEQaOF1RTl81wtnigT+DWO1DZVhjeRzJCQEbwbtg4SZKYsrf1b5VIUfvUo XU2h92dIsXDP6FoVlU4hfX9jMm9iHV0pMSNWQmK4uCtWkFsYj1u01FHraAuoxImtzv Zvd0EXjsM38P82V0WX5I8nqvpWPqjg3odDu8wVUvARSYbTKNqtxp+PLrAIwGmbQADv hkZ6HGF+Ey7nA== From: Chris Coffey To: Jonathan Cameron , Hartmut Knaack , Lars-Peter Clausen , Peter Meerwald-Stadler Cc: Peter Rosin , Slawomir Stepien , Rob Herring , Mark Rutland , linux-iio@vger.kernel.org, devicetree@vger.kernel.org, Chris Coffey Subject: [PATCH v2 1/2] dt-bindings: iio: potentiometer: Add Microchip MCP41xxx/42xxx Date: Wed, 14 Nov 2018 09:52:40 +0000 Message-Id: <20181114095241.27037-2-cmc@babblebit.net> X-Mailer: git-send-email 2.11.0 In-Reply-To: <20181114095241.27037-1-cmc@babblebit.net> References: <20181114095241.27037-1-cmc@babblebit.net> Sender: linux-iio-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-iio@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP This patch adds device tree documentation for the Microchip MCP41xxx/42xxx family of digital potentiometers. Signed-off-by: Chris Coffey --- .../bindings/iio/potentiometer/mcp41010.txt | 29 ++++++++++++++++++++++ 1 file changed, 29 insertions(+) create mode 100644 Documentation/devicetree/bindings/iio/potentiometer/mcp41010.txt diff --git a/Documentation/devicetree/bindings/iio/potentiometer/mcp41010.txt b/Documentation/devicetree/bindings/iio/potentiometer/mcp41010.txt new file mode 100644 index 0000000000..17565acace --- /dev/null +++ b/Documentation/devicetree/bindings/iio/potentiometer/mcp41010.txt @@ -0,0 +1,29 @@ +* Microchip MCP41010/41050/41100/42010/42050/42100 Digital Potentiometer + driver + +Datasheet publicly available at: +http://ww1.microchip.com/downloads/en/devicedoc/11195c.pdf + +The node for this driver must be a child node of a SPI controller, hence +all mandatory properties described in + + Documentation/devicetree/bindings/spi/spi-bus.txt + +must be specified. + +Required properties: + - compatible: Must be one of the following, depending on the + model: + "microchip,mcp41010" + "microchip,mcp41050" + "microchip,mcp41100" + "microchip,mcp42010" + "microchip,mcp42050" + "microchip,mcp42100" + +Example: +mcp41010: potentiometer@0 { + compatible = "mcp41010"; + reg = <0>; + spi-max-frequency = <500000>; +}; From patchwork Wed Nov 14 09:52:41 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Chris Coffey X-Patchwork-Id: 10682303 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 6F4F113B5 for ; Wed, 14 Nov 2018 09:53:05 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 61EF62B051 for ; Wed, 14 Nov 2018 09:53:05 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 553E32B058; Wed, 14 Nov 2018 09:53:05 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-7.7 required=2.0 tests=BAYES_00,DKIM_INVALID, DKIM_SIGNED,MAILING_LIST_MULTI,RCVD_IN_DNSWL_HI autolearn=ham version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id A70F52B051 for ; Wed, 14 Nov 2018 09:53:04 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1732446AbeKNTzf (ORCPT ); Wed, 14 Nov 2018 14:55:35 -0500 Received: from mail.babblebit.net ([37.139.8.208]:47098 "EHLO mail.babblebit.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1727558AbeKNTzf (ORCPT ); Wed, 14 Nov 2018 14:55:35 -0500 Received: from localhost.localdomain (80-44-164-194.dynamic.dsl.as9105.com [80.44.164.194]) by mail.babblebit.net (Postfix) with ESMTPSA id 5C73A20E4C; Wed, 14 Nov 2018 09:53:00 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=simple/simple; d=babblebit.net; s=mail; t=1542189180; bh=84V3+9SnvyoCV3hwKMcDe4RDU/XCowYIl1F0hI7IuWE=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=mxQZOvz03kVEwQClLSBavQZBvecoOrKVNKCwPpXRncIB5LID8TQ16Tu7qpO6GcPJ5 kfoN5wCiRyMmcvRVT9TPupH0OfUoxfYomgDPEerANoOy2lwQcIKuMQzhs3MBk+ulPO KGvmg6NTm8lVlSSRpkgSG4wOvY77yUaRV6PCnLihYANx9jaybTj2cepE+72v335L5b PVLRUMOuqzUNGK8MNH5LXb0/Tnf8KTlFqReueOCIb58w90UwN3KU3zEfL4Y8NBiRkd ZopabpvMsfAwlYuW/VdgqHa6tcWQ10a5JYvQnVpLkM+2gaNVYxZl29sJYmfHWTHBdP KZIStCEEaWLFQ== From: Chris Coffey To: Jonathan Cameron , Hartmut Knaack , Lars-Peter Clausen , Peter Meerwald-Stadler Cc: Peter Rosin , Slawomir Stepien , Rob Herring , Mark Rutland , linux-iio@vger.kernel.org, devicetree@vger.kernel.org, Chris Coffey Subject: [PATCH v2 2/2] iio: potentiometer: Add driver for Microchip MCP41xxx/42xxx Date: Wed, 14 Nov 2018 09:52:41 +0000 Message-Id: <20181114095241.27037-3-cmc@babblebit.net> X-Mailer: git-send-email 2.11.0 In-Reply-To: <20181114095241.27037-1-cmc@babblebit.net> References: <20181114095241.27037-1-cmc@babblebit.net> Sender: linux-iio-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-iio@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP This patch adds driver support for the Microchip MCP41xxx/42xxx family of digital potentiometers: DEVICE Wipers Positions Resistance (kOhm) MCP41010 1 256 10 MCP41050 1 256 50 MCP41100 1 256 100 MCP42010 2 256 10 MCP42050 2 256 50 MCP42100 2 256 100 Datasheet: http://ww1.microchip.com/downloads/en/devicedoc/11195c.pdf Signed-off-by: Chris Coffey --- drivers/iio/potentiometer/Kconfig | 12 ++ drivers/iio/potentiometer/Makefile | 1 + drivers/iio/potentiometer/mcp41010.c | 216 +++++++++++++++++++++++++++++++++++ 3 files changed, 229 insertions(+) create mode 100644 drivers/iio/potentiometer/mcp41010.c diff --git a/drivers/iio/potentiometer/Kconfig b/drivers/iio/potentiometer/Kconfig index 79ec2eba49..6303cbe799 100644 --- a/drivers/iio/potentiometer/Kconfig +++ b/drivers/iio/potentiometer/Kconfig @@ -90,6 +90,18 @@ config MCP4531 To compile this driver as a module, choose M here: the module will be called mcp4531. +config MCP41010 + tristate "Microchip MCP41xxx/MCP42xxx Digital Potentiometer driver" + depends on SPI + help + Say yes here to build support for the Microchip + MCP41010, MCP41050, MCP41100, + MCP42010, MCP42050, MCP42100 + digital potentiometer chips. + + To compile this driver as a module, choose M here: the + module will be called mcp41010. + config TPL0102 tristate "Texas Instruments digital potentiometer driver" depends on I2C diff --git a/drivers/iio/potentiometer/Makefile b/drivers/iio/potentiometer/Makefile index 4af657883c..8ff55138cf 100644 --- a/drivers/iio/potentiometer/Makefile +++ b/drivers/iio/potentiometer/Makefile @@ -11,4 +11,5 @@ obj-$(CONFIG_MAX5487) += max5487.o obj-$(CONFIG_MCP4018) += mcp4018.o obj-$(CONFIG_MCP4131) += mcp4131.o obj-$(CONFIG_MCP4531) += mcp4531.o +obj-$(CONFIG_MCP41010) += mcp41010.o obj-$(CONFIG_TPL0102) += tpl0102.o diff --git a/drivers/iio/potentiometer/mcp41010.c b/drivers/iio/potentiometer/mcp41010.c new file mode 100644 index 0000000000..19fa50c9ee --- /dev/null +++ b/drivers/iio/potentiometer/mcp41010.c @@ -0,0 +1,216 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Industrial I/O driver for Microchip digital potentiometers + * + * Copyright (c) 2018 Chris Coffey + * Based on: Slawomir Stepien's code from mcp4131.c + * + * Datasheet: http://ww1.microchip.com/downloads/en/devicedoc/11195c.pdf + * + * DEVID #Wipers #Positions Resistance (kOhm) + * mcp41010 1 256 10 + * mcp41050 1 256 50 + * mcp41100 1 256 100 + * mcp42010 2 256 10 + * mcp42050 2 256 50 + * mcp42100 2 256 100 + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define MCP41010_MAX_WIPERS 2 +#define MCP41010_WRITE BIT(4) +#define MCP41010_WIPER_MAX 255 +#define MCP41010_WIPER_CHANNEL BIT(0) + +struct mcp41010_cfg { + int wipers; + int kohms; +}; + +enum mcp41010_type { + MCP41010, + MCP41050, + MCP41100, + MCP42010, + MCP42050, + MCP42100, +}; + +static const struct mcp41010_cfg mcp41010_cfg[] = { + [MCP41010] = { .wipers = 1, .kohms = 10, }, + [MCP41050] = { .wipers = 1, .kohms = 50, }, + [MCP41100] = { .wipers = 1, .kohms = 100, }, + [MCP42010] = { .wipers = 2, .kohms = 10, }, + [MCP42050] = { .wipers = 2, .kohms = 50, }, + [MCP42100] = { .wipers = 2, .kohms = 100, }, +}; + +struct mcp41010_data { + struct spi_device *spi; + const struct mcp41010_cfg *cfg; + struct mutex lock; /* Protect write sequences */ + unsigned int value[MCP41010_MAX_WIPERS]; /* Cache wiper values */ + u8 buf[2] ____cacheline_aligned; +}; + +#define MCP41010_CHANNEL(ch) { \ + .type = IIO_RESISTANCE, \ + .indexed = 1, \ + .output = 1, \ + .channel = (ch), \ + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \ + .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), \ +} + +static const struct iio_chan_spec mcp41010_channels[] = { + MCP41010_CHANNEL(0), + MCP41010_CHANNEL(1), +}; + +static int mcp41010_read_raw(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, + int *val, int *val2, long mask) +{ + struct mcp41010_data *data = iio_priv(indio_dev); + int channel = chan->channel; + + switch (mask) { + case IIO_CHAN_INFO_RAW: + *val = data->value[channel]; + return IIO_VAL_INT; + + case IIO_CHAN_INFO_SCALE: + *val = 1000 * data->cfg->kohms; + *val2 = MCP41010_WIPER_MAX; + return IIO_VAL_FRACTIONAL; + } + + return -EINVAL; +} + +static int mcp41010_write_raw(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, + int val, int val2, long mask) +{ + int err; + struct mcp41010_data *data = iio_priv(indio_dev); + int channel = chan->channel; + + switch (mask) { + case IIO_CHAN_INFO_RAW: + if (val > MCP41010_WIPER_MAX || val < 0) + return -EINVAL; + break; + + default: + return -EINVAL; + } + + mutex_lock(&data->lock); + + data->buf[0] = MCP41010_WIPER_CHANNEL << channel; + data->buf[0] |= MCP41010_WRITE; + data->buf[1] = val & 0xff; + + err = spi_write(data->spi, data->buf, 2); + if (!err) + data->value[channel] = val; + + mutex_unlock(&data->lock); + + return err; +} + +static const struct iio_info mcp41010_info = { + .read_raw = mcp41010_read_raw, + .write_raw = mcp41010_write_raw, +}; + +static int mcp41010_probe(struct spi_device *spi) +{ + int err; + struct device *dev = &spi->dev; + unsigned long devid = spi_get_device_id(spi)->driver_data; + struct mcp41010_data *data; + struct iio_dev *indio_dev; + + indio_dev = devm_iio_device_alloc(dev, sizeof(*data)); + if (!indio_dev) + return -ENOMEM; + + data = iio_priv(indio_dev); + spi_set_drvdata(spi, indio_dev); + data->spi = spi; + data->cfg = of_device_get_match_data(&spi->dev); + if (!data->cfg) + data->cfg = &mcp41010_cfg[devid]; + + mutex_init(&data->lock); + + indio_dev->dev.parent = dev; + indio_dev->info = &mcp41010_info; + indio_dev->channels = mcp41010_channels; + indio_dev->num_channels = data->cfg->wipers; + indio_dev->name = spi_get_device_id(spi)->name; + + err = devm_iio_device_register(dev, indio_dev); + if (err) { + dev_info(&spi->dev, "Unable to register %s\n", indio_dev->name); + return err; + } + + return 0; +} + +static const struct of_device_id mcp41010_match[] = { + { .compatible = "microchip,mcp41010", + .data = &mcp41010_cfg[MCP41010] }, + { .compatible = "microchip,mcp41050", + .data = &mcp41010_cfg[MCP41050] }, + { .compatible = "microchip,mcp41100", + .data = &mcp41010_cfg[MCP41100] }, + { .compatible = "microchip,mcp42010", + .data = &mcp41010_cfg[MCP42010] }, + { .compatible = "microchip,mcp42050", + .data = &mcp41010_cfg[MCP42050] }, + { .compatible = "microchip,mcp42100", + .data = &mcp41010_cfg[MCP42100] }, + {} +}; +MODULE_DEVICE_TABLE(of, mcp41010_match); + +static const struct spi_device_id mcp41010_id[] = { + { "mcp41010", MCP41010 }, + { "mcp41050", MCP41050 }, + { "mcp41100", MCP41100 }, + { "mcp42010", MCP42010 }, + { "mcp42050", MCP42050 }, + { "mcp42100", MCP42100 }, + {} +}; +MODULE_DEVICE_TABLE(spi, mcp41010_id); + +static struct spi_driver mcp41010_driver = { + .driver = { + .name = "mcp41010", + .of_match_table = mcp41010_match, + }, + .probe = mcp41010_probe, + .id_table = mcp41010_id, +}; + +module_spi_driver(mcp41010_driver); + +MODULE_AUTHOR("Chris Coffey "); +MODULE_DESCRIPTION("MCP41010 digital potentiometer"); +MODULE_LICENSE("GPL v2");