From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1753346AbdARQEv (ORCPT ); Wed, 18 Jan 2017 11:04:51 -0500 Received: from mail-db5eur01on0092.outbound.protection.outlook.com ([104.47.2.92]:7097 "EHLO EUR01-DB5-obe.outbound.protection.outlook.com" rhost-flags-OK-OK-OK-FAIL) by vger.kernel.org with ESMTP id S1753038AbdARQDp (ORCPT ); Wed, 18 Jan 2017 11:03:45 -0500 Authentication-Results: spf=none (sender IP is ) smtp.mailfrom=peda@axentia.se; From: Peter Rosin To: CC: Peter Rosin , Wolfram Sang , Rob Herring , Mark Rutland , Jonathan Cameron , Hartmut Knaack , Lars-Peter Clausen , Peter Meerwald-Stadler , Jonathan Corbet , Andrew Morton , , , , Subject: [PATCH v8 10/12] mux: adg792a: add mux controller driver for ADG792A/G Date: Wed, 18 Jan 2017 16:57:13 +0100 Message-ID: <1484755035-25927-11-git-send-email-peda@axentia.se> X-Mailer: git-send-email 2.1.4 In-Reply-To: <1484755035-25927-1-git-send-email-peda@axentia.se> References: <1484755035-25927-1-git-send-email-peda@axentia.se> MIME-Version: 1.0 Content-Type: text/plain X-Originating-IP: [217.210.101.82] X-ClientProxiedBy: HE1PR0801CA0032.eurprd08.prod.outlook.com (10.167.184.42) To VI1PR0202MB2558.eurprd02.prod.outlook.com (10.173.79.137) X-MS-Office365-Filtering-Correlation-Id: 00f347fa-16a6-4b9b-2d66-08d43fbae708 X-Microsoft-Antispam: UriScan:;BCL:0;PCL:0;RULEID:(22001);SRVR:VI1PR0202MB2558; X-Microsoft-Exchange-Diagnostics: 1;VI1PR0202MB2558;3:GeDq3lRJVL4ZDjZjBcwvgxEslAvev78NeaHTRWJW/SkqC2KLwjhXwTFA0yS6X45GV5zFY5okPKOP755MCJNtNHQQok18PEqIwWTpWNkNwQKUx68QyuZF3CHhadpmvX3TvuxS/T92JNpXZWHB2mo8isdTGe+9kcNle2X8BxnfBO9XlTtsQChqHiUOe6CIrYBRXOTck9W6NbRKa9ZRt4JjfvjmwVWk+ksyibVwbWGpPJmaqPx2D4rU4YVoKeMgjmzb5lDuwnDDwccoMXhRMb0KJA== X-Microsoft-Exchange-Diagnostics: 1;VI1PR0202MB2558;25:275IsOQuR+jQrlyWSGq1AgbL5Mn1kHPQ511nWx2bHuxGqUpfYrtviPGFLkCyUVA8KRYGuz/QBSwJ5ob7mPYoDKWCKqbwLBR3ZgVOSaNKJFE2x/PygqCyerEW/edQQ8/w6akqiaVK51vi8vYIOaQbrFX83d2H74q5eirfI35wSzeIGHO0sUES7OxlEotijcJvcT/UzkAsdr7BCrtfvnhGhYtCt68tCheWwT7zXCWNJYG8OzfpoqR5mlW/XsuSOndYo+B6nXSXjuvtlvPuTDRwEOK0zXMzhMDsv6zeVIH9Z1e9LlBMxGaQsi+4USGjd0TOvd50Ffzgz0vebXk/JUOarz18hk1YQOQ/6FohbJVoCSdp7+tcJJ0Ny8zk6iqF5amo88YQFQNNoWyEQVKahAaqe163MoBJ2hyoBttd2OUXFwVi1wy5RDGeg++JKG7i1eTzWi358QjJw5ZDRXyLvLpVJimt6gF09foQLYJkSNH+6KPQ1GxaikIBAbliIPPZF4CO12OLZfRD6pZFinA1dXvtxWcDUpDcAT9YoVOjKCNaz2wz8iMkOZrVugOg4sEx04M821UuZhvnJ3V1OOvm7tg1m5GGKN2crr8eiiBXWIGlsPfnf7Lj9Muzu2u4eum9VHIP+IKeQJQcNO6WHv/Ztj3Cwem4COFpqA97LeFWamrjszowtSRxQZeniSUWKQvkG5bYwXRjBJbgxEU61fnTpgVTeqXwNnTkPK+xr14GtkKNNZtUseLNFXbzfJD84wmAaSRW X-Microsoft-Exchange-Diagnostics: 1;VI1PR0202MB2558;31:RJysr2KLlg+zQP+HHWAQ8jDXBC9QXLk42N/Wr1Y8BPWJIgeKjPXkXXOnj7Twq3+8NuCNBNii9kNXcV/WDzFVe8dCN9tOb9siF93PRm8iITETUlOtuml79FvwT+pOdfKhK6z11Dk/t/62ZUis3uQVwaZ0FSp5ZCUD6qDVoS+dPvo9fwvKvNLfYVLZ/Ix78LpjKN2MTklksrUxhm4nrXTNjpNkIC/dJ0uXFyCGsqL1njpHz1KysyAxLBC/T+xMLzNAQ13+nwJjHR20jG7W9NH23Q==;4:mKpT6CcMRllsV0taoXOvVz3pNHBJGp+gxPnpXiyPEvslh8Nuy4QhBhUPP9ibQh7o2NAS13cXpBQTdvHcShBQ62cfenzjb8xWen933N4R3y/afCsSjUQPdjV6x6QkZ8fjT/7EzMmidoXN1lLZy+It+EjCgThHLOB5PGTM+5JSQPHYKovCp5ft/Q/YcalL2fq7cO7bQPsZ0FRnub6UJE6OL/UaeRj115wBn+luj4eiISD/3k31oOT0UQJYwPdzgb9q/gT0bE6HBsgYb8vzfSbf96r8DrdQ7gTJ4hT9Z3F4Q3kY+0ISG+2zu7WUA+Sip9+MzCkodUQj4pMXdcAIQlPQvL17nPhJ0RRCH8TiCzXjTRGswNbxG8tLcmIpH0BN/3HUmw8eEmeJHGr+w+giQimRc+OC1ZEhF65xzo3elJqIl+bASbk7HZgGP7HUoAOJWkV0Z12QVo1pZsSZ6f64AKGqI1q4wstCvqRaegS1rJkyNE4Zqazi//1h4Javfkx8G8t9X0X3uav04whwOoJQK9FrKUuuSmIC3C26SQ7O687gDhJU6zHZOpJgXxZAVISMLhmQzxG5ryIg51HMPh1hs8hvmeynaYSv0eHxpYzIAX892fIALYFalMTfttRFhn635628 X-Microsoft-Antispam-PRVS: X-Exchange-Antispam-Report-Test: UriScan:; X-Exchange-Antispam-Report-CFA-Test: BCL:0;PCL:0;RULEID:(6040375)(601004)(2401047)(8121501046)(5005006)(10201501046)(3002001)(6041248)(2016111802025)(20161123555025)(20161123564025)(20161123562025)(20161123560025)(6072148)(6043046);SRVR:VI1PR0202MB2558;BCL:0;PCL:0;RULEID:;SRVR:VI1PR0202MB2558; X-Forefront-PRVS: 01917B1794 X-Forefront-Antispam-Report: SFV:NSPM;SFS:(10019020)(4630300001)(6009001)(6069001)(7916002)(39450400003)(39410400002)(39840400002)(189002)(199003)(3846002)(38730400001)(6512007)(5660300001)(50466002)(101416001)(47776003)(48376002)(54906002)(97736004)(76176999)(53936002)(189998001)(50986999)(305945005)(7416002)(4326007)(74482002)(106356001)(2950100002)(6666003)(86362001)(6116002)(81166006)(6916009)(68736007)(5003940100001)(36756003)(7736002)(2906002)(25786008)(8666007)(42186005)(2351001)(81156014)(33646002)(6486002)(110136003)(6506006)(66066001)(92566002)(105586002)(50226002)(8676002)(2004002)(42262002);DIR:OUT;SFP:1102;SCL:1;SRVR:VI1PR0202MB2558;H:localhost.localdomain;FPR:;SPF:None;PTR:InfoNoRecords;MX:1;A:1;LANG:en; X-Microsoft-Exchange-Diagnostics: =?us-ascii?Q?1;VI1PR0202MB2558;23:afoSFCKdt14gzxLvbvsOBS9+BjdrKlfxm/jj0XF?= =?us-ascii?Q?4kryayyJPVCd+Exv2ahtHSJiGAUUqeVjNBhdYOnQBZVmHLPwAvIIUnf5UgGo?= =?us-ascii?Q?PnnvtAVV4n78yNMzQUIHjcKyEmtj+3yERuoz7Mz/zzCd5uo8cdL+AeiQf2Xd?= =?us-ascii?Q?680+CVI+ELFAgaTKSaceFhwe/v1eRy/qWGz4Caz/K8UXKH4Pbm9kV4aOScVE?= =?us-ascii?Q?K0Twm2RjyAXxc9tU+JITuH6rclwLaXjulo5MzrHwm8GVFib8vSHiNv535ZfQ?= =?us-ascii?Q?3o7qas8pnv8QCcU56h3M5OdRoRgs3NktMxEnFiiNY8xMzxIa7HjOqt1IUH9i?= =?us-ascii?Q?Bu1CIhcCGmeL4u8aJ3QKL2JixUd8ViN7ltEWkMtk1F0Z7hsaWlTMzyZZ6vNQ?= =?us-ascii?Q?Qa5BbE1RqGtw5T7xHdd1gnCFP/F4n0mgkG46Y/vAbsWH4danXqnStvLe8cHf?= =?us-ascii?Q?US9m2zIhlvXsDJwObVpBjPPXkOHFVPrEailUwwVN384SAxbBKs/9YjHiBtZl?= =?us-ascii?Q?jTZB4SuCV+YWeobKrnJ54BItH0LPC8+DgIS8pOZSPXxQVCNB8ZUGvAvID/gm?= =?us-ascii?Q?E+9HGo+f/AIbinQTnHso68PgWowFgrWDLJftvsNHA4FnYR2KNKxQlC2zZcq4?= =?us-ascii?Q?+YPQaHWD1d/MxZbLTtIPvHIYk0oubs4fMmunQpIhFn1D/2FcYtN4hq7hDEAC?= =?us-ascii?Q?w1wWH+D+UbPGpGY/xEFGRdf9YChJww+hv/UqY+VRpmEqzoZSLVr2U3xLKYui?= =?us-ascii?Q?5nPNYtO8KekUPjm9fqJ12ns5G42gdXXLPV0v/ciwN0h7/2qvLMIb4N10OiOG?= =?us-ascii?Q?pTEm76W2RQ82GDw9cKsxfYndKBmF5LR9GidMslA6MEjg38O2cwW6URc7d2vt?= =?us-ascii?Q?w9Bvo2smElaBK4y56pfaTRuFFmARSW/BB6sjT61DkslLy7EmIPjrPuNjVcqR?= =?us-ascii?Q?QFUEhjeZwrrRqMEQ9nTXaPq/NziOi05VYAsZ+hMpSYpFm7ELGEp1bkympZEb?= =?us-ascii?Q?VZrTlZzED50CIHIgEoSqJ/9Wy1q+YlZtQtjNFcIEZd6z+G6Mwvxds07qZ1P1?= =?us-ascii?Q?v3s8IApPWa527qBrf2Rjx2mtXj4SMd0zIxvtJA1HoWUKP9/8n79WFoW3SdHl?= =?us-ascii?Q?mjKEKAuhngM1IIx4QKOvDklxsTEwy3DPLwuzeFQYMzpkp3OYAZmRdHJFMu/2?= =?us-ascii?Q?HCBsJuXK/7Ml3iuBHOKF7zNe8QxCIUoaJtgxs7MhTHMAxyPdchxLE8EWPmPe?= =?us-ascii?Q?h1AjYiIDjzHsDRlcSIvdrt2G6/pdv5dzfVezh30eBS3+JEQu8z/p5endCrOY?= =?us-ascii?Q?PtZ9A355m0kuOCkPh/CJDcO8=3D?= X-Microsoft-Exchange-Diagnostics: 1;VI1PR0202MB2558;6:ykfCEjMfUr/xzM2bMugw2+VFDtcdAbi1F4/H4AOMRu+/w5jLD8WLFxpTtpEA7EHt2fQn3Fnh0lV5uFrB+o8Ma4STzTVrqWXGQ5bvyCqnaC8jLeahIriHQT5conuKX1b38vWX57y+clX8uhmZb799j4OG+PiYXp3uccx9E/OFCncsTahrZ5MPfX4xSAt2wiKIy8Sm55zFAa+9I0bPuGK1QrgShmBa6RykL4q0DmGVH8UAOxYGQIsHB3YzZ8AXmmQo21R06MqxtjtUcupMYFvSxiAeCNl20wrXDaDGOR7PwHU2aguSyQVXET/8KPOcfKcMoTbsQayqiiCQYe8XuPNfm6/pyM5u/v67sRZQJviIseqOZSyQS0yklr5uUcl8Fgi3RL1fjaKPp52vRyTaxlwKG6AThkzZJ844Yvdeqhe91VKdEjW4m0AeL69MzjEgHOO9;5:vYO6ud0TekkRnbYuusxHEs2D9xAT0a1PLONLd4kkyRaoHgsZZ1kSOpjtr3kXIARhSy9BKniizfjrAwSw9F9k/0Z3PhBvqgimciNh2CV4XrKbunHpAfxEKmqz9zguzmsdGSnRysIiJRqv+Sz2Pl5eyQ==;24:bFkoc8P+O4XXODl35lR/mW2LYFUBsOReSVMeg2Y5Ef9SNYhHC8TZKYmnG1BVlma8qW0vQQMI7tT5CTbBbLP7vwC3y8bZLsMd5/nRcgvcIQ8= SpamDiagnosticOutput: 1:99 SpamDiagnosticMetadata: NSPM X-Microsoft-Exchange-Diagnostics: 1;VI1PR0202MB2558;7:6UNiBt/J46PtRgVoTzjEh8qhP10aCD2wvIXcSYK+aSWKtg+qfCAkN25WrUteLlXa9ac50wysYduuTLw4LknfHLhLHuS6PJY9/A1kpSTi0QLaKHEPmP87IO3uwUTNwi7IT9QcstWoPAEhwO5hZz/Wv0o8+vf+No4HfOF98KPaNKk21D1CedtNYrzPRFFfiO2iEVRzVhmcKFZ//6hZAFWeosYStuFXRq2E4fDeksMwZ4G0O8lPDr3ZBHZnzA0Df2lDcPNAVeNXd40+ZB+IiN8+DUH8oMLw4LX3HgYrCj/sChfo1eKcdqHNy/KimU79GCXqI1HGpzDnAkoLON3XhfZSK4joqZR1It0dcxm+WPxjsuYEbrN4iXKDXgtH/CpWES2yAhd1LEO6aUWGLQbB9QBcrg4tXS5avuiMhVyhEwD/DI2iIGUkDAYSKnUcgzFPdYbv1i8uGo6cfpLEHCe0qt9m8A== X-OriginatorOrg: axentia.se X-MS-Exchange-CrossTenant-OriginalArrivalTime: 18 Jan 2017 15:58:52.1407 (UTC) X-MS-Exchange-CrossTenant-FromEntityHeader: Hosted X-MS-Exchange-Transport-CrossTenantHeadersStamped: VI1PR0202MB2558 Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Analog Devices ADG792A/G is a triple 4:1 mux. Reviewed-by: Jonathan Cameron Signed-off-by: Peter Rosin --- drivers/mux/Kconfig | 12 ++++ drivers/mux/Makefile | 1 + drivers/mux/mux-adg792a.c | 167 ++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 180 insertions(+) create mode 100644 drivers/mux/mux-adg792a.c diff --git a/drivers/mux/Kconfig b/drivers/mux/Kconfig index 57e6f4e5fda9..d13fcf98958e 100644 --- a/drivers/mux/Kconfig +++ b/drivers/mux/Kconfig @@ -16,6 +16,18 @@ menuconfig MULTIPLEXER if MULTIPLEXER +config MUX_ADG792A + tristate "Analog Devices ADG792A/ADG792G Multiplexers" + depends on I2C + help + ADG792A and ADG792G Wide Bandwidth Triple 4:1 Multiplexers + + The driver supports both operating the three multiplexers in + parallel and operating them independently. + + To compile the driver as a module, choose M here: the module will + be called mux-adg792a. + config MUX_GPIO tristate "GPIO-controlled Multiplexer" depends on OF && GPIOLIB diff --git a/drivers/mux/Makefile b/drivers/mux/Makefile index facc43da3648..fddbb073fc77 100644 --- a/drivers/mux/Makefile +++ b/drivers/mux/Makefile @@ -3,4 +3,5 @@ # obj-$(CONFIG_MULTIPLEXER) += mux-core.o +obj-$(CONFIG_MUX_ADG792A) += mux-adg792a.o obj-$(CONFIG_MUX_GPIO) += mux-gpio.o diff --git a/drivers/mux/mux-adg792a.c b/drivers/mux/mux-adg792a.c new file mode 100644 index 000000000000..6a4c4c9f585b --- /dev/null +++ b/drivers/mux/mux-adg792a.c @@ -0,0 +1,167 @@ +/* + * Multiplexer driver for Analog Devices ADG792A/G Triple 4:1 mux + * + * Copyright (C) 2017 Axentia Technologies AB + * + * Author: Peter Rosin + * + * 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 + +#define ADG792A_LDSW BIT(0) +#define ADG792A_RESET BIT(1) +#define ADG792A_DISABLE(mux) (0x50 | (mux)) +#define ADG792A_DISABLE_ALL (0x5f) +#define ADG792A_MUX(mux, state) (0xc0 | (((mux) + 1) << 2) | (state)) +#define ADG792A_MUX_ALL(state) (0xc0 | (state)) + +#define ADG792A_DISABLE_STATE (4) + +static int adg792a_set(struct mux_control *mux, int state) +{ + struct i2c_client *i2c = to_i2c_client(mux->chip->dev.parent); + u8 cmd; + + if (mux->chip->controllers == 1) { + /* parallel mux controller operation */ + if (state == ADG792A_DISABLE_STATE) + cmd = ADG792A_DISABLE_ALL; + else + cmd = ADG792A_MUX_ALL(state); + } else { + unsigned int controller = mux_control_get_index(mux); + + if (state == ADG792A_DISABLE_STATE) + cmd = ADG792A_DISABLE(controller); + else + cmd = ADG792A_MUX(controller, state); + } + + return i2c_smbus_write_byte_data(i2c, cmd, ADG792A_LDSW); +} + +static const struct mux_control_ops adg792a_ops = { + .set = adg792a_set, +}; + +static int adg792a_probe(struct i2c_client *i2c, + const struct i2c_device_id *id) +{ + struct device *dev = &i2c->dev; + struct mux_chip *mux_chip; + bool parallel; + int count; + int ret; + int i; + + parallel = of_property_read_bool(i2c->dev.of_node, "adi,parallel"); + + mux_chip = devm_mux_chip_alloc(dev, parallel ? 1 : 3, 0); + if (!mux_chip) + return -ENOMEM; + + mux_chip->ops = &adg792a_ops; + + ret = i2c_smbus_write_byte_data(i2c, ADG792A_DISABLE_ALL, + ADG792A_RESET | ADG792A_LDSW); + if (ret < 0) + return ret; + + for (i = 0; i < mux_chip->controllers; ++i) { + struct mux_control *mux = &mux_chip->mux[i]; + + mux->states = 4; + } + + count = of_property_count_u32_elems(dev->of_node, "adi,idle-state"); + for (i = 0; i < count; i += 2) { + u32 index; + u32 idle_state; + + ret = of_property_read_u32_index(dev->of_node, + "adi,idle-state", i, + &index); + if (ret < 0) + return ret; + if (index >= mux_chip->controllers) { + dev_err(dev, "invalid mux %u\n", index); + return -EINVAL; + } + + ret = of_property_read_u32_index(dev->of_node, + "adi,idle-state", i + 1, + &idle_state); + if (ret < 0) + return ret; + if (idle_state >= ADG792A_DISABLE_STATE) { + dev_err(dev, "invalid idle-state %u for mux %u\n", + idle_state, index); + return -EINVAL; + } + mux_chip->mux[index].idle_state = idle_state; + } + + count = of_property_count_u32_elems(dev->of_node, + "adi,idle-high-impedance"); + for (i = 0; i < count; ++i) { + u32 index; + + ret = of_property_read_u32_index(dev->of_node, + "adi,idle-high-impedance", i, + &index); + if (ret < 0) + return ret; + if (index >= mux_chip->controllers) { + dev_err(dev, "invalid mux %u\n", index); + return -EINVAL; + } + + mux_chip->mux[index].idle_state = ADG792A_DISABLE_STATE; + } + + ret = devm_mux_chip_register(dev, mux_chip); + if (ret < 0) + return ret; + + if (parallel) + dev_info(dev, "triple pole quadruple throw mux registered\n"); + else + dev_info(dev, "3x single pole quadruple throw muxes registered\n"); + + return 0; +} + +static const struct i2c_device_id adg792a_id[] = { + { .name = "adg792a", }, + { .name = "adg792g", }, + { } +}; +MODULE_DEVICE_TABLE(i2c, adg792a_id); + +static const struct of_device_id adg792a_of_match[] = { + { .compatible = "adi,adg792a", }, + { .compatible = "adi,adg792g", }, + { } +}; +MODULE_DEVICE_TABLE(of, adg792a_of_match); + +static struct i2c_driver adg792a_driver = { + .driver = { + .name = "adg792a", + .of_match_table = of_match_ptr(adg792a_of_match), + }, + .probe = adg792a_probe, + .id_table = adg792a_id, +}; +module_i2c_driver(adg792a_driver); + +MODULE_DESCRIPTION("Analog Devices ADG792A/G Triple 4:1 mux driver"); +MODULE_AUTHOR("Peter Rosin