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

Merge tag 'i3c/for-6.12' of git://git.kernel.org/pub/scm/linux/kernel/git/i3c/linux

Pull i3c updates from Alexandre Belloni:
"This adds support for the I3C HCI controller of the AMD SoC which as
expected requires quirks. Also fixes for the other drivers, including
rate selection fixes for svc.

Core:
- allow adjusting first broadcast address speed

Drivers:
- cdns: few fixes
- mipi-i3c-hci: Add AMD SoC I3C controller support and quirks, fix
get_i3c_mode
- svc: adjust rates, fix race condition"

* tag 'i3c/for-6.12' of git://git.kernel.org/pub/scm/linux/kernel/git/i3c/linux:
i3c: master: svc: Fix use after free vulnerability in svc_i3c_master Driver Due to Race Condition
i3c: master: cdns: Fix use after free vulnerability in cdns_i3c_master Driver Due to Race Condition
i3c: master: svc: adjust SDR according to i3c spec
i3c: master: svc: use slow speed for first broadcast address
i3c: master: support to adjust first broadcast address speed
i3c/master: cmd_v1: Fix the rule for getting i3c mode
i3c: master: cdns: fix module autoloading
i3c: mipi-i3c-hci: Add a quirk to set Response buffer threshold
i3c: mipi-i3c-hci: Add a quirk to set timing parameters
i3c: mipi-i3c-hci: Relocate helper macros to HCI header file
i3c: mipi-i3c-hci: Add a quirk to set PIO mode
i3c: mipi-i3c-hci: Read HC_CONTROL_PIO_MODE only after i3c hci v1.1
i3c: mipi-i3c-hci: Add AMDI5017 ACPI ID to the I3C Support List

