Merge tag 'drm-xe-next-fixes-2026-08-27' of https://gitlab.freedesktop.org/drm/xe/kernel into drm-next

Cross-subsystem Changes:
- i2c global register definitions as dependency for xe/i2c fixes. (Heikki)

Driver Changes:
- Media workardound (Daniele)
- Add CCS to gt_idle debugfs print (Bala)
- Page fault related fix (Arvind)
- i2c related fixes (Heikki)
- System Controller mailbox bit fix (Anoop)

Signed-off-by: Dave Airlie <airlied@redhat.com>

From: Rodrigo Vivi <rodrigo.vivi@intel.com>
Link: https://patch.msgid.link/apBrVgvZwIRIfuhR@intel.com
This commit is contained in:
Dave Airlie
2026-08-28 13:14:31 +10:00
19 changed files with 450 additions and 196 deletions

View File

@@ -26253,6 +26253,7 @@ R: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
L: linux-i2c@vger.kernel.org
S: Supported
F: drivers/i2c/busses/i2c-designware-*
F: include/linux/designware_i2c.h
SYNOPSYS DESIGNWARE I2C DRIVER - AMDISP
M: Nirujogi Pratap <pratap.nirujogi@amd.com>

View File

@@ -153,7 +153,9 @@ xe-y += xe_bb.o \
xe_wait_user_fence.o \
xe_wopcm.o
xe-$(CONFIG_I2C) += xe_i2c.o
xe-$(CONFIG_I2C) += xe_i2c.o \
xe_amc.o
xe-$(CONFIG_DRM_XE_GPUSVM) += xe_svm.o
xe-$(CONFIG_DRM_GPUSVM) += xe_userptr.o

View File

@@ -20,4 +20,6 @@
#define I2C_CONFIG_CMD XE_REG(I2C_CONFIG_SPACE_OFFSET + PCI_COMMAND)
#define I2C_CONFIG_PMCSR XE_REG(I2C_CONFIG_SPACE_OFFSET + 0x84)
#define I2C_REG(reg) XE_REG((reg) + I2C_MEM_SPACE_OFFSET)
#endif /* _XE_I2C_REGS_H_ */

197
drivers/gpu/drm/xe/xe_amc.c Normal file
View File

