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> 162b6a321dSAndrew Duggan #include "rmi_driver.h" 172b6a321dSAndrew Duggan 182b6a321dSAndrew Duggan #define RMI_PRODUCT_ID_LENGTH 10 192b6a321dSAndrew Duggan #define RMI_PRODUCT_INFO_LENGTH 2 202b6a321dSAndrew Duggan 212b6a321dSAndrew Duggan #define RMI_DATE_CODE_LENGTH 3 222b6a321dSAndrew Duggan 232b6a321dSAndrew Duggan #define PRODUCT_ID_OFFSET 0x10 242b6a321dSAndrew Duggan #define PRODUCT_INFO_OFFSET 0x1E 252b6a321dSAndrew Duggan 262b6a321dSAndrew Duggan 272b6a321dSAndrew Duggan /* Force a firmware reset of the sensor */ 282b6a321dSAndrew Duggan #define RMI_F01_CMD_DEVICE_RESET 1 292b6a321dSAndrew Duggan 302b6a321dSAndrew Duggan /* Various F01_RMI_QueryX bits */ 312b6a321dSAndrew Duggan 322b6a321dSAndrew Duggan #define RMI_F01_QRY1_CUSTOM_MAP BIT(0) 332b6a321dSAndrew Duggan #define RMI_F01_QRY1_NON_COMPLIANT BIT(1) 342b6a321dSAndrew Duggan #define RMI_F01_QRY1_HAS_LTS BIT(2) 352b6a321dSAndrew Duggan #define RMI_F01_QRY1_HAS_SENSOR_ID BIT(3) 362b6a321dSAndrew Duggan #define RMI_F01_QRY1_HAS_CHARGER_INP BIT(4) 372b6a321dSAndrew Duggan #define RMI_F01_QRY1_HAS_ADJ_DOZE BIT(5) 382b6a321dSAndrew Duggan #define RMI_F01_QRY1_HAS_ADJ_DOZE_HOFF BIT(6) 392b6a321dSAndrew Duggan #define RMI_F01_QRY1_HAS_QUERY42 BIT(7) 402b6a321dSAndrew Duggan 412b6a321dSAndrew Duggan #define RMI_F01_QRY5_YEAR_MASK 0x1f 422b6a321dSAndrew Duggan #define RMI_F01_QRY6_MONTH_MASK 0x0f 432b6a321dSAndrew Duggan #define RMI_F01_QRY7_DAY_MASK 0x1f 442b6a321dSAndrew Duggan 452b6a321dSAndrew Duggan #define RMI_F01_QRY2_PRODINFO_MASK 0x7f 462b6a321dSAndrew Duggan 472b6a321dSAndrew Duggan #define RMI_F01_BASIC_QUERY_LEN 21 /* From Query 00 through 20 */ 482b6a321dSAndrew Duggan 492b6a321dSAndrew Duggan struct f01_basic_properties { 502b6a321dSAndrew Duggan u8 manufacturer_id; 512b6a321dSAndrew Duggan bool has_lts; 522b6a321dSAndrew Duggan bool has_adjustable_doze; 532b6a321dSAndrew Duggan bool has_adjustable_doze_holdoff; 542b6a321dSAndrew Duggan char dom[11]; /* YYYY/MM/DD + '\0' */ 552b6a321dSAndrew Duggan u8 product_id[RMI_PRODUCT_ID_LENGTH + 1]; 562b6a321dSAndrew Duggan u16 productinfo; 572b6a321dSAndrew Duggan u32 firmware_id; 582b6a321dSAndrew Duggan }; 592b6a321dSAndrew Duggan 602b6a321dSAndrew Duggan /* F01 device status bits */ 612b6a321dSAndrew Duggan 622b6a321dSAndrew Duggan /* Most recent device status event */ 632b6a321dSAndrew Duggan #define RMI_F01_STATUS_CODE(status) ((status) & 0x0f) 642b6a321dSAndrew Duggan /* The device has lost its configuration for some reason. */ 652b6a321dSAndrew Duggan #define RMI_F01_STATUS_UNCONFIGURED(status) (!!((status) & 0x80)) 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 /** 1062b6a321dSAndrew Duggan * @ctrl0 - see the bit definitions above. 1072b6a321dSAndrew Duggan * @doze_interval - controls the interval between checks for finger presence 1082b6a321dSAndrew Duggan * when the touch sensor is in doze mode, in units of 10ms. 1092b6a321dSAndrew Duggan * @wakeup_threshold - controls the capacitance threshold at which the touch 1102b6a321dSAndrew Duggan * sensor will decide to wake up from that low power state. 1112b6a321dSAndrew Duggan * @doze_holdoff - controls how long the touch sensor waits after the last 1122b6a321dSAndrew Duggan * finger lifts before entering the doze state, in units of 100ms. 1132b6a321dSAndrew Duggan */ 1142b6a321dSAndrew Duggan struct f01_device_control { 1152b6a321dSAndrew Duggan u8 ctrl0; 1162b6a321dSAndrew Duggan u8 doze_interval; 1172b6a321dSAndrew Duggan u8 wakeup_threshold; 1182b6a321dSAndrew Duggan u8 doze_holdoff; 1192b6a321dSAndrew Duggan }; 1202b6a321dSAndrew Duggan 1212b6a321dSAndrew Duggan struct f01_data { 1222b6a321dSAndrew Duggan struct f01_basic_properties properties; 1232b6a321dSAndrew Duggan struct f01_device_control device_control; 1242b6a321dSAndrew Duggan 1252b6a321dSAndrew Duggan u16 doze_interval_addr; 1262b6a321dSAndrew Duggan u16 wakeup_threshold_addr; 1272b6a321dSAndrew Duggan u16 doze_holdoff_addr; 1282b6a321dSAndrew Duggan 1292b6a321dSAndrew Duggan bool suspended; 1302b6a321dSAndrew Duggan bool old_nosleep; 1312b6a321dSAndrew Duggan 1322b6a321dSAndrew Duggan unsigned int num_of_irq_regs; 1332b6a321dSAndrew Duggan }; 1342b6a321dSAndrew Duggan 1352b6a321dSAndrew Duggan static int rmi_f01_read_properties(struct rmi_device *rmi_dev, 1362b6a321dSAndrew Duggan u16 query_base_addr, 1372b6a321dSAndrew Duggan struct f01_basic_properties *props) 1382b6a321dSAndrew Duggan { 1392b6a321dSAndrew Duggan u8 queries[RMI_F01_BASIC_QUERY_LEN]; 1402b6a321dSAndrew Duggan int ret; 1412b6a321dSAndrew Duggan int query_offset = query_base_addr; 1422b6a321dSAndrew Duggan bool has_ds4_queries = false; 1432b6a321dSAndrew Duggan bool has_query42 = false; 1442b6a321dSAndrew Duggan bool has_sensor_id = false; 1452b6a321dSAndrew Duggan bool has_package_id_query = false; 1462b6a321dSAndrew Duggan bool has_build_id_query = false; 1472b6a321dSAndrew Duggan u16 prod_info_addr; 1482b6a321dSAndrew Duggan u8 ds4_query_len; 1492b6a321dSAndrew Duggan 1502b6a321dSAndrew Duggan ret = rmi_read_block(rmi_dev, query_offset, 1512b6a321dSAndrew Duggan queries, RMI_F01_BASIC_QUERY_LEN); 1522b6a321dSAndrew Duggan if (ret) { 1532b6a321dSAndrew Duggan dev_err(&rmi_dev->dev, 1542b6a321dSAndrew Duggan "Failed to read device query registers: %d\n", ret); 1552b6a321dSAndrew Duggan return ret; 1562b6a321dSAndrew Duggan } 1572b6a321dSAndrew Duggan 1582b6a321dSAndrew Duggan prod_info_addr = query_offset + 17; 1592b6a321dSAndrew Duggan query_offset += RMI_F01_BASIC_QUERY_LEN; 1602b6a321dSAndrew Duggan 1612b6a321dSAndrew Duggan /* Now parse what we got */ 1622b6a321dSAndrew Duggan props->manufacturer_id = queries[0]; 1632b6a321dSAndrew Duggan 1642b6a321dSAndrew Duggan props->has_lts = queries[1] & RMI_F01_QRY1_HAS_LTS; 1652b6a321dSAndrew Duggan props->has_adjustable_doze = 1662b6a321dSAndrew Duggan queries[1] & RMI_F01_QRY1_HAS_ADJ_DOZE; 1672b6a321dSAndrew Duggan props->has_adjustable_doze_holdoff = 1682b6a321dSAndrew Duggan queries[1] & RMI_F01_QRY1_HAS_ADJ_DOZE_HOFF; 1692b6a321dSAndrew Duggan has_query42 = queries[1] & RMI_F01_QRY1_HAS_QUERY42; 1702b6a321dSAndrew Duggan has_sensor_id = queries[1] & RMI_F01_QRY1_HAS_SENSOR_ID; 1712b6a321dSAndrew Duggan 1722b6a321dSAndrew Duggan snprintf(props->dom, sizeof(props->dom), "20%02d/%02d/%02d", 1732b6a321dSAndrew Duggan queries[5] & RMI_F01_QRY5_YEAR_MASK, 1742b6a321dSAndrew Duggan queries[6] & RMI_F01_QRY6_MONTH_MASK, 1752b6a321dSAndrew Duggan queries[7] & RMI_F01_QRY7_DAY_MASK); 1762b6a321dSAndrew Duggan 1772b6a321dSAndrew Duggan memcpy(props->product_id, &queries[11], 1782b6a321dSAndrew Duggan RMI_PRODUCT_ID_LENGTH); 1792b6a321dSAndrew Duggan props->product_id[RMI_PRODUCT_ID_LENGTH] = '\0'; 1802b6a321dSAndrew Duggan 1812b6a321dSAndrew Duggan props->productinfo = 1822b6a321dSAndrew Duggan ((queries[2] & RMI_F01_QRY2_PRODINFO_MASK) << 7) | 1832b6a321dSAndrew Duggan (queries[3] & RMI_F01_QRY2_PRODINFO_MASK); 1842b6a321dSAndrew Duggan 1852b6a321dSAndrew Duggan if (has_sensor_id) 1862b6a321dSAndrew Duggan query_offset++; 1872b6a321dSAndrew Duggan 1882b6a321dSAndrew Duggan if (has_query42) { 1892b6a321dSAndrew Duggan ret = rmi_read(rmi_dev, query_offset, queries); 1902b6a321dSAndrew Duggan if (ret) { 1912b6a321dSAndrew Duggan dev_err(&rmi_dev->dev, 1922b6a321dSAndrew Duggan "Failed to read query 42 register: %d\n", ret); 1932b6a321dSAndrew Duggan return ret; 1942b6a321dSAndrew Duggan } 1952b6a321dSAndrew Duggan 1962b6a321dSAndrew Duggan has_ds4_queries = !!(queries[0] & BIT(0)); 1972b6a321dSAndrew Duggan query_offset++; 1982b6a321dSAndrew Duggan } 1992b6a321dSAndrew Duggan 2002b6a321dSAndrew Duggan if (has_ds4_queries) { 2012b6a321dSAndrew Duggan ret = rmi_read(rmi_dev, query_offset, &ds4_query_len); 2022b6a321dSAndrew Duggan if (ret) { 2032b6a321dSAndrew Duggan dev_err(&rmi_dev->dev, 2042b6a321dSAndrew Duggan "Failed to read DS4 queries length: %d\n", ret); 2052b6a321dSAndrew Duggan return ret; 2062b6a321dSAndrew Duggan } 2072b6a321dSAndrew Duggan query_offset++; 2082b6a321dSAndrew Duggan 2092b6a321dSAndrew Duggan if (ds4_query_len > 0) { 2102b6a321dSAndrew Duggan ret = rmi_read(rmi_dev, query_offset, queries); 2112b6a321dSAndrew Duggan if (ret) { 2122b6a321dSAndrew Duggan dev_err(&rmi_dev->dev, 2132b6a321dSAndrew Duggan "Failed to read DS4 queries: %d\n", 2142b6a321dSAndrew Duggan ret); 2152b6a321dSAndrew Duggan return ret; 2162b6a321dSAndrew Duggan } 2172b6a321dSAndrew Duggan 2182b6a321dSAndrew Duggan has_package_id_query = !!(queries[0] & BIT(0)); 2192b6a321dSAndrew Duggan has_build_id_query = !!(queries[0] & BIT(1)); 2202b6a321dSAndrew Duggan } 2212b6a321dSAndrew Duggan 2222b6a321dSAndrew Duggan if (has_package_id_query) 2232b6a321dSAndrew Duggan prod_info_addr++; 2242b6a321dSAndrew Duggan 2252b6a321dSAndrew Duggan if (has_build_id_query) { 2262b6a321dSAndrew Duggan ret = rmi_read_block(rmi_dev, prod_info_addr, queries, 2272b6a321dSAndrew Duggan 3); 2282b6a321dSAndrew Duggan if (ret) { 2292b6a321dSAndrew Duggan dev_err(&rmi_dev->dev, 2302b6a321dSAndrew Duggan "Failed to read product info: %d\n", 2312b6a321dSAndrew Duggan ret); 2322b6a321dSAndrew Duggan return ret; 2332b6a321dSAndrew Duggan } 2342b6a321dSAndrew Duggan 2352b6a321dSAndrew Duggan props->firmware_id = queries[1] << 8 | queries[0]; 2362b6a321dSAndrew Duggan props->firmware_id += queries[2] * 65536; 2372b6a321dSAndrew Duggan } 2382b6a321dSAndrew Duggan } 2392b6a321dSAndrew Duggan 2402b6a321dSAndrew Duggan return 0; 2412b6a321dSAndrew Duggan } 2422b6a321dSAndrew Duggan 2432b6a321dSAndrew Duggan char *rmi_f01_get_product_ID(struct rmi_function *fn) 2442b6a321dSAndrew Duggan { 2452b6a321dSAndrew Duggan struct f01_data *f01 = dev_get_drvdata(&fn->dev); 2462b6a321dSAndrew Duggan 2472b6a321dSAndrew Duggan return f01->properties.product_id; 2482b6a321dSAndrew Duggan } 2492b6a321dSAndrew Duggan 250d8a8b3edSAndrew Duggan #ifdef CONFIG_OF 251d8a8b3edSAndrew Duggan static int rmi_f01_of_probe(struct device *dev, 252d8a8b3edSAndrew Duggan struct rmi_device_platform_data *pdata) 253d8a8b3edSAndrew Duggan { 254d8a8b3edSAndrew Duggan int retval; 255d8a8b3edSAndrew Duggan u32 val; 256d8a8b3edSAndrew Duggan 257d8a8b3edSAndrew Duggan retval = rmi_of_property_read_u32(dev, 258d8a8b3edSAndrew Duggan (u32 *)&pdata->power_management.nosleep, 259d8a8b3edSAndrew Duggan "syna,nosleep-mode", 1); 260d8a8b3edSAndrew Duggan if (retval) 261d8a8b3edSAndrew Duggan return retval; 262d8a8b3edSAndrew Duggan 263d8a8b3edSAndrew Duggan retval = rmi_of_property_read_u32(dev, &val, 264d8a8b3edSAndrew Duggan "syna,wakeup-threshold", 1); 265d8a8b3edSAndrew Duggan if (retval) 266d8a8b3edSAndrew Duggan return retval; 267d8a8b3edSAndrew Duggan 268d8a8b3edSAndrew Duggan pdata->power_management.wakeup_threshold = val; 269d8a8b3edSAndrew Duggan 270d8a8b3edSAndrew Duggan retval = rmi_of_property_read_u32(dev, &val, 271d8a8b3edSAndrew Duggan "syna,doze-holdoff-ms", 1); 272d8a8b3edSAndrew Duggan if (retval) 273d8a8b3edSAndrew Duggan return retval; 274d8a8b3edSAndrew Duggan 275d8a8b3edSAndrew Duggan pdata->power_management.doze_holdoff = val * 100; 276d8a8b3edSAndrew Duggan 277d8a8b3edSAndrew Duggan retval = rmi_of_property_read_u32(dev, &val, 278d8a8b3edSAndrew Duggan "syna,doze-interval-ms", 1); 279d8a8b3edSAndrew Duggan if (retval) 280d8a8b3edSAndrew Duggan return retval; 281d8a8b3edSAndrew Duggan 282d8a8b3edSAndrew Duggan pdata->power_management.doze_interval = val / 10; 283d8a8b3edSAndrew Duggan 284d8a8b3edSAndrew Duggan return 0; 285d8a8b3edSAndrew Duggan } 286d8a8b3edSAndrew Duggan #else 287d8a8b3edSAndrew Duggan static inline int rmi_f01_of_probe(struct device *dev, 288d8a8b3edSAndrew Duggan struct rmi_device_platform_data *pdata) 289d8a8b3edSAndrew Duggan { 290d8a8b3edSAndrew Duggan return -ENODEV; 291d8a8b3edSAndrew Duggan } 292d8a8b3edSAndrew Duggan #endif 293d8a8b3edSAndrew Duggan 2942b6a321dSAndrew Duggan static int rmi_f01_probe(struct rmi_function *fn) 2952b6a321dSAndrew Duggan { 2962b6a321dSAndrew Duggan struct rmi_device *rmi_dev = fn->rmi_dev; 2972b6a321dSAndrew Duggan struct rmi_driver_data *driver_data = dev_get_drvdata(&rmi_dev->dev); 2982b6a321dSAndrew Duggan struct rmi_device_platform_data *pdata = rmi_get_platform_data(rmi_dev); 2992b6a321dSAndrew Duggan struct f01_data *f01; 3002b6a321dSAndrew Duggan int error; 3012b6a321dSAndrew Duggan u16 ctrl_base_addr = fn->fd.control_base_addr; 3022b6a321dSAndrew Duggan u8 device_status; 3032b6a321dSAndrew Duggan u8 temp; 3042b6a321dSAndrew Duggan 305d8a8b3edSAndrew Duggan if (fn->dev.of_node) { 306d8a8b3edSAndrew Duggan error = rmi_f01_of_probe(&fn->dev, pdata); 307d8a8b3edSAndrew Duggan if (error) 308d8a8b3edSAndrew Duggan return error; 309d8a8b3edSAndrew Duggan } 310d8a8b3edSAndrew Duggan 3112b6a321dSAndrew Duggan f01 = devm_kzalloc(&fn->dev, sizeof(struct f01_data), GFP_KERNEL); 3122b6a321dSAndrew Duggan if (!f01) 3132b6a321dSAndrew Duggan return -ENOMEM; 3142b6a321dSAndrew Duggan 3152b6a321dSAndrew Duggan f01->num_of_irq_regs = driver_data->num_of_irq_regs; 3162b6a321dSAndrew Duggan 3172b6a321dSAndrew Duggan /* 3182b6a321dSAndrew Duggan * Set the configured bit and (optionally) other important stuff 3192b6a321dSAndrew Duggan * in the device control register. 3202b6a321dSAndrew Duggan */ 3212b6a321dSAndrew Duggan 3222b6a321dSAndrew Duggan error = rmi_read(rmi_dev, fn->fd.control_base_addr, 3232b6a321dSAndrew Duggan &f01->device_control.ctrl0); 3242b6a321dSAndrew Duggan if (error) { 3252b6a321dSAndrew Duggan dev_err(&fn->dev, "Failed to read F01 control: %d\n", error); 3262b6a321dSAndrew Duggan return error; 3272b6a321dSAndrew Duggan } 3282b6a321dSAndrew Duggan 3292b6a321dSAndrew Duggan switch (pdata->power_management.nosleep) { 330*2775e523SAndrew Duggan case RMI_REG_STATE_DEFAULT: 3312b6a321dSAndrew Duggan break; 332*2775e523SAndrew Duggan case RMI_REG_STATE_OFF: 333e9000b79SNick Dyer f01->device_control.ctrl0 &= ~RMI_F01_CTRL0_NOSLEEP_BIT; 3342b6a321dSAndrew Duggan break; 335*2775e523SAndrew Duggan case RMI_REG_STATE_ON: 336e9000b79SNick Dyer f01->device_control.ctrl0 |= RMI_F01_CTRL0_NOSLEEP_BIT; 3372b6a321dSAndrew Duggan break; 3382b6a321dSAndrew Duggan } 3392b6a321dSAndrew Duggan 3402b6a321dSAndrew Duggan /* 3412b6a321dSAndrew Duggan * Sleep mode might be set as a hangover from a system crash or 3422b6a321dSAndrew Duggan * reboot without power cycle. If so, clear it so the sensor 3432b6a321dSAndrew Duggan * is certain to function. 3442b6a321dSAndrew Duggan */ 3452b6a321dSAndrew Duggan if ((f01->device_control.ctrl0 & RMI_F01_CTRL0_SLEEP_MODE_MASK) != 3462b6a321dSAndrew Duggan RMI_SLEEP_MODE_NORMAL) { 3472b6a321dSAndrew Duggan dev_warn(&fn->dev, 3482b6a321dSAndrew Duggan "WARNING: Non-zero sleep mode found. Clearing...\n"); 3492b6a321dSAndrew Duggan f01->device_control.ctrl0 &= ~RMI_F01_CTRL0_SLEEP_MODE_MASK; 3502b6a321dSAndrew Duggan } 3512b6a321dSAndrew Duggan 352e9000b79SNick Dyer f01->device_control.ctrl0 |= RMI_F01_CTRL0_CONFIGURED_BIT; 3532b6a321dSAndrew Duggan 3542b6a321dSAndrew Duggan error = rmi_write(rmi_dev, fn->fd.control_base_addr, 3552b6a321dSAndrew Duggan f01->device_control.ctrl0); 3562b6a321dSAndrew Duggan if (error) { 3572b6a321dSAndrew Duggan dev_err(&fn->dev, "Failed to write F01 control: %d\n", error); 3582b6a321dSAndrew Duggan return error; 3592b6a321dSAndrew Duggan } 3602b6a321dSAndrew Duggan 3612b6a321dSAndrew Duggan /* Dummy read in order to clear irqs */ 3622b6a321dSAndrew Duggan error = rmi_read(rmi_dev, fn->fd.data_base_addr + 1, &temp); 3632b6a321dSAndrew Duggan if (error < 0) { 3642b6a321dSAndrew Duggan dev_err(&fn->dev, "Failed to read Interrupt Status.\n"); 3652b6a321dSAndrew Duggan return error; 3662b6a321dSAndrew Duggan } 3672b6a321dSAndrew Duggan 3682b6a321dSAndrew Duggan error = rmi_f01_read_properties(rmi_dev, fn->fd.query_base_addr, 3692b6a321dSAndrew Duggan &f01->properties); 3702b6a321dSAndrew Duggan if (error < 0) { 3712b6a321dSAndrew Duggan dev_err(&fn->dev, "Failed to read F01 properties.\n"); 3722b6a321dSAndrew Duggan return error; 3732b6a321dSAndrew Duggan } 3742b6a321dSAndrew Duggan 3752b6a321dSAndrew Duggan dev_info(&fn->dev, "found RMI device, manufacturer: %s, product: %s, fw id: %d\n", 3762b6a321dSAndrew Duggan f01->properties.manufacturer_id == 1 ? "Synaptics" : "unknown", 3772b6a321dSAndrew Duggan f01->properties.product_id, f01->properties.firmware_id); 3782b6a321dSAndrew Duggan 3792b6a321dSAndrew Duggan /* Advance to interrupt control registers, then skip over them. */ 3802b6a321dSAndrew Duggan ctrl_base_addr++; 3812b6a321dSAndrew Duggan ctrl_base_addr += f01->num_of_irq_regs; 3822b6a321dSAndrew Duggan 3832b6a321dSAndrew Duggan /* read control register */ 3842b6a321dSAndrew Duggan if (f01->properties.has_adjustable_doze) { 3852b6a321dSAndrew Duggan f01->doze_interval_addr = ctrl_base_addr; 3862b6a321dSAndrew Duggan ctrl_base_addr++; 3872b6a321dSAndrew Duggan 3882b6a321dSAndrew Duggan if (pdata->power_management.doze_interval) { 3892b6a321dSAndrew Duggan f01->device_control.doze_interval = 3902b6a321dSAndrew Duggan pdata->power_management.doze_interval; 3912b6a321dSAndrew Duggan error = rmi_write(rmi_dev, f01->doze_interval_addr, 3922b6a321dSAndrew Duggan f01->device_control.doze_interval); 3932b6a321dSAndrew Duggan if (error) { 3942b6a321dSAndrew Duggan dev_err(&fn->dev, 3952b6a321dSAndrew Duggan "Failed to configure F01 doze interval register: %d\n", 3962b6a321dSAndrew Duggan error); 3972b6a321dSAndrew Duggan return error; 3982b6a321dSAndrew Duggan } 3992b6a321dSAndrew Duggan } else { 4002b6a321dSAndrew Duggan error = rmi_read(rmi_dev, f01->doze_interval_addr, 4012b6a321dSAndrew Duggan &f01->device_control.doze_interval); 4022b6a321dSAndrew Duggan if (error) { 4032b6a321dSAndrew Duggan dev_err(&fn->dev, 4042b6a321dSAndrew Duggan "Failed to read F01 doze interval register: %d\n", 4052b6a321dSAndrew Duggan error); 4062b6a321dSAndrew Duggan return error; 4072b6a321dSAndrew Duggan } 4082b6a321dSAndrew Duggan } 4092b6a321dSAndrew Duggan 4102b6a321dSAndrew Duggan f01->wakeup_threshold_addr = ctrl_base_addr; 4112b6a321dSAndrew Duggan ctrl_base_addr++; 4122b6a321dSAndrew Duggan 4132b6a321dSAndrew Duggan if (pdata->power_management.wakeup_threshold) { 4142b6a321dSAndrew Duggan f01->device_control.wakeup_threshold = 4152b6a321dSAndrew Duggan pdata->power_management.wakeup_threshold; 4162b6a321dSAndrew Duggan error = rmi_write(rmi_dev, f01->wakeup_threshold_addr, 4172b6a321dSAndrew Duggan f01->device_control.wakeup_threshold); 4182b6a321dSAndrew Duggan if (error) { 4192b6a321dSAndrew Duggan dev_err(&fn->dev, 4202b6a321dSAndrew Duggan "Failed to configure F01 wakeup threshold register: %d\n", 4212b6a321dSAndrew Duggan error); 4222b6a321dSAndrew Duggan return error; 4232b6a321dSAndrew Duggan } 4242b6a321dSAndrew Duggan } else { 4252b6a321dSAndrew Duggan error = rmi_read(rmi_dev, f01->wakeup_threshold_addr, 4262b6a321dSAndrew Duggan &f01->device_control.wakeup_threshold); 4272b6a321dSAndrew Duggan if (error < 0) { 4282b6a321dSAndrew Duggan dev_err(&fn->dev, 4292b6a321dSAndrew Duggan "Failed to read F01 wakeup threshold register: %d\n", 4302b6a321dSAndrew Duggan error); 4312b6a321dSAndrew Duggan return error; 4322b6a321dSAndrew Duggan } 4332b6a321dSAndrew Duggan } 4342b6a321dSAndrew Duggan } 4352b6a321dSAndrew Duggan 4362b6a321dSAndrew Duggan if (f01->properties.has_lts) 4372b6a321dSAndrew Duggan ctrl_base_addr++; 4382b6a321dSAndrew Duggan 4392b6a321dSAndrew Duggan if (f01->properties.has_adjustable_doze_holdoff) { 4402b6a321dSAndrew Duggan f01->doze_holdoff_addr = ctrl_base_addr; 4412b6a321dSAndrew Duggan ctrl_base_addr++; 4422b6a321dSAndrew Duggan 4432b6a321dSAndrew Duggan if (pdata->power_management.doze_holdoff) { 4442b6a321dSAndrew Duggan f01->device_control.doze_holdoff = 4452b6a321dSAndrew Duggan pdata->power_management.doze_holdoff; 4462b6a321dSAndrew Duggan error = rmi_write(rmi_dev, f01->doze_holdoff_addr, 4472b6a321dSAndrew Duggan f01->device_control.doze_holdoff); 4482b6a321dSAndrew Duggan if (error) { 4492b6a321dSAndrew Duggan dev_err(&fn->dev, 4502b6a321dSAndrew Duggan "Failed to configure F01 doze holdoff register: %d\n", 4512b6a321dSAndrew Duggan error); 4522b6a321dSAndrew Duggan return error; 4532b6a321dSAndrew Duggan } 4542b6a321dSAndrew Duggan } else { 4552b6a321dSAndrew Duggan error = rmi_read(rmi_dev, f01->doze_holdoff_addr, 4562b6a321dSAndrew Duggan &f01->device_control.doze_holdoff); 4572b6a321dSAndrew Duggan if (error) { 4582b6a321dSAndrew Duggan dev_err(&fn->dev, 4592b6a321dSAndrew Duggan "Failed to read F01 doze holdoff register: %d\n", 4602b6a321dSAndrew Duggan error); 4612b6a321dSAndrew Duggan return error; 4622b6a321dSAndrew Duggan } 4632b6a321dSAndrew Duggan } 4642b6a321dSAndrew Duggan } 4652b6a321dSAndrew Duggan 4662b6a321dSAndrew Duggan error = rmi_read(rmi_dev, fn->fd.data_base_addr, &device_status); 4672b6a321dSAndrew Duggan if (error < 0) { 4682b6a321dSAndrew Duggan dev_err(&fn->dev, 4692b6a321dSAndrew Duggan "Failed to read device status: %d\n", error); 4702b6a321dSAndrew Duggan return error; 4712b6a321dSAndrew Duggan } 4722b6a321dSAndrew Duggan 4732b6a321dSAndrew Duggan if (RMI_F01_STATUS_UNCONFIGURED(device_status)) { 4742b6a321dSAndrew Duggan dev_err(&fn->dev, 4752b6a321dSAndrew Duggan "Device was reset during configuration process, status: %#02x!\n", 4762b6a321dSAndrew Duggan RMI_F01_STATUS_CODE(device_status)); 4772b6a321dSAndrew Duggan return -EINVAL; 4782b6a321dSAndrew Duggan } 4792b6a321dSAndrew Duggan 4802b6a321dSAndrew Duggan dev_set_drvdata(&fn->dev, f01); 4812b6a321dSAndrew Duggan 4822b6a321dSAndrew Duggan return 0; 4832b6a321dSAndrew Duggan } 4842b6a321dSAndrew Duggan 4852b6a321dSAndrew Duggan static int rmi_f01_config(struct rmi_function *fn) 4862b6a321dSAndrew Duggan { 4872b6a321dSAndrew Duggan struct f01_data *f01 = dev_get_drvdata(&fn->dev); 4882b6a321dSAndrew Duggan int error; 4892b6a321dSAndrew Duggan 4902b6a321dSAndrew Duggan error = rmi_write(fn->rmi_dev, fn->fd.control_base_addr, 4912b6a321dSAndrew Duggan f01->device_control.ctrl0); 4922b6a321dSAndrew Duggan if (error) { 4932b6a321dSAndrew Duggan dev_err(&fn->dev, 4942b6a321dSAndrew Duggan "Failed to write device_control register: %d\n", error); 4952b6a321dSAndrew Duggan return error; 4962b6a321dSAndrew Duggan } 4972b6a321dSAndrew Duggan 4982b6a321dSAndrew Duggan if (f01->properties.has_adjustable_doze) { 4992b6a321dSAndrew Duggan error = rmi_write(fn->rmi_dev, f01->doze_interval_addr, 5002b6a321dSAndrew Duggan f01->device_control.doze_interval); 5012b6a321dSAndrew Duggan if (error) { 5022b6a321dSAndrew Duggan dev_err(&fn->dev, 5032b6a321dSAndrew Duggan "Failed to write doze interval: %d\n", error); 5042b6a321dSAndrew Duggan return error; 5052b6a321dSAndrew Duggan } 5062b6a321dSAndrew Duggan 5072b6a321dSAndrew Duggan error = rmi_write_block(fn->rmi_dev, 5082b6a321dSAndrew Duggan f01->wakeup_threshold_addr, 5092b6a321dSAndrew Duggan &f01->device_control.wakeup_threshold, 5102b6a321dSAndrew Duggan sizeof(u8)); 5112b6a321dSAndrew Duggan if (error) { 5122b6a321dSAndrew Duggan dev_err(&fn->dev, 5132b6a321dSAndrew Duggan "Failed to write wakeup threshold: %d\n", 5142b6a321dSAndrew Duggan error); 5152b6a321dSAndrew Duggan return error; 5162b6a321dSAndrew Duggan } 5172b6a321dSAndrew Duggan } 5182b6a321dSAndrew Duggan 5192b6a321dSAndrew Duggan if (f01->properties.has_adjustable_doze_holdoff) { 5202b6a321dSAndrew Duggan error = rmi_write(fn->rmi_dev, f01->doze_holdoff_addr, 5212b6a321dSAndrew Duggan f01->device_control.doze_holdoff); 5222b6a321dSAndrew Duggan if (error) { 5232b6a321dSAndrew Duggan dev_err(&fn->dev, 5242b6a321dSAndrew Duggan "Failed to write doze holdoff: %d\n", error); 5252b6a321dSAndrew Duggan return error; 5262b6a321dSAndrew Duggan } 5272b6a321dSAndrew Duggan } 5282b6a321dSAndrew Duggan 5292b6a321dSAndrew Duggan return 0; 5302b6a321dSAndrew Duggan } 5312b6a321dSAndrew Duggan 5322b6a321dSAndrew Duggan static int rmi_f01_suspend(struct rmi_function *fn) 5332b6a321dSAndrew Duggan { 5342b6a321dSAndrew Duggan struct f01_data *f01 = dev_get_drvdata(&fn->dev); 5352b6a321dSAndrew Duggan int error; 5362b6a321dSAndrew Duggan 5372b6a321dSAndrew Duggan f01->old_nosleep = 538e9000b79SNick Dyer f01->device_control.ctrl0 & RMI_F01_CTRL0_NOSLEEP_BIT; 539e9000b79SNick Dyer f01->device_control.ctrl0 &= ~RMI_F01_CTRL0_NOSLEEP_BIT; 5402b6a321dSAndrew Duggan 5412b6a321dSAndrew Duggan f01->device_control.ctrl0 &= ~RMI_F01_CTRL0_SLEEP_MODE_MASK; 5422b6a321dSAndrew Duggan if (device_may_wakeup(fn->rmi_dev->xport->dev)) 5432b6a321dSAndrew Duggan f01->device_control.ctrl0 |= RMI_SLEEP_MODE_RESERVED1; 5442b6a321dSAndrew Duggan else 5452b6a321dSAndrew Duggan f01->device_control.ctrl0 |= RMI_SLEEP_MODE_SENSOR_SLEEP; 5462b6a321dSAndrew Duggan 5472b6a321dSAndrew Duggan error = rmi_write(fn->rmi_dev, fn->fd.control_base_addr, 5482b6a321dSAndrew Duggan f01->device_control.ctrl0); 5492b6a321dSAndrew Duggan if (error) { 5502b6a321dSAndrew Duggan dev_err(&fn->dev, "Failed to write sleep mode: %d.\n", error); 5512b6a321dSAndrew Duggan if (f01->old_nosleep) 552e9000b79SNick Dyer f01->device_control.ctrl0 |= RMI_F01_CTRL0_NOSLEEP_BIT; 5532b6a321dSAndrew Duggan f01->device_control.ctrl0 &= ~RMI_F01_CTRL0_SLEEP_MODE_MASK; 5542b6a321dSAndrew Duggan f01->device_control.ctrl0 |= RMI_SLEEP_MODE_NORMAL; 5552b6a321dSAndrew Duggan return error; 5562b6a321dSAndrew Duggan } 5572b6a321dSAndrew Duggan 5582b6a321dSAndrew Duggan return 0; 5592b6a321dSAndrew Duggan } 5602b6a321dSAndrew Duggan 5612b6a321dSAndrew Duggan static int rmi_f01_resume(struct rmi_function *fn) 5622b6a321dSAndrew Duggan { 5632b6a321dSAndrew Duggan struct f01_data *f01 = dev_get_drvdata(&fn->dev); 5642b6a321dSAndrew Duggan int error; 5652b6a321dSAndrew Duggan 5662b6a321dSAndrew Duggan if (f01->old_nosleep) 567e9000b79SNick Dyer f01->device_control.ctrl0 |= RMI_F01_CTRL0_NOSLEEP_BIT; 5682b6a321dSAndrew Duggan 5692b6a321dSAndrew Duggan f01->device_control.ctrl0 &= ~RMI_F01_CTRL0_SLEEP_MODE_MASK; 5702b6a321dSAndrew Duggan f01->device_control.ctrl0 |= RMI_SLEEP_MODE_NORMAL; 5712b6a321dSAndrew Duggan 5722b6a321dSAndrew Duggan error = rmi_write(fn->rmi_dev, fn->fd.control_base_addr, 5732b6a321dSAndrew Duggan f01->device_control.ctrl0); 5742b6a321dSAndrew Duggan if (error) { 5752b6a321dSAndrew Duggan dev_err(&fn->dev, 5762b6a321dSAndrew Duggan "Failed to restore normal operation: %d.\n", error); 5772b6a321dSAndrew Duggan return error; 5782b6a321dSAndrew Duggan } 5792b6a321dSAndrew Duggan 5802b6a321dSAndrew Duggan return 0; 5812b6a321dSAndrew Duggan } 5822b6a321dSAndrew Duggan 5832b6a321dSAndrew Duggan static int rmi_f01_attention(struct rmi_function *fn, 5842b6a321dSAndrew Duggan unsigned long *irq_bits) 5852b6a321dSAndrew Duggan { 5862b6a321dSAndrew Duggan struct rmi_device *rmi_dev = fn->rmi_dev; 5872b6a321dSAndrew Duggan int error; 5882b6a321dSAndrew Duggan u8 device_status; 5892b6a321dSAndrew Duggan 5902b6a321dSAndrew Duggan error = rmi_read(rmi_dev, fn->fd.data_base_addr, &device_status); 5912b6a321dSAndrew Duggan if (error) { 5922b6a321dSAndrew Duggan dev_err(&fn->dev, 5932b6a321dSAndrew Duggan "Failed to read device status: %d.\n", error); 5942b6a321dSAndrew Duggan return error; 5952b6a321dSAndrew Duggan } 5962b6a321dSAndrew Duggan 5972b6a321dSAndrew Duggan if (RMI_F01_STATUS_UNCONFIGURED(device_status)) { 5982b6a321dSAndrew Duggan dev_warn(&fn->dev, "Device reset detected.\n"); 5992b6a321dSAndrew Duggan error = rmi_dev->driver->reset_handler(rmi_dev); 6002b6a321dSAndrew Duggan if (error) { 6012b6a321dSAndrew Duggan dev_err(&fn->dev, "Device reset failed: %d\n", error); 6022b6a321dSAndrew Duggan return error; 6032b6a321dSAndrew Duggan } 6042b6a321dSAndrew Duggan } 6052b6a321dSAndrew Duggan 6062b6a321dSAndrew Duggan return 0; 6072b6a321dSAndrew Duggan } 6082b6a321dSAndrew Duggan 6092b6a321dSAndrew Duggan struct rmi_function_handler rmi_f01_handler = { 6102b6a321dSAndrew Duggan .driver = { 6112b6a321dSAndrew Duggan .name = "rmi4_f01", 6122b6a321dSAndrew Duggan /* 6132b6a321dSAndrew Duggan * Do not allow user unbinding F01 as it is critical 6142b6a321dSAndrew Duggan * function. 6152b6a321dSAndrew Duggan */ 6162b6a321dSAndrew Duggan .suppress_bind_attrs = true, 6172b6a321dSAndrew Duggan }, 6182b6a321dSAndrew Duggan .func = 0x01, 6192b6a321dSAndrew Duggan .probe = rmi_f01_probe, 6202b6a321dSAndrew Duggan .config = rmi_f01_config, 6212b6a321dSAndrew Duggan .attention = rmi_f01_attention, 6222b6a321dSAndrew Duggan .suspend = rmi_f01_suspend, 6232b6a321dSAndrew Duggan .resume = rmi_f01_resume, 6242b6a321dSAndrew Duggan }; 625