18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * Copyright (c) 2011-2016 Synaptics Incorporated 48c2ecf20Sopenharmony_ci * Copyright (c) 2011 Unixphere 58c2ecf20Sopenharmony_ci */ 68c2ecf20Sopenharmony_ci 78c2ecf20Sopenharmony_ci#include <linux/i2c.h> 88c2ecf20Sopenharmony_ci#include <linux/rmi.h> 98c2ecf20Sopenharmony_ci#include <linux/of.h> 108c2ecf20Sopenharmony_ci#include <linux/delay.h> 118c2ecf20Sopenharmony_ci#include <linux/regulator/consumer.h> 128c2ecf20Sopenharmony_ci#include "rmi_driver.h" 138c2ecf20Sopenharmony_ci 148c2ecf20Sopenharmony_ci#define BUFFER_SIZE_INCREMENT 32 158c2ecf20Sopenharmony_ci 168c2ecf20Sopenharmony_ci/** 178c2ecf20Sopenharmony_ci * struct rmi_i2c_xport - stores information for i2c communication 188c2ecf20Sopenharmony_ci * 198c2ecf20Sopenharmony_ci * @xport: The transport interface structure 208c2ecf20Sopenharmony_ci * 218c2ecf20Sopenharmony_ci * @page_mutex: Locks current page to avoid changing pages in unexpected ways. 228c2ecf20Sopenharmony_ci * @page: Keeps track of the current virtual page 238c2ecf20Sopenharmony_ci * 248c2ecf20Sopenharmony_ci * @tx_buf: Buffer used for transmitting data to the sensor over i2c. 258c2ecf20Sopenharmony_ci * @tx_buf_size: Size of the buffer 268c2ecf20Sopenharmony_ci */ 278c2ecf20Sopenharmony_cistruct rmi_i2c_xport { 288c2ecf20Sopenharmony_ci struct rmi_transport_dev xport; 298c2ecf20Sopenharmony_ci struct i2c_client *client; 308c2ecf20Sopenharmony_ci 318c2ecf20Sopenharmony_ci struct mutex page_mutex; 328c2ecf20Sopenharmony_ci int page; 338c2ecf20Sopenharmony_ci 348c2ecf20Sopenharmony_ci u8 *tx_buf; 358c2ecf20Sopenharmony_ci size_t tx_buf_size; 368c2ecf20Sopenharmony_ci 378c2ecf20Sopenharmony_ci struct regulator_bulk_data supplies[2]; 388c2ecf20Sopenharmony_ci u32 startup_delay; 398c2ecf20Sopenharmony_ci}; 408c2ecf20Sopenharmony_ci 418c2ecf20Sopenharmony_ci#define RMI_PAGE_SELECT_REGISTER 0xff 428c2ecf20Sopenharmony_ci#define RMI_I2C_PAGE(addr) (((addr) >> 8) & 0xff) 438c2ecf20Sopenharmony_ci 448c2ecf20Sopenharmony_ci/* 458c2ecf20Sopenharmony_ci * rmi_set_page - Set RMI page 468c2ecf20Sopenharmony_ci * @xport: The pointer to the rmi_transport_dev struct 478c2ecf20Sopenharmony_ci * @page: The new page address. 488c2ecf20Sopenharmony_ci * 498c2ecf20Sopenharmony_ci * RMI devices have 16-bit addressing, but some of the transport 508c2ecf20Sopenharmony_ci * implementations (like SMBus) only have 8-bit addressing. So RMI implements 518c2ecf20Sopenharmony_ci * a page address at 0xff of every page so we can reliable page addresses 528c2ecf20Sopenharmony_ci * every 256 registers. 538c2ecf20Sopenharmony_ci * 548c2ecf20Sopenharmony_ci * The page_mutex lock must be held when this function is entered. 558c2ecf20Sopenharmony_ci * 568c2ecf20Sopenharmony_ci * Returns zero on success, non-zero on failure. 578c2ecf20Sopenharmony_ci */ 588c2ecf20Sopenharmony_cistatic int rmi_set_page(struct rmi_i2c_xport *rmi_i2c, u8 page) 598c2ecf20Sopenharmony_ci{ 608c2ecf20Sopenharmony_ci struct i2c_client *client = rmi_i2c->client; 618c2ecf20Sopenharmony_ci u8 txbuf[2] = {RMI_PAGE_SELECT_REGISTER, page}; 628c2ecf20Sopenharmony_ci int retval; 638c2ecf20Sopenharmony_ci 648c2ecf20Sopenharmony_ci retval = i2c_master_send(client, txbuf, sizeof(txbuf)); 658c2ecf20Sopenharmony_ci if (retval != sizeof(txbuf)) { 668c2ecf20Sopenharmony_ci dev_err(&client->dev, 678c2ecf20Sopenharmony_ci "%s: set page failed: %d.", __func__, retval); 688c2ecf20Sopenharmony_ci return (retval < 0) ? retval : -EIO; 698c2ecf20Sopenharmony_ci } 708c2ecf20Sopenharmony_ci 718c2ecf20Sopenharmony_ci rmi_i2c->page = page; 728c2ecf20Sopenharmony_ci return 0; 738c2ecf20Sopenharmony_ci} 748c2ecf20Sopenharmony_ci 758c2ecf20Sopenharmony_cistatic int rmi_i2c_write_block(struct rmi_transport_dev *xport, u16 addr, 768c2ecf20Sopenharmony_ci const void *buf, size_t len) 778c2ecf20Sopenharmony_ci{ 788c2ecf20Sopenharmony_ci struct rmi_i2c_xport *rmi_i2c = 798c2ecf20Sopenharmony_ci container_of(xport, struct rmi_i2c_xport, xport); 808c2ecf20Sopenharmony_ci struct i2c_client *client = rmi_i2c->client; 818c2ecf20Sopenharmony_ci size_t tx_size = len + 1; 828c2ecf20Sopenharmony_ci int retval; 838c2ecf20Sopenharmony_ci 848c2ecf20Sopenharmony_ci mutex_lock(&rmi_i2c->page_mutex); 858c2ecf20Sopenharmony_ci 868c2ecf20Sopenharmony_ci if (!rmi_i2c->tx_buf || rmi_i2c->tx_buf_size < tx_size) { 878c2ecf20Sopenharmony_ci if (rmi_i2c->tx_buf) 888c2ecf20Sopenharmony_ci devm_kfree(&client->dev, rmi_i2c->tx_buf); 898c2ecf20Sopenharmony_ci rmi_i2c->tx_buf_size = tx_size + BUFFER_SIZE_INCREMENT; 908c2ecf20Sopenharmony_ci rmi_i2c->tx_buf = devm_kzalloc(&client->dev, 918c2ecf20Sopenharmony_ci rmi_i2c->tx_buf_size, 928c2ecf20Sopenharmony_ci GFP_KERNEL); 938c2ecf20Sopenharmony_ci if (!rmi_i2c->tx_buf) { 948c2ecf20Sopenharmony_ci rmi_i2c->tx_buf_size = 0; 958c2ecf20Sopenharmony_ci retval = -ENOMEM; 968c2ecf20Sopenharmony_ci goto exit; 978c2ecf20Sopenharmony_ci } 988c2ecf20Sopenharmony_ci } 998c2ecf20Sopenharmony_ci 1008c2ecf20Sopenharmony_ci rmi_i2c->tx_buf[0] = addr & 0xff; 1018c2ecf20Sopenharmony_ci memcpy(rmi_i2c->tx_buf + 1, buf, len); 1028c2ecf20Sopenharmony_ci 1038c2ecf20Sopenharmony_ci if (RMI_I2C_PAGE(addr) != rmi_i2c->page) { 1048c2ecf20Sopenharmony_ci retval = rmi_set_page(rmi_i2c, RMI_I2C_PAGE(addr)); 1058c2ecf20Sopenharmony_ci if (retval) 1068c2ecf20Sopenharmony_ci goto exit; 1078c2ecf20Sopenharmony_ci } 1088c2ecf20Sopenharmony_ci 1098c2ecf20Sopenharmony_ci retval = i2c_master_send(client, rmi_i2c->tx_buf, tx_size); 1108c2ecf20Sopenharmony_ci if (retval == tx_size) 1118c2ecf20Sopenharmony_ci retval = 0; 1128c2ecf20Sopenharmony_ci else if (retval >= 0) 1138c2ecf20Sopenharmony_ci retval = -EIO; 1148c2ecf20Sopenharmony_ci 1158c2ecf20Sopenharmony_ciexit: 1168c2ecf20Sopenharmony_ci rmi_dbg(RMI_DEBUG_XPORT, &client->dev, 1178c2ecf20Sopenharmony_ci "write %zd bytes at %#06x: %d (%*ph)\n", 1188c2ecf20Sopenharmony_ci len, addr, retval, (int)len, buf); 1198c2ecf20Sopenharmony_ci 1208c2ecf20Sopenharmony_ci mutex_unlock(&rmi_i2c->page_mutex); 1218c2ecf20Sopenharmony_ci return retval; 1228c2ecf20Sopenharmony_ci} 1238c2ecf20Sopenharmony_ci 1248c2ecf20Sopenharmony_cistatic int rmi_i2c_read_block(struct rmi_transport_dev *xport, u16 addr, 1258c2ecf20Sopenharmony_ci void *buf, size_t len) 1268c2ecf20Sopenharmony_ci{ 1278c2ecf20Sopenharmony_ci struct rmi_i2c_xport *rmi_i2c = 1288c2ecf20Sopenharmony_ci container_of(xport, struct rmi_i2c_xport, xport); 1298c2ecf20Sopenharmony_ci struct i2c_client *client = rmi_i2c->client; 1308c2ecf20Sopenharmony_ci u8 addr_offset = addr & 0xff; 1318c2ecf20Sopenharmony_ci int retval; 1328c2ecf20Sopenharmony_ci struct i2c_msg msgs[] = { 1338c2ecf20Sopenharmony_ci { 1348c2ecf20Sopenharmony_ci .addr = client->addr, 1358c2ecf20Sopenharmony_ci .len = sizeof(addr_offset), 1368c2ecf20Sopenharmony_ci .buf = &addr_offset, 1378c2ecf20Sopenharmony_ci }, 1388c2ecf20Sopenharmony_ci { 1398c2ecf20Sopenharmony_ci .addr = client->addr, 1408c2ecf20Sopenharmony_ci .flags = I2C_M_RD, 1418c2ecf20Sopenharmony_ci .len = len, 1428c2ecf20Sopenharmony_ci .buf = buf, 1438c2ecf20Sopenharmony_ci }, 1448c2ecf20Sopenharmony_ci }; 1458c2ecf20Sopenharmony_ci 1468c2ecf20Sopenharmony_ci mutex_lock(&rmi_i2c->page_mutex); 1478c2ecf20Sopenharmony_ci 1488c2ecf20Sopenharmony_ci if (RMI_I2C_PAGE(addr) != rmi_i2c->page) { 1498c2ecf20Sopenharmony_ci retval = rmi_set_page(rmi_i2c, RMI_I2C_PAGE(addr)); 1508c2ecf20Sopenharmony_ci if (retval) 1518c2ecf20Sopenharmony_ci goto exit; 1528c2ecf20Sopenharmony_ci } 1538c2ecf20Sopenharmony_ci 1548c2ecf20Sopenharmony_ci retval = i2c_transfer(client->adapter, msgs, ARRAY_SIZE(msgs)); 1558c2ecf20Sopenharmony_ci if (retval == ARRAY_SIZE(msgs)) 1568c2ecf20Sopenharmony_ci retval = 0; /* success */ 1578c2ecf20Sopenharmony_ci else if (retval >= 0) 1588c2ecf20Sopenharmony_ci retval = -EIO; 1598c2ecf20Sopenharmony_ci 1608c2ecf20Sopenharmony_ciexit: 1618c2ecf20Sopenharmony_ci rmi_dbg(RMI_DEBUG_XPORT, &client->dev, 1628c2ecf20Sopenharmony_ci "read %zd bytes at %#06x: %d (%*ph)\n", 1638c2ecf20Sopenharmony_ci len, addr, retval, (int)len, buf); 1648c2ecf20Sopenharmony_ci 1658c2ecf20Sopenharmony_ci mutex_unlock(&rmi_i2c->page_mutex); 1668c2ecf20Sopenharmony_ci return retval; 1678c2ecf20Sopenharmony_ci} 1688c2ecf20Sopenharmony_ci 1698c2ecf20Sopenharmony_cistatic const struct rmi_transport_ops rmi_i2c_ops = { 1708c2ecf20Sopenharmony_ci .write_block = rmi_i2c_write_block, 1718c2ecf20Sopenharmony_ci .read_block = rmi_i2c_read_block, 1728c2ecf20Sopenharmony_ci}; 1738c2ecf20Sopenharmony_ci 1748c2ecf20Sopenharmony_ci#ifdef CONFIG_OF 1758c2ecf20Sopenharmony_cistatic const struct of_device_id rmi_i2c_of_match[] = { 1768c2ecf20Sopenharmony_ci { .compatible = "syna,rmi4-i2c" }, 1778c2ecf20Sopenharmony_ci {}, 1788c2ecf20Sopenharmony_ci}; 1798c2ecf20Sopenharmony_ciMODULE_DEVICE_TABLE(of, rmi_i2c_of_match); 1808c2ecf20Sopenharmony_ci#endif 1818c2ecf20Sopenharmony_ci 1828c2ecf20Sopenharmony_cistatic void rmi_i2c_regulator_bulk_disable(void *data) 1838c2ecf20Sopenharmony_ci{ 1848c2ecf20Sopenharmony_ci struct rmi_i2c_xport *rmi_i2c = data; 1858c2ecf20Sopenharmony_ci 1868c2ecf20Sopenharmony_ci regulator_bulk_disable(ARRAY_SIZE(rmi_i2c->supplies), 1878c2ecf20Sopenharmony_ci rmi_i2c->supplies); 1888c2ecf20Sopenharmony_ci} 1898c2ecf20Sopenharmony_ci 1908c2ecf20Sopenharmony_cistatic void rmi_i2c_unregister_transport(void *data) 1918c2ecf20Sopenharmony_ci{ 1928c2ecf20Sopenharmony_ci struct rmi_i2c_xport *rmi_i2c = data; 1938c2ecf20Sopenharmony_ci 1948c2ecf20Sopenharmony_ci rmi_unregister_transport_device(&rmi_i2c->xport); 1958c2ecf20Sopenharmony_ci} 1968c2ecf20Sopenharmony_ci 1978c2ecf20Sopenharmony_cistatic int rmi_i2c_probe(struct i2c_client *client, 1988c2ecf20Sopenharmony_ci const struct i2c_device_id *id) 1998c2ecf20Sopenharmony_ci{ 2008c2ecf20Sopenharmony_ci struct rmi_device_platform_data *pdata; 2018c2ecf20Sopenharmony_ci struct rmi_device_platform_data *client_pdata = 2028c2ecf20Sopenharmony_ci dev_get_platdata(&client->dev); 2038c2ecf20Sopenharmony_ci struct rmi_i2c_xport *rmi_i2c; 2048c2ecf20Sopenharmony_ci int error; 2058c2ecf20Sopenharmony_ci 2068c2ecf20Sopenharmony_ci rmi_i2c = devm_kzalloc(&client->dev, sizeof(struct rmi_i2c_xport), 2078c2ecf20Sopenharmony_ci GFP_KERNEL); 2088c2ecf20Sopenharmony_ci if (!rmi_i2c) 2098c2ecf20Sopenharmony_ci return -ENOMEM; 2108c2ecf20Sopenharmony_ci 2118c2ecf20Sopenharmony_ci pdata = &rmi_i2c->xport.pdata; 2128c2ecf20Sopenharmony_ci 2138c2ecf20Sopenharmony_ci if (!client->dev.of_node && client_pdata) 2148c2ecf20Sopenharmony_ci *pdata = *client_pdata; 2158c2ecf20Sopenharmony_ci 2168c2ecf20Sopenharmony_ci pdata->irq = client->irq; 2178c2ecf20Sopenharmony_ci 2188c2ecf20Sopenharmony_ci rmi_dbg(RMI_DEBUG_XPORT, &client->dev, "Probing %s.\n", 2198c2ecf20Sopenharmony_ci dev_name(&client->dev)); 2208c2ecf20Sopenharmony_ci 2218c2ecf20Sopenharmony_ci if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) { 2228c2ecf20Sopenharmony_ci dev_err(&client->dev, 2238c2ecf20Sopenharmony_ci "adapter does not support required functionality\n"); 2248c2ecf20Sopenharmony_ci return -ENODEV; 2258c2ecf20Sopenharmony_ci } 2268c2ecf20Sopenharmony_ci 2278c2ecf20Sopenharmony_ci rmi_i2c->supplies[0].supply = "vdd"; 2288c2ecf20Sopenharmony_ci rmi_i2c->supplies[1].supply = "vio"; 2298c2ecf20Sopenharmony_ci error = devm_regulator_bulk_get(&client->dev, 2308c2ecf20Sopenharmony_ci ARRAY_SIZE(rmi_i2c->supplies), 2318c2ecf20Sopenharmony_ci rmi_i2c->supplies); 2328c2ecf20Sopenharmony_ci if (error < 0) 2338c2ecf20Sopenharmony_ci return error; 2348c2ecf20Sopenharmony_ci 2358c2ecf20Sopenharmony_ci error = regulator_bulk_enable(ARRAY_SIZE(rmi_i2c->supplies), 2368c2ecf20Sopenharmony_ci rmi_i2c->supplies); 2378c2ecf20Sopenharmony_ci if (error < 0) 2388c2ecf20Sopenharmony_ci return error; 2398c2ecf20Sopenharmony_ci 2408c2ecf20Sopenharmony_ci error = devm_add_action_or_reset(&client->dev, 2418c2ecf20Sopenharmony_ci rmi_i2c_regulator_bulk_disable, 2428c2ecf20Sopenharmony_ci rmi_i2c); 2438c2ecf20Sopenharmony_ci if (error) 2448c2ecf20Sopenharmony_ci return error; 2458c2ecf20Sopenharmony_ci 2468c2ecf20Sopenharmony_ci of_property_read_u32(client->dev.of_node, "syna,startup-delay-ms", 2478c2ecf20Sopenharmony_ci &rmi_i2c->startup_delay); 2488c2ecf20Sopenharmony_ci 2498c2ecf20Sopenharmony_ci msleep(rmi_i2c->startup_delay); 2508c2ecf20Sopenharmony_ci 2518c2ecf20Sopenharmony_ci rmi_i2c->client = client; 2528c2ecf20Sopenharmony_ci mutex_init(&rmi_i2c->page_mutex); 2538c2ecf20Sopenharmony_ci 2548c2ecf20Sopenharmony_ci rmi_i2c->xport.dev = &client->dev; 2558c2ecf20Sopenharmony_ci rmi_i2c->xport.proto_name = "i2c"; 2568c2ecf20Sopenharmony_ci rmi_i2c->xport.ops = &rmi_i2c_ops; 2578c2ecf20Sopenharmony_ci 2588c2ecf20Sopenharmony_ci i2c_set_clientdata(client, rmi_i2c); 2598c2ecf20Sopenharmony_ci 2608c2ecf20Sopenharmony_ci /* 2618c2ecf20Sopenharmony_ci * Setting the page to zero will (a) make sure the PSR is in a 2628c2ecf20Sopenharmony_ci * known state, and (b) make sure we can talk to the device. 2638c2ecf20Sopenharmony_ci */ 2648c2ecf20Sopenharmony_ci error = rmi_set_page(rmi_i2c, 0); 2658c2ecf20Sopenharmony_ci if (error) { 2668c2ecf20Sopenharmony_ci dev_err(&client->dev, "Failed to set page select to 0\n"); 2678c2ecf20Sopenharmony_ci return error; 2688c2ecf20Sopenharmony_ci } 2698c2ecf20Sopenharmony_ci 2708c2ecf20Sopenharmony_ci dev_info(&client->dev, "registering I2C-connected sensor\n"); 2718c2ecf20Sopenharmony_ci 2728c2ecf20Sopenharmony_ci error = rmi_register_transport_device(&rmi_i2c->xport); 2738c2ecf20Sopenharmony_ci if (error) { 2748c2ecf20Sopenharmony_ci dev_err(&client->dev, "failed to register sensor: %d\n", error); 2758c2ecf20Sopenharmony_ci return error; 2768c2ecf20Sopenharmony_ci } 2778c2ecf20Sopenharmony_ci 2788c2ecf20Sopenharmony_ci error = devm_add_action_or_reset(&client->dev, 2798c2ecf20Sopenharmony_ci rmi_i2c_unregister_transport, 2808c2ecf20Sopenharmony_ci rmi_i2c); 2818c2ecf20Sopenharmony_ci if (error) 2828c2ecf20Sopenharmony_ci return error; 2838c2ecf20Sopenharmony_ci 2848c2ecf20Sopenharmony_ci return 0; 2858c2ecf20Sopenharmony_ci} 2868c2ecf20Sopenharmony_ci 2878c2ecf20Sopenharmony_ci#ifdef CONFIG_PM_SLEEP 2888c2ecf20Sopenharmony_cistatic int rmi_i2c_suspend(struct device *dev) 2898c2ecf20Sopenharmony_ci{ 2908c2ecf20Sopenharmony_ci struct i2c_client *client = to_i2c_client(dev); 2918c2ecf20Sopenharmony_ci struct rmi_i2c_xport *rmi_i2c = i2c_get_clientdata(client); 2928c2ecf20Sopenharmony_ci int ret; 2938c2ecf20Sopenharmony_ci 2948c2ecf20Sopenharmony_ci ret = rmi_driver_suspend(rmi_i2c->xport.rmi_dev, true); 2958c2ecf20Sopenharmony_ci if (ret) 2968c2ecf20Sopenharmony_ci dev_warn(dev, "Failed to resume device: %d\n", ret); 2978c2ecf20Sopenharmony_ci 2988c2ecf20Sopenharmony_ci regulator_bulk_disable(ARRAY_SIZE(rmi_i2c->supplies), 2998c2ecf20Sopenharmony_ci rmi_i2c->supplies); 3008c2ecf20Sopenharmony_ci 3018c2ecf20Sopenharmony_ci return ret; 3028c2ecf20Sopenharmony_ci} 3038c2ecf20Sopenharmony_ci 3048c2ecf20Sopenharmony_cistatic int rmi_i2c_resume(struct device *dev) 3058c2ecf20Sopenharmony_ci{ 3068c2ecf20Sopenharmony_ci struct i2c_client *client = to_i2c_client(dev); 3078c2ecf20Sopenharmony_ci struct rmi_i2c_xport *rmi_i2c = i2c_get_clientdata(client); 3088c2ecf20Sopenharmony_ci int ret; 3098c2ecf20Sopenharmony_ci 3108c2ecf20Sopenharmony_ci ret = regulator_bulk_enable(ARRAY_SIZE(rmi_i2c->supplies), 3118c2ecf20Sopenharmony_ci rmi_i2c->supplies); 3128c2ecf20Sopenharmony_ci if (ret) 3138c2ecf20Sopenharmony_ci return ret; 3148c2ecf20Sopenharmony_ci 3158c2ecf20Sopenharmony_ci msleep(rmi_i2c->startup_delay); 3168c2ecf20Sopenharmony_ci 3178c2ecf20Sopenharmony_ci ret = rmi_driver_resume(rmi_i2c->xport.rmi_dev, true); 3188c2ecf20Sopenharmony_ci if (ret) 3198c2ecf20Sopenharmony_ci dev_warn(dev, "Failed to resume device: %d\n", ret); 3208c2ecf20Sopenharmony_ci 3218c2ecf20Sopenharmony_ci return ret; 3228c2ecf20Sopenharmony_ci} 3238c2ecf20Sopenharmony_ci#endif 3248c2ecf20Sopenharmony_ci 3258c2ecf20Sopenharmony_ci#ifdef CONFIG_PM 3268c2ecf20Sopenharmony_cistatic int rmi_i2c_runtime_suspend(struct device *dev) 3278c2ecf20Sopenharmony_ci{ 3288c2ecf20Sopenharmony_ci struct i2c_client *client = to_i2c_client(dev); 3298c2ecf20Sopenharmony_ci struct rmi_i2c_xport *rmi_i2c = i2c_get_clientdata(client); 3308c2ecf20Sopenharmony_ci int ret; 3318c2ecf20Sopenharmony_ci 3328c2ecf20Sopenharmony_ci ret = rmi_driver_suspend(rmi_i2c->xport.rmi_dev, false); 3338c2ecf20Sopenharmony_ci if (ret) 3348c2ecf20Sopenharmony_ci dev_warn(dev, "Failed to resume device: %d\n", ret); 3358c2ecf20Sopenharmony_ci 3368c2ecf20Sopenharmony_ci regulator_bulk_disable(ARRAY_SIZE(rmi_i2c->supplies), 3378c2ecf20Sopenharmony_ci rmi_i2c->supplies); 3388c2ecf20Sopenharmony_ci 3398c2ecf20Sopenharmony_ci return 0; 3408c2ecf20Sopenharmony_ci} 3418c2ecf20Sopenharmony_ci 3428c2ecf20Sopenharmony_cistatic int rmi_i2c_runtime_resume(struct device *dev) 3438c2ecf20Sopenharmony_ci{ 3448c2ecf20Sopenharmony_ci struct i2c_client *client = to_i2c_client(dev); 3458c2ecf20Sopenharmony_ci struct rmi_i2c_xport *rmi_i2c = i2c_get_clientdata(client); 3468c2ecf20Sopenharmony_ci int ret; 3478c2ecf20Sopenharmony_ci 3488c2ecf20Sopenharmony_ci ret = regulator_bulk_enable(ARRAY_SIZE(rmi_i2c->supplies), 3498c2ecf20Sopenharmony_ci rmi_i2c->supplies); 3508c2ecf20Sopenharmony_ci if (ret) 3518c2ecf20Sopenharmony_ci return ret; 3528c2ecf20Sopenharmony_ci 3538c2ecf20Sopenharmony_ci msleep(rmi_i2c->startup_delay); 3548c2ecf20Sopenharmony_ci 3558c2ecf20Sopenharmony_ci ret = rmi_driver_resume(rmi_i2c->xport.rmi_dev, false); 3568c2ecf20Sopenharmony_ci if (ret) 3578c2ecf20Sopenharmony_ci dev_warn(dev, "Failed to resume device: %d\n", ret); 3588c2ecf20Sopenharmony_ci 3598c2ecf20Sopenharmony_ci return 0; 3608c2ecf20Sopenharmony_ci} 3618c2ecf20Sopenharmony_ci#endif 3628c2ecf20Sopenharmony_ci 3638c2ecf20Sopenharmony_cistatic const struct dev_pm_ops rmi_i2c_pm = { 3648c2ecf20Sopenharmony_ci SET_SYSTEM_SLEEP_PM_OPS(rmi_i2c_suspend, rmi_i2c_resume) 3658c2ecf20Sopenharmony_ci SET_RUNTIME_PM_OPS(rmi_i2c_runtime_suspend, rmi_i2c_runtime_resume, 3668c2ecf20Sopenharmony_ci NULL) 3678c2ecf20Sopenharmony_ci}; 3688c2ecf20Sopenharmony_ci 3698c2ecf20Sopenharmony_cistatic const struct i2c_device_id rmi_id[] = { 3708c2ecf20Sopenharmony_ci { "rmi4_i2c", 0 }, 3718c2ecf20Sopenharmony_ci { } 3728c2ecf20Sopenharmony_ci}; 3738c2ecf20Sopenharmony_ciMODULE_DEVICE_TABLE(i2c, rmi_id); 3748c2ecf20Sopenharmony_ci 3758c2ecf20Sopenharmony_cistatic struct i2c_driver rmi_i2c_driver = { 3768c2ecf20Sopenharmony_ci .driver = { 3778c2ecf20Sopenharmony_ci .name = "rmi4_i2c", 3788c2ecf20Sopenharmony_ci .pm = &rmi_i2c_pm, 3798c2ecf20Sopenharmony_ci .of_match_table = of_match_ptr(rmi_i2c_of_match), 3808c2ecf20Sopenharmony_ci }, 3818c2ecf20Sopenharmony_ci .id_table = rmi_id, 3828c2ecf20Sopenharmony_ci .probe = rmi_i2c_probe, 3838c2ecf20Sopenharmony_ci}; 3848c2ecf20Sopenharmony_ci 3858c2ecf20Sopenharmony_cimodule_i2c_driver(rmi_i2c_driver); 3868c2ecf20Sopenharmony_ci 3878c2ecf20Sopenharmony_ciMODULE_AUTHOR("Christopher Heiny <cheiny@synaptics.com>"); 3888c2ecf20Sopenharmony_ciMODULE_AUTHOR("Andrew Duggan <aduggan@synaptics.com>"); 3898c2ecf20Sopenharmony_ciMODULE_DESCRIPTION("RMI I2C driver"); 3908c2ecf20Sopenharmony_ciMODULE_LICENSE("GPL"); 391