12b6a321dSAndrew Duggan /* 22b6a321dSAndrew Duggan * Copyright (c) 2011-2016 Synaptics Incorporated 32b6a321dSAndrew Duggan * Copyright (c) 2011 Unixphere 42b6a321dSAndrew Duggan * 52b6a321dSAndrew Duggan * This program is free software; you can redistribute it and/or modify it 62b6a321dSAndrew Duggan * under the terms of the GNU General Public License version 2 as published by 72b6a321dSAndrew Duggan * the Free Software Foundation. 82b6a321dSAndrew Duggan */ 92b6a321dSAndrew Duggan 102b6a321dSAndrew Duggan #include <linux/kernel.h> 112b6a321dSAndrew Duggan #include <linux/kconfig.h> 122b6a321dSAndrew Duggan #include <linux/rmi.h> 132b6a321dSAndrew Duggan #include <linux/slab.h> 142b6a321dSAndrew Duggan #include <linux/uaccess.h> 152b6a321dSAndrew Duggan #include <linux/of.h> 16*ce363f0dSNick Dyer #include <asm/unaligned.h> 172b6a321dSAndrew Duggan #include "rmi_driver.h" 182b6a321dSAndrew Duggan 192b6a321dSAndrew Duggan #define RMI_PRODUCT_ID_LENGTH 10 202b6a321dSAndrew Duggan #define RMI_PRODUCT_INFO_LENGTH 2 212b6a321dSAndrew Duggan 222b6a321dSAndrew Duggan #define RMI_DATE_CODE_LENGTH 3 232b6a321dSAndrew Duggan 242b6a321dSAndrew Duggan #define PRODUCT_ID_OFFSET 0x10 252b6a321dSAndrew Duggan #define PRODUCT_INFO_OFFSET 0x1E 262b6a321dSAndrew Duggan 272b6a321dSAndrew Duggan 282b6a321dSAndrew Duggan /* Force a firmware reset of the sensor */ 292b6a321dSAndrew Duggan #define RMI_F01_CMD_DEVICE_RESET 1 302b6a321dSAndrew Duggan 312b6a321dSAndrew Duggan /* Various F01_RMI_QueryX bits */ 322b6a321dSAndrew Duggan 332b6a321dSAndrew Duggan #define RMI_F01_QRY1_CUSTOM_MAP BIT(0) 342b6a321dSAndrew Duggan #define RMI_F01_QRY1_NON_COMPLIANT BIT(1) 352b6a321dSAndrew Duggan #define RMI_F01_QRY1_HAS_LTS BIT(2) 362b6a321dSAndrew Duggan #define RMI_F01_QRY1_HAS_SENSOR_ID BIT(3) 372b6a321dSAndrew Duggan #define RMI_F01_QRY1_HAS_CHARGER_INP BIT(4) 382b6a321dSAndrew Duggan #define RMI_F01_QRY1_HAS_ADJ_DOZE BIT(5) 392b6a321dSAndrew Duggan #define RMI_F01_QRY1_HAS_ADJ_DOZE_HOFF BIT(6) 402b6a321dSAndrew Duggan #define RMI_F01_QRY1_HAS_QUERY42 BIT(7) 412b6a321dSAndrew Duggan 422b6a321dSAndrew Duggan #define RMI_F01_QRY5_YEAR_MASK 0x1f 432b6a321dSAndrew Duggan #define RMI_F01_QRY6_MONTH_MASK 0x0f 442b6a321dSAndrew Duggan #define RMI_F01_QRY7_DAY_MASK 0x1f 452b6a321dSAndrew Duggan 462b6a321dSAndrew Duggan #define RMI_F01_QRY2_PRODINFO_MASK 0x7f 472b6a321dSAndrew Duggan 482b6a321dSAndrew Duggan #define RMI_F01_BASIC_QUERY_LEN 21 /* From Query 00 through 20 */ 492b6a321dSAndrew Duggan 502b6a321dSAndrew Duggan struct f01_basic_properties { 512b6a321dSAndrew Duggan u8 manufacturer_id; 522b6a321dSAndrew Duggan bool has_lts; 532b6a321dSAndrew Duggan bool has_adjustable_doze; 542b6a321dSAndrew Duggan bool has_adjustable_doze_holdoff; 552b6a321dSAndrew Duggan char dom[11]; /* YYYY/MM/DD + '\0' */ 562b6a321dSAndrew Duggan u8 product_id[RMI_PRODUCT_ID_LENGTH + 1]; 572b6a321dSAndrew Duggan u16 productinfo; 582b6a321dSAndrew Duggan u32 firmware_id; 59*ce363f0dSNick Dyer u32 package_id; 602b6a321dSAndrew Duggan }; 612b6a321dSAndrew Duggan 622b6a321dSAndrew Duggan /* F01 device status bits */ 632b6a321dSAndrew Duggan 642b6a321dSAndrew Duggan /* Most recent device status event */ 652b6a321dSAndrew Duggan #define RMI_F01_STATUS_CODE(status) ((status) & 0x0f) 662b6a321dSAndrew Duggan /* The device has lost its configuration for some reason. */ 672b6a321dSAndrew Duggan #define RMI_F01_STATUS_UNCONFIGURED(status) (!!((status) & 0x80)) 6829fd0ec2SNick Dyer /* The device is in bootloader mode */ 6929fd0ec2SNick Dyer #define RMI_F01_STATUS_BOOTLOADER(status) ((status) & 0x40) 702b6a321dSAndrew Duggan 712b6a321dSAndrew Duggan /* Control register bits */ 722b6a321dSAndrew Duggan 732b6a321dSAndrew Duggan /* 742b6a321dSAndrew Duggan * Sleep mode controls power management on the device and affects all 752b6a321dSAndrew Duggan * functions of the device. 762b6a321dSAndrew Duggan */ 772b6a321dSAndrew Duggan #define RMI_F01_CTRL0_SLEEP_MODE_MASK 0x03 782b6a321dSAndrew Duggan 792b6a321dSAndrew Duggan #define RMI_SLEEP_MODE_NORMAL 0x00 802b6a321dSAndrew Duggan #define RMI_SLEEP_MODE_SENSOR_SLEEP 0x01 812b6a321dSAndrew Duggan #define RMI_SLEEP_MODE_RESERVED0 0x02 822b6a321dSAndrew Duggan #define RMI_SLEEP_MODE_RESERVED1 0x03 832b6a321dSAndrew Duggan 842b6a321dSAndrew Duggan /* 852b6a321dSAndrew Duggan * This bit disables whatever sleep mode may be selected by the sleep_mode 862b6a321dSAndrew Duggan * field and forces the device to run at full power without sleeping. 872b6a321dSAndrew Duggan */ 88e9000b79SNick Dyer #define RMI_F01_CTRL0_NOSLEEP_BIT BIT(2) 892b6a321dSAndrew Duggan 902b6a321dSAndrew Duggan /* 912b6a321dSAndrew Duggan * When this bit is set, the touch controller employs a noise-filtering 922b6a321dSAndrew Duggan * algorithm designed for use with a connected battery charger. 932b6a321dSAndrew Duggan */ 94e9000b79SNick Dyer #define RMI_F01_CTRL0_CHARGER_BIT BIT(5) 952b6a321dSAndrew Duggan 962b6a321dSAndrew Duggan /* 972b6a321dSAndrew Duggan * Sets the report rate for the device. The effect of this setting is 982b6a321dSAndrew Duggan * highly product dependent. Check the spec sheet for your particular 992b6a321dSAndrew Duggan * touch sensor. 1002b6a321dSAndrew Duggan */ 101e9000b79SNick Dyer #define RMI_F01_CTRL0_REPORTRATE_BIT BIT(6) 1022b6a321dSAndrew Duggan 1032b6a321dSAndrew Duggan /* 1042b6a321dSAndrew Duggan * Written by the host as an indicator that the device has been 1052b6a321dSAndrew Duggan * successfully configured. 1062b6a321dSAndrew Duggan */ 107e9000b79SNick Dyer #define RMI_F01_CTRL0_CONFIGURED_BIT BIT(7) 1082b6a321dSAndrew Duggan 1092b6a321dSAndrew Duggan /** 1102b6a321dSAndrew Duggan * @ctrl0 - see the bit definitions above. 1112b6a321dSAndrew Duggan * @doze_interval - controls the interval between checks for finger presence 1122b6a321dSAndrew Duggan * when the touch sensor is in doze mode, in units of 10ms. 1132b6a321dSAndrew Duggan * @wakeup_threshold - controls the capacitance threshold at which the touch 1142b6a321dSAndrew Duggan * sensor will decide to wake up from that low power state. 1152b6a321dSAndrew Duggan * @doze_holdoff - controls how long the touch sensor waits after the last 1162b6a321dSAndrew Duggan * finger lifts before entering the doze state, in units of 100ms. 1172b6a321dSAndrew Duggan */ 1182b6a321dSAndrew Duggan struct f01_device_control { 1192b6a321dSAndrew Duggan u8 ctrl0; 1202b6a321dSAndrew Duggan u8 doze_interval; 1212b6a321dSAndrew Duggan u8 wakeup_threshold; 1222b6a321dSAndrew Duggan u8 doze_holdoff; 1232b6a321dSAndrew Duggan }; 1242b6a321dSAndrew Duggan 1252b6a321dSAndrew Duggan struct f01_data { 1262b6a321dSAndrew Duggan struct f01_basic_properties properties; 1272b6a321dSAndrew Duggan struct f01_device_control device_control; 1282b6a321dSAndrew Duggan 1292b6a321dSAndrew Duggan u16 doze_interval_addr; 1302b6a321dSAndrew Duggan u16 wakeup_threshold_addr; 1312b6a321dSAndrew Duggan u16 doze_holdoff_addr; 1322b6a321dSAndrew Duggan 1332b6a321dSAndrew Duggan bool suspended; 1342b6a321dSAndrew Duggan bool old_nosleep; 1352b6a321dSAndrew Duggan 1362b6a321dSAndrew Duggan unsigned int num_of_irq_regs; 1372b6a321dSAndrew Duggan }; 1382b6a321dSAndrew Duggan 1392b6a321dSAndrew Duggan static int rmi_f01_read_properties(struct rmi_device *rmi_dev, 1402b6a321dSAndrew Duggan u16 query_base_addr, 1412b6a321dSAndrew Duggan struct f01_basic_properties *props) 1422b6a321dSAndrew Duggan { 1432b6a321dSAndrew Duggan u8 queries[RMI_F01_BASIC_QUERY_LEN]; 1442b6a321dSAndrew Duggan int ret; 1452b6a321dSAndrew Duggan int query_offset = query_base_addr; 1462b6a321dSAndrew Duggan bool has_ds4_queries = false; 1472b6a321dSAndrew Duggan bool has_query42 = false; 1482b6a321dSAndrew Duggan bool has_sensor_id = false; 1492b6a321dSAndrew Duggan bool has_package_id_query = false; 1502b6a321dSAndrew Duggan bool has_build_id_query = false; 1512b6a321dSAndrew Duggan u16 prod_info_addr; 1522b6a321dSAndrew Duggan u8 ds4_query_len; 1532b6a321dSAndrew Duggan 1542b6a321dSAndrew Duggan ret = rmi_read_block(rmi_dev, query_offset, 1552b6a321dSAndrew Duggan queries, RMI_F01_BASIC_QUERY_LEN); 1562b6a321dSAndrew Duggan if (ret) { 1572b6a321dSAndrew Duggan dev_err(&rmi_dev->dev, 1582b6a321dSAndrew Duggan "Failed to read device query registers: %d\n", ret); 1592b6a321dSAndrew Duggan return ret; 1602b6a321dSAndrew Duggan } 1612b6a321dSAndrew Duggan 1622b6a321dSAndrew Duggan prod_info_addr = query_offset + 17; 1632b6a321dSAndrew Duggan query_offset += RMI_F01_BASIC_QUERY_LEN; 1642b6a321dSAndrew Duggan 1652b6a321dSAndrew Duggan /* Now parse what we got */ 1662b6a321dSAndrew Duggan props->manufacturer_id = queries[0]; 1672b6a321dSAndrew Duggan 1682b6a321dSAndrew Duggan props->has_lts = queries[1] & RMI_F01_QRY1_HAS_LTS; 1692b6a321dSAndrew Duggan props->has_adjustable_doze = 1702b6a321dSAndrew Duggan queries[1] & RMI_F01_QRY1_HAS_ADJ_DOZE; 1712b6a321dSAndrew Duggan props->has_adjustable_doze_holdoff = 1722b6a321dSAndrew Duggan queries[1] & RMI_F01_QRY1_HAS_ADJ_DOZE_HOFF; 1732b6a321dSAndrew Duggan has_query42 = queries[1] & RMI_F01_QRY1_HAS_QUERY42; 1742b6a321dSAndrew Duggan has_sensor_id = queries[1] & RMI_F01_QRY1_HAS_SENSOR_ID; 1752b6a321dSAndrew Duggan 1762b6a321dSAndrew Duggan snprintf(props->dom, sizeof(props->dom), "20%02d/%02d/%02d", 1772b6a321dSAndrew Duggan queries[5] & RMI_F01_QRY5_YEAR_MASK, 1782b6a321dSAndrew Duggan queries[6] & RMI_F01_QRY6_MONTH_MASK, 1792b6a321dSAndrew Duggan queries[7] & RMI_F01_QRY7_DAY_MASK); 1802b6a321dSAndrew Duggan 1812b6a321dSAndrew Duggan memcpy(props->product_id, &queries[11], 1822b6a321dSAndrew Duggan RMI_PRODUCT_ID_LENGTH); 1832b6a321dSAndrew Duggan props->product_id[RMI_PRODUCT_ID_LENGTH] = '\0'; 1842b6a321dSAndrew Duggan 1852b6a321dSAndrew Duggan props->productinfo = 1862b6a321dSAndrew Duggan ((queries[2] & RMI_F01_QRY2_PRODINFO_MASK) << 7) | 1872b6a321dSAndrew Duggan (queries[3] & RMI_F01_QRY2_PRODINFO_MASK); 1882b6a321dSAndrew Duggan 1892b6a321dSAndrew Duggan if (has_sensor_id) 1902b6a321dSAndrew Duggan query_offset++; 1912b6a321dSAndrew Duggan 1922b6a321dSAndrew Duggan if (has_query42) { 1932b6a321dSAndrew Duggan ret = rmi_read(rmi_dev, query_offset, queries); 1942b6a321dSAndrew Duggan if (ret) { 1952b6a321dSAndrew Duggan dev_err(&rmi_dev->dev, 1962b6a321dSAndrew Duggan "Failed to read query 42 register: %d\n", ret); 1972b6a321dSAndrew Duggan return ret; 1982b6a321dSAndrew Duggan } 1992b6a321dSAndrew Duggan 2002b6a321dSAndrew Duggan has_ds4_queries = !!(queries[0] & BIT(0)); 2012b6a321dSAndrew Duggan query_offset++; 2022b6a321dSAndrew Duggan } 2032b6a321dSAndrew Duggan 2042b6a321dSAndrew Duggan if (has_ds4_queries) { 2052b6a321dSAndrew Duggan ret = rmi_read(rmi_dev, query_offset, &ds4_query_len); 2062b6a321dSAndrew Duggan if (ret) { 2072b6a321dSAndrew Duggan dev_err(&rmi_dev->dev, 2082b6a321dSAndrew Duggan "Failed to read DS4 queries length: %d\n", ret); 2092b6a321dSAndrew Duggan return ret; 2102b6a321dSAndrew Duggan } 2112b6a321dSAndrew Duggan query_offset++; 2122b6a321dSAndrew Duggan 2132b6a321dSAndrew Duggan if (ds4_query_len > 0) { 2142b6a321dSAndrew Duggan ret = rmi_read(rmi_dev, query_offset, queries); 2152b6a321dSAndrew Duggan if (ret) { 2162b6a321dSAndrew Duggan dev_err(&rmi_dev->dev, 2172b6a321dSAndrew Duggan "Failed to read DS4 queries: %d\n", 2182b6a321dSAndrew Duggan ret); 2192b6a321dSAndrew Duggan return ret; 2202b6a321dSAndrew Duggan } 2212b6a321dSAndrew Duggan 2222b6a321dSAndrew Duggan has_package_id_query = !!(queries[0] & BIT(0)); 2232b6a321dSAndrew Duggan has_build_id_query = !!(queries[0] & BIT(1)); 2242b6a321dSAndrew Duggan } 2252b6a321dSAndrew Duggan 226*ce363f0dSNick Dyer if (has_package_id_query) { 227*ce363f0dSNick Dyer ret = rmi_read_block(rmi_dev, prod_info_addr, 228*ce363f0dSNick Dyer queries, sizeof(__le64)); 229*ce363f0dSNick Dyer if (ret) { 230*ce363f0dSNick Dyer dev_err(&rmi_dev->dev, 231*ce363f0dSNick Dyer "Failed to read package info: %d\n", 232*ce363f0dSNick Dyer ret); 233*ce363f0dSNick Dyer return ret; 234*ce363f0dSNick Dyer } 235*ce363f0dSNick Dyer 236*ce363f0dSNick Dyer props->package_id = get_unaligned_le64(queries); 2372b6a321dSAndrew Duggan prod_info_addr++; 238*ce363f0dSNick Dyer } 2392b6a321dSAndrew Duggan 2402b6a321dSAndrew Duggan if (has_build_id_query) { 2412b6a321dSAndrew Duggan ret = rmi_read_block(rmi_dev, prod_info_addr, queries, 2422b6a321dSAndrew Duggan 3); 2432b6a321dSAndrew Duggan if (ret) { 2442b6a321dSAndrew Duggan dev_err(&rmi_dev->dev, 2452b6a321dSAndrew Duggan "Failed to read product info: %d\n", 2462b6a321dSAndrew Duggan ret); 2472b6a321dSAndrew Duggan return ret; 2482b6a321dSAndrew Duggan } 2492b6a321dSAndrew Duggan 2502b6a321dSAndrew Duggan props->firmware_id = queries[1] << 8 | queries[0]; 2512b6a321dSAndrew Duggan props->firmware_id += queries[2] * 65536; 2522b6a321dSAndrew Duggan } 2532b6a321dSAndrew Duggan } 2542b6a321dSAndrew Duggan 2552b6a321dSAndrew Duggan return 0; 2562b6a321dSAndrew Duggan } 2572b6a321dSAndrew Duggan 258*ce363f0dSNick Dyer const char *rmi_f01_get_product_ID(struct rmi_function *fn) 2592b6a321dSAndrew Duggan { 2602b6a321dSAndrew Duggan struct f01_data *f01 = dev_get_drvdata(&fn->dev); 2612b6a321dSAndrew Duggan 2622b6a321dSAndrew Duggan return f01->properties.product_id; 2632b6a321dSAndrew Duggan } 2642b6a321dSAndrew Duggan 265*ce363f0dSNick Dyer static ssize_t rmi_driver_manufacturer_id_show(struct device *dev, 266*ce363f0dSNick Dyer struct device_attribute *dattr, 267*ce363f0dSNick Dyer char *buf) 268*ce363f0dSNick Dyer { 269*ce363f0dSNick Dyer struct rmi_driver_data *data = dev_get_drvdata(dev); 270*ce363f0dSNick Dyer struct f01_data *f01 = dev_get_drvdata(&data->f01_container->dev); 271*ce363f0dSNick Dyer 272*ce363f0dSNick Dyer return scnprintf(buf, PAGE_SIZE, "%d\n", 273*ce363f0dSNick Dyer f01->properties.manufacturer_id); 274*ce363f0dSNick Dyer } 275*ce363f0dSNick Dyer 276*ce363f0dSNick Dyer static DEVICE_ATTR(manufacturer_id, 0444, 277*ce363f0dSNick Dyer rmi_driver_manufacturer_id_show, NULL); 278*ce363f0dSNick Dyer 279*ce363f0dSNick Dyer static ssize_t rmi_driver_dom_show(struct device *dev, 280*ce363f0dSNick Dyer struct device_attribute *dattr, char *buf) 281*ce363f0dSNick Dyer { 282*ce363f0dSNick Dyer struct rmi_driver_data *data = dev_get_drvdata(dev); 283*ce363f0dSNick Dyer struct f01_data *f01 = dev_get_drvdata(&data->f01_container->dev); 284*ce363f0dSNick Dyer 285*ce363f0dSNick Dyer return scnprintf(buf, PAGE_SIZE, "%s\n", f01->properties.dom); 286*ce363f0dSNick Dyer } 287*ce363f0dSNick Dyer 288*ce363f0dSNick Dyer static DEVICE_ATTR(date_of_manufacture, 0444, rmi_driver_dom_show, NULL); 289*ce363f0dSNick Dyer 290*ce363f0dSNick Dyer static ssize_t rmi_driver_product_id_show(struct device *dev, 291*ce363f0dSNick Dyer struct device_attribute *dattr, 292*ce363f0dSNick Dyer char *buf) 293*ce363f0dSNick Dyer { 294*ce363f0dSNick Dyer struct rmi_driver_data *data = dev_get_drvdata(dev); 295*ce363f0dSNick Dyer struct f01_data *f01 = dev_get_drvdata(&data->f01_container->dev); 296*ce363f0dSNick Dyer 297*ce363f0dSNick Dyer return scnprintf(buf, PAGE_SIZE, "%s\n", f01->properties.product_id); 298*ce363f0dSNick Dyer } 299*ce363f0dSNick Dyer 300*ce363f0dSNick Dyer static DEVICE_ATTR(product_id, 0444, rmi_driver_product_id_show, NULL); 301*ce363f0dSNick Dyer 302*ce363f0dSNick Dyer static ssize_t rmi_driver_firmware_id_show(struct device *dev, 303*ce363f0dSNick Dyer struct device_attribute *dattr, 304*ce363f0dSNick Dyer char *buf) 305*ce363f0dSNick Dyer { 306*ce363f0dSNick Dyer struct rmi_driver_data *data = dev_get_drvdata(dev); 307*ce363f0dSNick Dyer struct f01_data *f01 = dev_get_drvdata(&data->f01_container->dev); 308*ce363f0dSNick Dyer 309*ce363f0dSNick Dyer return scnprintf(buf, PAGE_SIZE, "%d\n", f01->properties.firmware_id); 310*ce363f0dSNick Dyer } 311*ce363f0dSNick Dyer 312*ce363f0dSNick Dyer static DEVICE_ATTR(firmware_id, 0444, rmi_driver_firmware_id_show, NULL); 313*ce363f0dSNick Dyer 314*ce363f0dSNick Dyer static ssize_t rmi_driver_package_id_show(struct device *dev, 315*ce363f0dSNick Dyer struct device_attribute *dattr, 316*ce363f0dSNick Dyer char *buf) 317*ce363f0dSNick Dyer { 318*ce363f0dSNick Dyer struct rmi_driver_data *data = dev_get_drvdata(dev); 319*ce363f0dSNick Dyer struct f01_data *f01 = dev_get_drvdata(&data->f01_container->dev); 320*ce363f0dSNick Dyer 321*ce363f0dSNick Dyer u32 package_id = f01->properties.package_id; 322*ce363f0dSNick Dyer 323*ce363f0dSNick Dyer return scnprintf(buf, PAGE_SIZE, "%04x.%04x\n", 324*ce363f0dSNick Dyer package_id & 0xffff, (package_id >> 16) & 0xffff); 325*ce363f0dSNick Dyer } 326*ce363f0dSNick Dyer 327*ce363f0dSNick Dyer static DEVICE_ATTR(package_id, 0444, rmi_driver_package_id_show, NULL); 328*ce363f0dSNick Dyer 329*ce363f0dSNick Dyer static struct attribute *rmi_f01_attrs[] = { 330*ce363f0dSNick Dyer &dev_attr_manufacturer_id.attr, 331*ce363f0dSNick Dyer &dev_attr_date_of_manufacture.attr, 332*ce363f0dSNick Dyer &dev_attr_product_id.attr, 333*ce363f0dSNick Dyer &dev_attr_firmware_id.attr, 334*ce363f0dSNick Dyer &dev_attr_package_id.attr, 335*ce363f0dSNick Dyer NULL 336*ce363f0dSNick Dyer }; 337*ce363f0dSNick Dyer 338*ce363f0dSNick Dyer static struct attribute_group rmi_f01_attr_group = { 339*ce363f0dSNick Dyer .attrs = rmi_f01_attrs, 340*ce363f0dSNick Dyer }; 341*ce363f0dSNick Dyer 342d8a8b3edSAndrew Duggan #ifdef CONFIG_OF 343d8a8b3edSAndrew Duggan static int rmi_f01_of_probe(struct device *dev, 344d8a8b3edSAndrew Duggan struct rmi_device_platform_data *pdata) 345d8a8b3edSAndrew Duggan { 346d8a8b3edSAndrew Duggan int retval; 347d8a8b3edSAndrew Duggan u32 val; 348d8a8b3edSAndrew Duggan 349d8a8b3edSAndrew Duggan retval = rmi_of_property_read_u32(dev, 350d8a8b3edSAndrew Duggan (u32 *)&pdata->power_management.nosleep, 351d8a8b3edSAndrew Duggan "syna,nosleep-mode", 1); 352d8a8b3edSAndrew Duggan if (retval) 353d8a8b3edSAndrew Duggan return retval; 354d8a8b3edSAndrew Duggan 355d8a8b3edSAndrew Duggan retval = rmi_of_property_read_u32(dev, &val, 356d8a8b3edSAndrew Duggan "syna,wakeup-threshold", 1); 357d8a8b3edSAndrew Duggan if (retval) 358d8a8b3edSAndrew Duggan return retval; 359d8a8b3edSAndrew Duggan 360d8a8b3edSAndrew Duggan pdata->power_management.wakeup_threshold = val; 361d8a8b3edSAndrew Duggan 362d8a8b3edSAndrew Duggan retval = rmi_of_property_read_u32(dev, &val, 363d8a8b3edSAndrew Duggan "syna,doze-holdoff-ms", 1); 364d8a8b3edSAndrew Duggan if (retval) 365d8a8b3edSAndrew Duggan return retval; 366d8a8b3edSAndrew Duggan 367d8a8b3edSAndrew Duggan pdata->power_management.doze_holdoff = val * 100; 368d8a8b3edSAndrew Duggan 369d8a8b3edSAndrew Duggan retval = rmi_of_property_read_u32(dev, &val, 370d8a8b3edSAndrew Duggan "syna,doze-interval-ms", 1); 371d8a8b3edSAndrew Duggan if (retval) 372d8a8b3edSAndrew Duggan return retval; 373d8a8b3edSAndrew Duggan 374d8a8b3edSAndrew Duggan pdata->power_management.doze_interval = val / 10; 375d8a8b3edSAndrew Duggan 376d8a8b3edSAndrew Duggan return 0; 377d8a8b3edSAndrew Duggan } 378d8a8b3edSAndrew Duggan #else 379d8a8b3edSAndrew Duggan static inline int rmi_f01_of_probe(struct device *dev, 380d8a8b3edSAndrew Duggan struct rmi_device_platform_data *pdata) 381d8a8b3edSAndrew Duggan { 382d8a8b3edSAndrew Duggan return -ENODEV; 383d8a8b3edSAndrew Duggan } 384d8a8b3edSAndrew Duggan #endif 385d8a8b3edSAndrew Duggan 3862b6a321dSAndrew Duggan static int rmi_f01_probe(struct rmi_function *fn) 3872b6a321dSAndrew Duggan { 3882b6a321dSAndrew Duggan struct rmi_device *rmi_dev = fn->rmi_dev; 3892b6a321dSAndrew Duggan struct rmi_driver_data *driver_data = dev_get_drvdata(&rmi_dev->dev); 3902b6a321dSAndrew Duggan struct rmi_device_platform_data *pdata = rmi_get_platform_data(rmi_dev); 3912b6a321dSAndrew Duggan struct f01_data *f01; 3922b6a321dSAndrew Duggan int error; 3932b6a321dSAndrew Duggan u16 ctrl_base_addr = fn->fd.control_base_addr; 3942b6a321dSAndrew Duggan u8 device_status; 3952b6a321dSAndrew Duggan u8 temp; 3962b6a321dSAndrew Duggan 397d8a8b3edSAndrew Duggan if (fn->dev.of_node) { 398d8a8b3edSAndrew Duggan error = rmi_f01_of_probe(&fn->dev, pdata); 399d8a8b3edSAndrew Duggan if (error) 400d8a8b3edSAndrew Duggan return error; 401d8a8b3edSAndrew Duggan } 402d8a8b3edSAndrew Duggan 4032b6a321dSAndrew Duggan f01 = devm_kzalloc(&fn->dev, sizeof(struct f01_data), GFP_KERNEL); 4042b6a321dSAndrew Duggan if (!f01) 4052b6a321dSAndrew Duggan return -ENOMEM; 4062b6a321dSAndrew Duggan 4072b6a321dSAndrew Duggan f01->num_of_irq_regs = driver_data->num_of_irq_regs; 4082b6a321dSAndrew Duggan 4092b6a321dSAndrew Duggan /* 4102b6a321dSAndrew Duggan * Set the configured bit and (optionally) other important stuff 4112b6a321dSAndrew Duggan * in the device control register. 4122b6a321dSAndrew Duggan */ 4132b6a321dSAndrew Duggan 4142b6a321dSAndrew Duggan error = rmi_read(rmi_dev, fn->fd.control_base_addr, 4152b6a321dSAndrew Duggan &f01->device_control.ctrl0); 4162b6a321dSAndrew Duggan if (error) { 4172b6a321dSAndrew Duggan dev_err(&fn->dev, "Failed to read F01 control: %d\n", error); 4182b6a321dSAndrew Duggan return error; 4192b6a321dSAndrew Duggan } 4202b6a321dSAndrew Duggan 4212b6a321dSAndrew Duggan switch (pdata->power_management.nosleep) { 4222775e523SAndrew Duggan case RMI_REG_STATE_DEFAULT: 4232b6a321dSAndrew Duggan break; 4242775e523SAndrew Duggan case RMI_REG_STATE_OFF: 425e9000b79SNick Dyer f01->device_control.ctrl0 &= ~RMI_F01_CTRL0_NOSLEEP_BIT; 4262b6a321dSAndrew Duggan break; 4272775e523SAndrew Duggan case RMI_REG_STATE_ON: 428e9000b79SNick Dyer f01->device_control.ctrl0 |= RMI_F01_CTRL0_NOSLEEP_BIT; 4292b6a321dSAndrew Duggan break; 4302b6a321dSAndrew Duggan } 4312b6a321dSAndrew Duggan 4322b6a321dSAndrew Duggan /* 4332b6a321dSAndrew Duggan * Sleep mode might be set as a hangover from a system crash or 4342b6a321dSAndrew Duggan * reboot without power cycle. If so, clear it so the sensor 4352b6a321dSAndrew Duggan * is certain to function. 4362b6a321dSAndrew Duggan */ 4372b6a321dSAndrew Duggan if ((f01->device_control.ctrl0 & RMI_F01_CTRL0_SLEEP_MODE_MASK) != 4382b6a321dSAndrew Duggan RMI_SLEEP_MODE_NORMAL) { 4392b6a321dSAndrew Duggan dev_warn(&fn->dev, 4402b6a321dSAndrew Duggan "WARNING: Non-zero sleep mode found. Clearing...\n"); 4412b6a321dSAndrew Duggan f01->device_control.ctrl0 &= ~RMI_F01_CTRL0_SLEEP_MODE_MASK; 4422b6a321dSAndrew Duggan } 4432b6a321dSAndrew Duggan 444e9000b79SNick Dyer f01->device_control.ctrl0 |= RMI_F01_CTRL0_CONFIGURED_BIT; 4452b6a321dSAndrew Duggan 4462b6a321dSAndrew Duggan error = rmi_write(rmi_dev, fn->fd.control_base_addr, 4472b6a321dSAndrew Duggan f01->device_control.ctrl0); 4482b6a321dSAndrew Duggan if (error) { 4492b6a321dSAndrew Duggan dev_err(&fn->dev, "Failed to write F01 control: %d\n", error); 4502b6a321dSAndrew Duggan return error; 4512b6a321dSAndrew Duggan } 4522b6a321dSAndrew Duggan 4532b6a321dSAndrew Duggan /* Dummy read in order to clear irqs */ 4542b6a321dSAndrew Duggan error = rmi_read(rmi_dev, fn->fd.data_base_addr + 1, &temp); 4552b6a321dSAndrew Duggan if (error < 0) { 4562b6a321dSAndrew Duggan dev_err(&fn->dev, "Failed to read Interrupt Status.\n"); 4572b6a321dSAndrew Duggan return error; 4582b6a321dSAndrew Duggan } 4592b6a321dSAndrew Duggan 4602b6a321dSAndrew Duggan error = rmi_f01_read_properties(rmi_dev, fn->fd.query_base_addr, 4612b6a321dSAndrew Duggan &f01->properties); 4622b6a321dSAndrew Duggan if (error < 0) { 4632b6a321dSAndrew Duggan dev_err(&fn->dev, "Failed to read F01 properties.\n"); 4642b6a321dSAndrew Duggan return error; 4652b6a321dSAndrew Duggan } 4662b6a321dSAndrew Duggan 4672b6a321dSAndrew Duggan dev_info(&fn->dev, "found RMI device, manufacturer: %s, product: %s, fw id: %d\n", 4682b6a321dSAndrew Duggan f01->properties.manufacturer_id == 1 ? "Synaptics" : "unknown", 4692b6a321dSAndrew Duggan f01->properties.product_id, f01->properties.firmware_id); 4702b6a321dSAndrew Duggan 4712b6a321dSAndrew Duggan /* Advance to interrupt control registers, then skip over them. */ 4722b6a321dSAndrew Duggan ctrl_base_addr++; 4732b6a321dSAndrew Duggan ctrl_base_addr += f01->num_of_irq_regs; 4742b6a321dSAndrew Duggan 4752b6a321dSAndrew Duggan /* read control register */ 4762b6a321dSAndrew Duggan if (f01->properties.has_adjustable_doze) { 4772b6a321dSAndrew Duggan f01->doze_interval_addr = ctrl_base_addr; 4782b6a321dSAndrew Duggan ctrl_base_addr++; 4792b6a321dSAndrew Duggan 4802b6a321dSAndrew Duggan if (pdata->power_management.doze_interval) { 4812b6a321dSAndrew Duggan f01->device_control.doze_interval = 4822b6a321dSAndrew Duggan pdata->power_management.doze_interval; 4832b6a321dSAndrew Duggan error = rmi_write(rmi_dev, f01->doze_interval_addr, 4842b6a321dSAndrew Duggan f01->device_control.doze_interval); 4852b6a321dSAndrew Duggan if (error) { 4862b6a321dSAndrew Duggan dev_err(&fn->dev, 4872b6a321dSAndrew Duggan "Failed to configure F01 doze interval register: %d\n", 4882b6a321dSAndrew Duggan error); 4892b6a321dSAndrew Duggan return error; 4902b6a321dSAndrew Duggan } 4912b6a321dSAndrew Duggan } else { 4922b6a321dSAndrew Duggan error = rmi_read(rmi_dev, f01->doze_interval_addr, 4932b6a321dSAndrew Duggan &f01->device_control.doze_interval); 4942b6a321dSAndrew Duggan if (error) { 4952b6a321dSAndrew Duggan dev_err(&fn->dev, 4962b6a321dSAndrew Duggan "Failed to read F01 doze interval register: %d\n", 4972b6a321dSAndrew Duggan error); 4982b6a321dSAndrew Duggan return error; 4992b6a321dSAndrew Duggan } 5002b6a321dSAndrew Duggan } 5012b6a321dSAndrew Duggan 5022b6a321dSAndrew Duggan f01->wakeup_threshold_addr = ctrl_base_addr; 5032b6a321dSAndrew Duggan ctrl_base_addr++; 5042b6a321dSAndrew Duggan 5052b6a321dSAndrew Duggan if (pdata->power_management.wakeup_threshold) { 5062b6a321dSAndrew Duggan f01->device_control.wakeup_threshold = 5072b6a321dSAndrew Duggan pdata->power_management.wakeup_threshold; 5082b6a321dSAndrew Duggan error = rmi_write(rmi_dev, f01->wakeup_threshold_addr, 5092b6a321dSAndrew Duggan f01->device_control.wakeup_threshold); 5102b6a321dSAndrew Duggan if (error) { 5112b6a321dSAndrew Duggan dev_err(&fn->dev, 5122b6a321dSAndrew Duggan "Failed to configure F01 wakeup threshold register: %d\n", 5132b6a321dSAndrew Duggan error); 5142b6a321dSAndrew Duggan return error; 5152b6a321dSAndrew Duggan } 5162b6a321dSAndrew Duggan } else { 5172b6a321dSAndrew Duggan error = rmi_read(rmi_dev, f01->wakeup_threshold_addr, 5182b6a321dSAndrew Duggan &f01->device_control.wakeup_threshold); 5192b6a321dSAndrew Duggan if (error < 0) { 5202b6a321dSAndrew Duggan dev_err(&fn->dev, 5212b6a321dSAndrew Duggan "Failed to read F01 wakeup threshold register: %d\n", 5222b6a321dSAndrew Duggan error); 5232b6a321dSAndrew Duggan return error; 5242b6a321dSAndrew Duggan } 5252b6a321dSAndrew Duggan } 5262b6a321dSAndrew Duggan } 5272b6a321dSAndrew Duggan 5282b6a321dSAndrew Duggan if (f01->properties.has_lts) 5292b6a321dSAndrew Duggan ctrl_base_addr++; 5302b6a321dSAndrew Duggan 5312b6a321dSAndrew Duggan if (f01->properties.has_adjustable_doze_holdoff) { 5322b6a321dSAndrew Duggan f01->doze_holdoff_addr = ctrl_base_addr; 5332b6a321dSAndrew Duggan ctrl_base_addr++; 5342b6a321dSAndrew Duggan 5352b6a321dSAndrew Duggan if (pdata->power_management.doze_holdoff) { 5362b6a321dSAndrew Duggan f01->device_control.doze_holdoff = 5372b6a321dSAndrew Duggan pdata->power_management.doze_holdoff; 5382b6a321dSAndrew Duggan error = rmi_write(rmi_dev, f01->doze_holdoff_addr, 5392b6a321dSAndrew Duggan f01->device_control.doze_holdoff); 5402b6a321dSAndrew Duggan if (error) { 5412b6a321dSAndrew Duggan dev_err(&fn->dev, 5422b6a321dSAndrew Duggan "Failed to configure F01 doze holdoff register: %d\n", 5432b6a321dSAndrew Duggan error); 5442b6a321dSAndrew Duggan return error; 5452b6a321dSAndrew Duggan } 5462b6a321dSAndrew Duggan } else { 5472b6a321dSAndrew Duggan error = rmi_read(rmi_dev, f01->doze_holdoff_addr, 5482b6a321dSAndrew Duggan &f01->device_control.doze_holdoff); 5492b6a321dSAndrew Duggan if (error) { 5502b6a321dSAndrew Duggan dev_err(&fn->dev, 5512b6a321dSAndrew Duggan "Failed to read F01 doze holdoff register: %d\n", 5522b6a321dSAndrew Duggan error); 5532b6a321dSAndrew Duggan return error; 5542b6a321dSAndrew Duggan } 5552b6a321dSAndrew Duggan } 5562b6a321dSAndrew Duggan } 5572b6a321dSAndrew Duggan 5582b6a321dSAndrew Duggan error = rmi_read(rmi_dev, fn->fd.data_base_addr, &device_status); 5592b6a321dSAndrew Duggan if (error < 0) { 5602b6a321dSAndrew Duggan dev_err(&fn->dev, 5612b6a321dSAndrew Duggan "Failed to read device status: %d\n", error); 5622b6a321dSAndrew Duggan return error; 5632b6a321dSAndrew Duggan } 5642b6a321dSAndrew Duggan 5652b6a321dSAndrew Duggan if (RMI_F01_STATUS_UNCONFIGURED(device_status)) { 5662b6a321dSAndrew Duggan dev_err(&fn->dev, 5672b6a321dSAndrew Duggan "Device was reset during configuration process, status: %#02x!\n", 5682b6a321dSAndrew Duggan RMI_F01_STATUS_CODE(device_status)); 5692b6a321dSAndrew Duggan return -EINVAL; 5702b6a321dSAndrew Duggan } 5712b6a321dSAndrew Duggan 5722b6a321dSAndrew Duggan dev_set_drvdata(&fn->dev, f01); 5732b6a321dSAndrew Duggan 574*ce363f0dSNick Dyer error = sysfs_create_group(&fn->rmi_dev->dev.kobj, &rmi_f01_attr_group); 575*ce363f0dSNick Dyer if (error) 576*ce363f0dSNick Dyer dev_warn(&fn->dev, "Failed to create sysfs group: %d\n", error); 577*ce363f0dSNick Dyer 5782b6a321dSAndrew Duggan return 0; 5792b6a321dSAndrew Duggan } 5802b6a321dSAndrew Duggan 581*ce363f0dSNick Dyer static void rmi_f01_remove(struct rmi_function *fn) 582*ce363f0dSNick Dyer { 583*ce363f0dSNick Dyer sysfs_remove_group(&fn->rmi_dev->dev.kobj, &rmi_f01_attr_group); 584*ce363f0dSNick Dyer } 585*ce363f0dSNick Dyer 5862b6a321dSAndrew Duggan static int rmi_f01_config(struct rmi_function *fn) 5872b6a321dSAndrew Duggan { 5882b6a321dSAndrew Duggan struct f01_data *f01 = dev_get_drvdata(&fn->dev); 5892b6a321dSAndrew Duggan int error; 5902b6a321dSAndrew Duggan 5912b6a321dSAndrew Duggan error = rmi_write(fn->rmi_dev, fn->fd.control_base_addr, 5922b6a321dSAndrew Duggan f01->device_control.ctrl0); 5932b6a321dSAndrew Duggan if (error) { 5942b6a321dSAndrew Duggan dev_err(&fn->dev, 5952b6a321dSAndrew Duggan "Failed to write device_control register: %d\n", error); 5962b6a321dSAndrew Duggan return error; 5972b6a321dSAndrew Duggan } 5982b6a321dSAndrew Duggan 5992b6a321dSAndrew Duggan if (f01->properties.has_adjustable_doze) { 6002b6a321dSAndrew Duggan error = rmi_write(fn->rmi_dev, f01->doze_interval_addr, 6012b6a321dSAndrew Duggan f01->device_control.doze_interval); 6022b6a321dSAndrew Duggan if (error) { 6032b6a321dSAndrew Duggan dev_err(&fn->dev, 6042b6a321dSAndrew Duggan "Failed to write doze interval: %d\n", error); 6052b6a321dSAndrew Duggan return error; 6062b6a321dSAndrew Duggan } 6072b6a321dSAndrew Duggan 6082b6a321dSAndrew Duggan error = rmi_write_block(fn->rmi_dev, 6092b6a321dSAndrew Duggan f01->wakeup_threshold_addr, 6102b6a321dSAndrew Duggan &f01->device_control.wakeup_threshold, 6112b6a321dSAndrew Duggan sizeof(u8)); 6122b6a321dSAndrew Duggan if (error) { 6132b6a321dSAndrew Duggan dev_err(&fn->dev, 6142b6a321dSAndrew Duggan "Failed to write wakeup threshold: %d\n", 6152b6a321dSAndrew Duggan error); 6162b6a321dSAndrew Duggan return error; 6172b6a321dSAndrew Duggan } 6182b6a321dSAndrew Duggan } 6192b6a321dSAndrew Duggan 6202b6a321dSAndrew Duggan if (f01->properties.has_adjustable_doze_holdoff) { 6212b6a321dSAndrew Duggan error = rmi_write(fn->rmi_dev, f01->doze_holdoff_addr, 6222b6a321dSAndrew Duggan f01->device_control.doze_holdoff); 6232b6a321dSAndrew Duggan if (error) { 6242b6a321dSAndrew Duggan dev_err(&fn->dev, 6252b6a321dSAndrew Duggan "Failed to write doze holdoff: %d\n", error); 6262b6a321dSAndrew Duggan return error; 6272b6a321dSAndrew Duggan } 6282b6a321dSAndrew Duggan } 6292b6a321dSAndrew Duggan 6302b6a321dSAndrew Duggan return 0; 6312b6a321dSAndrew Duggan } 6322b6a321dSAndrew Duggan 6332b6a321dSAndrew Duggan static int rmi_f01_suspend(struct rmi_function *fn) 6342b6a321dSAndrew Duggan { 6352b6a321dSAndrew Duggan struct f01_data *f01 = dev_get_drvdata(&fn->dev); 6362b6a321dSAndrew Duggan int error; 6372b6a321dSAndrew Duggan 6382b6a321dSAndrew Duggan f01->old_nosleep = 639e9000b79SNick Dyer f01->device_control.ctrl0 & RMI_F01_CTRL0_NOSLEEP_BIT; 640e9000b79SNick Dyer f01->device_control.ctrl0 &= ~RMI_F01_CTRL0_NOSLEEP_BIT; 6412b6a321dSAndrew Duggan 6422b6a321dSAndrew Duggan f01->device_control.ctrl0 &= ~RMI_F01_CTRL0_SLEEP_MODE_MASK; 6432b6a321dSAndrew Duggan if (device_may_wakeup(fn->rmi_dev->xport->dev)) 6442b6a321dSAndrew Duggan f01->device_control.ctrl0 |= RMI_SLEEP_MODE_RESERVED1; 6452b6a321dSAndrew Duggan else 6462b6a321dSAndrew Duggan f01->device_control.ctrl0 |= RMI_SLEEP_MODE_SENSOR_SLEEP; 6472b6a321dSAndrew Duggan 6482b6a321dSAndrew Duggan error = rmi_write(fn->rmi_dev, fn->fd.control_base_addr, 6492b6a321dSAndrew Duggan f01->device_control.ctrl0); 6502b6a321dSAndrew Duggan if (error) { 6512b6a321dSAndrew Duggan dev_err(&fn->dev, "Failed to write sleep mode: %d.\n", error); 6522b6a321dSAndrew Duggan if (f01->old_nosleep) 653e9000b79SNick Dyer f01->device_control.ctrl0 |= RMI_F01_CTRL0_NOSLEEP_BIT; 6542b6a321dSAndrew Duggan f01->device_control.ctrl0 &= ~RMI_F01_CTRL0_SLEEP_MODE_MASK; 6552b6a321dSAndrew Duggan f01->device_control.ctrl0 |= RMI_SLEEP_MODE_NORMAL; 6562b6a321dSAndrew Duggan return error; 6572b6a321dSAndrew Duggan } 6582b6a321dSAndrew Duggan 6592b6a321dSAndrew Duggan return 0; 6602b6a321dSAndrew Duggan } 6612b6a321dSAndrew Duggan 6622b6a321dSAndrew Duggan static int rmi_f01_resume(struct rmi_function *fn) 6632b6a321dSAndrew Duggan { 6642b6a321dSAndrew Duggan struct f01_data *f01 = dev_get_drvdata(&fn->dev); 6652b6a321dSAndrew Duggan int error; 6662b6a321dSAndrew Duggan 6672b6a321dSAndrew Duggan if (f01->old_nosleep) 668e9000b79SNick Dyer f01->device_control.ctrl0 |= RMI_F01_CTRL0_NOSLEEP_BIT; 6692b6a321dSAndrew Duggan 6702b6a321dSAndrew Duggan f01->device_control.ctrl0 &= ~RMI_F01_CTRL0_SLEEP_MODE_MASK; 6712b6a321dSAndrew Duggan f01->device_control.ctrl0 |= RMI_SLEEP_MODE_NORMAL; 6722b6a321dSAndrew Duggan 6732b6a321dSAndrew Duggan error = rmi_write(fn->rmi_dev, fn->fd.control_base_addr, 6742b6a321dSAndrew Duggan f01->device_control.ctrl0); 6752b6a321dSAndrew Duggan if (error) { 6762b6a321dSAndrew Duggan dev_err(&fn->dev, 6772b6a321dSAndrew Duggan "Failed to restore normal operation: %d.\n", error); 6782b6a321dSAndrew Duggan return error; 6792b6a321dSAndrew Duggan } 6802b6a321dSAndrew Duggan 6812b6a321dSAndrew Duggan return 0; 6822b6a321dSAndrew Duggan } 6832b6a321dSAndrew Duggan 6842b6a321dSAndrew Duggan static int rmi_f01_attention(struct rmi_function *fn, 6852b6a321dSAndrew Duggan unsigned long *irq_bits) 6862b6a321dSAndrew Duggan { 6872b6a321dSAndrew Duggan struct rmi_device *rmi_dev = fn->rmi_dev; 6882b6a321dSAndrew Duggan int error; 6892b6a321dSAndrew Duggan u8 device_status; 6902b6a321dSAndrew Duggan 6912b6a321dSAndrew Duggan error = rmi_read(rmi_dev, fn->fd.data_base_addr, &device_status); 6922b6a321dSAndrew Duggan if (error) { 6932b6a321dSAndrew Duggan dev_err(&fn->dev, 6942b6a321dSAndrew Duggan "Failed to read device status: %d.\n", error); 6952b6a321dSAndrew Duggan return error; 6962b6a321dSAndrew Duggan } 6972b6a321dSAndrew Duggan 69829fd0ec2SNick Dyer if (RMI_F01_STATUS_BOOTLOADER(device_status)) 69929fd0ec2SNick Dyer dev_warn(&fn->dev, 70029fd0ec2SNick Dyer "Device in bootloader mode, please update firmware\n"); 70129fd0ec2SNick Dyer 7022b6a321dSAndrew Duggan if (RMI_F01_STATUS_UNCONFIGURED(device_status)) { 7032b6a321dSAndrew Duggan dev_warn(&fn->dev, "Device reset detected.\n"); 7042b6a321dSAndrew Duggan error = rmi_dev->driver->reset_handler(rmi_dev); 7052b6a321dSAndrew Duggan if (error) { 7062b6a321dSAndrew Duggan dev_err(&fn->dev, "Device reset failed: %d\n", error); 7072b6a321dSAndrew Duggan return error; 7082b6a321dSAndrew Duggan } 7092b6a321dSAndrew Duggan } 7102b6a321dSAndrew Duggan 7112b6a321dSAndrew Duggan return 0; 7122b6a321dSAndrew Duggan } 7132b6a321dSAndrew Duggan 7142b6a321dSAndrew Duggan struct rmi_function_handler rmi_f01_handler = { 7152b6a321dSAndrew Duggan .driver = { 7162b6a321dSAndrew Duggan .name = "rmi4_f01", 7172b6a321dSAndrew Duggan /* 7182b6a321dSAndrew Duggan * Do not allow user unbinding F01 as it is critical 7192b6a321dSAndrew Duggan * function. 7202b6a321dSAndrew Duggan */ 7212b6a321dSAndrew Duggan .suppress_bind_attrs = true, 7222b6a321dSAndrew Duggan }, 7232b6a321dSAndrew Duggan .func = 0x01, 7242b6a321dSAndrew Duggan .probe = rmi_f01_probe, 725*ce363f0dSNick Dyer .remove = rmi_f01_remove, 7262b6a321dSAndrew Duggan .config = rmi_f01_config, 7272b6a321dSAndrew Duggan .attention = rmi_f01_attention, 7282b6a321dSAndrew Duggan .suspend = rmi_f01_suspend, 7292b6a321dSAndrew Duggan .resume = rmi_f01_resume, 7302b6a321dSAndrew Duggan }; 731