Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

mux: adgs1408: new driver for Analog Devices ADGS1408/1409 mux

This patch adds basic support for Analog Device ADGS1408/09 SPI mux
controller.

The device is probed and set to a disabled state. It uses the new mux
controller framework.

Signed-off-by: Mircea Caprioru <mircea.caprioru@analog.com>
Signed-off-by: Peter Rosin <peda@axentia.se>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>

authored by

Mircea Caprioru and committed by
Greg Kroah-Hartman
8b9ce695 94aea0c6

+143
+10
drivers/mux/Kconfig
··· 21 21 To compile the driver as a module, choose M here: the module will 22 22 be called mux-adg792a. 23 23 24 + config MUX_ADGS1408 25 + tristate "Analog Devices ADGS1408/ADGS1409 Multiplexers" 26 + depends on SPI 27 + help 28 + ADGS1408 8:1 multiplexer and ADGS1409 double 4:1 multiplexer 29 + switches. 30 + 31 + To compile the driver as a module, choose M here: the module will 32 + be called mux-adgs1408. 33 + 24 34 config MUX_GPIO 25 35 tristate "GPIO-controlled Multiplexer" 26 36 depends on GPIOLIB || COMPILE_TEST
+2
drivers/mux/Makefile
··· 5 5 6 6 mux-core-objs := core.o 7 7 mux-adg792a-objs := adg792a.o 8 + mux-adgs1408-objs := adgs1408.o 8 9 mux-gpio-objs := gpio.o 9 10 mux-mmio-objs := mmio.o 10 11 11 12 obj-$(CONFIG_MULTIPLEXER) += mux-core.o 12 13 obj-$(CONFIG_MUX_ADG792A) += mux-adg792a.o 14 + obj-$(CONFIG_MUX_ADGS1408) += mux-adgs1408.o 13 15 obj-$(CONFIG_MUX_GPIO) += mux-gpio.o 14 16 obj-$(CONFIG_MUX_MMIO) += mux-mmio.o
+131
drivers/mux/adgs1408.c
··· 1 + // SPDX-License-Identifier: GPL-2.0-or-later 2 + /* 3 + * ADGS1408/ADGS1409 SPI MUX driver 4 + * 5 + * Copyright 2018 Analog Devices Inc. 6 + */ 7 + 8 + #include <linux/err.h> 9 + #include <linux/module.h> 10 + #include <linux/mux/driver.h> 11 + #include <linux/of_platform.h> 12 + #include <linux/property.h> 13 + #include <linux/spi/spi.h> 14 + 15 + #define ADGS1408_SW_DATA (0x01) 16 + #define ADGS1408_REG_READ(reg) ((reg) | 0x80) 17 + #define ADGS1408_DISABLE (0x00) 18 + #define ADGS1408_MUX(state) (((state) << 1) | 1) 19 + 20 + enum adgs1408_chip_id { 21 + ADGS1408 = 1, 22 + ADGS1409, 23 + }; 24 + 25 + static int adgs1408_spi_reg_write(struct spi_device *spi, 26 + u8 reg_addr, u8 reg_data) 27 + { 28 + u8 tx_buf[2]; 29 + 30 + tx_buf[0] = reg_addr; 31 + tx_buf[1] = reg_data; 32 + 33 + return spi_write_then_read(spi, tx_buf, sizeof(tx_buf), NULL, 0); 34 + } 35 + 36 + static int adgs1408_set(struct mux_control *mux, int state) 37 + { 38 + struct spi_device *spi = to_spi_device(mux->chip->dev.parent); 39 + u8 reg; 40 + 41 + if (state == MUX_IDLE_DISCONNECT) 42 + reg = ADGS1408_DISABLE; 43 + else 44 + reg = ADGS1408_MUX(state); 45 + 46 + return adgs1408_spi_reg_write(spi, ADGS1408_SW_DATA, reg); 47 + } 48 + 49 + static const struct mux_control_ops adgs1408_ops = { 50 + .set = adgs1408_set, 51 + }; 52 + 53 + static int adgs1408_probe(struct spi_device *spi) 54 + { 55 + struct device *dev = &spi->dev; 56 + enum adgs1408_chip_id chip_id; 57 + struct mux_chip *mux_chip; 58 + struct mux_control *mux; 59 + s32 idle_state; 60 + int ret; 61 + 62 + chip_id = (enum adgs1408_chip_id)of_device_get_match_data(dev); 63 + if (!chip_id) 64 + chip_id = spi_get_device_id(spi)->driver_data; 65 + 66 + mux_chip = devm_mux_chip_alloc(dev, 1, 0); 67 + if (IS_ERR(mux_chip)) 68 + return PTR_ERR(mux_chip); 69 + 70 + mux_chip->ops = &adgs1408_ops; 71 + 72 + ret = adgs1408_spi_reg_write(spi, ADGS1408_SW_DATA, ADGS1408_DISABLE); 73 + if (ret < 0) 74 + return ret; 75 + 76 + ret = device_property_read_u32(dev, "idle-state", (u32 *)&idle_state); 77 + if (ret < 0) 78 + idle_state = MUX_IDLE_AS_IS; 79 + 80 + mux = mux_chip->mux; 81 + 82 + if (chip_id == ADGS1408) 83 + mux->states = 8; 84 + else 85 + mux->states = 4; 86 + 87 + switch (idle_state) { 88 + case MUX_IDLE_DISCONNECT: 89 + case MUX_IDLE_AS_IS: 90 + case 0 ... 7: 91 + /* adgs1409 supports only 4 states */ 92 + if (idle_state < mux->states) { 93 + mux->idle_state = idle_state; 94 + break; 95 + } 96 + /* fall through */ 97 + default: 98 + dev_err(dev, "invalid idle-state %d\n", idle_state); 99 + return -EINVAL; 100 + } 101 + 102 + return devm_mux_chip_register(dev, mux_chip); 103 + } 104 + 105 + static const struct spi_device_id adgs1408_spi_id[] = { 106 + { "adgs1408", ADGS1408 }, 107 + { "adgs1409", ADGS1409 }, 108 + { } 109 + }; 110 + MODULE_DEVICE_TABLE(spi, adgs1408_spi_id); 111 + 112 + static const struct of_device_id adgs1408_of_match[] = { 113 + { .compatible = "adi,adgs1408", .data = (void *)ADGS1408, }, 114 + { .compatible = "adi,adgs1409", .data = (void *)ADGS1409, }, 115 + { } 116 + }; 117 + MODULE_DEVICE_TABLE(of, adgs1408_of_match); 118 + 119 + static struct spi_driver adgs1408_driver = { 120 + .driver = { 121 + .name = "adgs1408", 122 + .of_match_table = of_match_ptr(adgs1408_of_match), 123 + }, 124 + .probe = adgs1408_probe, 125 + .id_table = adgs1408_spi_id, 126 + }; 127 + module_spi_driver(adgs1408_driver); 128 + 129 + MODULE_AUTHOR("Mircea Caprioru <mircea.caprioru@analog.com>"); 130 + MODULE_DESCRIPTION("Analog Devices ADGS1408 MUX driver"); 131 + MODULE_LICENSE("GPL v2");