Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

iio: accel: kxcjk-1013: Add support for KX023-1025

The KX023-1025 accelerometer [1] seems to be some mixture of
KXCJK and KXTF9. It has the motion interrupt functionality from KXCJK
but also the tap detection from KXTF9, and a lot more functionality.

The configuration register map seems fairly different at first,
but actually all register bits used by the kxcjk-1013 driver are
available at the same bit positions on KX023-1025. It's just quite
misleading because:

1. The registers have entirely different names and are at different
addresses, but the bits are mostly named the same (and mean the same).
2. There are many more registers and bits used that are reserved on KXCJK
to enable additional functionality.

Ignoring all additionally available functionality for now, the KX023
works just fine after setting up the struct with the correct register
addresses. The only difference that needs to be handled additionally
is that the KX023 supports two configurable interrupt lines (INT1/2).

For now only INT1 is supported so we route all interrupts used by
the driver there.

[1]: https://kionixfs.azureedge.net/en/datasheet/KX023-1025%20Specifications%20Rev%2012.0.pdf

Cc: Srinivas Pandruvada <srinivas.pandruvada@linux.intel.com>
Reviewed-by: Hans de Goede <hdegoede@redhat.com>
Signed-off-by: Stephan Gerhold <stephan@gerhold.net>
Signed-off-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>

authored by

Stephan Gerhold and committed by
Jonathan Cameron
c630c176 ae4467f6

