Lines Matching +full:io +full:- +full:channel +full:- +full:mux
1 // SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0
3 * Mellanox i2c mux driver
5 * Copyright (C) 2016-2020 Mellanox Technologies
10 #include <linux/i2c-mux.h>
11 #include <linux/io.h>
18 /* mlxcpld_mux - mux control structure:
19 * @last_val - last selected register value or -1 if mux deselected
20 * @client - I2C device client
29 /* MUX logic description.
30 * Driver can support different mux control logic, according to CPLD
35 * i2c-mlxcpld Digital Analog
37 * *--------* * -> mux1 (virt bus2) -> mux -> |
38 * | I2CLPC | i2c physical * -> mux2 (virt bus3) -> mux -> |
39 * | bridge | bus 1 *---------* |
40 * | logic |---------------------> * mux reg * |
41 * | in CPLD| *---------* |
42 * *--------* i2c-mux-mlxpcld ^ * -> muxn (virt busn) -> mux -> |
44 * | *---------------* | Devices
46 * | * registers for *--------*
47 * | * mux selection * deselect
48 * | *---------------*
50 * <--------> <----------->
52 * reg space space (mux select,
53 * IO, LED, WD, info)
57 /* Write to mux register. Don't use i2c_transfer() and i2c_smbus_xfer()
61 struct mlxcpld_mux *mux, u32 val) in mlxcpld_mux_reg_write() argument
63 struct i2c_client *client = mux->client; in mlxcpld_mux_reg_write()
68 switch (mux->pdata.reg_size) { in mlxcpld_mux_reg_write()
71 return __i2c_smbus_xfer(adap, client->addr, client->flags, in mlxcpld_mux_reg_write()
72 I2C_SMBUS_WRITE, mux->pdata.sel_reg_addr, in mlxcpld_mux_reg_write()
75 buf[0] = mux->pdata.sel_reg_addr >> 8; in mlxcpld_mux_reg_write()
76 buf[1] = mux->pdata.sel_reg_addr; in mlxcpld_mux_reg_write()
78 msg.addr = client->addr; in mlxcpld_mux_reg_write()
80 msg.len = mux->pdata.reg_size + 1; in mlxcpld_mux_reg_write()
84 return -EINVAL; in mlxcpld_mux_reg_write()
90 struct mlxcpld_mux *mux = i2c_mux_priv(muxc); in mlxcpld_mux_select_chan() local
94 if (mux->pdata.reg_size == 1) in mlxcpld_mux_select_chan()
97 /* Only select the channel if its different from the last channel */ in mlxcpld_mux_select_chan()
98 if (mux->last_val != regval) { in mlxcpld_mux_select_chan()
99 err = mlxcpld_mux_reg_write(muxc->parent, mux, regval); in mlxcpld_mux_select_chan()
100 mux->last_val = err < 0 ? -1 : regval; in mlxcpld_mux_select_chan()
108 struct mlxcpld_mux *mux = i2c_mux_priv(muxc); in mlxcpld_mux_deselect() local
110 /* Deselect active channel */ in mlxcpld_mux_deselect()
111 mux->last_val = -1; in mlxcpld_mux_deselect()
113 return mlxcpld_mux_reg_write(muxc->parent, mux, 0); in mlxcpld_mux_deselect()
119 struct mlxcpld_mux_plat_data *pdata = dev_get_platdata(&pdev->dev); in mlxcpld_mux_probe()
120 struct i2c_client *client = to_i2c_client(pdev->dev.parent); in mlxcpld_mux_probe()
127 return -EINVAL; in mlxcpld_mux_probe()
129 switch (pdata->reg_size) { in mlxcpld_mux_probe()
137 return -EINVAL; in mlxcpld_mux_probe()
140 if (!i2c_check_functionality(client->adapter, func)) in mlxcpld_mux_probe()
141 return -ENODEV; in mlxcpld_mux_probe()
143 muxc = i2c_mux_alloc(client->adapter, &pdev->dev, pdata->num_adaps, in mlxcpld_mux_probe()
147 return -ENOMEM; in mlxcpld_mux_probe()
151 data->client = client; in mlxcpld_mux_probe()
152 memcpy(&data->pdata, pdata, sizeof(*pdata)); in mlxcpld_mux_probe()
153 data->last_val = -1; /* force the first selection */ in mlxcpld_mux_probe()
155 /* Create an adapter for each channel. */ in mlxcpld_mux_probe()
156 for (num = 0; num < pdata->num_adaps; num++) { in mlxcpld_mux_probe()
157 err = i2c_mux_add_adapter(muxc, 0, pdata->chan_ids[num], 0); in mlxcpld_mux_probe()
163 if (pdata->completion_notify) in mlxcpld_mux_probe()
164 pdata->completion_notify(pdata->handle, muxc->parent, muxc->adapter); in mlxcpld_mux_probe()
182 .name = "i2c-mux-mlxcpld",
191 MODULE_DESCRIPTION("Mellanox I2C-CPLD-MUX driver");
193 MODULE_ALIAS("platform:i2c-mux-mlxcpld");