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

Configure Feed

Select the types of activity you want to include in your feed.

NFC: trf7970a: Create device-tree parameter for RX gain reduction

The TRF7970a device is sensitive to RF disturbances, which can make it
hard to pass some EMC immunity tests. By reducing the RX antenna gain,
the device becomes less sensitive to EMC disturbances, as a trade-off
against antenna performance.

Add a device tree option to select RX gain reduction to improve EMC
performance.

Selecting a communication standard in the ISO control register resets
the RX antenna gain settings. Therefore set the RX gain reduction
everytime the ISO control register changes, when the option is used.

Signed-off-by: Paul Geurts <paul.geurts@prodrive-technologies.com>
Reviewed-by: Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
Link: https://patch.msgid.link/20250626141242.3749958-3-paul.geurts@prodrive-technologies.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>

authored by

Paul Geurts and committed by
Jakub Kicinski
5d693518 2bee162a

+80 -11
+80 -11
drivers/nfc/trf7970a.c
··· 272 272 #define TRF7970A_MODULATOR_EN_OOK BIT(6) 273 273 #define TRF7970A_MODULATOR_27MHZ BIT(7) 274 274 275 + #define TRF7970A_RX_GAIN_REDUCTION_MAX_DB 15 276 + #define TRF7970A_RX_GAIN_REDUCTION_DB_PER_LSB 5 275 277 #define TRF7970A_RX_SPECIAL_SETTINGS_NO_LIM BIT(0) 276 278 #define TRF7970A_RX_SPECIAL_SETTINGS_AGCR BIT(1) 277 - #define TRF7970A_RX_SPECIAL_SETTINGS_GD_0DB (0x0 << 2) 278 - #define TRF7970A_RX_SPECIAL_SETTINGS_GD_5DB (0x1 << 2) 279 - #define TRF7970A_RX_SPECIAL_SETTINGS_GD_10DB (0x2 << 2) 280 - #define TRF7970A_RX_SPECIAL_SETTINGS_GD_15DB (0x3 << 2) 279 + #define TRF7970A_RX_SPECIAL_SETTINGS_GD_SHIFT 2 280 + #define TRF7970A_RX_SPECIAL_SETTINGS_GD_MAX (0x3) 281 + #define TRF7970A_RX_SPECIAL_SETTINGS_GD_MASK (TRF7970A_RX_SPECIAL_SETTINGS_GD_MAX << \ 282 + TRF7970A_RX_SPECIAL_SETTINGS_GD_SHIFT) 283 + #define TRF7970A_RX_SPECIAL_SETTINGS_GD_0DB (0x0 << TRF7970A_RX_SPECIAL_SETTINGS_GD_SHIFT) 284 + #define TRF7970A_RX_SPECIAL_SETTINGS_GD_5DB (0x1 << TRF7970A_RX_SPECIAL_SETTINGS_GD_SHIFT) 285 + #define TRF7970A_RX_SPECIAL_SETTINGS_GD_10DB (0x2 << TRF7970A_RX_SPECIAL_SETTINGS_GD_SHIFT) 286 + #define TRF7970A_RX_SPECIAL_SETTINGS_GD_15DB (0x3 << TRF7970A_RX_SPECIAL_SETTINGS_GD_SHIFT) 281 287 #define TRF7970A_RX_SPECIAL_SETTINGS_HBT BIT(4) 282 288 #define TRF7970A_RX_SPECIAL_SETTINGS_M848 BIT(5) 283 289 #define TRF7970A_RX_SPECIAL_SETTINGS_C424 BIT(6) ··· 458 452 unsigned int timeout; 459 453 bool ignore_timeout; 460 454 struct delayed_work timeout_work; 455 + u8 rx_gain_reduction; 456 + bool custom_rx_gain_reduction; 461 457 }; 462 458 463 459 static int trf7970a_cmd(struct trf7970a *trf, u8 opcode) ··· 555 547 __func__, ret); 556 548 else 557 549 *status = buf[0]; 550 + 551 + return ret; 552 + } 553 + 554 + static int trf7970a_update_rx_gain_reduction(struct trf7970a *trf) 555 + { 556 + int ret = 0; 557 + u8 reg; 558 + 559 + if (!trf->custom_rx_gain_reduction) 560 + return 0; 561 + 562 + ret = trf7970a_read(trf, TRF7970A_RX_SPECIAL_SETTINGS, &reg); 563 + if (ret) 564 + return ret; 565 + reg &= ~(TRF7970A_RX_SPECIAL_SETTINGS_GD_MASK); 566 + reg |= trf->rx_gain_reduction; 567 + 568 + ret = trf7970a_write(trf, TRF7970A_RX_SPECIAL_SETTINGS, reg); 569 + 570 + return ret; 571 + } 572 + 573 + static int trf7970a_update_iso_ctrl_register(struct trf7970a *trf, u8 iso_ctrl) 574 + { 575 + int ret; 576 + 577 + ret = trf7970a_write(trf, TRF7970A_ISO_CTRL, iso_ctrl); 578 + if (ret) 579 + return ret; 580 + /* 581 + * Every time the ISO_CTRL register is written, the RX special setting register is reset by 582 + * the chip. When a custom gain reguduction is required, it should be rewritten now. 583 + */ 584 + ret = trf7970a_update_rx_gain_reduction(trf); 558 585 559 586 return ret; 560 587 } ··· 973 930 } 974 931 975 932 if (iso_ctrl != trf->iso_ctrl) { 976 - ret = trf7970a_write(trf, TRF7970A_ISO_CTRL, 977 - iso_ctrl); 933 + ret = trf7970a_update_iso_ctrl_register(trf, iso_ctrl); 978 934 if (ret) 979 935 goto err_unlock_exit; 980 936 ··· 1074 1032 dev_dbg(trf->dev, "Initializing device - state: %d\n", trf->state); 1075 1033 1076 1034 ret = trf7970a_cmd(trf, TRF7970A_CMD_SOFT_INIT); 1035 + if (ret) 1036 + goto err_out; 1037 + 1038 + /* Set the gain reduction after soft init */ 1039 + ret = trf7970a_update_rx_gain_reduction(trf); 1077 1040 if (ret) 1078 1041 goto err_out; 1079 1042 ··· 1356 1309 } 1357 1310 1358 1311 if (iso_ctrl != trf->iso_ctrl) { 1359 - ret = trf7970a_write(trf, TRF7970A_ISO_CTRL, iso_ctrl); 1312 + ret = trf7970a_update_iso_ctrl_register(trf, iso_ctrl); 1360 1313 if (ret) 1361 1314 return ret; 1362 1315 ··· 1488 1441 } 1489 1442 1490 1443 if (iso_ctrl != trf->iso_ctrl) { 1491 - ret = trf7970a_write(trf, TRF7970A_ISO_CTRL, iso_ctrl); 1444 + ret = trf7970a_update_iso_ctrl_register(trf, iso_ctrl); 1492 1445 if (ret) 1493 1446 return ret; 1494 1447 ··· 1652 1605 */ 1653 1606 if ((trf->framing == NFC_DIGITAL_FRAMING_NFC_DEP_ACTIVATED) && 1654 1607 (trf->iso_ctrl_tech != trf->iso_ctrl)) { 1655 - ret = trf7970a_write(trf, TRF7970A_ISO_CTRL, 1656 - trf->iso_ctrl_tech); 1608 + ret = trf7970a_update_iso_ctrl_register(trf, trf->iso_ctrl_tech); 1657 1609 1658 1610 trf->iso_ctrl = trf->iso_ctrl_tech; 1659 1611 } ··· 1700 1654 trf->framing = framing; 1701 1655 1702 1656 if (iso_ctrl != trf->iso_ctrl) { 1703 - ret = trf7970a_write(trf, TRF7970A_ISO_CTRL, iso_ctrl); 1657 + ret = trf7970a_update_iso_ctrl_register(trf, iso_ctrl); 1704 1658 if (ret) 1705 1659 return ret; 1706 1660 ··· 1798 1752 TRF7970A_RX_SPECIAL_SETTINGS_M848 | 1799 1753 TRF7970A_RX_SPECIAL_SETTINGS_C424 | 1800 1754 TRF7970A_RX_SPECIAL_SETTINGS_C212); 1755 + if (ret) 1756 + goto out_err; 1757 + 1758 + ret = trf7970a_update_rx_gain_reduction(trf); 1801 1759 if (ret) 1802 1760 goto out_err; 1803 1761 ··· 1995 1945 if (ret) 1996 1946 return ret; 1997 1947 1948 + ret = trf7970a_update_rx_gain_reduction(trf); 1949 + if (ret) 1950 + return ret; 1951 + 1998 1952 pm_runtime_set_active(trf->dev); 1999 1953 pm_runtime_enable(trf->dev); 2000 1954 pm_runtime_mark_last_busy(trf->dev); ··· 2047 1993 struct trf7970a *trf; 2048 1994 int uvolts, autosuspend_delay, ret; 2049 1995 u32 clk_freq = TRF7970A_13MHZ_CLOCK_FREQUENCY; 1996 + u32 rx_gain_reduction_db; 2050 1997 2051 1998 if (!np) { 2052 1999 dev_err(&spi->dev, "No Device Tree entry\n"); ··· 2107 2052 dev_dbg(trf->dev, "trf7970a configured for 27MHz crystal\n"); 2108 2053 } else { 2109 2054 trf->modulator_sys_clk_ctrl = 0; 2055 + } 2056 + 2057 + if (of_property_read_u32(np, "ti,rx-gain-reduction-db", &rx_gain_reduction_db) == 0) { 2058 + if (rx_gain_reduction_db > TRF7970A_RX_GAIN_REDUCTION_MAX_DB) { 2059 + dev_warn(trf->dev, "RX Gain reduction too high. Ignored\n"); 2060 + } else if ((rx_gain_reduction_db % TRF7970A_RX_GAIN_REDUCTION_DB_PER_LSB)) { 2061 + dev_warn(trf->dev, "RX Gain must be set in 5 dB increments. Ignored\n"); 2062 + } else { 2063 + dev_dbg(trf->dev, "RX gain set to -%udB\n", rx_gain_reduction_db); 2064 + trf->rx_gain_reduction = ((rx_gain_reduction_db / 2065 + TRF7970A_RX_GAIN_REDUCTION_DB_PER_LSB) << 2066 + TRF7970A_RX_SPECIAL_SETTINGS_GD_SHIFT); 2067 + trf->custom_rx_gain_reduction = true; 2068 + } 2110 2069 } 2111 2070 2112 2071 ret = devm_request_threaded_irq(trf->dev, spi->irq, NULL,