+93
+93
drivers/iio/accel/kxcjk-1013.c
··· 79 79 #define KXTF9_REG_HYST_SET 0x5F 80 80 #define KXCJK1013_REG_WAKE_THRES 0x6A 81 81 82 + /* Everything up to 0x11 is equal to KXCJK1013/KXTF9 above */ 83 + #define KX023_REG_INS1 0x12 84 + #define KX023_REG_INS2 0x13 85 + #define KX023_REG_INS3 0x14 86 + #define KX023_REG_STAT 0x15 87 + #define KX023_REG_INT_REL 0x17 88 + #define KX023_REG_CNTL1 0x18 89 + #define KX023_REG_CNTL2 0x19 90 + #define KX023_REG_CNTL3 0x1A 91 + #define KX023_REG_ODCNTL 0x1B 92 + #define KX023_REG_INC1 0x1C 93 + #define KX023_REG_INC2 0x1D 94 + #define KX023_REG_INC3 0x1E 95 + #define KX023_REG_INC4 0x1F 96 + #define KX023_REG_INC5 0x20 97 + #define KX023_REG_INC6 0x21 98 + #define KX023_REG_TILT_TIMER 0x22 99 + #define KX023_REG_WUFC 0x23 100 + #define KX023_REG_TDTRC 0x24 101 + #define KX023_REG_TDTC 0x25 102 + #define KX023_REG_TTH 0x26 103 + #define KX023_REG_TTL 0x27 104 + #define KX023_REG_FTD 0x28 105 + #define KX023_REG_STD 0x29 106 + #define KX023_REG_TLT 0x2A 107 + #define KX023_REG_TWS 0x2B 108 + #define KX023_REG_ATH 0x30 109 + #define KX023_REG_TILT_ANGLE_LL 0x32 110 + #define KX023_REG_TILT_ANGLE_HL 0x33 111 + #define KX023_REG_HYST_SET 0x34 112 + #define KX023_REG_LP_CNTL 0x35 113 + #define KX023_REG_BUF_CNTL1 0x3A 114 + #define KX023_REG_BUF_CNTL2 0x3B 115 + #define KX023_REG_BUF_STATUS_1 0x3C 116 + #define KX023_REG_BUF_STATUS_2 0x3D 117 + #define KX023_REG_BUF_CLEAR 0x3E 118 + #define KX023_REG_BUF_READ 0x3F 119 + #define KX023_REG_SELF_TEST 0x60 120 + 82 121 #define KXCJK1013_REG_CTRL1_BIT_PC1 BIT(7) 83 122 #define KXCJK1013_REG_CTRL1_BIT_RES BIT(6) 84 123 #define KXCJK1013_REG_CTRL1_BIT_DRDY BIT(5) ··· 158 119 #define KXCJK1013_REG_INT_SRC2_BIT_XP BIT(4) 159 120 #define KXCJK1013_REG_INT_SRC2_BIT_XN BIT(5) 160 121 122 + /* KX023 interrupt routing to INT1. INT2 can be configured with INC6 */ 123 + #define KX023_REG_INC4_BFI1 BIT(6) 124 + #define KX023_REG_INC4_WMI1 BIT(5) 125 + #define KX023_REG_INC4_DRDY1 BIT(4) 126 + #define KX023_REG_INC4_TDTI1 BIT(2) 127 + #define KX023_REG_INC4_WUFI1 BIT(1) 128 + #define KX023_REG_INC4_TPI1 BIT(0) 129 + 161 130 #define KXCJK1013_DEFAULT_WAKE_THRES 1 162 131 163 132 enum kx_chipset { ··· 173 126 KXCJ91008, 174 127 KXTJ21009, 175 128 KXTF9, 129 + KX0231025, 176 130 KX_MAX_CHIPS /* this must be last */ 177 131 }; 178 132 ··· 218 170 .data_ctrl = KXCJK1013_REG_DATA_CTRL, 219 171 .wake_timer = KXCJK1013_REG_WAKE_TIMER, 220 172 .wake_thres = KXTF9_REG_WAKE_THRESH, 173 + }; 174 + 175 + /* The registers have totally different names but the bits are compatible */ 176 + static const struct kx_chipset_regs kx0231025_regs = { 177 + .int_src1 = KX023_REG_INS2, 178 + .int_src2 = KX023_REG_INS3, 179 + .int_rel = KX023_REG_INT_REL, 180 + .ctrl1 = KX023_REG_CNTL1, 181 + .wuf_ctrl = KX023_REG_CNTL3, 182 + .int_ctrl1 = KX023_REG_INC1, 183 + .data_ctrl = KX023_REG_ODCNTL, 184 + .wake_timer = KX023_REG_WUFC, 185 + .wake_thres = KX023_REG_ATH, 221 186 }; 222 187 223 188 struct kxcjk1013_data { ··· 368 307 {0x04, 11000}, 369 308 {0x05, 5100}, 370 309 {0x06, 2700}, 310 + }, 311 + /* KX023-1025 */ 312 + { 313 + /* First 4 are not in datasheet, taken from KXCTJ2-1009 */ 314 + {0x08, 1240000}, 315 + {0x09, 621000}, 316 + {0x0A, 309000}, 317 + {0x0B, 151000}, 318 + {0, 81000}, 319 + {0x01, 40000}, 320 + {0x02, 22000}, 321 + {0x03, 12000}, 322 + {0x04, 7000}, 323 + {0x05, 4400}, 324 + {0x06, 3000}, 325 + {0x07, 3000}, 371 326 }, 372 327 }; 373 328 ··· 558 481 if (ret < 0) { 559 482 dev_err(&data->client->dev, "Error writing reg_int_ctrl1\n"); 560 483 return ret; 484 + } 485 + 486 + /* On KX023, route all used interrupts to INT1 for now */ 487 + if (data->chipset == KX0231025 && data->client->irq > 0) { 488 + ret = i2c_smbus_write_byte_data(data->client, KX023_REG_INC4, 489 + KX023_REG_INC4_DRDY1 | 490 + KX023_REG_INC4_WUFI1); 491 + if (ret < 0) { 492 + dev_err(&data->client->dev, "Error writing reg_inc4\n"); 493 + return ret; 494 + } 561 495 } 562 496 563 497 ret = kxcjk1013_set_mode(data, OPERATION); ··· 1502 1414 case KXTF9: 1503 1415 data->regs = &kxtf9_regs; 1504 1416 break; 1417 + case KX0231025: 1418 + data->regs = &kx0231025_regs; 1419 + break; 1505 1420 default: 1506 1421 return -EINVAL; 1507 1422 } ··· 1724 1633 {"kxcj91008", KXCJ91008}, 1725 1634 {"kxtj21009", KXTJ21009}, 1726 1635 {"kxtf9", KXTF9}, 1636 + {"kx023-1025", KX0231025}, 1727 1637 {"SMO8500", KXCJ91008}, 1728 1638 {} 1729 1639 }; ··· 1736 1644 { .compatible = "kionix,kxcj91008", }, 1737 1645 { .compatible = "kionix,kxtj21009", }, 1738 1646 { .compatible = "kionix,kxtf9", }, 1647 + { .compatible = "kionix,kx023-1025", }, 1739 1648 { } 1740 1649 }; 1741 1650 MODULE_DEVICE_TABLE(of, kxcjk1013_of_match);