From patchwork Mon Sep 25 19:14:11 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ismail Kose X-Patchwork-Id: 9970377 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork.web.codeaurora.org (Postfix) with ESMTP id 5E6C6602D8 for ; Mon, 25 Sep 2017 19:14:49 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 4FDD428CBD for ; Mon, 25 Sep 2017 19:14:49 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 4469D28CBF; Mon, 25 Sep 2017 19:14:49 +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=-6.8 required=2.0 tests=BAYES_00,DKIM_SIGNED, RCVD_IN_DNSWL_HI,T_DKIM_INVALID 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 12B3C28CBD for ; Mon, 25 Sep 2017 19:14:47 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S935891AbdIYTOr (ORCPT ); Mon, 25 Sep 2017 15:14:47 -0400 Received: from mail-by2nam01on0093.outbound.protection.outlook.com ([104.47.34.93]:41504 "EHLO NAM01-BY2-obe.outbound.protection.outlook.com" rhost-flags-OK-OK-OK-FAIL) by vger.kernel.org with ESMTP id S934555AbdIYTOo (ORCPT ); Mon, 25 Sep 2017 15:14:44 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=maximintegrated.onmicrosoft.com; s=selector1-maximintegrated-com; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version; bh=XgSnQDSGtOn2wF6PanZfPx1W32KBypjV7FOpzjEtBxM=; b=mX9TkfQZBEVyyH3f4Ys/WrzvFy8aGMb0D+nRpRfAMQh4GQUJOuUJXLnGycufHQGm3Hs7CEuS7ll/ijmGilVaO69VyEvyP8/hRy20KadATxmKM1j9HoSlPBStZSaMGrw3pTN05jrzT8Svp/x7eLFfdbDWmJUB3scZwt5co6rXz7I= Authentication-Results: spf=none (sender IP is ) smtp.mailfrom=Ismail.Kose@maximintegrated.com; Received: from kose.maxim-ic.com (204.17.143.20) by BN6PR11MB1859.namprd11.prod.outlook.com (10.175.100.7) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384_P256) id 15.20.77.7; Mon, 25 Sep 2017 19:14:39 +0000 From: "Ismail H. Kose" Cc: ihkose@gmail.com, Ismail.Kose@maximintegrated.com, Jonathan Cameron , Hartmut Knaack , Lars-Peter Clausen , Peter Meerwald-Stadler , Peter Rosin , Jean-Francois Dagenais , Fabrice Gasnier , Maxime Roussin-Belanger , Mike Looijmans , linux-kernel@vger.kernel.org, linux-iio@vger.kernel.org Subject: [PATCH v7 1/2] iio: dac: ds4422/ds4424 dac driver Date: Mon, 25 Sep 2017 12:14:11 -0700 Message-Id: <20170925191425.1684-1-Ismail.Kose@maximintegrated.com> X-Mailer: git-send-email 2.11.0 MIME-Version: 1.0 X-Originating-IP: [204.17.143.20] X-ClientProxiedBy: CY4PR0601CA0077.namprd06.prod.outlook.com (52.132.96.146) To BN6PR11MB1859.namprd11.prod.outlook.com (10.175.100.7) X-MS-PublicTrafficType: Email X-MS-Office365-Filtering-Correlation-Id: ae3e5de6-5471-447a-2221-08d50449ac41 X-MS-Office365-Filtering-HT: Tenant X-Microsoft-Antispam: UriScan:; BCL:0; PCL:0; RULEID:(22001)(2017030254152)(48565401081)(2017052603199)(201703131423075)(201703031133081)(201702281549075); SRVR:BN6PR11MB1859; X-Microsoft-Exchange-Diagnostics: 1; BN6PR11MB1859; 3:JPrW1L+ZxIqHGzZDECRV2LtQCGv1ev2VO+IkTM/fpsvMPn9xnmzhCT5YmgTWPow+C/pBKyWR18nx+tul6zA2Ay+O7j3nJuDacvNySI20yCu9I9RVQsvENMgcvIpp7g9BjRI7yohur6scIoVSbr7JW7ATD6PuFN96JqLUkF+/onp0jgESDDEHmzNSNCVKtLjmpqcO27vDbNCLF5TJ5DoKlKOFqGCg8bcmFCT4opwHwdBuRWK3l/16mYR0teIqx2D/; 25:1gB08OAFNcYRqYQVo+noJkAxefqly3ueetQZW2gqZ4c2RPFaCfrD5HVDGE8OFxqIZt7I8oubOU/cZprZZARwaoF8ZtLpl06tnTV+lNVJx33vARGKORmAI/5xdAAdIv6Z3vc2OKw46D9IelddYDt1yLx8slfQhMwaSHj8PIqJB6o+h+VoO9njz55YgvvdPUtSqnZN8VSoTnM/XtmhHYvlak24KP2Jf3pEiEQAkdSRRe4RMHFnaDw6Mf4KyDG+3dSAF4NoNfm49FvrsvfQNS8Wder3Sq4gvGyeYDTXFOLBXO+qpa+0rX0JVL+U3i2kMi2p/XAWO472PnNOn+TYm0oD7g==; 31:7LsjYVQt3CIAsmuRrsAJbCxAL7edCXNj47cxHsVO8vXMDHg9fs3pvEt9YhcBWY6ZwtB85AjJunbWcOD8FKknhFyF3yx4G2b8LqS2AABqcvRBXU6b2d2FaZFJwgQEPAhSW3Jkz+enxpLXESg1hqoVGVtUJvcUzotRnNOmhq7mDEhTngNMnmxuBrp6cpzdirjtBgoxMsuyhvtZLDcqQpFWOwaRO8JzVMcm3iC7FqZ2vqU= X-MS-TrafficTypeDiagnostic: BN6PR11MB1859: X-Microsoft-Exchange-Diagnostics: 1; BN6PR11MB1859; 20:i1qk6/3DrwQV941nMq0E4HIXBVzf7JZgrEWui28QNf00RO4QpXN3hYO7LdYRWBeBkPS1YqB7fZZe3tezzS45nxNY6Nk5e4bk6w2p/dIkA/tQ5krnLRqxFFywL0+Lmk96HBI7wqLgX/TPWSdHK2hgMACM+7e3y9Xt3oACi0AEH4+RFvyDp8PJigPPLlwX64Iaw6zuHysHpQ4y80To7+gaQqdz0Q8+y5gOH0PsyWl2LJIivDz2Jv78/OwICBLAnCSo9aPy2T9FeMoFvaNdxweslfCFi8MWb4ZIjN5wVoD08o4WHEUYCf759xGfjoJaZU3J+0wZFKqWv+f769qkNSvDXUmAsRKp3ZnZgJ9GW2CHwKqWz4gO63JhkJNq1KZw8sOq0RvJfB5BV4zCCO9ArBH52ARJypbHTbzls9rxvog7FLCYpWxgfRzLVgNWQWVSfh4SEp6UuL94dczog63PlLAU/OKIl3TbHFIO5KtvDqNG+j5+k+3GJh0r6qhPpUZxFnwV; 4:d1+8gf+6PzsaqJ7Ryibw5kBSUYDV2vx+1i8tj9buRPwZMc4S6OMg/f7oGdLwtTx4tq1svESu2Lgn6w1rseQBH4negguUvZOK1TfIRSvpsCoIHZKJaFjFTQ1pTacChiCIdMGkg+RatHIHLa1M83duaeA/ivDwrF0ClYcCFaGrsMmFNqn3NHFSvL4wvErC2UxPZyGEKnIiqVAk+HZqQMT1Pr+2aru210KvkgzB3BF1S5M69fb3+if3pCFQGsKX00TuWOguPLXSSIyYgG8K47swL4MdBH3nvNYroULenHwzhuk= X-Exchange-Antispam-Report-Test: UriScan:(108721460000369); X-Microsoft-Antispam-PRVS: X-Exchange-Antispam-Report-CFA-Test: BCL:0; PCL:0; RULEID:(100000700101)(100105000095)(100000701101)(100105300095)(100000702101)(100105100095)(6040450)(2401047)(5005006)(8121501046)(93006095)(93001095)(100000703101)(100105400095)(10201501046)(3002001)(6055026)(6041248)(20161123558100)(20161123562025)(20161123560025)(20161123555025)(20161123564025)(201703131423075)(201702281528075)(201703061421075)(201703061406153)(6072148)(201708071742011)(100000704101)(100105200095)(100000705101)(100105500095); SRVR:BN6PR11MB1859; BCL:0; PCL:0; RULEID:(100000800101)(100110000095)(100000801101)(100110300095)(100000802101)(100110100095)(100000803101)(100110400095)(100000804101)(100110200095)(100000805101)(100110500095); SRVR:BN6PR11MB1859; X-Forefront-PRVS: 04410E544A X-Forefront-Antispam-Report: SFV:NSPM; SFS:(10019020)(6009001)(346002)(39860400002)(376002)(199003)(189002)(36756003)(2906002)(81166006)(8936002)(39060400002)(8676002)(81156014)(7416002)(66066001)(86362001)(69596002)(7736002)(305945005)(6506006)(54906003)(47776003)(6486002)(50226002)(53936002)(68736007)(97736004)(6666003)(1671002)(50466002)(6116002)(25786009)(50986999)(3846002)(4326008)(5003940100001)(478600001)(48376002)(72206003)(5660300001)(16586007)(101416001)(189998001)(8666007)(105586002)(1076002)(109986005)(106356001)(6512007)(16526017)(53416004)(316002)(266003)(2004002); DIR:OUT; SFP:1102; SCL:1; SRVR:BN6PR11MB1859; H:kose.maxim-ic.com; FPR:; SPF:None; PTR:InfoNoRecords; A:1; MX:1; LANG:en; Received-SPF: None (protection.outlook.com: maximintegrated.com does not designate permitted sender hosts) X-Microsoft-Exchange-Diagnostics: =?us-ascii?Q?1; BN6PR11MB1859; 23:3U9fA8AJ9TKoSXOWyiFoUa5P8lTPKlMxKmu4Gwn1/?= =?us-ascii?Q?O1bWYaTy2lBF4JXoUwlxnQGO3C4fNoQKq1GK5gKfs6AdUDuCpTTndZgLj8LC?= =?us-ascii?Q?cASrJVNqiZSTHHg3JUXiV88kSohCxqV8kwCdBXfmPyjmrXtcKkfBWSu4FM38?= =?us-ascii?Q?b8sMviaparzVMTBosAIQdwNEG8I1ZbWaYwB5ycqFeOL4VWM3/q//rPwICbIW?= =?us-ascii?Q?Mk2m+JYzbIJvgeXM9E2WyTpu7di5HcAQrs6TixsjJj4pDFt7Px31PzvEdxK7?= =?us-ascii?Q?fYY8s8y5qU19bohZvjFu46+Twtew7UFU820X437f2RfgwJkuMirIOzM6ZidW?= =?us-ascii?Q?xPZhurGId6+PY5oLZ3vZhac5mnQjMf6f2TIjUN/wE1Lf4THavDCFLiv8xG62?= =?us-ascii?Q?L/UEYFU3QoxlSFEifAeAEGl5Vc5duKodtGyPSrDccN6AUV55Lc7ky8GW8BvN?= =?us-ascii?Q?riYJQwy1Ve4DE4PNUqUhXFdI68A5ztiuJDMc+Sa9MU5tYyFmvmVe1OeRuf9V?= =?us-ascii?Q?cUmUMsFlisW4VO59z2BeapV+3ZPaCz7sowQsY6eBY5lzPYr/wXBepUKSYOEY?= =?us-ascii?Q?6/sKzC7PyPidFxkrryXhUSNjbWepImRDT0D0Wymn5JScR/moVlxwi10V9a8O?= =?us-ascii?Q?p7kHWHsk7zeKeQ7SE3XS8agYiJdmAD8qKVzAKuaMkWifRZ84L0fsMMQexjq2?= =?us-ascii?Q?P6y2iiD8BmzE2VKA7JMb+PnwdyaBmaDshhbqf68B5nl8bE4CmLxqdCg/G7jg?= =?us-ascii?Q?0wPGvcaXs6zojTW9tRtiRHI3MzG/OzVdwku7IAQKrnswWC3yjkGYhJ9dbo2W?= =?us-ascii?Q?fcX8x7TR51jkfoUkW07oBDl/qjD9iV4SJRfTbeNK15eWB+26lKztHGzPt2tO?= =?us-ascii?Q?pCmMHwJpCWWENTH8WpVuvzqtPRRCzdLVPGfiIz/AbNWNiLv0pOkiBp9HPkQM?= =?us-ascii?Q?1+AG9rZ0QmjlvgYBrP90jZcqghfbWU5PbHUrK7ztGaOV+uSYDOW5hCETUNW/?= =?us-ascii?Q?1xsHwmOznrQntxJKOsKnzcBJMa6qNOO5X0BVKxd4Iip4qedyYCIJ2ps9Laa3?= =?us-ascii?Q?MIr4Vs+27b3VkOdrVpvjUjMMYVdePdtV/3LaeEKyoo4AYRg5Eafre1yS7h2y?= =?us-ascii?Q?GThhaTK8TJTQ24osSq9gNDpbIKXoz71TJloiKqM5yRigPgE9EdbDVeKnTMZ+?= =?us-ascii?Q?4P/juWahwPcMgHd/BO/WF/QlQ9BKosAVNICfRvDhlYvf8Smkbo/URtygrQPp?= =?us-ascii?Q?cG3zC7RhyrbOqxbj88=3D?= X-Microsoft-Exchange-Diagnostics: 1; BN6PR11MB1859; 6:tM0HRjVBuaGqZHn3OX1y/Ih4dr34r1I6SeJ0yRNOgw3QeOqgW7Nd+1dvBUWrwrKIxGEqKMwTjPBAX+1/En/ubE4b5QStZ7GdQWO0TKp1vWDjzoqHXPp4MFv4+Hw98mcqx1AMlKv5kXKUs1Fnza6FwxTyUqpK/eHfTSk/Yx31HgfyTTY1z7M38/+Tf75KkX4A4O1emQcUoqzB7HLhK4w/ZxALbfHkltXZGhiD6OeebMdtCrktv/+BiM2MAjEvYCMecbk02dssMN5tTHzY8rIYsPPjYFWu7B9C15Q6cIPzwfRXRPOrrnqjv35p/mLV9hrKBAJayuSildZ1GxvB5SgD4w==; 5:BZdnPtUL7r6rX1VR6P4bn6hbG2HUTL20+6krNY1KqYxvzEiVOTY1fLH8T8ZV/A/JCRx0jAgqLSdpL4fn5vdKIfbPSYU5DbNGamoLfRGNEWWunsxp3Nw+m8EbawjN7TiWkXENpcReOKbgJDm2lpFmlA==; 24:BlExpt8aYA8peiavDLM3pyaz2xORg4i2ts6C4kRPFnvVtefwjRk8F2IIsoKOnTJcRVVxdlI32znM5AL6uo5JlpEos+xgPcV0g5cOgOI+Nfk=; 7:Qyw4+8mq4beYxTkKNGedTnM48/QioY3wC19IDNq87ryatyEe4DKKcqbJdSJgUso2FtRHIxg+2av8FkfVaaQQ/tv43b9MEGcDIuFgtdRpkbj4XGy2DJahSWN6zYth26GIuO/s8fepbu2ed9f5lIYme5XHC8nzt+f9dpkFkN8KI8WemtW71LGqo+J9j4xL7bNfi+HiHBbORuB7OGFIscXNNZAfL8c5SdEYQKj0QGv+VEE= SpamDiagnosticOutput: 1:99 SpamDiagnosticMetadata: NSPM X-OriginatorOrg: maximintegrated.com X-MS-Exchange-CrossTenant-OriginalArrivalTime: 25 Sep 2017 19:14:39.8897 (UTC) X-MS-Exchange-CrossTenant-FromEntityHeader: Hosted X-MS-Exchange-CrossTenant-Id: fbd909df-ea69-4788-a554-f24b7854ad03 X-MS-Exchange-Transport-CrossTenantHeadersStamped: BN6PR11MB1859 To: unlisted-recipients:; (no To-header on input) 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 provides an iio device driver for DS4422/DS4424 chips that support two/four channel 7-bit Sink/Source Current DAC. Signed-off-by: Ismail H. Kose Signed-off-by: Ismail H. Kose --- v7: * Revised function exits and fixed error code v6: * Removed reference resistor parsing v5: * Removed unused variable v4: * Removed unnecessary code and space optimization * Alphabetic order in Kconfig and Makefile v3: * Removed iio-map and platform file support * Removed ds4424.h file * Fixed ADC value read bug * Removed confused comments * Added device tree binding file * Fixed bugs in probe and read function v2: * Fixed coding style and removed unncessary code * Removed min/max rfs, ifs-scale, etc values from device tree * Removed unused code, definitions and some comments * Removed regulator control and made standard structure * Removed data processing and channel scale * Removed device tree binding file drivers/iio/dac/Kconfig | 9 ++ drivers/iio/dac/Makefile | 1 + drivers/iio/dac/ds4424.c | 341 +++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 351 insertions(+) create mode 100644 drivers/iio/dac/ds4424.c diff --git a/drivers/iio/dac/Kconfig b/drivers/iio/dac/Kconfig index 25bed2d7d2b9..57c179830981 100644 --- a/drivers/iio/dac/Kconfig +++ b/drivers/iio/dac/Kconfig @@ -211,6 +211,15 @@ config AD8801 To compile this driver as a module choose M here: the module will be called ad8801. +config DS4424 + tristate "Maxim Integrated DS4422/DS4424 DAC driver" + depends on I2C + help + If you say yes here you get support for Maxim chips DS4422, DS4424. + + This driver can also be built as a module. If so, the module + will be called ds4424. + config DPOT_DAC tristate "DAC emulation using a DPOT" depends on OF diff --git a/drivers/iio/dac/Makefile b/drivers/iio/dac/Makefile index 603587cc2f07..abf5c3094454 100644 --- a/drivers/iio/dac/Makefile +++ b/drivers/iio/dac/Makefile @@ -22,6 +22,7 @@ obj-$(CONFIG_AD5686) += ad5686.o obj-$(CONFIG_AD7303) += ad7303.o obj-$(CONFIG_AD8801) += ad8801.o obj-$(CONFIG_CIO_DAC) += cio-dac.o +obj-$(CONFIG_DS4424) += ds4424.o obj-$(CONFIG_DPOT_DAC) += dpot-dac.o obj-$(CONFIG_LPC18XX_DAC) += lpc18xx_dac.o obj-$(CONFIG_LTC2632) += ltc2632.o diff --git a/drivers/iio/dac/ds4424.c b/drivers/iio/dac/ds4424.c new file mode 100644 index 000000000000..c94afd02da50 --- /dev/null +++ b/drivers/iio/dac/ds4424.c @@ -0,0 +1,341 @@ +/* + * Maxim Integrated + * 7-bit, Multi-Channel Sink/Source Current DAC Driver + * Copyright (C) 2017 Maxim Integrated + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define DS4422_MAX_DAC_CHANNELS 2 +#define DS4424_MAX_DAC_CHANNELS 4 + +#define DS4424_DAC_ADDR(chan) ((chan) + 0xf8) +#define DS4424_SOURCE_I 1 +#define DS4424_SINK_I 0 + +#define DS4424_CHANNEL(chan) { \ + .type = IIO_CURRENT, \ + .indexed = 1, \ + .output = 1, \ + .channel = chan, \ + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \ +} + +/* + * DS4424 DAC control register 8 bits + * [7] 0: to sink; 1: to source + * [6:0] steps to sink/source + * bit[7] looks like a sign bit, but the value of the register is + * not a two's complement code considering the bit[6:0] is a absolute + * distance from the zero point. + */ +union ds4424_raw_data { + struct { + u8 dx:7; + u8 source_bit:1; + }; + u8 bits; +}; + +enum ds4424_device_ids { + ID_DS4422, + ID_DS4424, +}; + +struct ds4424_data { + struct i2c_client *client; + struct mutex lock; + __maybe_unused uint8_t save[DS4424_MAX_DAC_CHANNELS]; + struct regulator *vcc_reg; + uint8_t raw[DS4424_MAX_DAC_CHANNELS]; +}; + +static const struct iio_chan_spec ds4424_channels[] = { + DS4424_CHANNEL(0), + DS4424_CHANNEL(1), + DS4424_CHANNEL(2), + DS4424_CHANNEL(3), +}; + +static int ds4424_get_value(struct iio_dev *indio_dev, + int *val, int channel) +{ + struct ds4424_data *data = iio_priv(indio_dev); + int ret; + + mutex_lock(&data->lock); + ret = i2c_smbus_read_byte_data(data->client, DS4424_DAC_ADDR(channel)); + if (ret < 0) + goto fail; + + *val = ret; + +fail: + mutex_unlock(&data->lock); + return ret; +} + +static int ds4424_set_value(struct iio_dev *indio_dev, + int val, struct iio_chan_spec const *chan) +{ + struct ds4424_data *data = iio_priv(indio_dev); + int ret; + + mutex_lock(&data->lock); + ret = i2c_smbus_write_byte_data(data->client, + DS4424_DAC_ADDR(chan->channel), val); + if (ret < 0) + goto fail; + + data->raw[chan->channel] = val; + +fail: + mutex_unlock(&data->lock); + return ret; +} + +static int ds4424_read_raw(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, + int *val, int *val2, long mask) +{ + union ds4424_raw_data raw; + int ret; + + switch (mask) { + case IIO_CHAN_INFO_RAW: + ret = ds4424_get_value(indio_dev, val, chan->channel); + if (ret < 0) { + pr_err("%s : ds4424_get_value returned %d\n", + __func__, ret); + return ret; + } + raw.bits = *val; + *val = raw.dx; + if (raw.source_bit == DS4424_SINK_I) + *val = -*val; + return IIO_VAL_INT; + + default: + return -EINVAL; + } +} + +static int ds4424_write_raw(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, + int val, int val2, long mask) +{ + union ds4424_raw_data raw; + + if (val2 != 0) + return -EINVAL; + + switch (mask) { + case IIO_CHAN_INFO_RAW: + if (val < S8_MIN || val > S8_MAX) + return -EINVAL; + + if (val > 0) { + raw.source_bit = DS4424_SOURCE_I; + raw.dx = val; + } else { + raw.source_bit = DS4424_SINK_I; + raw.dx = -val; + } + + return ds4424_set_value(indio_dev, raw.bits, chan); + + default: + return -EINVAL; + } +} + +static int ds4424_verify_chip(struct iio_dev *indio_dev) +{ + int ret, val; + + ret = ds4424_get_value(indio_dev, &val, DS4424_DAC_ADDR(0)); + if (ret < 0) + dev_err(&indio_dev->dev, + "%s failed. ret: %d\n", __func__, ret); + + return ret; +} + +static int __maybe_unused ds4424_suspend(struct device *dev) +{ + struct i2c_client *client = to_i2c_client(dev); + struct iio_dev *indio_dev = i2c_get_clientdata(client); + struct ds4424_data *data = iio_priv(indio_dev); + int ret = 0; + int i; + + for (i = 0; i < indio_dev->num_channels; i++) { + data->save[i] = data->raw[i]; + ret = ds4424_set_value(indio_dev, 0, + &indio_dev->channels[i]); + if (ret < 0) + return ret; + } + return ret; +} + +static int __maybe_unused ds4424_resume(struct device *dev) +{ + struct i2c_client *client = to_i2c_client(dev); + struct iio_dev *indio_dev = i2c_get_clientdata(client); + struct ds4424_data *data = iio_priv(indio_dev); + int ret = 0; + int i; + + for (i = 0; i < indio_dev->num_channels; i++) { + ret = ds4424_set_value(indio_dev, data->save[i], + &indio_dev->channels[i]); + if (ret < 0) + return ret; + } + return ret; +} + +static SIMPLE_DEV_PM_OPS(ds4424_pm_ops, ds4424_suspend, ds4424_resume); + +static const struct iio_info ds4424_info = { + .read_raw = ds4424_read_raw, + .write_raw = ds4424_write_raw, +}; + +static int ds4424_probe(struct i2c_client *client, + const struct i2c_device_id *id) +{ + struct ds4424_data *data; + struct iio_dev *indio_dev; + int ret; + + indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*data)); + if (!indio_dev) { + dev_err(&client->dev, "iio dev alloc failed.\n"); + return -ENOMEM; + } + + data = iio_priv(indio_dev); + i2c_set_clientdata(client, indio_dev); + data->client = client; + indio_dev->name = id->name; + indio_dev->dev.of_node = client->dev.of_node; + indio_dev->dev.parent = &client->dev; + + if (!client->dev.of_node) { + dev_err(&client->dev, + "Not found DT.\n"); + return -ENODEV; + } + + data->vcc_reg = devm_regulator_get(&client->dev, "vcc"); + if (IS_ERR(data->vcc_reg)) { + dev_err(&client->dev, + "Failed to get vcc-supply regulator. err: %ld\n", + PTR_ERR(data->vcc_reg)); + return PTR_ERR(data->vcc_reg); + } + + mutex_init(&data->lock); + ret = regulator_enable(data->vcc_reg); + if (ret < 0) { + dev_err(&client->dev, + "Unable to enable the regulator.\n"); + return ret; + } + + usleep_range(1000, 1200); + ret = ds4424_verify_chip(indio_dev); + if (ret < 0) + goto fail; + + switch (id->driver_data) { + case ID_DS4422: + indio_dev->num_channels = DS4422_MAX_DAC_CHANNELS; + break; + case ID_DS4424: + indio_dev->num_channels = DS4424_MAX_DAC_CHANNELS; + break; + default: + dev_err(&client->dev, + "ds4424: Invalid chip id.\n"); + ret = -ENXIO; + goto fail; + } + + indio_dev->channels = ds4424_channels; + indio_dev->modes = INDIO_DIRECT_MODE; + indio_dev->info = &ds4424_info; + + ret = iio_device_register(indio_dev); + if (ret < 0) { + dev_err(&client->dev, + "iio_device_register failed. ret: %d\n", ret); + goto fail; + } + + return ret; + +fail: + regulator_disable(data->vcc_reg); + return ret; +} + +static int ds4424_remove(struct i2c_client *client) +{ + struct iio_dev *indio_dev = i2c_get_clientdata(client); + struct ds4424_data *data = iio_priv(indio_dev); + + iio_device_unregister(indio_dev); + regulator_disable(data->vcc_reg); + + return 0; +} + +static const struct i2c_device_id ds4424_id[] = { + { "ds4422", ID_DS4422 }, + { "ds4424", ID_DS4424 }, + { } +}; + +MODULE_DEVICE_TABLE(i2c, ds4424_id); + +static const struct of_device_id ds4424_of_match[] = { + { .compatible = "maxim,ds4422" }, + { .compatible = "maxim,ds4424" }, + { }, +}; + +MODULE_DEVICE_TABLE(of, ds4424_of_match); + +static struct i2c_driver ds4424_driver = { + .driver = { + .name = "ds4424", + .of_match_table = ds4424_of_match, + .pm = &ds4424_pm_ops, + }, + .probe = ds4424_probe, + .remove = ds4424_remove, + .id_table = ds4424_id, +}; +module_i2c_driver(ds4424_driver); + +MODULE_DESCRIPTION("Maxim DS4424 DAC Driver"); +MODULE_AUTHOR("Ismail H. Kose "); +MODULE_AUTHOR("Vishal Sood "); +MODULE_AUTHOR("David Jung "); +MODULE_LICENSE("GPL v2");