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

Merge tag 'peci-next-6.6-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/iwi/linux into char-misc-next

Iwona writes:

Update peci-next for v6.6-rc1

* Add Intel Sapphire Rapids support.
* Add Nuvoton controller driver.

* tag 'peci-next-6.6-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/iwi/linux:
arm64: dts: nuvoton: Add PECI controller node
ARM: dts: nuvoton: Add PECI controller node
peci: Add peci-npcm controller driver
dt-bindings: Add bindings for peci-npcm
hwmon: (peci/dimmtemp) Add Sapphire Rapids support
hwmon: (peci/cputemp) Add Intel Sapphire Rapids support
peci: cpu: Add Intel Sapphire Rapids support

+462
+56
Documentation/devicetree/bindings/peci/nuvoton,npcm-peci.yaml
··· 1 + # SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) 2 + %YAML 1.2 3 + --- 4 + $id: http://devicetree.org/schemas/peci/nuvoton,npcm-peci.yaml# 5 + $schema: http://devicetree.org/meta-schemas/core.yaml# 6 + 7 + title: Nuvoton PECI Bus 8 + 9 + maintainers: 10 + - Tomer Maimon <tmaimon77@gmail.com> 11 + 12 + allOf: 13 + - $ref: peci-controller.yaml# 14 + 15 + properties: 16 + compatible: 17 + enum: 18 + - nuvoton,npcm750-peci 19 + - nuvoton,npcm845-peci 20 + 21 + reg: 22 + maxItems: 1 23 + 24 + interrupts: 25 + maxItems: 1 26 + 27 + clocks: 28 + description: 29 + Clock source for PECI controller. Should reference the APB clock. 30 + maxItems: 1 31 + 32 + cmd-timeout-ms: 33 + minimum: 1 34 + maximum: 1000 35 + default: 1000 36 + 37 + required: 38 + - compatible 39 + - reg 40 + - interrupts 41 + - clocks 42 + 43 + additionalProperties: false 44 + 45 + examples: 46 + - | 47 + #include <dt-bindings/clock/nuvoton,npcm7xx-clock.h> 48 + #include <dt-bindings/interrupt-controller/arm-gic.h> 49 + peci-controller@f0100000 { 50 + compatible = "nuvoton,npcm750-peci"; 51 + reg = <0xf0100000 0x200>; 52 + interrupts = <GIC_SPI 6 IRQ_TYPE_LEVEL_HIGH>; 53 + clocks = <&clk NPCM7XX_CLK_APB3>; 54 + cmd-timeout-ms = <1000>; 55 + }; 56 + ...
+9
arch/arm/boot/dts/nuvoton/nuvoton-common-npcm7xx.dtsi
··· 220 220 }; 221 221 }; 222 222 223 + peci: peci-controller@f0100000 { 224 + compatible = "nuvoton,npcm750-peci"; 225 + reg = <0xf0100000 0x200>; 226 + interrupts = <GIC_SPI 6 IRQ_TYPE_LEVEL_HIGH>; 227 + clocks = <&clk NPCM7XX_CLK_APB3>; 228 + cmd-timeout-ms = <1000>; 229 + status = "disabled"; 230 + }; 231 + 223 232 spi0: spi@200000 { 224 233 compatible = "nuvoton,npcm750-pspi"; 225 234 reg = <0x200000 0x1000>;
+9
arch/arm64/boot/dts/nuvoton/nuvoton-common-npcm8xx.dtsi
··· 68 68 ranges = <0x0 0x0 0xf0000000 0x00300000>, 69 69 <0xfff00000 0x0 0xfff00000 0x00016000>; 70 70 71 + peci: peci-controller@100000 { 72 + compatible = "nuvoton,npcm845-peci"; 73 + reg = <0x100000 0x1000>; 74 + interrupts = <GIC_SPI 6 IRQ_TYPE_LEVEL_HIGH>; 75 + clocks = <&clk NPCM8XX_CLK_APB3>; 76 + cmd-timeout-ms = <1000>; 77 + status = "disabled"; 78 + }; 79 + 71 80 timer0: timer@8000 { 72 81 compatible = "nuvoton,npcm845-timer"; 73 82 interrupts = <GIC_SPI 32 IRQ_TYPE_LEVEL_HIGH>;
+18
drivers/hwmon/peci/cputemp.c
··· 363 363 switch (peci_dev->info.model) { 364 364 case INTEL_FAM6_ICELAKE_X: 365 365 case INTEL_FAM6_ICELAKE_D: 366 + case INTEL_FAM6_SAPPHIRERAPIDS_X: 366 367 ret = peci_ep_pci_local_read(peci_dev, 0, reg->bus, reg->dev, 367 368 reg->func, reg->offset + 4, &data); 368 369 if (ret) ··· 532 531 .offset = 0xd0, 533 532 }; 534 533 534 + static struct resolved_cores_reg resolved_cores_reg_spr = { 535 + .bus = 31, 536 + .dev = 30, 537 + .func = 6, 538 + .offset = 0x80, 539 + }; 540 + 535 541 static const struct cpu_info cpu_hsx = { 536 542 .reg = &resolved_cores_reg_hsx, 537 543 .min_peci_revision = 0x33, ··· 553 545 554 546 static const struct cpu_info cpu_icx = { 555 547 .reg = &resolved_cores_reg_icx, 548 + .min_peci_revision = 0x40, 549 + .thermal_margin_to_millidegree = &dts_ten_dot_six_to_millidegree, 550 + }; 551 + 552 + static const struct cpu_info cpu_spr = { 553 + .reg = &resolved_cores_reg_spr, 556 554 .min_peci_revision = 0x40, 557 555 .thermal_margin_to_millidegree = &dts_ten_dot_six_to_millidegree, 558 556 }; ··· 587 573 { 588 574 .name = "peci_cpu.cputemp.icxd", 589 575 .driver_data = (kernel_ulong_t)&cpu_icx, 576 + }, 577 + { 578 + .name = "peci_cpu.cputemp.spr", 579 + .driver_data = (kernel_ulong_t)&cpu_spr, 590 580 }, 591 581 { } 592 582 };
+50
drivers/hwmon/peci/dimmtemp.c
··· 30 30 #define DIMM_IDX_MAX_ON_ICX 2 31 31 #define CHAN_RANK_MAX_ON_ICXD 4 32 32 #define DIMM_IDX_MAX_ON_ICXD 2 33 + #define CHAN_RANK_MAX_ON_SPR 8 34 + #define DIMM_IDX_MAX_ON_SPR 2 33 35 34 36 #define CHAN_RANK_MAX CHAN_RANK_MAX_ON_HSX 35 37 #define DIMM_IDX_MAX DIMM_IDX_MAX_ON_HSX ··· 532 530 return 0; 533 531 } 534 532 533 + static int 534 + read_thresholds_spr(struct peci_dimmtemp *priv, int dimm_order, int chan_rank, u32 *data) 535 + { 536 + u32 reg_val; 537 + u64 offset; 538 + int ret; 539 + u8 dev; 540 + 541 + ret = peci_ep_pci_local_read(priv->peci_dev, 0, 30, 0, 2, 0xd4, &reg_val); 542 + if (ret || !(reg_val & BIT(31))) 543 + return -ENODATA; /* Use default or previous value */ 544 + 545 + ret = peci_ep_pci_local_read(priv->peci_dev, 0, 30, 0, 2, 0xd0, &reg_val); 546 + if (ret) 547 + return -ENODATA; /* Use default or previous value */ 548 + 549 + /* 550 + * Device 26, Offset 219a8: IMC 0 channel 0 -> rank 0 551 + * Device 26, Offset 299a8: IMC 0 channel 1 -> rank 1 552 + * Device 27, Offset 219a8: IMC 1 channel 0 -> rank 2 553 + * Device 27, Offset 299a8: IMC 1 channel 1 -> rank 3 554 + * Device 28, Offset 219a8: IMC 2 channel 0 -> rank 4 555 + * Device 28, Offset 299a8: IMC 2 channel 1 -> rank 5 556 + * Device 29, Offset 219a8: IMC 3 channel 0 -> rank 6 557 + * Device 29, Offset 299a8: IMC 3 channel 1 -> rank 7 558 + */ 559 + dev = 26 + chan_rank / 2; 560 + offset = 0x219a8 + dimm_order * 4 + (chan_rank % 2) * 0x8000; 561 + 562 + ret = peci_mmio_read(priv->peci_dev, 0, GET_CPU_SEG(reg_val), GET_CPU_BUS(reg_val), 563 + dev, 0, offset, data); 564 + if (ret) 565 + return ret; 566 + 567 + return 0; 568 + } 569 + 535 570 static const struct dimm_info dimm_hsx = { 536 571 .chan_rank_max = CHAN_RANK_MAX_ON_HSX, 537 572 .dimm_idx_max = DIMM_IDX_MAX_ON_HSX, ··· 611 572 .read_thresholds = &read_thresholds_icx, 612 573 }; 613 574 575 + static const struct dimm_info dimm_spr = { 576 + .chan_rank_max = CHAN_RANK_MAX_ON_SPR, 577 + .dimm_idx_max = DIMM_IDX_MAX_ON_SPR, 578 + .min_peci_revision = 0x40, 579 + .read_thresholds = &read_thresholds_spr, 580 + }; 581 + 614 582 static const struct auxiliary_device_id peci_dimmtemp_ids[] = { 615 583 { 616 584 .name = "peci_cpu.dimmtemp.hsx", ··· 642 596 { 643 597 .name = "peci_cpu.dimmtemp.icxd", 644 598 .driver_data = (kernel_ulong_t)&dimm_icxd, 599 + }, 600 + { 601 + .name = "peci_cpu.dimmtemp.spr", 602 + .driver_data = (kernel_ulong_t)&dimm_spr, 645 603 }, 646 604 { } 647 605 };
+16
drivers/peci/controller/Kconfig
··· 16 16 17 17 This driver can also be built as a module. If so, the module will 18 18 be called peci-aspeed. 19 + 20 + config PECI_NPCM 21 + tristate "Nuvoton NPCM PECI support" 22 + depends on ARCH_NPCM || COMPILE_TEST 23 + depends on OF 24 + select REGMAP_MMIO 25 + help 26 + This option enables PECI controller driver for Nuvoton NPCM7XX 27 + and NPCM8XX SoCs. It allows BMC to discover devices connected 28 + to it and communicate with them using PECI protocol. 29 + 30 + Say Y here if you want support for the Platform Environment Control 31 + Interface (PECI) bus adapter driver on the Nuvoton NPCM SoCs. 32 + 33 + This support is also available as a module. If so, the module 34 + will be called peci-npcm.
+1
drivers/peci/controller/Makefile
··· 1 1 # SPDX-License-Identifier: GPL-2.0-only 2 2 3 3 obj-$(CONFIG_PECI_ASPEED) += peci-aspeed.o 4 + obj-$(CONFIG_PECI_NPCM) += peci-npcm.o
+298
drivers/peci/controller/peci-npcm.c
··· 1 + // SPDX-License-Identifier: GPL-2.0 2 + // Copyright (c) 2019 Nuvoton Technology corporation 3 + 4 + #include <linux/bitfield.h> 5 + #include <linux/clk.h> 6 + #include <linux/interrupt.h> 7 + #include <linux/jiffies.h> 8 + #include <linux/module.h> 9 + #include <linux/of.h> 10 + #include <linux/peci.h> 11 + #include <linux/platform_device.h> 12 + #include <linux/regmap.h> 13 + #include <linux/reset.h> 14 + 15 + /* NPCM GCR module */ 16 + #define NPCM_INTCR3_OFFSET 0x9C 17 + #define NPCM_INTCR3_PECIVSEL BIT(19) 18 + 19 + /* NPCM PECI Registers */ 20 + #define NPCM_PECI_CTL_STS 0x00 21 + #define NPCM_PECI_RD_LENGTH 0x04 22 + #define NPCM_PECI_ADDR 0x08 23 + #define NPCM_PECI_CMD 0x0C 24 + #define NPCM_PECI_CTL2 0x10 25 + #define NPCM_PECI_WR_LENGTH 0x1C 26 + #define NPCM_PECI_PDDR 0x2C 27 + #define NPCM_PECI_DAT_INOUT(n) (0x100 + ((n) * 4)) 28 + 29 + #define NPCM_PECI_MAX_REG 0x200 30 + 31 + /* NPCM_PECI_CTL_STS - 0x00 : Control Register */ 32 + #define NPCM_PECI_CTRL_DONE_INT_EN BIT(6) 33 + #define NPCM_PECI_CTRL_ABRT_ERR BIT(4) 34 + #define NPCM_PECI_CTRL_CRC_ERR BIT(3) 35 + #define NPCM_PECI_CTRL_DONE BIT(1) 36 + #define NPCM_PECI_CTRL_START_BUSY BIT(0) 37 + 38 + /* NPCM_PECI_RD_LENGTH - 0x04 : Command Register */ 39 + #define NPCM_PECI_RD_LEN_MASK GENMASK(6, 0) 40 + 41 + /* NPCM_PECI_CMD - 0x10 : Command Register */ 42 + #define NPCM_PECI_CTL2_MASK GENMASK(7, 6) 43 + 44 + /* NPCM_PECI_WR_LENGTH - 0x1C : Command Register */ 45 + #define NPCM_PECI_WR_LEN_MASK GENMASK(6, 0) 46 + 47 + /* NPCM_PECI_PDDR - 0x2C : Command Register */ 48 + #define NPCM_PECI_PDDR_MASK GENMASK(4, 0) 49 + 50 + #define NPCM_PECI_INT_MASK (NPCM_PECI_CTRL_ABRT_ERR | \ 51 + NPCM_PECI_CTRL_CRC_ERR | \ 52 + NPCM_PECI_CTRL_DONE) 53 + 54 + #define NPCM_PECI_IDLE_CHECK_TIMEOUT_USEC (50 * USEC_PER_MSEC) 55 + #define NPCM_PECI_IDLE_CHECK_INTERVAL_USEC (10 * USEC_PER_MSEC) 56 + #define NPCM_PECI_CMD_TIMEOUT_MS_DEFAULT 1000 57 + #define NPCM_PECI_CMD_TIMEOUT_MS_MAX 60000 58 + #define NPCM_PECI_HOST_NEG_BIT_RATE_DEFAULT 15 59 + #define NPCM_PECI_PULL_DOWN_DEFAULT 0 60 + 61 + struct npcm_peci { 62 + u32 cmd_timeout_ms; 63 + struct completion xfer_complete; 64 + struct regmap *regmap; 65 + u32 status; 66 + spinlock_t lock; /* to sync completion status handling */ 67 + struct peci_controller *controller; 68 + struct device *dev; 69 + struct clk *clk; 70 + int irq; 71 + }; 72 + 73 + static int npcm_peci_xfer(struct peci_controller *controller, u8 addr, struct peci_request *req) 74 + { 75 + struct npcm_peci *priv = dev_get_drvdata(controller->dev.parent); 76 + unsigned long timeout = msecs_to_jiffies(priv->cmd_timeout_ms); 77 + unsigned int msg_rd; 78 + u32 cmd_sts; 79 + int i, ret; 80 + 81 + /* Check command sts and bus idle state */ 82 + ret = regmap_read_poll_timeout(priv->regmap, NPCM_PECI_CTL_STS, cmd_sts, 83 + !(cmd_sts & NPCM_PECI_CTRL_START_BUSY), 84 + NPCM_PECI_IDLE_CHECK_INTERVAL_USEC, 85 + NPCM_PECI_IDLE_CHECK_TIMEOUT_USEC); 86 + if (ret) 87 + return ret; /* -ETIMEDOUT */ 88 + 89 + spin_lock_irq(&priv->lock); 90 + reinit_completion(&priv->xfer_complete); 91 + 92 + regmap_write(priv->regmap, NPCM_PECI_ADDR, addr); 93 + regmap_write(priv->regmap, NPCM_PECI_RD_LENGTH, NPCM_PECI_WR_LEN_MASK & req->rx.len); 94 + regmap_write(priv->regmap, NPCM_PECI_WR_LENGTH, NPCM_PECI_WR_LEN_MASK & req->tx.len); 95 + 96 + if (req->tx.len) { 97 + regmap_write(priv->regmap, NPCM_PECI_CMD, req->tx.buf[0]); 98 + 99 + for (i = 0; i < (req->tx.len - 1); i++) 100 + regmap_write(priv->regmap, NPCM_PECI_DAT_INOUT(i), req->tx.buf[i + 1]); 101 + } 102 + 103 + #if IS_ENABLED(CONFIG_DYNAMIC_DEBUG) 104 + dev_dbg(priv->dev, "addr : %#02x, tx.len : %#02x, rx.len : %#02x\n", 105 + addr, req->tx.len, req->rx.len); 106 + print_hex_dump_bytes("TX : ", DUMP_PREFIX_NONE, req->tx.buf, req->tx.len); 107 + #endif 108 + 109 + priv->status = 0; 110 + regmap_update_bits(priv->regmap, NPCM_PECI_CTL_STS, NPCM_PECI_CTRL_START_BUSY, 111 + NPCM_PECI_CTRL_START_BUSY); 112 + 113 + spin_unlock_irq(&priv->lock); 114 + 115 + ret = wait_for_completion_interruptible_timeout(&priv->xfer_complete, timeout); 116 + if (ret < 0) 117 + return ret; 118 + 119 + if (ret == 0) { 120 + dev_dbg(priv->dev, "timeout waiting for a response\n"); 121 + return -ETIMEDOUT; 122 + } 123 + 124 + spin_lock_irq(&priv->lock); 125 + 126 + if (priv->status != NPCM_PECI_CTRL_DONE) { 127 + spin_unlock_irq(&priv->lock); 128 + dev_dbg(priv->dev, "no valid response, status: %#02x\n", priv->status); 129 + return -EIO; 130 + } 131 + 132 + regmap_write(priv->regmap, NPCM_PECI_CMD, 0); 133 + 134 + for (i = 0; i < req->rx.len; i++) { 135 + regmap_read(priv->regmap, NPCM_PECI_DAT_INOUT(i), &msg_rd); 136 + req->rx.buf[i] = (u8)msg_rd; 137 + } 138 + 139 + spin_unlock_irq(&priv->lock); 140 + 141 + #if IS_ENABLED(CONFIG_DYNAMIC_DEBUG) 142 + print_hex_dump_bytes("RX : ", DUMP_PREFIX_NONE, req->rx.buf, req->rx.len); 143 + #endif 144 + return 0; 145 + } 146 + 147 + static irqreturn_t npcm_peci_irq_handler(int irq, void *arg) 148 + { 149 + struct npcm_peci *priv = arg; 150 + u32 status_ack = 0; 151 + u32 status; 152 + 153 + spin_lock(&priv->lock); 154 + regmap_read(priv->regmap, NPCM_PECI_CTL_STS, &status); 155 + priv->status |= (status & NPCM_PECI_INT_MASK); 156 + 157 + if (status & NPCM_PECI_CTRL_CRC_ERR) 158 + status_ack |= NPCM_PECI_CTRL_CRC_ERR; 159 + 160 + if (status & NPCM_PECI_CTRL_ABRT_ERR) 161 + status_ack |= NPCM_PECI_CTRL_ABRT_ERR; 162 + 163 + /* 164 + * All commands should be ended up with a NPCM_PECI_CTRL_DONE 165 + * bit set even in an error case. 166 + */ 167 + if (status & NPCM_PECI_CTRL_DONE) { 168 + status_ack |= NPCM_PECI_CTRL_DONE; 169 + complete(&priv->xfer_complete); 170 + } 171 + 172 + regmap_write_bits(priv->regmap, NPCM_PECI_CTL_STS, NPCM_PECI_INT_MASK, status_ack); 173 + 174 + spin_unlock(&priv->lock); 175 + return IRQ_HANDLED; 176 + } 177 + 178 + static int npcm_peci_init_ctrl(struct npcm_peci *priv) 179 + { 180 + u32 cmd_sts; 181 + int ret; 182 + 183 + priv->clk = devm_clk_get_enabled(priv->dev, NULL); 184 + if (IS_ERR(priv->clk)) { 185 + dev_err(priv->dev, "failed to get ref clock\n"); 186 + return PTR_ERR(priv->clk); 187 + } 188 + 189 + ret = device_property_read_u32(priv->dev, "cmd-timeout-ms", &priv->cmd_timeout_ms); 190 + if (ret) { 191 + priv->cmd_timeout_ms = NPCM_PECI_CMD_TIMEOUT_MS_DEFAULT; 192 + } else if (priv->cmd_timeout_ms > NPCM_PECI_CMD_TIMEOUT_MS_MAX || 193 + priv->cmd_timeout_ms == 0) { 194 + dev_warn(priv->dev, "invalid cmd-timeout-ms: %u, falling back to: %u\n", 195 + priv->cmd_timeout_ms, NPCM_PECI_CMD_TIMEOUT_MS_DEFAULT); 196 + 197 + priv->cmd_timeout_ms = NPCM_PECI_CMD_TIMEOUT_MS_DEFAULT; 198 + } 199 + 200 + regmap_update_bits(priv->regmap, NPCM_PECI_CTL2, NPCM_PECI_CTL2_MASK, 201 + NPCM_PECI_PULL_DOWN_DEFAULT << 6); 202 + 203 + regmap_update_bits(priv->regmap, NPCM_PECI_PDDR, NPCM_PECI_PDDR_MASK, 204 + NPCM_PECI_HOST_NEG_BIT_RATE_DEFAULT); 205 + 206 + ret = regmap_read_poll_timeout(priv->regmap, NPCM_PECI_CTL_STS, cmd_sts, 207 + !(cmd_sts & NPCM_PECI_CTRL_START_BUSY), 208 + NPCM_PECI_IDLE_CHECK_INTERVAL_USEC, 209 + NPCM_PECI_IDLE_CHECK_TIMEOUT_USEC); 210 + if (ret) 211 + return ret; /* -ETIMEDOUT */ 212 + 213 + /* PECI interrupt enable */ 214 + regmap_update_bits(priv->regmap, NPCM_PECI_CTL_STS, NPCM_PECI_CTRL_DONE_INT_EN, 215 + NPCM_PECI_CTRL_DONE_INT_EN); 216 + 217 + return 0; 218 + } 219 + 220 + static const struct regmap_config npcm_peci_regmap_config = { 221 + .reg_bits = 8, 222 + .val_bits = 8, 223 + .max_register = NPCM_PECI_MAX_REG, 224 + .fast_io = true, 225 + }; 226 + 227 + static struct peci_controller_ops npcm_ops = { 228 + .xfer = npcm_peci_xfer, 229 + }; 230 + 231 + static int npcm_peci_probe(struct platform_device *pdev) 232 + { 233 + struct peci_controller *controller; 234 + struct npcm_peci *priv; 235 + void __iomem *base; 236 + int ret; 237 + 238 + priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL); 239 + if (!priv) 240 + return -ENOMEM; 241 + 242 + priv->dev = &pdev->dev; 243 + dev_set_drvdata(&pdev->dev, priv); 244 + 245 + base = devm_platform_ioremap_resource(pdev, 0); 246 + if (IS_ERR(base)) 247 + return PTR_ERR(base); 248 + 249 + priv->regmap = devm_regmap_init_mmio(&pdev->dev, base, &npcm_peci_regmap_config); 250 + if (IS_ERR(priv->regmap)) 251 + return PTR_ERR(priv->regmap); 252 + 253 + priv->irq = platform_get_irq(pdev, 0); 254 + if (priv->irq < 0) 255 + return priv->irq; 256 + 257 + ret = devm_request_irq(&pdev->dev, priv->irq, npcm_peci_irq_handler, 258 + 0, "peci-npcm-irq", priv); 259 + if (ret) 260 + return ret; 261 + 262 + init_completion(&priv->xfer_complete); 263 + spin_lock_init(&priv->lock); 264 + 265 + ret = npcm_peci_init_ctrl(priv); 266 + if (ret) 267 + return ret; 268 + 269 + controller = devm_peci_controller_add(priv->dev, &npcm_ops); 270 + if (IS_ERR(controller)) 271 + return dev_err_probe(priv->dev, PTR_ERR(controller), 272 + "failed to add npcm peci controller\n"); 273 + 274 + priv->controller = controller; 275 + 276 + return 0; 277 + } 278 + 279 + static const struct of_device_id npcm_peci_of_table[] = { 280 + { .compatible = "nuvoton,npcm750-peci", }, 281 + { .compatible = "nuvoton,npcm845-peci", }, 282 + { } 283 + }; 284 + MODULE_DEVICE_TABLE(of, npcm_peci_of_table); 285 + 286 + static struct platform_driver npcm_peci_driver = { 287 + .probe = npcm_peci_probe, 288 + .driver = { 289 + .name = KBUILD_MODNAME, 290 + .of_match_table = npcm_peci_of_table, 291 + }, 292 + }; 293 + module_platform_driver(npcm_peci_driver); 294 + 295 + MODULE_AUTHOR("Tomer Maimon <tomer.maimon@nuvoton.com>"); 296 + MODULE_DESCRIPTION("NPCM PECI driver"); 297 + MODULE_LICENSE("GPL"); 298 + MODULE_IMPORT_NS(PECI);
+5
drivers/peci/cpu.c
··· 323 323 .model = INTEL_FAM6_ICELAKE_D, 324 324 .data = "icxd", 325 325 }, 326 + { /* Sapphire Rapids Xeon */ 327 + .family = 6, 328 + .model = INTEL_FAM6_SAPPHIRERAPIDS_X, 329 + .data = "spr", 330 + }, 326 331 { } 327 332 }; 328 333 MODULE_DEVICE_TABLE(peci, peci_cpu_device_ids);