@@ -0,0 +1,197 @@
// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (C) 2026 Intel Corporation.
*/
#include <linux/delay.h>
#include <linux/dev_printk.h>
#include <linux/err.h>
#include <linux/i2c.h>
#include <linux/pci_ids.h>
#include <linux/slab.h>
#include <linux/string.h>
#include <linux/workqueue.h>
#include "regs/xe_i2c_regs.h"
#include "xe_amc.h"
#include "xe_device.h"
#include "xe_i2c.h"
#include "xe_mmio.h"
/**
* DOC: Add-In Management Controller (AMC)
*
* Handler for the SMBus Alerts from the AMC. All the alerts from AMC will cause
* the device to be declared wedged.
*/
#define AMC_COMMAND 0x0f
#define AMC_GPU_I2C_ADDR 0x8f
#define AMC_VERSION_V1 0x01
#define AMC_DESTINATION_ID 12
#define AMC_SOURCE_ID 8
#define AMC_FLAGS 0xc8
#define AMC_MSG_TYPE 0x7e
#define AMC_GET_ALERT_REASON 0x01
enum xe_amc_alert {
AMC_ALERT_UNKNOWN,
AMC_ALERT_FW_DOWNLOAD,
AMC_ALERT_THERMAL_TRIP,
AMC_ALERT_OOB_REQUEST,
AMC_ALERT_OOB_RESET,
AMC_ALERT_CATERR,
};
static const char * const amc_alert[] = {
[AMC_ALERT_FW_DOWNLOAD] = "Firmware Download",
[AMC_ALERT_THERMAL_TRIP] = "Thermal Trip",
[AMC_ALERT_OOB_REQUEST] = "OOB Request",
[AMC_ALERT_OOB_RESET] = "OOB Reset",
[AMC_ALERT_CATERR] = "Catastrophic",
};
struct xe_amc {
struct xe_i2c *i2c;
struct work_struct work;
};
struct amc_header {
u8 command;
u8 len;
u8 address;
u8 version;
u8 destination;
u8 source;
u8 flags;
} __packed;
struct amc_message {
u8 type;
u16 vendor;
u8 command;
} __packed;
struct amc_request {
struct amc_header header;
struct amc_message message;
u32 reserved;
} __packed;
struct amc_response {
struct amc_header header;
struct amc_message message;
u8 error;
u8 value;
} __packed;
static const struct amc_request amc_get_alert_reason = {
.header = {
.command = AMC_COMMAND,
.len = sizeof(struct amc_request) - 2,
.address = AMC_GPU_I2C_ADDR,
.version = AMC_VERSION_V1,
.destination = AMC_DESTINATION_ID,
.source = AMC_SOURCE_ID,
.flags = AMC_FLAGS,
},
.message = {
.type = AMC_MSG_TYPE,
.vendor = htons(PCI_VENDOR_ID_INTEL),
.command = AMC_GET_ALERT_REASON,
},
};
static void xe_amc_work(struct work_struct *work)
{
const struct amc_request *request = &amc_get_alert_reason;
struct xe_amc *amc = from_work(amc, work, work);
u8 alert_reason = AMC_ALERT_UNKNOWN;
struct amc_response response;
struct i2c_client *client;
int ret;
client = amc->i2c->client[XE_I2C_CLIENT_AMC];
if (IS_ERR_OR_NULL(client))
goto out_reassert_interrupt;
ret = i2c_master_send(client, (u8 *)request, sizeof(*request));
if (ret < 0) {
dev_err(&client->dev, "failed to send request (%d)\n", ret);
goto out_reassert_interrupt;
}
/* AMC needs 20ms to generate the response. */
fsleep(20 * USEC_PER_MSEC);
ret = i2c_master_recv(client, (u8 *)&response, sizeof(response));
if (ret < 0) {
dev_err(&client->dev, "failed to read response (%d)\n", ret);
goto out_reassert_interrupt;
}
if (!response.header.len) {
dev_err(&client->dev, "empty response from AMC\n");
goto out_reassert_interrupt;
}
if (memcmp(&response.message, &request->message, sizeof(struct amc_message))) {
dev_err(&client->dev, "response does not match the request\n");
goto out_reassert_interrupt;
}
if (response.error) {
dev_err(&client->dev, "AMC error 0x%02x\n", response.error);
goto out_reassert_interrupt;
}
alert_reason = response.value;
dev_dbg(&client->dev, "Alert reason: %d\n", alert_reason);
out_reassert_interrupt:
xe_mmio_rmw32(amc->i2c->mmio, I2C_CONFIG_CMD, PCI_COMMAND_INTX_DISABLE, 0);
switch (alert_reason) {
case AMC_ALERT_FW_DOWNLOAD:
case AMC_ALERT_THERMAL_TRIP:
case AMC_ALERT_OOB_REQUEST:
case AMC_ALERT_OOB_RESET:
case AMC_ALERT_CATERR:
dev_warn(amc->i2c->drm_dev, "AMC Alert: %s\n", amc_alert[alert_reason]);
xe_device_declare_wedged(i2c_client_to_xe_device(client));
break;
default:
dev_warn(amc->i2c->drm_dev, "unknown AMC alert: %d\n", alert_reason);
break;
}
}
void xe_amc_handle_alert(struct xe_i2c *i2c)
{
queue_work(system_long_wq, &i2c->amc->work);
}
int xe_amc_init(struct xe_i2c *i2c)
{
struct xe_amc *amc;
amc = kzalloc(sizeof(*amc), GFP_KERNEL);
if (!amc)
return -ENOMEM;
INIT_WORK(&amc->work, xe_amc_work);
i2c->amc = amc;
amc->i2c = i2c;
return 0;
}
void xe_amc_exit(struct xe_i2c *i2c)
{
if (i2c->amc) {
cancel_work_sync(&i2c->amc->work);
kfree(i2c->amc);
}
}

View File

@@ -0,0 +1,25 @@
/* SPDX-License-Identifier: GPL-2.0 */
#ifndef _XE_AMC_H_
#define _XE_AMC_H_
#include <linux/i2c.h>
#include "xe_device.h"
struct xe_i2c;
static inline struct xe_device *i2c_adapter_to_xe_device(struct i2c_adapter *adapter)
{
return kdev_to_xe_device(adapter->dev.parent->parent);
}
static inline struct xe_device *i2c_client_to_xe_device(struct i2c_client *client)
{
return i2c_adapter_to_xe_device(client->adapter);
}
int xe_amc_init(struct xe_i2c *i2c);
void xe_amc_exit(struct xe_i2c *i2c);
void xe_amc_handle_alert(struct xe_i2c *i2c);
#endif /* _XE_AMC_H_ */

View File

