1 // SPDX-License-Identifier: GPL-2.0
3 * Multiplexer driver for Analog Devices ADG792A/G Triple 4:1 mux
5 * Copyright (C) 2017 Axentia Technologies AB
7 * Author: Peter Rosin <peda@axentia.se>
10 #include <linux/err.h>
11 #include <linux/i2c.h>
12 #include <linux/module.h>
13 #include <linux/mux/driver.h>
14 #include <linux/property.h>
16 #define ADG792A_LDSW BIT(0)
17 #define ADG792A_RESETB BIT(1)
18 #define ADG792A_DISABLE(mux) (0x50 | (mux))
19 #define ADG792A_DISABLE_ALL (0x5f)
20 #define ADG792A_MUX(mux, state) (0xc0 | (((mux) + 1) << 2) | (state))
21 #define ADG792A_MUX_ALL(state) (0xc0 | (state))
23 static int adg792a_write_cmd(struct i2c_client
*i2c
, u8 cmd
, int reset
)
25 u8 data
= ADG792A_RESETB
| ADG792A_LDSW
;
27 /* ADG792A_RESETB is active low, the chip resets when it is zero. */
29 data
&= ~ADG792A_RESETB
;
31 return i2c_smbus_write_byte_data(i2c
, cmd
, data
);
34 static int adg792a_set(struct mux_control
*mux
, int state
)
36 struct i2c_client
*i2c
= to_i2c_client(mux
->chip
->dev
.parent
);
39 if (mux
->chip
->controllers
== 1) {
40 /* parallel mux controller operation */
41 if (state
== MUX_IDLE_DISCONNECT
)
42 cmd
= ADG792A_DISABLE_ALL
;
44 cmd
= ADG792A_MUX_ALL(state
);
46 unsigned int controller
= mux_control_get_index(mux
);
48 if (state
== MUX_IDLE_DISCONNECT
)
49 cmd
= ADG792A_DISABLE(controller
);
51 cmd
= ADG792A_MUX(controller
, state
);
54 return adg792a_write_cmd(i2c
, cmd
, 0);
57 static const struct mux_control_ops adg792a_ops
= {
61 static int adg792a_probe(struct i2c_client
*i2c
)
63 struct device
*dev
= &i2c
->dev
;
64 struct mux_chip
*mux_chip
;
70 if (!i2c_check_functionality(i2c
->adapter
, I2C_FUNC_SMBUS_BYTE_DATA
))
73 ret
= device_property_read_u32(dev
, "#mux-control-cells", &cells
);
79 mux_chip
= devm_mux_chip_alloc(dev
, cells
? 3 : 1, 0);
81 return PTR_ERR(mux_chip
);
83 mux_chip
->ops
= &adg792a_ops
;
85 ret
= adg792a_write_cmd(i2c
, ADG792A_DISABLE_ALL
, 1);
89 ret
= device_property_read_u32_array(dev
, "idle-state",
91 mux_chip
->controllers
);
93 idle_state
[0] = MUX_IDLE_AS_IS
;
94 idle_state
[1] = MUX_IDLE_AS_IS
;
95 idle_state
[2] = MUX_IDLE_AS_IS
;
98 for (i
= 0; i
< mux_chip
->controllers
; ++i
) {
99 struct mux_control
*mux
= &mux_chip
->mux
[i
];
103 switch (idle_state
[i
]) {
104 case MUX_IDLE_DISCONNECT
:
107 mux
->idle_state
= idle_state
[i
];
110 dev_err(dev
, "invalid idle-state %d\n", idle_state
[i
]);
115 ret
= devm_mux_chip_register(dev
, mux_chip
);
120 dev_info(dev
, "3x single pole quadruple throw muxes registered\n");
122 dev_info(dev
, "triple pole quadruple throw mux registered\n");
127 static const struct i2c_device_id adg792a_id
[] = {
128 { .name
= "adg792a", },
129 { .name
= "adg792g", },
132 MODULE_DEVICE_TABLE(i2c
, adg792a_id
);
134 static const struct of_device_id adg792a_of_match
[] = {
135 { .compatible
= "adi,adg792a", },
136 { .compatible
= "adi,adg792g", },
139 MODULE_DEVICE_TABLE(of
, adg792a_of_match
);
141 static struct i2c_driver adg792a_driver
= {
144 .of_match_table
= of_match_ptr(adg792a_of_match
),
146 .probe_new
= adg792a_probe
,
147 .id_table
= adg792a_id
,
149 module_i2c_driver(adg792a_driver
);
151 MODULE_DESCRIPTION("Analog Devices ADG792A/G Triple 4:1 mux driver");
152 MODULE_AUTHOR("Peter Rosin <peda@axentia.se>");
153 MODULE_LICENSE("GPL v2");