+193 -26
+12
drivers/i3c/master.c
··· 1868 1868 goto err_bus_cleanup; 1869 1869 } 1870 1870 1871 + if (master->ops->set_speed) { 1872 + ret = master->ops->set_speed(master, I3C_OPEN_DRAIN_SLOW_SPEED); 1873 + if (ret) 1874 + goto err_bus_cleanup; 1875 + } 1876 + 1871 1877 /* 1872 1878 * Reset all dynamic address that may have been assigned before 1873 1879 * (assigned by the bootloader for example). ··· 1881 1875 ret = i3c_master_rstdaa_locked(master, I3C_BROADCAST_ADDR); 1882 1876 if (ret && ret != I3C_ERROR_M2) 1883 1877 goto err_bus_cleanup; 1878 + 1879 + if (master->ops->set_speed) { 1880 + master->ops->set_speed(master, I3C_OPEN_DRAIN_NORMAL_SPEED); 1881 + if (ret) 1882 + goto err_bus_cleanup; 1883 + } 1884 1884 1885 1885 /* Disable all slave events before starting DAA. */ 1886 1886 ret = i3c_master_disec_locked(master, I3C_BROADCAST_ADDR,
+2
drivers/i3c/master/i3c-master-cdns.c
··· 1562 1562 { .compatible = "cdns,i3c-master", .data = &cdns_i3c_devdata }, 1563 1563 { /* sentinel */ }, 1564 1564 }; 1565 + MODULE_DEVICE_TABLE(of, cdns_i3c_master_of_ids); 1565 1566 1566 1567 static int cdns_i3c_master_probe(struct platform_device *pdev) 1567 1568 { ··· 1667 1666 { 1668 1667 struct cdns_i3c_master *master = platform_get_drvdata(pdev); 1669 1668 1669 + cancel_work_sync(&master->hj_work); 1670 1670 i3c_master_unregister(&master->base); 1671 1671 1672 1672 clk_disable_unprepare(master->sysclk);
+2 -1
drivers/i3c/master/mipi-i3c-hci/Makefile
··· 3 3 obj-$(CONFIG_MIPI_I3C_HCI) += mipi-i3c-hci.o 4 4 mipi-i3c-hci-y := core.o ext_caps.o pio.o dma.o \ 5 5 cmd_v1.o cmd_v2.o \ 6 - dat_v1.o dct_v1.o 6 + dat_v1.o dct_v1.o \ 7 + hci_quirks.o
+5 -7
drivers/i3c/master/mipi-i3c-hci/cmd_v1.c
··· 123 123 { 124 124 struct i3c_bus *bus = i3c_master_get_bus(&hci->master); 125 125 126 - if (bus->scl_rate.i3c >= 12500000) 127 - return MODE_I3C_SDR0; 128 126 if (bus->scl_rate.i3c > 8000000) 129 - return MODE_I3C_SDR1; 127 + return MODE_I3C_SDR0; 130 128 if (bus->scl_rate.i3c > 6000000) 131 - return MODE_I3C_SDR2; 129 + return MODE_I3C_SDR1; 132 130 if (bus->scl_rate.i3c > 4000000) 133 - return MODE_I3C_SDR3; 131 + return MODE_I3C_SDR2; 134 132 if (bus->scl_rate.i3c > 2000000) 135 - return MODE_I3C_SDR4; 136 - return MODE_I3C_Fm_FmP; 133 + return MODE_I3C_SDR3; 134 + return MODE_I3C_SDR4; 137 135 } 138 136 139 137 static enum hci_cmd_mode get_i2c_mode(struct i3c_hci *hci)
+27 -9
drivers/i3c/master/mipi-i3c-hci/core.c
··· 12 12 #include <linux/errno.h> 13 13 #include <linux/i3c/master.h> 14 14 #include <linux/interrupt.h> 15 - #include <linux/io.h> 16 15 #include <linux/iopoll.h> 17 16 #include <linux/module.h> 18 17 #include <linux/platform_device.h> ··· 25 26 /* 26 27 * Host Controller Capabilities and Operation Registers 27 28 */ 28 - 29 - #define reg_read(r) readl(hci->base_regs + (r)) 30 - #define reg_write(r, v) writel(v, hci->base_regs + (r)) 31 - #define reg_set(r, v) reg_write(r, reg_read(r) | (v)) 32 - #define reg_clear(r, v) reg_write(r, reg_read(r) & ~(v)) 33 29 34 30 #define HCI_VERSION 0x00 /* HCI Version (in BCD) */ 35 31 ··· 145 151 ret = hci->io->init(hci); 146 152 if (ret) 147 153 return ret; 154 + 155 + /* Set RESP_BUF_THLD to 0(n) to get 1(n+1) response */ 156 + if (hci->quirks & HCI_QUIRK_RESP_BUF_THLD) 157 + amd_set_resp_buf_thld(hci); 148 158 149 159 reg_set(HC_CONTROL, HC_CONTROL_BUS_ENABLE); 150 160 DBG("HC_CONTROL = %#x", reg_read(HC_CONTROL)); ··· 628 630 629 631 static int i3c_hci_init(struct i3c_hci *hci) 630 632 { 633 + bool size_in_dwords, mode_selector; 631 634 u32 regval, offset; 632 - bool size_in_dwords; 633 635 int ret; 634 636 635 637 /* Validate HCI hardware version */ ··· 751 753 return -EINVAL; 752 754 } 753 755 756 + mode_selector = hci->version_major > 1 || 757 + (hci->version_major == 1 && hci->version_minor > 0); 758 + 759 + /* Quirk for HCI_QUIRK_PIO_MODE on AMD platforms */ 760 + if (hci->quirks & HCI_QUIRK_PIO_MODE) 761 + hci->RHS_regs = NULL; 762 + 754 763 /* Try activating DMA operations first */ 755 764 if (hci->RHS_regs) { 756 765 reg_clear(HC_CONTROL, HC_CONTROL_PIO_MODE); 757 - if (reg_read(HC_CONTROL) & HC_CONTROL_PIO_MODE) { 766 + if (mode_selector && (reg_read(HC_CONTROL) & HC_CONTROL_PIO_MODE)) { 758 767 dev_err(&hci->master.dev, "PIO mode is stuck\n"); 759 768 ret = -EIO; 760 769 } else { ··· 773 768 /* If no DMA, try PIO */ 774 769 if (!hci->io && hci->PIO_regs) { 775 770 reg_set(HC_CONTROL, HC_CONTROL_PIO_MODE); 776 - if (!(reg_read(HC_CONTROL) & HC_CONTROL_PIO_MODE)) { 771 + if (mode_selector && !(reg_read(HC_CONTROL) & HC_CONTROL_PIO_MODE)) { 777 772 dev_err(&hci->master.dev, "DMA mode is stuck\n"); 778 773 ret = -EIO; 779 774 } else { ··· 788 783 ret = -EINVAL; 789 784 return ret; 790 785 } 786 + 787 + /* Configure OD and PP timings for AMD platforms */ 788 + if (hci->quirks & HCI_QUIRK_OD_PP_TIMING) 789 + amd_set_od_pp_timing(hci); 791 790 792 791 return 0; 793 792 } ··· 811 802 platform_set_drvdata(pdev, hci); 812 803 /* temporary for dev_printk's, to be replaced in i3c_master_register */ 813 804 hci->master.dev.init_name = dev_name(&pdev->dev); 805 + 806 + hci->quirks = (unsigned long)device_get_match_data(&pdev->dev); 814 807 815 808 ret = i3c_hci_init(hci); 816 809 if (ret) ··· 845 834 }; 846 835 MODULE_DEVICE_TABLE(of, i3c_hci_of_match); 847 836 837 + static const struct acpi_device_id i3c_hci_acpi_match[] = { 838 + { "AMDI5017", HCI_QUIRK_PIO_MODE | HCI_QUIRK_OD_PP_TIMING | HCI_QUIRK_RESP_BUF_THLD }, 839 + {} 840 + }; 841 + MODULE_DEVICE_TABLE(acpi, i3c_hci_acpi_match); 842 + 848 843 static struct platform_driver i3c_hci_driver = { 849 844 .probe = i3c_hci_probe, 850 845 .remove_new = i3c_hci_remove, 851 846 .driver = { 852 847 .name = "mipi-i3c-hci", 853 848 .of_match_table = of_match_ptr(i3c_hci_of_match), 849 + .acpi_match_table = i3c_hci_acpi_match, 854 850 }, 855 851 }; 856 852 module_platform_driver(i3c_hci_driver);
+10
drivers/i3c/master/mipi-i3c-hci/hci.h
··· 10 10 #ifndef HCI_H 11 11 #define HCI_H 12 12 13 + #include <linux/io.h> 13 14 14 15 /* Handy logging macro to save on line length */ 15 16 #define DBG(x, ...) pr_devel("%s: " x "\n", __func__, ##__VA_ARGS__) ··· 27 26 #define W2_BIT_(x) BIT((x) - 64) 28 27 #define W3_BIT_(x) BIT((x) - 96) 29 28 29 + #define reg_read(r) readl(hci->base_regs + (r)) 30 + #define reg_write(r, v) writel(v, hci->base_regs + (r)) 31 + #define reg_set(r, v) reg_write(r, reg_read(r) | (v)) 32 + #define reg_clear(r, v) reg_write(r, reg_read(r) & ~(v)) 30 33 31 34 struct hci_cmd_ops; 32 35 ··· 140 135 141 136 /* list of quirks */ 142 137 #define HCI_QUIRK_RAW_CCC BIT(1) /* CCC framing must be explicit */ 138 + #define HCI_QUIRK_PIO_MODE BIT(2) /* Set PIO mode for AMD platforms */ 139 + #define HCI_QUIRK_OD_PP_TIMING BIT(3) /* Set OD and PP timings for AMD platforms */ 140 + #define HCI_QUIRK_RESP_BUF_THLD BIT(4) /* Set resp buf thld to 0 for AMD platforms */ 143 141 144 142 145 143 /* global functions */ 146 144 void mipi_i3c_hci_resume(struct i3c_hci *hci); 147 145 void mipi_i3c_hci_pio_reset(struct i3c_hci *hci); 148 146 void mipi_i3c_hci_dct_index_reset(struct i3c_hci *hci); 147 + void amd_set_od_pp_timing(struct i3c_hci *hci); 148 + void amd_set_resp_buf_thld(struct i3c_hci *hci); 149 149 150 150 #endif
+44
drivers/i3c/master/mipi-i3c-hci/hci_quirks.c
··· 1 + // SPDX-License-Identifier: GPL-2.0-or-later 2 + /* 3 + * I3C HCI Quirks 4 + * 5 + * Copyright 2024 Advanced Micro Devices, Inc. 6 + * 7 + * Authors: Shyam Sundar S K <Shyam-sundar.S-k@amd.com> 8 + * Guruvendra Punugupati <Guruvendra.Punugupati@amd.com> 9 + */ 10 + 11 + #include <linux/i3c/master.h> 12 + #include "hci.h" 13 + 14 + /* Timing registers */ 15 + #define HCI_SCL_I3C_OD_TIMING 0x214 16 + #define HCI_SCL_I3C_PP_TIMING 0x218 17 + #define HCI_SDA_HOLD_SWITCH_DLY_TIMING 0x230 18 + 19 + /* Timing values to configure 9MHz frequency */ 20 + #define AMD_SCL_I3C_OD_TIMING 0x00cf00cf 21 + #define AMD_SCL_I3C_PP_TIMING 0x00160016 22 + 23 + #define QUEUE_THLD_CTRL 0xD0 24 + 25 + void amd_set_od_pp_timing(struct i3c_hci *hci) 26 + { 27 + u32 data; 28 + 29 + reg_write(HCI_SCL_I3C_OD_TIMING, AMD_SCL_I3C_OD_TIMING); 30 + reg_write(HCI_SCL_I3C_PP_TIMING, AMD_SCL_I3C_PP_TIMING); 31 + data = reg_read(HCI_SDA_HOLD_SWITCH_DLY_TIMING); 32 + /* Configure maximum TX hold time */ 33 + data |= W0_MASK(18, 16); 34 + reg_write(HCI_SDA_HOLD_SWITCH_DLY_TIMING, data); 35 + } 36 + 37 + void amd_set_resp_buf_thld(struct i3c_hci *hci) 38 + { 39 + u32 data; 40 + 41 + data = reg_read(QUEUE_THLD_CTRL); 42 + data = data & ~W0_MASK(15, 8); 43 + reg_write(QUEUE_THLD_CTRL, data); 44 + }
+75 -9
drivers/i3c/master/svc-i3c-master.c
··· 127 127 128 128 /* This parameter depends on the implementation and may be tuned */ 129 129 #define SVC_I3C_FIFO_SIZE 16 130 + #define SVC_I3C_PPBAUD_MAX 15 131 + #define SVC_I3C_QUICK_I2C_CLK 4170000 130 132 131 133 #define SVC_I3C_EVENT_IBI BIT(0) 132 134 #define SVC_I3C_EVENT_HOTJOIN BIT(1) ··· 184 182 * @ibi.lock: IBI lock 185 183 * @lock: Transfer lock, protect between IBI work thread and callbacks from master 186 184 * @enabled_events: Bit masks for enable events (IBI, HotJoin). 185 + * @mctrl_config: Configuration value in SVC_I3C_MCTRL for setting speed back. 187 186 */ 188 187 struct svc_i3c_master { 189 188 struct i3c_master_controller base; ··· 215 212 } ibi; 216 213 struct mutex lock; 217 214 int enabled_events; 215 + u32 mctrl_config; 218 216 }; 219 217 220 218 /** ··· 533 529 return IRQ_HANDLED; 534 530 } 535 531 532 + static int svc_i3c_master_set_speed(struct i3c_master_controller *m, 533 + enum i3c_open_drain_speed speed) 534 + { 535 + struct svc_i3c_master *master = to_svc_i3c_master(m); 536 + struct i3c_bus *bus = i3c_master_get_bus(&master->base); 537 + u32 ppbaud, odbaud, odhpp, mconfig; 538 + unsigned long fclk_rate; 539 + int ret; 540 + 541 + ret = pm_runtime_resume_and_get(master->dev); 542 + if (ret < 0) { 543 + dev_err(master->dev, "<%s> Cannot get runtime PM.\n", __func__); 544 + return ret; 545 + } 546 + 547 + switch (speed) { 548 + case I3C_OPEN_DRAIN_SLOW_SPEED: 549 + fclk_rate = clk_get_rate(master->fclk); 550 + if (!fclk_rate) { 551 + ret = -EINVAL; 552 + goto rpm_out; 553 + } 554 + /* 555 + * Set 50% duty-cycle I2C speed to I3C OPEN-DRAIN mode, so the first 556 + * broadcast address is visible to all I2C/I3C devices on the I3C bus. 557 + * I3C device working as a I2C device will turn off its 50ns Spike 558 + * Filter to change to I3C mode. 559 + */ 560 + mconfig = master->mctrl_config; 561 + ppbaud = FIELD_GET(GENMASK(11, 8), mconfig); 562 + odhpp = 0; 563 + odbaud = DIV_ROUND_UP(fclk_rate, bus->scl_rate.i2c * (2 + 2 * ppbaud)) - 1; 564 + mconfig &= ~GENMASK(24, 16); 565 + mconfig |= SVC_I3C_MCONFIG_ODBAUD(odbaud) | SVC_I3C_MCONFIG_ODHPP(odhpp); 566 + writel(mconfig, master->regs + SVC_I3C_MCONFIG); 567 + break; 568 + case I3C_OPEN_DRAIN_NORMAL_SPEED: 569 + writel(master->mctrl_config, master->regs + SVC_I3C_MCONFIG); 570 + break; 571 + } 572 + 573 + rpm_out: 574 + pm_runtime_mark_last_busy(master->dev); 575 + pm_runtime_put_autosuspend(master->dev); 576 + 577 + return ret; 578 + } 579 + 536 580 static int svc_i3c_master_bus_init(struct i3c_master_controller *m) 537 581 { 538 582 struct svc_i3c_master *master = to_svc_i3c_master(m); 539 583 struct i3c_bus *bus = i3c_master_get_bus(m); 540 584 struct i3c_device_info info = {}; 541 585 unsigned long fclk_rate, fclk_period_ns; 586 + unsigned long i2c_period_ns, i2c_scl_rate, i3c_scl_rate; 542 587 unsigned int high_period_ns, od_low_period_ns; 543 588 u32 ppbaud, pplow, odhpp, odbaud, odstop, i2cbaud, reg; 544 589 int ret; ··· 608 555 } 609 556 610 557 fclk_period_ns = DIV_ROUND_UP(1000000000, fclk_rate); 558 + i2c_period_ns = DIV_ROUND_UP(1000000000, bus->scl_rate.i2c); 559 + i2c_scl_rate = bus->scl_rate.i2c; 560 + i3c_scl_rate = bus->scl_rate.i3c; 611 561 612 562 /* 613 563 * Using I3C Push-Pull mode, target is 12.5MHz/80ns period. 614 564 * Simplest configuration is using a 50% duty-cycle of 40ns. 615 565 */ 616 - ppbaud = DIV_ROUND_UP(40, fclk_period_ns) - 1; 566 + ppbaud = DIV_ROUND_UP(fclk_rate / 2, i3c_scl_rate) - 1; 617 567 pplow = 0; 618 568 619 569 /* ··· 626 570 */ 627 571 odhpp = 1; 628 572 high_period_ns = (ppbaud + 1) * fclk_period_ns; 629 - odbaud = DIV_ROUND_UP(240 - high_period_ns, high_period_ns) - 1; 573 + odbaud = DIV_ROUND_UP(fclk_rate, SVC_I3C_QUICK_I2C_CLK * (1 + ppbaud)) - 2; 630 574 od_low_period_ns = (odbaud + 1) * high_period_ns; 631 575 632 576 switch (bus->mode) { ··· 635 579 odstop = 0; 636 580 break; 637 581 case I3C_BUS_MODE_MIXED_FAST: 638 - case I3C_BUS_MODE_MIXED_LIMITED: 639 582 /* 640 583 * Using I2C Fm+ mode, target is 1MHz/1000ns, the difference 641 584 * between the high and low period does not really matter. 642 585 */ 643 - i2cbaud = DIV_ROUND_UP(1000, od_low_period_ns) - 2; 586 + i2cbaud = DIV_ROUND_UP(i2c_period_ns, od_low_period_ns) - 2; 644 587 odstop = 1; 645 588 break; 589 + case I3C_BUS_MODE_MIXED_LIMITED: 646 590 case I3C_BUS_MODE_MIXED_SLOW: 647 - /* 648 - * Using I2C Fm mode, target is 0.4MHz/2500ns, with the same 649 - * constraints as the FM+ mode. 650 - */ 651 - i2cbaud = DIV_ROUND_UP(2500, od_low_period_ns) - 2; 591 + /* I3C PP + I3C OP + I2C OP both use i2c clk rate */ 592 + if (ppbaud > SVC_I3C_PPBAUD_MAX) { 593 + ppbaud = SVC_I3C_PPBAUD_MAX; 594 + pplow = DIV_ROUND_UP(fclk_rate, i3c_scl_rate) - (2 + 2 * ppbaud); 595 + } 596 + 597 + high_period_ns = (ppbaud + 1) * fclk_period_ns; 598 + odhpp = 0; 599 + odbaud = DIV_ROUND_UP(fclk_rate, i2c_scl_rate * (2 + 2 * ppbaud)) - 1; 600 + 601 + od_low_period_ns = (odbaud + 1) * high_period_ns; 602 + i2cbaud = DIV_ROUND_UP(i2c_period_ns, od_low_period_ns) - 2; 652 603 odstop = 1; 653 604 break; 654 605 default: ··· 674 611 SVC_I3C_MCONFIG_I2CBAUD(i2cbaud); 675 612 writel(reg, master->regs + SVC_I3C_MCONFIG); 676 613 614 + master->mctrl_config = reg; 677 615 /* Master core's registration */ 678 616 ret = i3c_master_get_free_addr(m, 0); 679 617 if (ret < 0) ··· 1709 1645 .disable_ibi = svc_i3c_master_disable_ibi, 1710 1646 .enable_hotjoin = svc_i3c_master_enable_hotjoin, 1711 1647 .disable_hotjoin = svc_i3c_master_disable_hotjoin, 1648 + .set_speed = svc_i3c_master_set_speed, 1712 1649 }; 1713 1650 1714 1651 static int svc_i3c_master_prepare_clks(struct svc_i3c_master *master) ··· 1840 1775 { 1841 1776 struct svc_i3c_master *master = platform_get_drvdata(pdev); 1842 1777 1778 + cancel_work_sync(&master->hj_work); 1843 1779 i3c_master_unregister(&master->base); 1844 1780 1845 1781 pm_runtime_dont_use_autosuspend(&pdev->dev);
+16
include/linux/i3c/master.h
··· 278 278 }; 279 279 280 280 /** 281 + * enum i3c_open_drain_speed - I3C open-drain speed 282 + * @I3C_OPEN_DRAIN_SLOW_SPEED: Slow open-drain speed for sending the first 283 + * broadcast address. The first broadcast address at this speed 284 + * will be visible to all devices on the I3C bus. I3C devices 285 + * working in I2C mode will turn off their spike filter when 286 + * switching into I3C mode. 287 + * @I3C_OPEN_DRAIN_NORMAL_SPEED: Normal open-drain speed in I3C bus mode. 288 + */ 289 + enum i3c_open_drain_speed { 290 + I3C_OPEN_DRAIN_SLOW_SPEED, 291 + I3C_OPEN_DRAIN_NORMAL_SPEED, 292 + }; 293 + 294 + /** 281 295 * enum i3c_addr_slot_status - I3C address slot status 282 296 * @I3C_ADDR_SLOT_FREE: address is free 283 297 * @I3C_ADDR_SLOT_RSVD: address is reserved ··· 450 436 * NULL. 451 437 * @enable_hotjoin: enable hot join event detect. 452 438 * @disable_hotjoin: disable hot join event detect. 439 + * @set_speed: adjust I3C open drain mode timing. 453 440 */ 454 441 struct i3c_master_controller_ops { 455 442 int (*bus_init)(struct i3c_master_controller *master); ··· 479 464 struct i3c_ibi_slot *slot); 480 465 int (*enable_hotjoin)(struct i3c_master_controller *master); 481 466 int (*disable_hotjoin)(struct i3c_master_controller *master); 467 + int (*set_speed)(struct i3c_master_controller *master, enum i3c_open_drain_speed speed); 482 468 }; 483 469 484 470 /**