@@ -248,7 +248,8 @@ int xe_gt_idle_pg_print(struct xe_gt *gt, struct drm_printer *p)
pg_status = xe_mmio_read32(&gt->mmio, POWERGATE_DOMAIN_STATUS);
}
if (gt->info.engine_mask & XE_HW_ENGINE_RCS_MASK) {
if (gt->info.engine_mask &
(XE_HW_ENGINE_RCS_MASK | XE_HW_ENGINE_CCS_MASK)) {
drm_printf(p, "Render Power Gating Enabled: %s\n",
str_yes_no(pg_enabled & RENDER_POWERGATE_ENABLE));

View File

@@ -8,12 +8,11 @@
#include <drm/drm_print.h>
#include <linux/array_size.h>
#include <linux/container_of.h>
#include <linux/delay.h>
#include <linux/device.h>
#include <linux/err.h>
#include <linux/i2c.h>
#include <linux/ioport.h>
#include <linux/irq.h>
#include <linux/irqdomain.h>
#include <linux/notifier.h>
#include <linux/pci.h>
#include <linux/platform_device.h>
@@ -24,9 +23,12 @@
#include <linux/types.h>
#include <linux/workqueue.h>
#include <linux/designware_i2c.h>
#include "regs/xe_i2c_regs.h"
#include "regs/xe_irq_regs.h"
#include "xe_amc.h"
#include "xe_device.h"
#include "xe_i2c.h"
#include "xe_mmio.h"
@@ -61,16 +63,32 @@ static inline void xe_i2c_read_endpoint(struct xe_mmio *mmio, void *ep)
val[1] = xe_mmio_read32(mmio, REG_SG_REMAP_ADDR_POSTFIX);
}
static void xe_i2c_handle_smbus_alert(struct xe_i2c *i2c)
{
u32 stat;
stat = xe_mmio_read32(i2c->mmio, I2C_REG(DW_IC_SMBUS_INTR_STAT));
if (!stat)
return;
xe_mmio_write32(i2c->mmio, I2C_REG(DW_IC_CLR_SMBUS_INTR), stat);
if (stat & DW_IC_SMBUS_INTR_ALERT && i2c->amc)
xe_amc_handle_alert(i2c);
else
xe_mmio_rmw32(i2c->mmio, I2C_CONFIG_CMD, PCI_COMMAND_INTX_DISABLE, 0);
}
static void xe_i2c_client_work(struct work_struct *work)
{
struct xe_i2c *i2c = container_of(work, struct xe_i2c, work);
struct i2c_board_info info = {
.type = "amc",
.flags = I2C_CLIENT_HOST_NOTIFY,
.addr = i2c->ep.addr[1],
.addr = i2c->ep.addr[XE_I2C_CLIENT_AMC],
};
i2c->client[0] = i2c_new_client_device(i2c->adapter, &info);
i2c->client[XE_I2C_CLIENT_AMC] = i2c_new_client_device(i2c->adapter, &info);
}
static int xe_i2c_notifier(struct notifier_block *nb, unsigned long action, void *data)
@@ -115,16 +133,6 @@ static int xe_i2c_register_adapter(struct xe_i2c *i2c)
goto err_fwnode_remove;
}
if (i2c->adapter_irq) {
struct resource res;
res = DEFINE_RES_IRQ_NAMED(i2c->adapter_irq, "xe_i2c");
ret = platform_device_add_resources(pdev, &res, 1);
if (ret)
goto err_pdev_put;
}
pdev->dev.parent = i2c->drm_dev;
pdev->dev.fwnode = fwnode;
i2c->adapter_node = fwnode;
@@ -166,7 +174,8 @@ bool xe_i2c_present(struct xe_device *xe)
static bool xe_i2c_irq_present(struct xe_device *xe)
{
return xe->i2c && xe->i2c->adapter_irq;
return xe->i2c && xe->i2c->ep.capabilities & XE_I2C_EP_CAP_IRQ &&
!xe_survivability_mode_is_boot_enabled(xe);
}
/**
@@ -179,18 +188,10 @@ static bool xe_i2c_irq_present(struct xe_device *xe)
*/
void xe_i2c_irq_handler(struct xe_device *xe, u32 master_ctl)
{
struct xe_mmio *mmio = xe_root_tile_mmio(xe);
if (!(master_ctl & I2C_IRQ) || !xe_i2c_irq_present(xe))
return;
/* Forward interrupt to I2C adapter */
generic_handle_irq_safe(xe->i2c->adapter_irq);
/* Deassert after I2C adapter clears the interrupt */
xe_mmio_rmw32(mmio, I2C_CONFIG_CMD, 0, PCI_COMMAND_INTX_DISABLE);
/* Reassert to allow subsequent interrupt generation */
xe_mmio_rmw32(mmio, I2C_CONFIG_CMD, PCI_COMMAND_INTX_DISABLE, 0);
xe_i2c_handle_smbus_alert(xe->i2c);
}
void xe_i2c_irq_reset(struct xe_device *xe)
@@ -215,50 +216,40 @@ void xe_i2c_irq_postinstall(struct xe_device *xe)
xe_mmio_rmw32(mmio, I2C_CONFIG_CMD, PCI_COMMAND_INTX_DISABLE, 0);
}
static int xe_i2c_irq_map(struct irq_domain *h, unsigned int virq,
irq_hw_number_t hw_irq_num)
/* See "Disabling DW_apb_i2c" in the DesignWare DW_abp_i2c databook. */
static void xe_i2c_disable(struct xe_i2c *i2c)
{
irq_set_chip_and_handler(virq, &dummy_irq_chip, handle_simple_irq);
return 0;
}
int timeout = 100;
u32 status;
static const struct irq_domain_ops xe_i2c_irq_ops = {
.map = xe_i2c_irq_map,
};
xe_mmio_rmw32(i2c->mmio, I2C_REG(DW_IC_ENABLE), DW_IC_ENABLE_ENABLE, 0);
static int xe_i2c_create_irq(struct xe_device *xe)
{
struct xe_i2c *i2c = xe->i2c;
struct irq_domain *domain;
do {
status = xe_mmio_read32(i2c->mmio, I2C_REG(DW_IC_ENABLE_STATUS));
if (!(status & DW_IC_ENABLE_ENABLE))
return;
/* Can't sleep here. */
udelay(25);
} while (timeout--);
if (!(i2c->ep.capabilities & XE_I2C_EP_CAP_IRQ) ||
xe_survivability_mode_is_boot_enabled(xe))
return 0;
domain = irq_domain_create_linear(dev_fwnode(i2c->drm_dev), 1, &xe_i2c_irq_ops, NULL);
if (!domain)
return -ENOMEM;
i2c->adapter_irq = irq_create_mapping(domain, 0);
i2c->irqdomain = domain;
return 0;
}
static void xe_i2c_remove_irq(struct xe_i2c *i2c)
{
if (!i2c->irqdomain)
return;
irq_dispose_mapping(i2c->adapter_irq);
irq_domain_remove(i2c->irqdomain);
dev_warn(i2c->drm_dev, "timeout in disabling i2c adapter\n");
}
static int xe_i2c_read(void *context, unsigned int reg, unsigned int *val)
{
struct xe_i2c *i2c = context;
*val = xe_mmio_read32(i2c->mmio, XE_REG(reg + I2C_MEM_SPACE_OFFSET));
*val = xe_mmio_read32(i2c->mmio, I2C_REG(reg));
switch (reg) {
case DW_IC_ENABLE:
case DW_IC_ENABLE_STATUS:
FIELD_MODIFY(DW_IC_ENABLE_ENABLE, val,
i2c->ic_enable & DW_IC_ENABLE_ENABLE);
break;
default:
break;
}
return 0;
}
@@ -267,8 +258,33 @@ static int xe_i2c_write(void *context, unsigned int reg, unsigned int val)
{
struct xe_i2c *i2c = context;
xe_mmio_write32(i2c->mmio, XE_REG(reg + I2C_MEM_SPACE_OFFSET), val);
switch (reg) {
case DW_IC_CON:
case DW_IC_TAR:
case DW_IC_SAR:
/* Disable the controller. */
xe_i2c_disable(i2c);
/* Write the register. */
xe_mmio_write32(i2c->mmio, I2C_REG(reg), val);
/* Enable the controller. */
xe_mmio_rmw32(i2c->mmio, I2C_REG(DW_IC_ENABLE), 0, DW_IC_ENABLE_ENABLE);
return 0;
case DW_IC_ENABLE:
i2c->ic_enable = val;
/* Other fields can be updated except the enable bit. */
val |= DW_IC_ENABLE_ENABLE;
break;
case DW_IC_SMBUS_INTR_MASK:
/* Make sure the Alert is never masked. */
val |= DW_IC_SMBUS_INTR_ALERT;
break;
default:
break;
}
xe_mmio_write32(i2c->mmio, I2C_REG(reg), val);
return 0;
}
@@ -310,12 +326,15 @@ static void xe_i2c_remove(void *data)
struct xe_i2c *i2c = data;
unsigned int i;
for (i = 0; i < XE_I2C_MAX_CLIENTS; i++)
xe_amc_exit(i2c);
for (i = 0; i < XE_I2C_MAX_CLIENTS; i++) {
i2c_unregister_device(i2c->client[i]);
i2c->client[i] = NULL;
}
bus_unregister_notifier(&i2c_bus_type, &i2c->bus_notifier);
xe_i2c_unregister_adapter(i2c);
xe_i2c_remove_irq(i2c);
}
/**
@@ -363,22 +382,18 @@ int xe_i2c_probe(struct xe_device *xe)
if (ret)
return ret;
ret = xe_i2c_create_irq(xe);
if (ret)
goto err_unregister_notifier;
ret = xe_i2c_register_adapter(i2c);
if (ret)
goto err_remove_irq;
if (ret) {
bus_unregister_notifier(&i2c_bus_type, &i2c->bus_notifier);
return ret;
}
ret = xe_amc_init(i2c);
if (ret) {
xe_i2c_remove(i2c);
return ret;
}
xe_i2c_irq_postinstall(xe);
return devm_add_action_or_reset(drm_dev, xe_i2c_remove, i2c);
err_remove_irq:
xe_i2c_remove_irq(i2c);
err_unregister_notifier:
bus_unregister_notifier(&i2c_bus_type, &i2c->bus_notifier);
return ret;
}

View File

@@ -11,18 +11,21 @@ struct device;
struct fwnode_handle;
struct i2c_adapter;
struct i2c_client;
struct irq_domain;
struct platform_device;
struct xe_amc;
struct xe_device;
struct xe_mmio;
#define XE_I2C_MAX_CLIENTS 3
#define XE_I2C_EP_COOKIE_DEVICE 0xde
/* Endpoint Capabilities */
#define XE_I2C_EP_CAP_IRQ BIT(0)
enum XE_I2C_CLIENT {
XE_I2C_CLIENT_AMC = 1,
XE_I2C_MAX_CLIENTS = 3,
};
struct xe_i2c_endpoint {
u8 cookie;
u8 capabilities;
@@ -34,17 +37,16 @@ struct xe_i2c {
struct platform_device *pdev;
struct i2c_adapter *adapter;
struct i2c_client *client[XE_I2C_MAX_CLIENTS];
unsigned int ic_enable;
struct notifier_block bus_notifier;
struct work_struct work;
struct irq_domain *irqdomain;
int adapter_irq;
struct xe_i2c_endpoint ep;
struct device *drm_dev;
struct xe_mmio *mmio;
struct xe_amc *amc;
};
#if IS_ENABLED(CONFIG_I2C)

View File

@@ -158,7 +158,7 @@ static struct xe_vm *xe_pagefault_asid_to_vm(struct xe_device *xe, u32 asid)
down_read(&xe->usm.lock);
vm = xa_load(&xe->usm.asid_to_vm, asid);
if (vm && (xe_vm_in_fault_mode(vm) || xe_vm_has_scratch(vm)))
if (vm && xe_vm_in_fault_mode(vm))
xe_vm_get(vm);
else
vm = ERR_PTR(-EINVAL);

View File

@@ -85,7 +85,6 @@ int xe_sysctrl_init(struct xe_device *xe)
return ret;
xe->soc_remapper.set_sysctrl_region(xe, SYSCTRL_MAILBOX_INDEX);
xe_sysctrl_mailbox_init(sc);
INIT_WORK(&sc->work, xe_sysctrl_work);
return devm_add_action_or_reset(xe->drm.dev, sysctrl_fini, xe);
@@ -114,12 +113,10 @@ void xe_sysctrl_irq_handler(struct xe_device *xe, u32 master_ctl)
* @xe: xe device instance
*
* Invoked during system resume (S3/S4 to S0) and runtime resume from D3cold.
* Restores SoC remapper configuration and reinitializes mailbox interface.
* Restores SoC remapper configuration.
*/
void xe_sysctrl_pm_resume(struct xe_device *xe)
{
struct xe_sysctrl *sc = &xe->sc;
if (!xe->info.has_soc_remapper_sysctrl)
return;
@@ -127,6 +124,4 @@ void xe_sysctrl_pm_resume(struct xe_device *xe)
return;
xe->soc_remapper.set_sysctrl_region(xe, SYSCTRL_MAILBOX_INDEX);
xe_sysctrl_mailbox_init(sc);
}

View File

@@ -145,6 +145,7 @@ static int sysctrl_send_frames(struct xe_sysctrl *sc,
struct xe_device *xe = sc_to_xe(sc);
u32 ctrl_reg, total_frames, frame;
size_t bytes_sent, frame_size;
bool phase;
total_frames = DIV_ROUND_UP(cmd_size, XE_SYSCTRL_MB_FRAME_SIZE);
@@ -153,7 +154,8 @@ static int sysctrl_send_frames(struct xe_sysctrl *sc,
return -EBUSY;
}
sc->phase_bit ^= 1;
ctrl_reg = xe_mmio_read32(sc->mmio, SYSCTRL_MB_CTRL);
phase = !(ctrl_reg & SYSCTRL_FRAME_PHASE);
bytes_sent = 0;
for (frame = 0; frame < total_frames; frame++) {
@@ -161,7 +163,6 @@ static int sysctrl_send_frames(struct xe_sysctrl *sc,
if (sysctrl_write_frame(sc, mbox_cmd + bytes_sent, frame_size)) {
xe_err(xe, "sysctrl: Failed to write frame %u\n", frame);
sc->phase_bit = 0;
return -EIO;
}
@@ -169,13 +170,12 @@ static int sysctrl_send_frames(struct xe_sysctrl *sc,
REG_FIELD_PREP(SYSCTRL_FRAME_CURRENT_MASK, frame) |
REG_FIELD_PREP(SYSCTRL_FRAME_TOTAL_MASK, total_frames - 1) |
SYSCTRL_MB_CTRL_CMD |
(sc->phase_bit ? SYSCTRL_FRAME_PHASE : 0);
(phase ? SYSCTRL_FRAME_PHASE : 0);
xe_mmio_write32(sc->mmio, SYSCTRL_MB_CTRL, ctrl_reg);
if (!sysctrl_wait_bit_clear(sc, SYSCTRL_MB_CTRL_RUN_BUSY, timeout_ms)) {
xe_err(xe, "sysctrl: Frame %u acknowledgment timeout\n", frame);
sc->phase_bit = 0;
return -ETIMEDOUT;
}
@@ -321,20 +321,6 @@ void xe_sysctrl_create_command(struct xe_sysctrl_mailbox_command *command, u8 gr
command->data_out_len = response_len;
}
/**
* xe_sysctrl_mailbox_init - Initialize System Controller mailbox interface
* @sc: System controller structure
*
* Initialize system controller mailbox interface for communication.
*/
void xe_sysctrl_mailbox_init(struct xe_sysctrl *sc)
{
u32 ctrl_reg;
ctrl_reg = xe_mmio_read32(sc->mmio, SYSCTRL_MB_CTRL);
sc->phase_bit = (ctrl_reg & SYSCTRL_FRAME_PHASE) ? 1 : 0;
}
/**
* xe_sysctrl_send_command() - Send mailbox command to System Controller
* @sc: System Controller instance

View File

@@ -26,7 +26,6 @@ struct xe_sysctrl_mailbox_command;
void xe_sysctrl_create_command(struct xe_sysctrl_mailbox_command *command, u8 group_id, u8 cmd_id,
void *request, size_t request_len, void *response,
size_t response_len);
void xe_sysctrl_mailbox_init(struct xe_sysctrl *sc);
int xe_sysctrl_send_command(struct xe_sysctrl *sc,
struct xe_sysctrl_mailbox_command *cmd,
size_t *rdata_len);

View File

@@ -26,9 +26,6 @@ struct xe_sysctrl {
/** @cmd_lock: Mutex protecting mailbox command operations */
struct mutex cmd_lock;
/** @phase_bit: Message boundary phase toggle bit (0 or 1) */
bool phase_bit;
/** @work: Pending events worker */
struct work_struct work;

View File

@@ -63,7 +63,7 @@
16026007364 MEDIA_VERSION(3000)
14020316580 MEDIA_VERSION(1301)
14025883347 MEDIA_VERSION_RANGE(1301, 3503)
14025883347 MEDIA_VERSION_RANGE(1301, 3500)
GRAPHICS_VERSION_RANGE(2004, 3005)
16029380221 MEDIA_VERSION(3500)
22022079272 MEDIA_VERSION(3503)

View File

@@ -33,6 +33,8 @@
#include <linux/types.h>
#include <linux/units.h>
#include <linux/designware_i2c.h>
#include "i2c-designware-core.h"
#define DW_IC_DEFAULT_BUS_CAPACITANCE_pF 100

View File

@@ -18,6 +18,8 @@
#include <linux/regmap.h>
#include <linux/types.h>
#include <linux/designware_i2c.h>
#define DW_IC_DEFAULT_FUNCTIONALITY (I2C_FUNC_I2C | \
I2C_FUNC_SMBUS_BYTE | \
I2C_FUNC_SMBUS_BYTE_DATA | \
@@ -25,23 +27,6 @@
I2C_FUNC_SMBUS_BLOCK_DATA | \
I2C_FUNC_SMBUS_I2C_BLOCK)
#define DW_IC_CON_MASTER BIT(0)
#define DW_IC_CON_SPEED_STD (1 << 1)
#define DW_IC_CON_SPEED_FAST (2 << 1)
#define DW_IC_CON_SPEED_HIGH (3 << 1)
#define DW_IC_CON_SPEED_MASK GENMASK(2, 1)
#define DW_IC_CON_10BITADDR_SLAVE BIT(3)
#define DW_IC_CON_10BITADDR_MASTER BIT(4)
#define DW_IC_CON_RESTART_EN BIT(5)
#define DW_IC_CON_SLAVE_DISABLE BIT(6)
#define DW_IC_CON_STOP_DET_IFADDRESSED BIT(7)
#define DW_IC_CON_TX_EMPTY_CTRL BIT(8)
#define DW_IC_CON_RX_FIFO_FULL_HLD_CTRL BIT(9)
#define DW_IC_CON_BUS_CLEAR_CTRL BIT(11)
#define DW_IC_DATA_CMD_DAT GENMASK(7, 0)
#define DW_IC_DATA_CMD_FIRST_DATA_BYTE BIT(11)
/*
* Register access parameters
*/
@@ -55,65 +40,9 @@
#define DW_IC_FIFO_RX_FIELD GENMASK(15, 8)
#define DW_IC_FIFO_MIN_DEPTH 2
/*
* Registers offset
*/
#define DW_IC_CON 0x00
#define DW_IC_TAR 0x04
#define DW_IC_SAR 0x08
#define DW_IC_DATA_CMD 0x10
#define DW_IC_SS_SCL_HCNT 0x14
#define DW_IC_SS_SCL_LCNT 0x18
#define DW_IC_FS_SCL_HCNT 0x1c
#define DW_IC_FS_SCL_LCNT 0x20
#define DW_IC_HS_SCL_HCNT 0x24
#define DW_IC_HS_SCL_LCNT 0x28
#define DW_IC_INTR_STAT 0x2c
#define DW_IC_INTR_MASK 0x30
#define DW_IC_RAW_INTR_STAT 0x34
#define DW_IC_RX_TL 0x38
#define DW_IC_TX_TL 0x3c
#define DW_IC_CLR_INTR 0x40
#define DW_IC_CLR_RX_UNDER 0x44
#define DW_IC_CLR_RX_OVER 0x48
#define DW_IC_CLR_TX_OVER 0x4c
#define DW_IC_CLR_RD_REQ 0x50
#define DW_IC_CLR_TX_ABRT 0x54
#define DW_IC_CLR_RX_DONE 0x58
#define DW_IC_CLR_ACTIVITY 0x5c
#define DW_IC_CLR_STOP_DET 0x60
#define DW_IC_CLR_START_DET 0x64
#define DW_IC_CLR_GEN_CALL 0x68
#define DW_IC_ENABLE 0x6c
#define DW_IC_STATUS 0x70
#define DW_IC_TXFLR 0x74
#define DW_IC_RXFLR 0x78
#define DW_IC_SDA_HOLD 0x7c
#define DW_IC_TX_ABRT_SOURCE 0x80
#define DW_IC_ENABLE_STATUS 0x9c
#define DW_IC_CLR_RESTART_DET 0xa8
#define DW_IC_SMBUS_INTR_MASK 0xcc
#define DW_IC_COMP_PARAM_1 0xf4
#define DW_IC_COMP_VERSION 0xf8
#define DW_IC_SDA_HOLD_MIN_VERS 0x3131312A /* "111*" == v1.11* */
#define DW_IC_COMP_TYPE 0xfc
#define DW_IC_COMP_TYPE_VALUE 0x44570140 /* "DW" + 0x0140 */
#define DW_IC_INTR_RX_UNDER BIT(0)
#define DW_IC_INTR_RX_OVER BIT(1)
#define DW_IC_INTR_RX_FULL BIT(2)
#define DW_IC_INTR_TX_OVER BIT(3)
#define DW_IC_INTR_TX_EMPTY BIT(4)
#define DW_IC_INTR_RD_REQ BIT(5)
#define DW_IC_INTR_TX_ABRT BIT(6)
#define DW_IC_INTR_RX_DONE BIT(7)
#define DW_IC_INTR_ACTIVITY BIT(8)
#define DW_IC_INTR_STOP_DET BIT(9)
#define DW_IC_INTR_START_DET BIT(10)
#define DW_IC_INTR_GEN_CALL BIT(11)
#define DW_IC_INTR_RESTART_DET BIT(12)
#define DW_IC_INTR_MST_ON_HOLD BIT(13)
#define DW_IC_INTR_DEFAULT_MASK (DW_IC_INTR_RX_FULL | \
DW_IC_INTR_TX_ABRT | \
DW_IC_INTR_STOP_DET)
@@ -123,16 +52,6 @@
DW_IC_INTR_RX_UNDER | \
DW_IC_INTR_RD_REQ)
#define DW_IC_ENABLE_ENABLE BIT(0)
#define DW_IC_ENABLE_ABORT BIT(1)
#define DW_IC_STATUS_ACTIVITY BIT(0)
#define DW_IC_STATUS_TFE BIT(2)
#define DW_IC_STATUS_RFNE BIT(3)
#define DW_IC_STATUS_MASTER_ACTIVITY BIT(5)
#define DW_IC_STATUS_SLAVE_ACTIVITY BIT(6)
#define DW_IC_STATUS_MASTER_HOLD_TX_FIFO_EMPTY BIT(7)
#define DW_IC_SDA_HOLD_RX_SHIFT 16
#define DW_IC_SDA_HOLD_RX_MASK GENMASK(23, 16)

View File

@@ -25,6 +25,8 @@
#include <linux/regmap.h>
#include <linux/reset.h>
#include <linux/designware_i2c.h>
#include "i2c-designware-core.h"
#define AMD_TIMEOUT_MIN_US 25

View File

@@ -19,6 +19,8 @@
#include <linux/pm_runtime.h>
#include <linux/regmap.h>
#include <linux/designware_i2c.h>
#include "i2c-designware-core.h"
int i2c_dw_reg_slave(struct i2c_client *slave)

View File

@@ -0,0 +1,107 @@
/* SPDX-License-Identifier: GPL-2.0 */
/*
* Synopsys DesignWare I2C register definitions
*
* Copyright (C) 2026, Intel Corporation
*/
#ifndef __LINUX_DESIGNWARE_I2C_H
#define __LINUX_DESIGNWARE_I2C_H
#include <linux/bits.h>
/*
* Registers offset
*/
#define DW_IC_CON 0x00
#define DW_IC_TAR 0x04
#define DW_IC_SAR 0x08
#define DW_IC_DATA_CMD 0x10
#define DW_IC_SS_SCL_HCNT 0x14
#define DW_IC_SS_SCL_LCNT 0x18
#define DW_IC_FS_SCL_HCNT 0x1c
#define DW_IC_FS_SCL_LCNT 0x20
#define DW_IC_HS_SCL_HCNT 0x24
#define DW_IC_HS_SCL_LCNT 0x28
#define DW_IC_INTR_STAT 0x2c
#define DW_IC_INTR_MASK 0x30
#define DW_IC_RAW_INTR_STAT 0x34
#define DW_IC_RX_TL 0x38
#define DW_IC_TX_TL 0x3c
#define DW_IC_CLR_INTR 0x40
#define DW_IC_CLR_RX_UNDER 0x44
#define DW_IC_CLR_RX_OVER 0x48
#define DW_IC_CLR_TX_OVER 0x4c
#define DW_IC_CLR_RD_REQ 0x50
#define DW_IC_CLR_TX_ABRT 0x54
#define DW_IC_CLR_RX_DONE 0x58
#define DW_IC_CLR_ACTIVITY 0x5c
#define DW_IC_CLR_STOP_DET 0x60
#define DW_IC_CLR_START_DET 0x64
#define DW_IC_CLR_GEN_CALL 0x68
#define DW_IC_ENABLE 0x6c
#define DW_IC_STATUS 0x70
#define DW_IC_TXFLR 0x74
#define DW_IC_RXFLR 0x78
#define DW_IC_SDA_HOLD 0x7c
#define DW_IC_TX_ABRT_SOURCE 0x80
#define DW_IC_ENABLE_STATUS 0x9c
#define DW_IC_CLR_RESTART_DET 0xa8
#define DW_IC_SMBUS_INTR_STAT 0xc8
#define DW_IC_SMBUS_INTR_MASK 0xcc
#define DW_IC_CLR_SMBUS_INTR 0xd4
#define DW_IC_COMP_PARAM_1 0xf4
#define DW_IC_COMP_VERSION 0xf8
#define DW_IC_COMP_TYPE 0xfc
/* DW_IC_CON bits */
#define DW_IC_CON_MASTER BIT(0)
#define DW_IC_CON_SPEED_STD (1 << 1)
#define DW_IC_CON_SPEED_FAST (2 << 1)
#define DW_IC_CON_SPEED_HIGH (3 << 1)
#define DW_IC_CON_SPEED_MASK GENMASK(2, 1)
#define DW_IC_CON_10BITADDR_SLAVE BIT(3)
#define DW_IC_CON_10BITADDR_MASTER BIT(4)
#define DW_IC_CON_RESTART_EN BIT(5)
#define DW_IC_CON_SLAVE_DISABLE BIT(6)
#define DW_IC_CON_STOP_DET_IFADDRESSED BIT(7)
#define DW_IC_CON_TX_EMPTY_CTRL BIT(8)
#define DW_IC_CON_RX_FIFO_FULL_HLD_CTRL BIT(9)
#define DW_IC_CON_BUS_CLEAR_CTRL BIT(11)
/* DW_IC_DATA_CMD bits */
#define DW_IC_DATA_CMD_DAT GENMASK(7, 0)
#define DW_IC_DATA_CMD_FIRST_DATA_BYTE BIT(11)
/* DW_IC_INTR_* bits */
#define DW_IC_INTR_RX_UNDER BIT(0)
#define DW_IC_INTR_RX_OVER BIT(1)
#define DW_IC_INTR_RX_FULL BIT(2)
#define DW_IC_INTR_TX_OVER BIT(3)
#define DW_IC_INTR_TX_EMPTY BIT(4)
#define DW_IC_INTR_RD_REQ BIT(5)
#define DW_IC_INTR_TX_ABRT BIT(6)
#define DW_IC_INTR_RX_DONE BIT(7)
#define DW_IC_INTR_ACTIVITY BIT(8)
#define DW_IC_INTR_STOP_DET BIT(9)
#define DW_IC_INTR_START_DET BIT(10)
#define DW_IC_INTR_GEN_CALL BIT(11)
#define DW_IC_INTR_RESTART_DET BIT(12)
#define DW_IC_INTR_MST_ON_HOLD BIT(13)
/* DW_IC_ENABLE bits */
#define DW_IC_ENABLE_ENABLE BIT(0)
#define DW_IC_ENABLE_ABORT BIT(1)
/* DW_IC_STATUS bits */
#define DW_IC_STATUS_ACTIVITY BIT(0)
#define DW_IC_STATUS_TFE BIT(2)
#define DW_IC_STATUS_RFNE BIT(3)
#define DW_IC_STATUS_MASTER_ACTIVITY BIT(5)
#define DW_IC_STATUS_SLAVE_ACTIVITY BIT(6)
#define DW_IC_STATUS_MASTER_HOLD_TX_FIFO_EMPTY BIT(7)
/* DW_IC_SMBUS_INTR_* bits */
#define DW_IC_SMBUS_INTR_ALERT BIT(10)
#endif /* __LINUX_DESIGNWARE_I2C_H */