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