18c2ecf20Sopenharmony_ci/* 28c2ecf20Sopenharmony_ci * I2C multiplexer driver for PCA9541 bus master selector 38c2ecf20Sopenharmony_ci * 48c2ecf20Sopenharmony_ci * Copyright (c) 2010 Ericsson AB. 58c2ecf20Sopenharmony_ci * 68c2ecf20Sopenharmony_ci * Author: Guenter Roeck <linux@roeck-us.net> 78c2ecf20Sopenharmony_ci * 88c2ecf20Sopenharmony_ci * Derived from: 98c2ecf20Sopenharmony_ci * pca954x.c 108c2ecf20Sopenharmony_ci * 118c2ecf20Sopenharmony_ci * Copyright (c) 2008-2009 Rodolfo Giometti <giometti@linux.it> 128c2ecf20Sopenharmony_ci * Copyright (c) 2008-2009 Eurotech S.p.A. <info@eurotech.it> 138c2ecf20Sopenharmony_ci * 148c2ecf20Sopenharmony_ci * This file is licensed under the terms of the GNU General Public 158c2ecf20Sopenharmony_ci * License version 2. This program is licensed "as is" without any 168c2ecf20Sopenharmony_ci * warranty of any kind, whether express or implied. 178c2ecf20Sopenharmony_ci */ 188c2ecf20Sopenharmony_ci 198c2ecf20Sopenharmony_ci#include <linux/bitops.h> 208c2ecf20Sopenharmony_ci#include <linux/delay.h> 218c2ecf20Sopenharmony_ci#include <linux/device.h> 228c2ecf20Sopenharmony_ci#include <linux/i2c.h> 238c2ecf20Sopenharmony_ci#include <linux/i2c-mux.h> 248c2ecf20Sopenharmony_ci#include <linux/jiffies.h> 258c2ecf20Sopenharmony_ci#include <linux/module.h> 268c2ecf20Sopenharmony_ci#include <linux/slab.h> 278c2ecf20Sopenharmony_ci 288c2ecf20Sopenharmony_ci/* 298c2ecf20Sopenharmony_ci * The PCA9541 is a bus master selector. It supports two I2C masters connected 308c2ecf20Sopenharmony_ci * to a single slave bus. 318c2ecf20Sopenharmony_ci * 328c2ecf20Sopenharmony_ci * Before each bus transaction, a master has to acquire bus ownership. After the 338c2ecf20Sopenharmony_ci * transaction is complete, bus ownership has to be released. This fits well 348c2ecf20Sopenharmony_ci * into the I2C multiplexer framework, which provides select and release 358c2ecf20Sopenharmony_ci * functions for this purpose. For this reason, this driver is modeled as 368c2ecf20Sopenharmony_ci * single-channel I2C bus multiplexer. 378c2ecf20Sopenharmony_ci * 388c2ecf20Sopenharmony_ci * This driver assumes that the two bus masters are controlled by two different 398c2ecf20Sopenharmony_ci * hosts. If a single host controls both masters, platform code has to ensure 408c2ecf20Sopenharmony_ci * that only one of the masters is instantiated at any given time. 418c2ecf20Sopenharmony_ci */ 428c2ecf20Sopenharmony_ci 438c2ecf20Sopenharmony_ci#define PCA9541_CONTROL 0x01 448c2ecf20Sopenharmony_ci#define PCA9541_ISTAT 0x02 458c2ecf20Sopenharmony_ci 468c2ecf20Sopenharmony_ci#define PCA9541_CTL_MYBUS BIT(0) 478c2ecf20Sopenharmony_ci#define PCA9541_CTL_NMYBUS BIT(1) 488c2ecf20Sopenharmony_ci#define PCA9541_CTL_BUSON BIT(2) 498c2ecf20Sopenharmony_ci#define PCA9541_CTL_NBUSON BIT(3) 508c2ecf20Sopenharmony_ci#define PCA9541_CTL_BUSINIT BIT(4) 518c2ecf20Sopenharmony_ci#define PCA9541_CTL_TESTON BIT(6) 528c2ecf20Sopenharmony_ci#define PCA9541_CTL_NTESTON BIT(7) 538c2ecf20Sopenharmony_ci 548c2ecf20Sopenharmony_ci#define PCA9541_ISTAT_INTIN BIT(0) 558c2ecf20Sopenharmony_ci#define PCA9541_ISTAT_BUSINIT BIT(1) 568c2ecf20Sopenharmony_ci#define PCA9541_ISTAT_BUSOK BIT(2) 578c2ecf20Sopenharmony_ci#define PCA9541_ISTAT_BUSLOST BIT(3) 588c2ecf20Sopenharmony_ci#define PCA9541_ISTAT_MYTEST BIT(6) 598c2ecf20Sopenharmony_ci#define PCA9541_ISTAT_NMYTEST BIT(7) 608c2ecf20Sopenharmony_ci 618c2ecf20Sopenharmony_ci#define BUSON (PCA9541_CTL_BUSON | PCA9541_CTL_NBUSON) 628c2ecf20Sopenharmony_ci#define MYBUS (PCA9541_CTL_MYBUS | PCA9541_CTL_NMYBUS) 638c2ecf20Sopenharmony_ci#define mybus(x) (!((x) & MYBUS) || ((x) & MYBUS) == MYBUS) 648c2ecf20Sopenharmony_ci#define busoff(x) (!((x) & BUSON) || ((x) & BUSON) == BUSON) 658c2ecf20Sopenharmony_ci 668c2ecf20Sopenharmony_ci/* arbitration timeouts, in jiffies */ 678c2ecf20Sopenharmony_ci#define ARB_TIMEOUT (HZ / 8) /* 125 ms until forcing bus ownership */ 688c2ecf20Sopenharmony_ci#define ARB2_TIMEOUT (HZ / 4) /* 250 ms until acquisition failure */ 698c2ecf20Sopenharmony_ci 708c2ecf20Sopenharmony_ci/* arbitration retry delays, in us */ 718c2ecf20Sopenharmony_ci#define SELECT_DELAY_SHORT 50 728c2ecf20Sopenharmony_ci#define SELECT_DELAY_LONG 1000 738c2ecf20Sopenharmony_ci 748c2ecf20Sopenharmony_cistruct pca9541 { 758c2ecf20Sopenharmony_ci struct i2c_client *client; 768c2ecf20Sopenharmony_ci unsigned long select_timeout; 778c2ecf20Sopenharmony_ci unsigned long arb_timeout; 788c2ecf20Sopenharmony_ci}; 798c2ecf20Sopenharmony_ci 808c2ecf20Sopenharmony_cistatic const struct i2c_device_id pca9541_id[] = { 818c2ecf20Sopenharmony_ci {"pca9541", 0}, 828c2ecf20Sopenharmony_ci {} 838c2ecf20Sopenharmony_ci}; 848c2ecf20Sopenharmony_ci 858c2ecf20Sopenharmony_ciMODULE_DEVICE_TABLE(i2c, pca9541_id); 868c2ecf20Sopenharmony_ci 878c2ecf20Sopenharmony_ci#ifdef CONFIG_OF 888c2ecf20Sopenharmony_cistatic const struct of_device_id pca9541_of_match[] = { 898c2ecf20Sopenharmony_ci { .compatible = "nxp,pca9541" }, 908c2ecf20Sopenharmony_ci {} 918c2ecf20Sopenharmony_ci}; 928c2ecf20Sopenharmony_ciMODULE_DEVICE_TABLE(of, pca9541_of_match); 938c2ecf20Sopenharmony_ci#endif 948c2ecf20Sopenharmony_ci 958c2ecf20Sopenharmony_ci/* 968c2ecf20Sopenharmony_ci * Write to chip register. Don't use i2c_transfer()/i2c_smbus_xfer() 978c2ecf20Sopenharmony_ci * as they will try to lock the adapter a second time. 988c2ecf20Sopenharmony_ci */ 998c2ecf20Sopenharmony_cistatic int pca9541_reg_write(struct i2c_client *client, u8 command, u8 val) 1008c2ecf20Sopenharmony_ci{ 1018c2ecf20Sopenharmony_ci struct i2c_adapter *adap = client->adapter; 1028c2ecf20Sopenharmony_ci union i2c_smbus_data data = { .byte = val }; 1038c2ecf20Sopenharmony_ci 1048c2ecf20Sopenharmony_ci return __i2c_smbus_xfer(adap, client->addr, client->flags, 1058c2ecf20Sopenharmony_ci I2C_SMBUS_WRITE, command, 1068c2ecf20Sopenharmony_ci I2C_SMBUS_BYTE_DATA, &data); 1078c2ecf20Sopenharmony_ci} 1088c2ecf20Sopenharmony_ci 1098c2ecf20Sopenharmony_ci/* 1108c2ecf20Sopenharmony_ci * Read from chip register. Don't use i2c_transfer()/i2c_smbus_xfer() 1118c2ecf20Sopenharmony_ci * as they will try to lock adapter a second time. 1128c2ecf20Sopenharmony_ci */ 1138c2ecf20Sopenharmony_cistatic int pca9541_reg_read(struct i2c_client *client, u8 command) 1148c2ecf20Sopenharmony_ci{ 1158c2ecf20Sopenharmony_ci struct i2c_adapter *adap = client->adapter; 1168c2ecf20Sopenharmony_ci union i2c_smbus_data data; 1178c2ecf20Sopenharmony_ci int ret; 1188c2ecf20Sopenharmony_ci 1198c2ecf20Sopenharmony_ci ret = __i2c_smbus_xfer(adap, client->addr, client->flags, 1208c2ecf20Sopenharmony_ci I2C_SMBUS_READ, command, 1218c2ecf20Sopenharmony_ci I2C_SMBUS_BYTE_DATA, &data); 1228c2ecf20Sopenharmony_ci 1238c2ecf20Sopenharmony_ci return ret ?: data.byte; 1248c2ecf20Sopenharmony_ci} 1258c2ecf20Sopenharmony_ci 1268c2ecf20Sopenharmony_ci/* 1278c2ecf20Sopenharmony_ci * Arbitration management functions 1288c2ecf20Sopenharmony_ci */ 1298c2ecf20Sopenharmony_ci 1308c2ecf20Sopenharmony_ci/* Release bus. Also reset NTESTON and BUSINIT if it was set. */ 1318c2ecf20Sopenharmony_cistatic void pca9541_release_bus(struct i2c_client *client) 1328c2ecf20Sopenharmony_ci{ 1338c2ecf20Sopenharmony_ci int reg; 1348c2ecf20Sopenharmony_ci 1358c2ecf20Sopenharmony_ci reg = pca9541_reg_read(client, PCA9541_CONTROL); 1368c2ecf20Sopenharmony_ci if (reg >= 0 && !busoff(reg) && mybus(reg)) 1378c2ecf20Sopenharmony_ci pca9541_reg_write(client, PCA9541_CONTROL, 1388c2ecf20Sopenharmony_ci (reg & PCA9541_CTL_NBUSON) >> 1); 1398c2ecf20Sopenharmony_ci} 1408c2ecf20Sopenharmony_ci 1418c2ecf20Sopenharmony_ci/* 1428c2ecf20Sopenharmony_ci * Arbitration is defined as a two-step process. A bus master can only activate 1438c2ecf20Sopenharmony_ci * the slave bus if it owns it; otherwise it has to request ownership first. 1448c2ecf20Sopenharmony_ci * This multi-step process ensures that access contention is resolved 1458c2ecf20Sopenharmony_ci * gracefully. 1468c2ecf20Sopenharmony_ci * 1478c2ecf20Sopenharmony_ci * Bus Ownership Other master Action 1488c2ecf20Sopenharmony_ci * state requested access 1498c2ecf20Sopenharmony_ci * ---------------------------------------------------- 1508c2ecf20Sopenharmony_ci * off - yes wait for arbitration timeout or 1518c2ecf20Sopenharmony_ci * for other master to drop request 1528c2ecf20Sopenharmony_ci * off no no take ownership 1538c2ecf20Sopenharmony_ci * off yes no turn on bus 1548c2ecf20Sopenharmony_ci * on yes - done 1558c2ecf20Sopenharmony_ci * on no - wait for arbitration timeout or 1568c2ecf20Sopenharmony_ci * for other master to release bus 1578c2ecf20Sopenharmony_ci * 1588c2ecf20Sopenharmony_ci * The main contention point occurs if the slave bus is off and both masters 1598c2ecf20Sopenharmony_ci * request ownership at the same time. In this case, one master will turn on 1608c2ecf20Sopenharmony_ci * the slave bus, believing that it owns it. The other master will request 1618c2ecf20Sopenharmony_ci * bus ownership. Result is that the bus is turned on, and master which did 1628c2ecf20Sopenharmony_ci * _not_ own the slave bus before ends up owning it. 1638c2ecf20Sopenharmony_ci */ 1648c2ecf20Sopenharmony_ci 1658c2ecf20Sopenharmony_ci/* Control commands per PCA9541 datasheet */ 1668c2ecf20Sopenharmony_cistatic const u8 pca9541_control[16] = { 1678c2ecf20Sopenharmony_ci 4, 0, 1, 5, 4, 4, 5, 5, 0, 0, 1, 1, 0, 4, 5, 1 1688c2ecf20Sopenharmony_ci}; 1698c2ecf20Sopenharmony_ci 1708c2ecf20Sopenharmony_ci/* 1718c2ecf20Sopenharmony_ci * Channel arbitration 1728c2ecf20Sopenharmony_ci * 1738c2ecf20Sopenharmony_ci * Return values: 1748c2ecf20Sopenharmony_ci * <0: error 1758c2ecf20Sopenharmony_ci * 0 : bus not acquired 1768c2ecf20Sopenharmony_ci * 1 : bus acquired 1778c2ecf20Sopenharmony_ci */ 1788c2ecf20Sopenharmony_cistatic int pca9541_arbitrate(struct i2c_client *client) 1798c2ecf20Sopenharmony_ci{ 1808c2ecf20Sopenharmony_ci struct i2c_mux_core *muxc = i2c_get_clientdata(client); 1818c2ecf20Sopenharmony_ci struct pca9541 *data = i2c_mux_priv(muxc); 1828c2ecf20Sopenharmony_ci int reg; 1838c2ecf20Sopenharmony_ci 1848c2ecf20Sopenharmony_ci reg = pca9541_reg_read(client, PCA9541_CONTROL); 1858c2ecf20Sopenharmony_ci if (reg < 0) 1868c2ecf20Sopenharmony_ci return reg; 1878c2ecf20Sopenharmony_ci 1888c2ecf20Sopenharmony_ci if (busoff(reg)) { 1898c2ecf20Sopenharmony_ci int istat; 1908c2ecf20Sopenharmony_ci /* 1918c2ecf20Sopenharmony_ci * Bus is off. Request ownership or turn it on unless 1928c2ecf20Sopenharmony_ci * other master requested ownership. 1938c2ecf20Sopenharmony_ci */ 1948c2ecf20Sopenharmony_ci istat = pca9541_reg_read(client, PCA9541_ISTAT); 1958c2ecf20Sopenharmony_ci if (!(istat & PCA9541_ISTAT_NMYTEST) 1968c2ecf20Sopenharmony_ci || time_is_before_eq_jiffies(data->arb_timeout)) { 1978c2ecf20Sopenharmony_ci /* 1988c2ecf20Sopenharmony_ci * Other master did not request ownership, 1998c2ecf20Sopenharmony_ci * or arbitration timeout expired. Take the bus. 2008c2ecf20Sopenharmony_ci */ 2018c2ecf20Sopenharmony_ci pca9541_reg_write(client, 2028c2ecf20Sopenharmony_ci PCA9541_CONTROL, 2038c2ecf20Sopenharmony_ci pca9541_control[reg & 0x0f] 2048c2ecf20Sopenharmony_ci | PCA9541_CTL_NTESTON); 2058c2ecf20Sopenharmony_ci data->select_timeout = SELECT_DELAY_SHORT; 2068c2ecf20Sopenharmony_ci } else { 2078c2ecf20Sopenharmony_ci /* 2088c2ecf20Sopenharmony_ci * Other master requested ownership. 2098c2ecf20Sopenharmony_ci * Set extra long timeout to give it time to acquire it. 2108c2ecf20Sopenharmony_ci */ 2118c2ecf20Sopenharmony_ci data->select_timeout = SELECT_DELAY_LONG * 2; 2128c2ecf20Sopenharmony_ci } 2138c2ecf20Sopenharmony_ci } else if (mybus(reg)) { 2148c2ecf20Sopenharmony_ci /* 2158c2ecf20Sopenharmony_ci * Bus is on, and we own it. We are done with acquisition. 2168c2ecf20Sopenharmony_ci * Reset NTESTON and BUSINIT, then return success. 2178c2ecf20Sopenharmony_ci */ 2188c2ecf20Sopenharmony_ci if (reg & (PCA9541_CTL_NTESTON | PCA9541_CTL_BUSINIT)) 2198c2ecf20Sopenharmony_ci pca9541_reg_write(client, 2208c2ecf20Sopenharmony_ci PCA9541_CONTROL, 2218c2ecf20Sopenharmony_ci reg & ~(PCA9541_CTL_NTESTON 2228c2ecf20Sopenharmony_ci | PCA9541_CTL_BUSINIT)); 2238c2ecf20Sopenharmony_ci return 1; 2248c2ecf20Sopenharmony_ci } else { 2258c2ecf20Sopenharmony_ci /* 2268c2ecf20Sopenharmony_ci * Other master owns the bus. 2278c2ecf20Sopenharmony_ci * If arbitration timeout has expired, force ownership. 2288c2ecf20Sopenharmony_ci * Otherwise request it. 2298c2ecf20Sopenharmony_ci */ 2308c2ecf20Sopenharmony_ci data->select_timeout = SELECT_DELAY_LONG; 2318c2ecf20Sopenharmony_ci if (time_is_before_eq_jiffies(data->arb_timeout)) { 2328c2ecf20Sopenharmony_ci /* Time is up, take the bus and reset it. */ 2338c2ecf20Sopenharmony_ci pca9541_reg_write(client, 2348c2ecf20Sopenharmony_ci PCA9541_CONTROL, 2358c2ecf20Sopenharmony_ci pca9541_control[reg & 0x0f] 2368c2ecf20Sopenharmony_ci | PCA9541_CTL_BUSINIT 2378c2ecf20Sopenharmony_ci | PCA9541_CTL_NTESTON); 2388c2ecf20Sopenharmony_ci } else { 2398c2ecf20Sopenharmony_ci /* Request bus ownership if needed */ 2408c2ecf20Sopenharmony_ci if (!(reg & PCA9541_CTL_NTESTON)) 2418c2ecf20Sopenharmony_ci pca9541_reg_write(client, 2428c2ecf20Sopenharmony_ci PCA9541_CONTROL, 2438c2ecf20Sopenharmony_ci reg | PCA9541_CTL_NTESTON); 2448c2ecf20Sopenharmony_ci } 2458c2ecf20Sopenharmony_ci } 2468c2ecf20Sopenharmony_ci return 0; 2478c2ecf20Sopenharmony_ci} 2488c2ecf20Sopenharmony_ci 2498c2ecf20Sopenharmony_cistatic int pca9541_select_chan(struct i2c_mux_core *muxc, u32 chan) 2508c2ecf20Sopenharmony_ci{ 2518c2ecf20Sopenharmony_ci struct pca9541 *data = i2c_mux_priv(muxc); 2528c2ecf20Sopenharmony_ci struct i2c_client *client = data->client; 2538c2ecf20Sopenharmony_ci int ret; 2548c2ecf20Sopenharmony_ci unsigned long timeout = jiffies + ARB2_TIMEOUT; 2558c2ecf20Sopenharmony_ci /* give up after this time */ 2568c2ecf20Sopenharmony_ci 2578c2ecf20Sopenharmony_ci data->arb_timeout = jiffies + ARB_TIMEOUT; 2588c2ecf20Sopenharmony_ci /* force bus ownership after this time */ 2598c2ecf20Sopenharmony_ci 2608c2ecf20Sopenharmony_ci do { 2618c2ecf20Sopenharmony_ci ret = pca9541_arbitrate(client); 2628c2ecf20Sopenharmony_ci if (ret) 2638c2ecf20Sopenharmony_ci return ret < 0 ? ret : 0; 2648c2ecf20Sopenharmony_ci 2658c2ecf20Sopenharmony_ci if (data->select_timeout == SELECT_DELAY_SHORT) 2668c2ecf20Sopenharmony_ci udelay(data->select_timeout); 2678c2ecf20Sopenharmony_ci else 2688c2ecf20Sopenharmony_ci msleep(data->select_timeout / 1000); 2698c2ecf20Sopenharmony_ci } while (time_is_after_eq_jiffies(timeout)); 2708c2ecf20Sopenharmony_ci 2718c2ecf20Sopenharmony_ci return -ETIMEDOUT; 2728c2ecf20Sopenharmony_ci} 2738c2ecf20Sopenharmony_ci 2748c2ecf20Sopenharmony_cistatic int pca9541_release_chan(struct i2c_mux_core *muxc, u32 chan) 2758c2ecf20Sopenharmony_ci{ 2768c2ecf20Sopenharmony_ci struct pca9541 *data = i2c_mux_priv(muxc); 2778c2ecf20Sopenharmony_ci struct i2c_client *client = data->client; 2788c2ecf20Sopenharmony_ci 2798c2ecf20Sopenharmony_ci pca9541_release_bus(client); 2808c2ecf20Sopenharmony_ci return 0; 2818c2ecf20Sopenharmony_ci} 2828c2ecf20Sopenharmony_ci 2838c2ecf20Sopenharmony_ci/* 2848c2ecf20Sopenharmony_ci * I2C init/probing/exit functions 2858c2ecf20Sopenharmony_ci */ 2868c2ecf20Sopenharmony_cistatic int pca9541_probe(struct i2c_client *client, 2878c2ecf20Sopenharmony_ci const struct i2c_device_id *id) 2888c2ecf20Sopenharmony_ci{ 2898c2ecf20Sopenharmony_ci struct i2c_adapter *adap = client->adapter; 2908c2ecf20Sopenharmony_ci struct i2c_mux_core *muxc; 2918c2ecf20Sopenharmony_ci struct pca9541 *data; 2928c2ecf20Sopenharmony_ci int ret; 2938c2ecf20Sopenharmony_ci 2948c2ecf20Sopenharmony_ci if (!i2c_check_functionality(adap, I2C_FUNC_SMBUS_BYTE_DATA)) 2958c2ecf20Sopenharmony_ci return -ENODEV; 2968c2ecf20Sopenharmony_ci 2978c2ecf20Sopenharmony_ci /* 2988c2ecf20Sopenharmony_ci * I2C accesses are unprotected here. 2998c2ecf20Sopenharmony_ci * We have to lock the I2C segment before releasing the bus. 3008c2ecf20Sopenharmony_ci */ 3018c2ecf20Sopenharmony_ci i2c_lock_bus(adap, I2C_LOCK_SEGMENT); 3028c2ecf20Sopenharmony_ci pca9541_release_bus(client); 3038c2ecf20Sopenharmony_ci i2c_unlock_bus(adap, I2C_LOCK_SEGMENT); 3048c2ecf20Sopenharmony_ci 3058c2ecf20Sopenharmony_ci /* Create mux adapter */ 3068c2ecf20Sopenharmony_ci 3078c2ecf20Sopenharmony_ci muxc = i2c_mux_alloc(adap, &client->dev, 1, sizeof(*data), 3088c2ecf20Sopenharmony_ci I2C_MUX_ARBITRATOR, 3098c2ecf20Sopenharmony_ci pca9541_select_chan, pca9541_release_chan); 3108c2ecf20Sopenharmony_ci if (!muxc) 3118c2ecf20Sopenharmony_ci return -ENOMEM; 3128c2ecf20Sopenharmony_ci 3138c2ecf20Sopenharmony_ci data = i2c_mux_priv(muxc); 3148c2ecf20Sopenharmony_ci data->client = client; 3158c2ecf20Sopenharmony_ci 3168c2ecf20Sopenharmony_ci i2c_set_clientdata(client, muxc); 3178c2ecf20Sopenharmony_ci 3188c2ecf20Sopenharmony_ci ret = i2c_mux_add_adapter(muxc, 0, 0, 0); 3198c2ecf20Sopenharmony_ci if (ret) 3208c2ecf20Sopenharmony_ci return ret; 3218c2ecf20Sopenharmony_ci 3228c2ecf20Sopenharmony_ci dev_info(&client->dev, "registered master selector for I2C %s\n", 3238c2ecf20Sopenharmony_ci client->name); 3248c2ecf20Sopenharmony_ci 3258c2ecf20Sopenharmony_ci return 0; 3268c2ecf20Sopenharmony_ci} 3278c2ecf20Sopenharmony_ci 3288c2ecf20Sopenharmony_cistatic int pca9541_remove(struct i2c_client *client) 3298c2ecf20Sopenharmony_ci{ 3308c2ecf20Sopenharmony_ci struct i2c_mux_core *muxc = i2c_get_clientdata(client); 3318c2ecf20Sopenharmony_ci 3328c2ecf20Sopenharmony_ci i2c_mux_del_adapters(muxc); 3338c2ecf20Sopenharmony_ci return 0; 3348c2ecf20Sopenharmony_ci} 3358c2ecf20Sopenharmony_ci 3368c2ecf20Sopenharmony_cistatic struct i2c_driver pca9541_driver = { 3378c2ecf20Sopenharmony_ci .driver = { 3388c2ecf20Sopenharmony_ci .name = "pca9541", 3398c2ecf20Sopenharmony_ci .of_match_table = of_match_ptr(pca9541_of_match), 3408c2ecf20Sopenharmony_ci }, 3418c2ecf20Sopenharmony_ci .probe = pca9541_probe, 3428c2ecf20Sopenharmony_ci .remove = pca9541_remove, 3438c2ecf20Sopenharmony_ci .id_table = pca9541_id, 3448c2ecf20Sopenharmony_ci}; 3458c2ecf20Sopenharmony_ci 3468c2ecf20Sopenharmony_cimodule_i2c_driver(pca9541_driver); 3478c2ecf20Sopenharmony_ci 3488c2ecf20Sopenharmony_ciMODULE_AUTHOR("Guenter Roeck <linux@roeck-us.net>"); 3498c2ecf20Sopenharmony_ciMODULE_DESCRIPTION("PCA9541 I2C master selector driver"); 3508c2ecf20Sopenharmony_ciMODULE_LICENSE("GPL v2"); 351