Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1751935AbdC0HXC (ORCPT ); Mon, 27 Mar 2017 03:23:02 -0400 Received: from mail-bl2nam02on0085.outbound.protection.outlook.com ([104.47.38.85]:53205 "EHLO NAM02-BL2-obe.outbound.protection.outlook.com" rhost-flags-OK-OK-OK-FAIL) by vger.kernel.org with ESMTP id S1751457AbdC0HWz (ORCPT ); Mon, 27 Mar 2017 03:22:55 -0400 Authentication-Results: spf=pass (sender IP is 137.71.25.55) smtp.mailfrom=analog.com; vger.kernel.org; dkim=none (message not signed) header.d=none;vger.kernel.org; dmarc=bestguesspass action=none header.from=analog.com; From: To: , , , , , CC: , , , Michael Hennerich Subject: [PATCH v2] iio:adc: Driver for Linear Technology LTC2497 ADC Date: Mon, 27 Mar 2017 09:23:53 +0200 Message-ID: <1490599433-6103-1-git-send-email-michael.hennerich@analog.com> X-Mailer: git-send-email 2.7.4 MIME-Version: 1.0 Content-Type: text/plain X-EOPAttributedMessage: 0 X-MS-Office365-Filtering-HT: Tenant X-Forefront-Antispam-Report: CIP:137.71.25.55;IPV:NLI;CTRY:US;EFV:NLI;SFV:NSPM;SFS:(10009020)(6009001)(39860400002)(39840400002)(39450400003)(39410400002)(2980300002)(438002)(199003)(189002)(48376002)(77096006)(2876002)(50466002)(5660300001)(106466001)(5003940100001)(47776003)(356003)(966004)(107886003)(8666007)(4326008)(305945005)(38730400002)(6306002)(7636002)(86152003)(2906002)(54906002)(50986999)(50226002)(36756003)(2201001)(86362001)(6666003)(8936002)(8676002)(189998001)(33646002)(1720100001)(562404015);DIR:OUT;SFP:1101;SCL:1;SRVR:SN1PR0301MB1552;H:nwd2mta1.analog.com;FPR:;SPF:Pass;MLV:sfv;A:1;MX:1;LANG:en; X-Microsoft-Exchange-Diagnostics: 1;BY2FFO11FD032;1:HGsSW72QOyTIRUf3X+pmDGED8/UdcCTalYb9nOnNHM9lliupxd9C8NV2RR8I6TJ4KbFKZTTPZeynF+eofhksEVRK2eS6LdYTzzDyL4tUUOY2/y9NpzUXYqoziquxh5VTDVyjFL1sGcoyPlNS4r5el5sVHUTOFranaSxhGNsJwA2eXlssV0IdAiuHg4AWcT+5NZpMSd6Ur1n1w3doHreENJ6hqWw7ZZizMCXMuebEoFePfSrs4hQ0wZVCa820B2PwLwB/dK1Lvu/lNLYatAzhfFV54Qd+1KLsu1RUtdr/+YfB79X05DlCUUoM6/HP0R8fzxBTiV7xekpFX2wByxHkY5TtQe7h7p9rDhUpi82PzboIiatKs1wcVgwhexUgxQbZeE8zoI97ZG02LHzoomGWyfvB7Xa0jjlBF+YoIqmSekAv9QUmv9Wf5c0yUe+6SX0+VyrxeaOVhnVoiK2okogtrBowe+Nbq215YyeglxLKmIWa85rc+vi5BNhfkMTl1COBanD+FqmI6itHYC0mcTsNpQfye3IKLeFxi0KtMtdQm9RrNhZfNtTMzjsJ7GoSCOcDemXFrQmYqOaQLhHssw/vjyi2s0V82WuQ+E89V4hvzVM9XFa0fkvKXg0EFShrAib6 X-MS-Office365-Filtering-Correlation-Id: 4974c823-ef71-432b-f699-08d474e20b52 X-Microsoft-Antispam: UriScan:;BCL:0;PCL:0;RULEID:(22001)(8251501002)(2017030254075);SRVR:SN1PR0301MB1552; X-Microsoft-Exchange-Diagnostics: 1;SN1PR0301MB1552;3:uKp0ovaZbiGrzmcrcAqmbKUW1g6Vvt4WjyO++gRdEzMBNNndg7Y3KLFDi62rB8rgpL/sZ6JvMigUNCw5O4jUghc1IsaopIxn4Puqck9vWVZ0GI+pM8eu1mf+v22tJAUMtD5cg1bA1O5EsnuYHYJoyAA0HXtP8tzvwQKt7xH0cP+fnfGpAvSYB2YLX98Ah4XDOvswMig0kyu9yltw5ibvtrOPqgq4FqvzbgRHCQ5LoDrcoiJku8iKfwyGUD1iiyf3fd7irEx8U2tuk8NCbmwD1I8LmpLQDq1hIewCBR8k7sCzADQiYrbGrRaBprzwb7/6FYnEml2WCE/Lh6jUyOEPsECLKOFPQaHhz+hDkWAsvdd3RnJk/LRxYWIb/rPRgb+zB7Sa0IN3o9Vs+oMVGcC/t+VO4YavkmRtO+qH7E54A78=;25:9n9U+b8C9Ccq6gJQviBK9z/lGtGV3BAhc6p02bfcT+2a2lIzsuLEHIiMftlpz0tZCfaeB3yVSY6KuGoTw7GP3YJYTT7Eu3IRh/DwV+bnQEXDa1rIvNSqKgPa79MVz9KmzGqXWQ00srNTUOr3lRCskzy1vlMJVPmCO5O/6wLabbphjitBDeDxMEW/V4xj44+DUlf1EvLTHaEjObSM5fh5gE6uaISTVIHNppodg/5T/RFfJ+1612Jmrq0nZBNAjF2MOslo8u6XWLZpVRPV+Gz7tVj37mOTHJWRA7SPcXsYnJmvpk8w5feU0oosUyqk8Qd+VX4ItLnt4Un/594H+rJckDutNNwRnxGNRpF5C1b4bdUn65G9Umi5yXGQMJpKat4eXy6LJVTbAjhP55xwORTfF3e57u44BtIbbyat9kXwA7hOD65ftqxE+IzKK7eLCXcZK9bCn4FMQ9owq+FAvyvmZw== X-Microsoft-Exchange-Diagnostics: 1;SN1PR0301MB1552;31:BN0FzAhggMidyGVjp5affKivZdXtSX6/MmKY0ovlvg8rQ87v75ce0OuEWiN4ec94tigXoIowSBhB7RotWrhmnAWhoIAoH2cD+QHc3vxw+OnDTTLRE/jngrX9Z4uduAQ8ALaqfdvdI0lHur+d07cqPQcWuOi1cEoD+arGybN8yGmlbFGP3qdf9TD2ZT6LpBOoPFndnAx5orhOHOP6PM2BFrQkIHOVLyBpJa6Ge6+avh2Ib5af58XwuZzmL3Pi+5dWWiKiMotjdcXLYv8wa32CsKrjkw0EtDvyFkns7CowPLc=;20:skaM9pCrFjd+Ba1YcB44uXi4/wTpw52AHTKYfHFdQAJBFTx4FymTy1gDZmmO2YtYe9sq/Pkcz8eFQSJ2t1uKRgeHqZHBtZYJmCLKkF04t9qYAEaz+K0U1YO+Ru5Io9kxaaKf1grhzGMaf9LeeXfUd/zVUz/hIGRWDLNkBb4ZYzmA30hN2MbtDqDuBlAhhpXoyfs7kaDLolcGMiZAfQYlBVp6Jc+yZwCcilRT6njApubbb9h5ylZm7zGhafjh7rztmqMcX8SupOLCGSloZtUeIrEll7uHxEiko3ctl020z/lAV06CcgDCvmWn1sQhcaeCwkfiYrTe/hhtqc5s1ByA+fc1wwoB2h+v2xNUx5jPi5Qwv6hyGM+FGzAcKbyAmf/gIOxY0vAOFqTYLdGbOTyZDllniICruYWiaaYIIlZ5DqqEK3Rt/SR6tnpIuqIgzO5N2eOBQNIJ3B1q2kApC7GnGB4DdFyco3Vr9qCgpux5bKE0uKruIOpZGRVBwavzLsvb X-Microsoft-Antispam-PRVS: X-Exchange-Antispam-Report-Test: UriScan:(232431446821674)(170811661138872); X-Exchange-Antispam-Report-CFA-Test: BCL:0;PCL:0;RULEID:(6040375)(601004)(2401047)(5005006)(13023025)(13017025)(13015025)(8121501046)(13018025)(13024025)(10201501046)(3002001)(6055026)(6041248)(20161123558025)(20161123562025)(20161123564025)(20161123555025)(20161123560025)(6072148);SRVR:SN1PR0301MB1552;BCL:0;PCL:0;RULEID:;SRVR:SN1PR0301MB1552; X-Microsoft-Exchange-Diagnostics: 1;SN1PR0301MB1552;4:+jt/i4y4n/qxG27eQY6Enw3H+F161evsmtzpSufigIcmzQggI2AoMEDiQWjzbxIKLbYOqoFW61tJ7LiFW609Sl1FU244VTgzMSdRrx11QXSTb8uADZp4juow/gO2ILLvhxFhWH5mRpT+mb1Xe54AIKFxO3q4U4MnKDwOE/GOG8K5StzmVYQ0eADyNe6IceC2dtx8n7eNMJNP4dsAKVMsqo1k4VQH9CSi69Nhg9H/cC0lcLQ55Z5+VRdbesnDKuSvkiMHDDPt4unMswzWj5zIZ4Dm8F9UY7aVA5d9wqgAUJFGg7AHGSqXBtFF/9vhxBM0B27AOZtgYY35n3O/43nWczzvIoIXOFc1jKCI2UCe+/xnC9BeYPpLuT6rxtbicPEpGayk6M1M1+fdJGD4Sgucr5Jf1NfCXRLevz0k8gvwXxEwGQDIWIuL35dzGtCVwn6iD5CoMEhn6YHJrj9m9vxgROPmcV8uFRvuBm21euQEG7iJmtTKotGn16q4SHmP6ZYrq21kfPB09kkSbo17D3U8KERjUxtWLsGBxcL7pY/nWpw2uZ9FeDM/KaNjB4qqz3ZAjfEfHVA7Mk7n6RKkcwrEAAP07u6//GUyeuzMZxFLJiV5mZV5jRaluzklh3DtcMe1uptn1+F1PmfErxlc8h7lEQRvGvW+63CoUEZvIZb1Drt6lhY3jYVQ0i2lAB+lv9EcqIK4F07tjfPUcMZzAIQ3JM7E4gr2uCp9zrn8cxsO1Kb8jlDFWYSvaMMCNKgXNHzJyKzQoTP3193pnqacTTt11eVraR5TFauLy+GAX6aTqSg= X-Forefront-PRVS: 02596AB7DA X-Microsoft-Exchange-Diagnostics: =?us-ascii?Q?1;SN1PR0301MB1552;23:UQSCiR6G32j3f+7NM8YIlsuVw3nBWI6G1jZbW8A?= =?us-ascii?Q?u/w3UaCbphboHMcH4fRfIrxqFdlP28q8vAIh7B8YwA0TEUtIOCqVyPnKo/Ff?= =?us-ascii?Q?DcDHTm/pVMw9XoNdnd3puo7Q+vBo9DdJunOZnQS/JpcVHCy0yNdcMpIeMC1I?= =?us-ascii?Q?WqxTN6sSlGmPgA2diBoTwei/yCllCL5D8Hfs56gZ0YZidMc57+xbOT0+y4La?= =?us-ascii?Q?BC52zg4EJaFJ/lw8pSpuhHTQVk64goDkKc61ElNzi/ly10UrnCe0AWEMG8kL?= =?us-ascii?Q?r2efvomUfv124lX8LFNYbC1moh+Y5Hg/vOr2FTs+50XwSXbSnKPJ/VsMpjwS?= =?us-ascii?Q?GAfA7cPZJLpqu9wr2Hs13fU7120m7AWoDkxJpgdp7bB7bU+O6HGFgieE6eX1?= =?us-ascii?Q?HSc1lZOleI+S1RSKQRFu49tjmAc3cXqcDKHKXoogR4FTT2dWPeF2A7nfnm6y?= =?us-ascii?Q?bryqqM8RLi0BV8VmwEcpIvLdgdLeu7QeTehqcVoJdrF/5BT7ht3jQOqLG9Kb?= =?us-ascii?Q?M7+LOmk2/oqB+Nl1xDBLiJj3qtlfUmk18FuQFrhvBfnSfd/TFwdfPNOhCA13?= =?us-ascii?Q?T1/+vpLcNs4+i4Ney/FPj195ieMTNjayuwaC4Ml0FBBlSx5u6TDwYQ8r5kdp?= =?us-ascii?Q?oBUhWKed/IeHzxE6K1Vtf1kldpDLzUNpj9gxMgTI6vYTiHua9Qpx5lIv1kdr?= =?us-ascii?Q?yAsQqYxwkwKm4do0M4OPcVSZrsWSUraIRIGpWWPHnNsKp8T10FkkPDnqLeE5?= =?us-ascii?Q?SZBkqeJKrxeG64Lmju8lavhxjTmEvT2Pm2w4/urc15DFtu05Glvarh6iHw9P?= =?us-ascii?Q?UbRHlAB3ONMgY8D++oOLmE1Z5SdLIMnlCWFOFc27cqQsEmk1jZLglDgHgQ3K?= =?us-ascii?Q?+oWsWPW19+jwS6vSSQP0GfZFN6SDmkWLAjML0WAsGyhhRqagZSA5o7Ps6gzo?= =?us-ascii?Q?xNUxKx53mOtjiWdTfW8LmPmiK6zYsV8Kt10JIKtQ9xvbiT5Cy3tr6djpdoCf?= =?us-ascii?Q?pXkRezC5rZRT5KH9LG8LfhRvb?= X-Microsoft-Exchange-Diagnostics: 1;SN1PR0301MB1552;6:YNe9E3NWZ/usn/i6keF8dG4bfUAm1bfgkigzSxj+bqo7dI2iS9IkRS/rLTDNsaI3BEL0N24IYJIvHLUOukBdrJg4BFIa4nj4B3q4P3G5hl0ymbWlne/9pjxc1VY+MvjoEVhwJqqk3LUPYk2D7ukq2NTq/w/Sy7zVEUq50idzv4UTK29eZHDCVmkND/wj4MmNpDFFQwAhgE7aUdZJs87Uf8wn6Ag7ofQfzvDlAtu393fRPWYcwFLOmWkuOVdmgN5OHyB+fGveLV0qVc5QDlo45+ykSbU6HcYENqs721uo02TKwL7RcK1IWYMJinoOzfmrKDjoBUQ34fdagD2SO4MJyj7F5aoKik3QEJLNgCbkoBHITLTFjnJkpRNZ/wlOm6I/VZj57KSTbDr4z1ELw0OdNxf8CRAwqXQPRwMSGapAz4Y=;5:Zp1BhcbbkSYWGvkarCKciMV+GJdqcXxh5aF8jjxIkqOFiWkYxS+EgV7xXBIRFoq2A9IYOVuDw6VGOGRFsD5AcBhjJGNSuY4Qh3KCgjtSA5Rkq1suWS9YjbHOnnQdtl3YW+tiodwM43JytxgqaPILAA==;24:8QtgLFXBbxWP2Z44LWEmSxt/G6Bx8kvgjB2oheYNxDnrCfi+cd0r+z+Lq/yCuu1bG/L8PTL4BB1zQjpEAGnleUXsZEEpdEMOhbKSDIi+qsI= SpamDiagnosticOutput: 1:99 SpamDiagnosticMetadata: NSPM X-Microsoft-Exchange-Diagnostics: 1;SN1PR0301MB1552;7:MVuO/WpyAX1rzPFR79AFDQPVUYweUpdPKPpWow3Hy0kuyULEou1ioJ4AhL978z5K/zIGijjaec+S9FZ3kVlkdkYqRuejMcZBpRnFsBOdnLhp8fr9zKppRLsGzZ2G0XJBBDHMSQFMHJGppccJReHvEYV8LpE81YhM9Xmmsx0Q6U4jhdw/NC6zLvqlf5SkmBb0jfr7g3lvuPqzQVRqPZ+Bi0vtVO6PgLlMYv7VQUV9OE/OKSBs3vGn3onp/AWadTAW6eNs2k/v8VCQzr6WAO5c1+clk11ZPuD+u3j9r0NcTU24mOcdLhexLz4LxOt0BjydJbQ8czt3nib4lKV3IJt8OQ== X-OriginatorOrg: analog.com X-MS-Exchange-CrossTenant-OriginalArrivalTime: 27 Mar 2017 07:22:36.4535 (UTC) X-MS-Exchange-CrossTenant-Id: eaa689b4-8f87-40e0-9c6f-7228de4d754a X-MS-Exchange-CrossTenant-OriginalAttributedTenantConnectingIp: TenantId=eaa689b4-8f87-40e0-9c6f-7228de4d754a;Ip=[137.71.25.55];Helo=[nwd2mta1.analog.com] X-MS-Exchange-CrossTenant-FromEntityHeader: HybridOnPrem X-MS-Exchange-Transport-CrossTenantHeadersStamped: SN1PR0301MB1552 Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Length: 10322 Lines: 369 From: Michael Hennerich This patch adds support for the Analog Devices / Linear Technology LTC2497 ADCs. The LTC2497 is a 16-channel (eight differential), 16-bit, high precision, delta-sigma ADC with an automatic, differential, input current cancellation front end and a 2-wire, I2C interface. Signed-off-by: Michael Hennerich --- Changes since v1: - remove confusing kconfig help text - use proper defines - add descriptive comment - fix removal order - add poper commit mssage --- .../devicetree/bindings/iio/adc/ltc2497.txt | 13 + MAINTAINERS | 1 + drivers/iio/adc/Kconfig | 10 + drivers/iio/adc/Makefile | 1 + drivers/iio/adc/ltc2497.c | 269 +++++++++++++++++++++ 5 files changed, 294 insertions(+) create mode 100644 Documentation/devicetree/bindings/iio/adc/ltc2497.txt create mode 100644 drivers/iio/adc/ltc2497.c diff --git a/Documentation/devicetree/bindings/iio/adc/ltc2497.txt b/Documentation/devicetree/bindings/iio/adc/ltc2497.txt new file mode 100644 index 0000000..c2829c19 --- /dev/null +++ b/Documentation/devicetree/bindings/iio/adc/ltc2497.txt @@ -0,0 +1,13 @@ +* Linear Technology / Analog Devices LTC2497 ADC + +Required properties: + - compatible: Should be "lltc,ltc2497" + - reg: Should contain the ADC I2C address + - vref-supply: The regulator supply for ADC reference voltage + +Example: + ltc2497: adc@76 { + compatible = "lltc,ltc2497"; + reg = <0x76>; + vref-supply = <<c2497_reg>; + }; diff --git a/MAINTAINERS b/MAINTAINERS index a7d6f9a..173043c 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -813,6 +813,7 @@ W: http://wiki.analog.com/ W: http://ez.analog.com/community/linux-device-drivers S: Supported F: drivers/iio/*/ad* +F: drivers/iio/adc/ltc2497* X: drivers/iio/*/adjd* F: drivers/staging/iio/*/ad* F: drivers/staging/iio/trigger/iio-trig-bfin-timer.c diff --git a/drivers/iio/adc/Kconfig b/drivers/iio/adc/Kconfig index 2268a6f..acc115b 100644 --- a/drivers/iio/adc/Kconfig +++ b/drivers/iio/adc/Kconfig @@ -326,6 +326,16 @@ config LTC2485 To compile this driver as a module, choose M here: the module will be called ltc2485. +config LTC2497 + tristate "Linear Technology LTC2497 ADC driver" + depends on I2C + help + Say yes here to build support for Linear Technology LTC2497 + 16-Bit 8-/16-Channel Delta Sigma ADC. + + To compile this driver as a module, choose M here: the module will be + called ltc2497. + config MAX1027 tristate "Maxim max1027 ADC driver" depends on SPI diff --git a/drivers/iio/adc/Makefile b/drivers/iio/adc/Makefile index 73dbe39..9d626b5 100644 --- a/drivers/iio/adc/Makefile +++ b/drivers/iio/adc/Makefile @@ -32,6 +32,7 @@ obj-$(CONFIG_LP8788_ADC) += lp8788_adc.o obj-$(CONFIG_LPC18XX_ADC) += lpc18xx_adc.o obj-$(CONFIG_LPC32XX_ADC) += lpc32xx_adc.o obj-$(CONFIG_LTC2485) += ltc2485.o +obj-$(CONFIG_LTC2497) += ltc2497.o obj-$(CONFIG_MAX1027) += max1027.o obj-$(CONFIG_MAX11100) += max11100.o obj-$(CONFIG_MAX1363) += max1363.o diff --git a/drivers/iio/adc/ltc2497.c b/drivers/iio/adc/ltc2497.c new file mode 100644 index 0000000..7907534 --- /dev/null +++ b/drivers/iio/adc/ltc2497.c @@ -0,0 +1,269 @@ +/* + * ltc2497.c - Driver for Linear Technology LTC2497 ADC + * + * Copyright (C) 2017 Analog Devices Inc. + * + * Licensed under the GPL-2. + * + * Datasheet: http://cds.linear.com/docs/en/datasheet/2497fd.pdf + */ + +#include +#include +#include +#include +#include + +#include +#include + +#define LTC2497_ENABLE 0xA0 +#define LTC2497_SGL (1 << 4) +#define LTC2497_DIFF (0 << 4) +#define LTC2497_SIGN (1 << 3) +#define LTC2497_CONFIG_DEFAULT LTC2497_ENABLE +#define LTC2497_CONVERSION_TIME_MS 150ULL + +struct ltc2497_st { + struct i2c_client *client; + struct regulator *ref; + ktime_t time_prev; + u8 addr_prev; +}; + +static int ltc2497_wait_conv(struct ltc2497_st *st) +{ + s64 time_elapsed; + + time_elapsed = ktime_ms_delta(ktime_get(), st->time_prev); + + if (time_elapsed < LTC2497_CONVERSION_TIME_MS) { + /* delay if conversion time not passed + * since last read or write + */ + msleep(LTC2497_CONVERSION_TIME_MS - time_elapsed); + return 0; + } + + if (time_elapsed - LTC2497_CONVERSION_TIME_MS <= 0) { + /* We're in automatic mode - + * so the last reading is stil not outdated + */ + return 0; + } + + return -ETIMEDOUT; +} + +static int ltc2497_read(struct ltc2497_st *st, u8 address, int *val) +{ + struct i2c_client *client = st->client; + __be32 buf = 0; + int ret; + + ret = ltc2497_wait_conv(st); + if (ret < 0 || st->addr_prev != address) { + ret = i2c_smbus_write_byte(st->client, + LTC2497_ENABLE | address); + if (ret < 0) + return ret; + st->addr_prev = address; + msleep(LTC2497_CONVERSION_TIME_MS); + } + ret = i2c_master_recv(client, (char *)&buf, 3); + if (ret < 0) { + dev_err(&client->dev, "i2c_master_recv failed\n"); + return ret; + } + st->time_prev = ktime_get(); + + /* convert and shift the result, + * and finally convert from offset binary to signed integer + */ + *val = (be32_to_cpu(buf) >> 14) - (1 << 17); + + return ret; +} + +static int ltc2497_read_raw(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, + int *val, int *val2, long mask) +{ + struct ltc2497_st *st = iio_priv(indio_dev); + int ret; + + switch (mask) { + case IIO_CHAN_INFO_RAW: + mutex_lock(&indio_dev->mlock); + ret = ltc2497_read(st, chan->address, val); + mutex_unlock(&indio_dev->mlock); + if (ret < 0) + return ret; + + return IIO_VAL_INT; + + case IIO_CHAN_INFO_SCALE: + ret = regulator_get_voltage(st->ref); + if (ret < 0) + return ret; + + *val = ret / 1000; + *val2 = 17; + + return IIO_VAL_FRACTIONAL_LOG2; + + default: + return -EINVAL; + } +} + +#define LTC2497_CHAN(_chan, _addr) { \ + .type = IIO_VOLTAGE, \ + .indexed = 1, \ + .channel = (_chan), \ + .address = (_addr | (_chan / 2) | ((_chan & 1) ? LTC2497_SIGN : 0)), \ + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \ + .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), \ +} + +#define LTC2497_CHAN_DIFF(_chan, _addr) { \ + .type = IIO_VOLTAGE, \ + .indexed = 1, \ + .channel = (_chan) * 2 + ((_addr) & LTC2497_SIGN ? 1 : 0), \ + .channel2 = (_chan) * 2 + ((_addr) & LTC2497_SIGN ? 0 : 1),\ + .address = (_addr | _chan), \ + .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \ + .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), \ + .differential = 1, \ +} + +static const struct iio_chan_spec ltc2497_channel[] = { + LTC2497_CHAN(0, LTC2497_SGL), + LTC2497_CHAN(1, LTC2497_SGL), + LTC2497_CHAN(2, LTC2497_SGL), + LTC2497_CHAN(3, LTC2497_SGL), + LTC2497_CHAN(4, LTC2497_SGL), + LTC2497_CHAN(5, LTC2497_SGL), + LTC2497_CHAN(6, LTC2497_SGL), + LTC2497_CHAN(7, LTC2497_SGL), + LTC2497_CHAN(8, LTC2497_SGL), + LTC2497_CHAN(9, LTC2497_SGL), + LTC2497_CHAN(10, LTC2497_SGL), + LTC2497_CHAN(11, LTC2497_SGL), + LTC2497_CHAN(12, LTC2497_SGL), + LTC2497_CHAN(13, LTC2497_SGL), + LTC2497_CHAN(14, LTC2497_SGL), + LTC2497_CHAN(15, LTC2497_SGL), + LTC2497_CHAN_DIFF(0, LTC2497_DIFF), + LTC2497_CHAN_DIFF(1, LTC2497_DIFF), + LTC2497_CHAN_DIFF(2, LTC2497_DIFF), + LTC2497_CHAN_DIFF(3, LTC2497_DIFF), + LTC2497_CHAN_DIFF(4, LTC2497_DIFF), + LTC2497_CHAN_DIFF(5, LTC2497_DIFF), + LTC2497_CHAN_DIFF(6, LTC2497_DIFF), + LTC2497_CHAN_DIFF(7, LTC2497_DIFF), + LTC2497_CHAN_DIFF(0, LTC2497_DIFF | LTC2497_SIGN), + LTC2497_CHAN_DIFF(1, LTC2497_DIFF | LTC2497_SIGN), + LTC2497_CHAN_DIFF(2, LTC2497_DIFF | LTC2497_SIGN), + LTC2497_CHAN_DIFF(3, LTC2497_DIFF | LTC2497_SIGN), + LTC2497_CHAN_DIFF(4, LTC2497_DIFF | LTC2497_SIGN), + LTC2497_CHAN_DIFF(5, LTC2497_DIFF | LTC2497_SIGN), + LTC2497_CHAN_DIFF(6, LTC2497_DIFF | LTC2497_SIGN), + LTC2497_CHAN_DIFF(7, LTC2497_DIFF | LTC2497_SIGN), +}; + +static const struct iio_info ltc2497_info = { + .read_raw = ltc2497_read_raw, + .driver_module = THIS_MODULE, +}; + +static int ltc2497_probe(struct i2c_client *client, + const struct i2c_device_id *id) +{ + struct iio_dev *indio_dev; + struct ltc2497_st *st; + int ret; + + if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C | + I2C_FUNC_SMBUS_WRITE_BYTE)) + return -EOPNOTSUPP; + + indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*st)); + if (!indio_dev) + return -ENOMEM; + + st = iio_priv(indio_dev); + i2c_set_clientdata(client, indio_dev); + st->client = client; + + indio_dev->dev.parent = &client->dev; + indio_dev->name = id->name; + indio_dev->info = <c2497_info; + indio_dev->modes = INDIO_DIRECT_MODE; + indio_dev->channels = ltc2497_channel; + indio_dev->num_channels = ARRAY_SIZE(ltc2497_channel); + + st->ref = devm_regulator_get(&client->dev, "vref"); + if (IS_ERR(st->ref)) + return PTR_ERR(st->ref); + + ret = regulator_enable(st->ref); + if (ret < 0) + return ret; + + ret = i2c_smbus_write_byte(st->client, LTC2497_CONFIG_DEFAULT); + if (ret < 0) + goto err_regulator_disable; + + st->addr_prev = LTC2497_CONFIG_DEFAULT; + st->time_prev = ktime_get(); + + ret = iio_device_register(indio_dev); + if (ret < 0) + goto err_regulator_disable; + + return 0; + +err_regulator_disable: + regulator_disable(st->ref); + + return ret; +} + +static int ltc2497_remove(struct i2c_client *client) +{ + struct iio_dev *indio_dev = i2c_get_clientdata(client); + struct ltc2497_st *st = iio_priv(indio_dev); + + iio_device_unregister(indio_dev); + regulator_disable(st->ref); + + return 0; +} + +static const struct i2c_device_id ltc2497_id[] = { + { "ltc2497", 0 }, + { } +}; +MODULE_DEVICE_TABLE(i2c, ltc2497_id); + +static const struct of_device_id ltc2497_of_match[] = { + { .compatible = "lltc,ltc2497", }, + {}, +}; +MODULE_DEVICE_TABLE(of, ltc2497_of_match); + +static struct i2c_driver ltc2497_driver = { + .driver = { + .name = "ltc2497", + .of_match_table = of_match_ptr(ltc2497_of_match), + }, + .probe = ltc2497_probe, + .remove = ltc2497_remove, + .id_table = ltc2497_id, +}; +module_i2c_driver(ltc2497_driver); + +MODULE_AUTHOR("Michael Hennerich "); +MODULE_DESCRIPTION("Linear Technology LTC2497 ADC driver"); +MODULE_LICENSE("GPL v2"); -- 2.7.4