* [PATCH 1/7] media: ipu6: update ipu7 InSys ABI to 1.2.1.20251215_224531
2026-09-30 9:01 [PATCH 0/7] media: ipu6: add IPU8 support Divyamani Tripathi
@ 2026-09-30 9:01 ` Divyamani Tripathi
2026-09-30 9:01 ` [PATCH 2/7] media: ipu6: add IS_IPU8() macro Divyamani Tripathi
` (5 subsequent siblings)
6 siblings, 0 replies; 8+ messages in thread
From: Divyamani Tripathi @ 2026-09-30 9:01 UTC (permalink / raw)
To: linux-kernel
Cc: sakari.ailus, antti.laakso, sarang.sapre, manik.bajpai,
Divyamani Tripathi
Drop the retired IPU_INSYS_RESP_TYPE_PWM_IRQ response type and add the
mipi_fn field the firmware now reports in its place, matching staging
ipu7's ABI bump. The boot-ABI and psys message changes from that
commit don't apply here: this driver has no equivalents to touch.
Signed-off-by: Divyamani Tripathi <divyamani.tripathi@intel.com>
---
drivers/media/pci/intel/ipu6/ipu7-fw-isys.h | 8 ++++++--
1 file changed, 6 insertions(+), 2 deletions(-)
diff --git a/drivers/media/pci/intel/ipu6/ipu7-fw-isys.h b/drivers/media/pci/intel/ipu6/ipu7-fw-isys.h
index d5289f6add8c..6b72560b0a15 100644
--- a/drivers/media/pci/intel/ipu6/ipu7-fw-isys.h
+++ b/drivers/media/pci/intel/ipu6/ipu7-fw-isys.h
@@ -4,6 +4,8 @@
#ifndef IPU7_FW_ISYS_H
#define IPU7_FW_ISYS_H
+#include <linux/limits.h>
+
#define IPU7_FWLOG_MAX_LOGGER_SOURCES (64U)
#define IPU7_INSYS_MAX_OUTPUT_QUEUES 3U
#define IPU7_INSYS_STREAM_ID_MAX 16U
@@ -24,6 +26,9 @@
#define IPU7_ISYS_NUM_RECV_QUEUE 1U
#define IPU7_INSYS_SEND_QUEUE_TOKEN_FLAG_NONE 0U
+/* Value of mipi_fn below when firmware ABI < 1.2.1 does not report it. */
+#define IPU7_INSYS_MIPI_FRAME_NUMBER_DONT_CARE U16_MAX
+
#define IPU7_LOGGER_CFG_CHANNEL_ENABLE_SYSCOM BIT(1)
#define IPU7_ISYS_MAX_STREAMS 16U
@@ -107,7 +112,6 @@ enum ipu7_insys_resp_type {
IPU7_INSYS_RESP_TYPE_FRAME_EOF = 8,
IPU7_INSYS_RESP_TYPE_STREAM_START_AND_CAPTURE_DONE = 9,
IPU7_INSYS_RESP_TYPE_STREAM_CAPTURE_DONE = 10,
- IPU7_INSYS_RESP_TYPE_PWM_IRQ = 11,
N_IPU7_INSYS_RESP_TYPE
};
@@ -198,7 +202,7 @@ struct ipu7_insys_resp {
u8 pin_id;
u8 frame_id;
u8 skip_frame;
- u8 pad[2];
+ u16 mipi_fn;
};
struct ipu7_insys_resp_queue_token {
--
2.43.0
^ permalink raw reply [flat|nested] 8+ messages in thread* [PATCH 2/7] media: ipu6: add IS_IPU8() macro
2026-09-30 9:01 [PATCH 0/7] media: ipu6: add IPU8 support Divyamani Tripathi
2026-09-30 9:01 ` [PATCH 1/7] media: ipu6: update ipu7 InSys ABI to 1.2.1.20251215_224531 Divyamani Tripathi
@ 2026-09-30 9:01 ` Divyamani Tripathi
2026-09-30 9:01 ` [PATCH 3/7] media: ipu6: add IPU8 InSys ABI 1.0.14 support Divyamani Tripathi
` (4 subsequent siblings)
6 siblings, 0 replies; 8+ messages in thread
From: Divyamani Tripathi @ 2026-09-30 9:01 UTC (permalink / raw)
To: linux-kernel
Cc: sakari.ailus, antti.laakso, sarang.sapre, manik.bajpai,
Divyamani Tripathi
Add IPU_VERSION_8 and an IS_IPU8() accessor mirroring
IS_IPU7()/IS_IPU7P5(), plus the IPU8 firmware/model name defines, as
the baseline for the rest of this series.
Signed-off-by: Divyamani Tripathi <divyamani.tripathi@intel.com>
---
drivers/media/pci/intel/ipu6/ipu6.h | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/drivers/media/pci/intel/ipu6/ipu6.h b/drivers/media/pci/intel/ipu6/ipu6.h
index 72c5063d5198..20ffbb4a9934 100644
--- a/drivers/media/pci/intel/ipu6/ipu6.h
+++ b/drivers/media/pci/intel/ipu6/ipu6.h
@@ -18,6 +18,7 @@ struct ipu6_bus_device;
#define IPU6_MEDIA_DEV_MODEL_NAME "ipu6"
#define IPU7_MEDIA_DEV_MODEL_NAME "ipu7"
#define IPU7P5_MEDIA_DEV_MODEL_NAME "ipu7.5"
+#define IPU8_MEDIA_DEV_MODEL_NAME "ipu8"
#define IPU6SE_FIRMWARE_NAME "intel/ipu/ipu6se_fw.bin"
#define IPU6EP_FIRMWARE_NAME "intel/ipu/ipu6ep_fw.bin"
@@ -26,6 +27,7 @@ struct ipu6_bus_device;
#define IPU6EPADLN_FIRMWARE_NAME "intel/ipu/ipu6epadln_fw.bin"
#define IPU7_FIRMWARE_NAME "intel/ipu/ipu7_fw.bin"
#define IPU7P5_FIRMWARE_NAME "intel/ipu/ipu7ptl_fw.bin"
+#define IPU8_FIRMWARE_NAME "intel/ipu/ipu8_fw.bin"
#define IPU_VERSION_6 BIT(0) /* TGL */
#define IPU_VERSION_6SE BIT(1) /* JSL */
@@ -33,6 +35,7 @@ struct ipu6_bus_device;
#define IPU_VERSION_6EP_MTL BIT(3) /* MTL */
#define IPU_VERSION_7 BIT(4) /* LNL */
#define IPU_VERSION_7P5 BIT(5) /* PTL */
+#define IPU_VERSION_8 BIT(6) /* NVL */
#define IS_IPU6_TGL(isp) ((isp)->hw_ver & IPU_VERSION_6)
#define IS_IPU6SE(isp) ((isp)->hw_ver & IPU_VERSION_6SE)
@@ -42,6 +45,7 @@ struct ipu6_bus_device;
(IPU_VERSION_7 | IPU_VERSION_7P5))
#define IS_IPU7_MTL(isp) ((isp)->hw_ver & IPU_VERSION_7)
#define IS_IPU7P5(isp) ((isp)->hw_ver & IPU_VERSION_7P5)
+#define IS_IPU8(isp) ((isp)->hw_ver & IPU_VERSION_8)
/*
* ISYS DMA can overshoot. For higher resolutions over allocation is one line
--
2.43.0
^ permalink raw reply [flat|nested] 8+ messages in thread* [PATCH 3/7] media: ipu6: add IPU8 InSys ABI 1.0.14 support
2026-09-30 9:01 [PATCH 0/7] media: ipu6: add IPU8 support Divyamani Tripathi
2026-09-30 9:01 ` [PATCH 1/7] media: ipu6: update ipu7 InSys ABI to 1.2.1.20251215_224531 Divyamani Tripathi
2026-09-30 9:01 ` [PATCH 2/7] media: ipu6: add IS_IPU8() macro Divyamani Tripathi
@ 2026-09-30 9:01 ` Divyamani Tripathi
2026-09-30 9:01 ` [PATCH 4/7] media: ipu6: make ipu7 gpreg stride configurable as per IPU version Divyamani Tripathi
` (3 subsequent siblings)
6 siblings, 0 replies; 8+ messages in thread
From: Divyamani Tripathi @ 2026-09-30 9:01 UTC (permalink / raw)
To: linux-kernel
Cc: sakari.ailus, antti.laakso, sarang.sapre, manik.bajpai,
Divyamani Tripathi
Firmware ABI 1.0.14 diverges from IPU7's InSys message layout (uPipe
config, CFA dimension, binning factor, wider output cropping) and
expects boot-message major version 2 instead of IPU7's 1; without the
version fix the IPU8 firmware rejects the boot handshake with
IA_GOFO_FW_BOOT_STATE_CRIT_MSG_VERSION (0xdead0301), confirmed on real
hardware.
Add the IPU8 layout as additional '_ipu8' structs and convert to it at
send time when running on IPU8, keeping the existing IPU7 layout as
the shared driver-internal representation used by the common isys
queue/video code.
Signed-off-by: Divyamani Tripathi <divyamani.tripathi@intel.com>
---
drivers/media/pci/intel/ipu6/ipu6-isys.h | 3 +
drivers/media/pci/intel/ipu6/ipu7-fw-isys.c | 83 +++++++++++++++++++--
drivers/media/pci/intel/ipu6/ipu7-fw-isys.h | 70 +++++++++++++++++
3 files changed, 149 insertions(+), 7 deletions(-)
diff --git a/drivers/media/pci/intel/ipu6/ipu6-isys.h b/drivers/media/pci/intel/ipu6/ipu6-isys.h
index 2af20f56a965..c5c8ede8e64e 100644
--- a/drivers/media/pci/intel/ipu6/ipu6-isys.h
+++ b/drivers/media/pci/intel/ipu6/ipu6-isys.h
@@ -139,6 +139,9 @@ struct isys_fw_msgs {
union {
struct ipu7_fw_isys_frame_buff_set frame;
struct ipu7_fw_isys_stream_cfg stream;
+ /* sizes the union for the larger IPU8 (ABI 1.0.14) layout */
+ struct ipu7_fw_isys_frame_buff_set_ipu8 frame_ipu8;
+ struct ipu7_fw_isys_stream_cfg_ipu8 stream_ipu8;
} ipu7;
};
struct list_head head;
diff --git a/drivers/media/pci/intel/ipu6/ipu7-fw-isys.c b/drivers/media/pci/intel/ipu6/ipu7-fw-isys.c
index 0876cc54faa7..0a66bb4b6eac 100644
--- a/drivers/media/pci/intel/ipu6/ipu7-fw-isys.c
+++ b/drivers/media/pci/intel/ipu6/ipu7-fw-isys.c
@@ -133,8 +133,10 @@ static int ipu7_fw_isys_init(struct ipu6_isys *isys, unsigned int num_streams)
isys->fwctx = fwctx;
+ /* IPU8 firmware expects boot-message major version 2, not 1 */
ret = ipu6_ipu7_init_boot_config(adev, queue_configs, num_queues,
- freq, fw_config_dma_addr, 1U);
+ freq, fw_config_dma_addr,
+ IS_IPU8(adev->isp) ? 2U : 1U);
if (ret) {
ipu7_fw_isys_cleanup(isys);
return ret;
@@ -412,10 +414,59 @@ ipu7_fw_isys_prepare_buf_set(struct isys_fw_msgs *msg,
set->output_pins[0].addr, set->output_pins[0].user_token);
}
+static void isys_stream_cfg_to_ipu8(struct ipu7_fw_isys_stream_cfg_ipu8 *dst,
+ const struct ipu7_fw_isys_stream_cfg *src)
+{
+ memset(dst, 0, sizeof(*dst));
+ memcpy(dst->input_pins, src->input_pins, sizeof(dst->input_pins));
+ dst->stream_msg_map = src->stream_msg_map;
+ dst->port_id = src->port_id;
+ dst->vc = src->vc;
+ dst->nof_input_pins = src->nof_input_pins;
+ dst->nof_output_pins = src->nof_output_pins;
+ for (unsigned int i = 0; i < ARRAY_SIZE(src->output_pins); i++) {
+ dst->output_pins[i].link = src->output_pins[i].link;
+ dst->output_pins[i].crop.line_top =
+ src->output_pins[i].crop.line_top;
+ dst->output_pins[i].crop.line_bottom =
+ src->output_pins[i].crop.line_bottom;
+ dst->output_pins[i].dpcm = src->output_pins[i].dpcm;
+ dst->output_pins[i].stride = src->output_pins[i].stride;
+ dst->output_pins[i].ft = src->output_pins[i].ft;
+ dst->output_pins[i].send_irq = src->output_pins[i].send_irq;
+ dst->output_pins[i].input_pin_id =
+ src->output_pins[i].input_pin_id;
+ dst->output_pins[i].early_ack_en =
+ src->output_pins[i].early_ack_en;
+ }
+}
+
+static void isys_buffset_to_ipu8(struct ipu7_fw_isys_frame_buff_set_ipu8 *dst,
+ const struct ipu7_fw_isys_frame_buff_set *src)
+{
+ memset(dst, 0, sizeof(*dst));
+ for (unsigned int i = 0; i < ARRAY_SIZE(src->output_pins); i++)
+ dst->output_pins[i].pin_payload = src->output_pins[i];
+ dst->capture_msg_map = src->capture_msg_map;
+ dst->frame_id = src->frame_id;
+ dst->skip_frame = src->skip_frame;
+}
+
static int ipu7_fw_isys_stream_open(struct ipu6_isys *isys,
const unsigned int stream_handle,
struct isys_fw_msgs *msg)
{
+ if (IS_IPU8(isys->adev->isp)) {
+ isys_stream_cfg_to_ipu8(&msg->ipu7.stream_ipu8,
+ &msg->ipu7.stream);
+
+ return ipu7_fw_isys_send_cmd(isys, stream_handle,
+ &msg->ipu7.stream_ipu8,
+ msg->dma_addr,
+ sizeof(msg->ipu7.stream_ipu8),
+ IPU7_INSYS_SEND_TYPE_STREAM_OPEN);
+ }
+
return ipu7_fw_isys_send_cmd(isys, stream_handle, &msg->ipu7.stream,
msg->dma_addr, sizeof(msg->ipu7.stream),
IPU7_INSYS_SEND_TYPE_STREAM_OPEN);
@@ -435,22 +486,40 @@ static int ipu7_fw_isys_stream_flush(struct ipu6_isys *isys,
IPU7_INSYS_SEND_TYPE_STREAM_FLUSH);
}
+static int ipu7_fw_isys_send_frame_buff_set(struct ipu6_isys *isys,
+ const unsigned int stream_handle,
+ struct isys_fw_msgs *msg, u16 send_type)
+{
+ if (IS_IPU8(isys->adev->isp)) {
+ isys_buffset_to_ipu8(&msg->ipu7.frame_ipu8,
+ &msg->ipu7.frame);
+
+ return ipu7_fw_isys_send_cmd(isys, stream_handle,
+ &msg->ipu7.frame_ipu8,
+ msg->dma_addr,
+ sizeof(msg->ipu7.frame_ipu8),
+ send_type);
+ }
+
+ return ipu7_fw_isys_send_cmd(isys, stream_handle, &msg->ipu7.frame,
+ msg->dma_addr, sizeof(msg->ipu7.frame),
+ send_type);
+}
+
static int ipu7_fw_isys_stream_start(struct ipu6_isys *isys,
const unsigned int stream_handle,
struct isys_fw_msgs *msg, bool capture)
{
- return ipu7_fw_isys_send_cmd(isys, stream_handle, &msg->ipu7.frame,
- msg->dma_addr, sizeof(msg->ipu7.frame),
- IPU7_INSYS_SEND_TYPE_STREAM_START_AND_CAPTURE);
+ return ipu7_fw_isys_send_frame_buff_set(isys, stream_handle, msg,
+ IPU7_INSYS_SEND_TYPE_STREAM_START_AND_CAPTURE);
}
static int ipu7_fw_isys_stream_capture(struct ipu6_isys *isys,
const unsigned int stream_handle,
struct isys_fw_msgs *msg)
{
- return ipu7_fw_isys_send_cmd(isys, stream_handle, &msg->ipu7.frame,
- msg->dma_addr, sizeof(msg->ipu7.frame),
- IPU7_INSYS_SEND_TYPE_STREAM_CAPTURE);
+ return ipu7_fw_isys_send_frame_buff_set(isys, stream_handle, msg,
+ IPU7_INSYS_SEND_TYPE_STREAM_CAPTURE);
}
const struct ipu6_fw_isys_ops ipu7_fw_isys_ops = {
diff --git a/drivers/media/pci/intel/ipu6/ipu7-fw-isys.h b/drivers/media/pci/intel/ipu6/ipu7-fw-isys.h
index 6b72560b0a15..30289d73be6c 100644
--- a/drivers/media/pci/intel/ipu6/ipu7-fw-isys.h
+++ b/drivers/media/pci/intel/ipu6/ipu7-fw-isys.h
@@ -235,6 +235,14 @@ struct ipu7_fw_isys_output_cropping {
u16 line_bottom;
} __packed;
+/* IPU8 InSys firmware layout, ABI 1.0.14. */
+struct ipu7_fw_isys_output_cropping_ipu8 {
+ u16 line_top;
+ u16 line_bottom;
+ u16 column_left;
+ u16 column_right;
+} __packed;
+
struct ipu7_fw_isys_output_dpcm {
u8 enable;
u8 type;
@@ -242,6 +250,25 @@ struct ipu7_fw_isys_output_dpcm {
u8 pad;
} __packed;
+/* IPU8 (InSys ABI 1.0.14) only. */
+enum ipu7_insys_cfa_dim {
+ IPU7_INSYS_CFA_DIM_2X2 = 0,
+ IPU7_INSYS_CFA_DIM_4X4 = 1,
+ N_IPU7_INSYS_CFA_DIM
+};
+
+#define IPU7_INSYS_MAX_BINNING_FACTOR 4U
+
+/* IPU8 (InSys ABI 1.0.14) only. */
+struct ipu7_fw_isys_upipe_output_pin_ipu8 {
+ u32 opaque_pin_cfg;
+ u16 plane_offset_1;
+ u16 plane_offset_2;
+ u8 single_uob_fifo;
+ u8 shared_uob_fifo;
+ u8 pad[2];
+} __packed;
+
struct ipu7_fw_isys_output_pin {
struct ipu7_fw_isys_output_link link;
struct ipu7_fw_isys_output_cropping crop;
@@ -254,6 +281,22 @@ struct ipu7_fw_isys_output_pin {
u8 pad[3];
} __packed;
+/* IPU8 InSys firmware layout, ABI 1.0.14. */
+struct ipu7_fw_isys_output_pin_ipu8 {
+ struct ipu7_fw_isys_output_link link;
+ struct ipu7_fw_isys_output_cropping_ipu8 crop;
+ struct ipu7_fw_isys_output_dpcm dpcm;
+ struct ipu7_fw_isys_upipe_output_pin_ipu8 upipe_pin_cfg;
+ u32 stride;
+ u16 ft;
+ u8 upipe_enable;
+ u8 send_irq;
+ u8 input_pin_id;
+ u8 early_ack_en;
+ u8 cfa_dim;
+ u8 binning_factor;
+} __packed;
+
struct ipu7_fw_isys_resolution {
u32 width;
u32 height;
@@ -280,12 +323,30 @@ struct ipu7_fw_isys_stream_cfg {
u8 pad[2];
} __packed;
+/* IPU8 InSys firmware layout, ABI 1.0.14. */
+struct ipu7_fw_isys_stream_cfg_ipu8 {
+ struct ipu7_fw_isys_input_pin input_pins[IPU7_MAX_IPINS];
+ struct ipu7_fw_isys_output_pin_ipu8 output_pins[IPU7_MAX_OPINS];
+ u16 stream_msg_map;
+ u8 port_id;
+ u8 vc;
+ u8 nof_input_pins;
+ u8 nof_output_pins;
+ u8 pad[2];
+} __packed;
+
struct ipu7_fw_isys_capture_output_pin {
u64 user_token;
u32 addr;
u8 pad[4];
} __packed;
+/* IPU8 (InSys ABI 1.0.14) only. */
+struct ipu7_fw_isys_capture_output_pin_cfg_ipu8 {
+ struct ipu7_fw_isys_capture_output_pin pin_payload;
+ u32 upipe_capture_cfg;
+} __packed;
+
struct ipu7_fw_isys_frame_buff_set {
struct ipu7_fw_isys_capture_output_pin output_pins[IPU7_MAX_OPINS];
u8 capture_msg_map;
@@ -294,6 +355,15 @@ struct ipu7_fw_isys_frame_buff_set {
u8 pad[5];
} __packed;
+/* IPU8 InSys firmware layout, ABI 1.0.14. */
+struct ipu7_fw_isys_frame_buff_set_ipu8 {
+ struct ipu7_fw_isys_capture_output_pin_cfg_ipu8 output_pins[IPU7_MAX_OPINS];
+ u8 capture_msg_map;
+ u8 frame_id;
+ u8 skip_frame;
+ u8 pad[5];
+} __packed;
+
struct ipu6_fw_isys_ops *ipu7_fw_isys_get_ops(void);
irqreturn_t ipu7_isys_isr(struct ipu6_bus_device *adev);
--
2.43.0
^ permalink raw reply [flat|nested] 8+ messages in thread* [PATCH 4/7] media: ipu6: make ipu7 gpreg stride configurable as per IPU version
2026-09-30 9:01 [PATCH 0/7] media: ipu6: add IPU8 support Divyamani Tripathi
` (2 preceding siblings ...)
2026-09-30 9:01 ` [PATCH 3/7] media: ipu6: add IPU8 InSys ABI 1.0.14 support Divyamani Tripathi
@ 2026-09-30 9:01 ` Divyamani Tripathi
2026-09-30 9:01 ` [PATCH 5/7] media: ipu6: add IPU8 isys chip/MMU enablement Divyamani Tripathi
` (2 subsequent siblings)
6 siblings, 0 replies; 8+ messages in thread
From: Divyamani Tripathi @ 2026-09-30 9:01 UTC (permalink / raw)
To: linux-kernel
Cc: sakari.ailus, antti.laakso, sarang.sapre, manik.bajpai,
Divyamani Tripathi
IPU8's GPREG stride is 0x2000, not IPU7's hardcoded 0x1000. Add
csi2.gpreg_stride and use it in the two gpreg accessors instead of the
fixed value, wiring it up for both IPU7 and IPU8 in
ipu6_internal_pdata_init().
Signed-off-by: Divyamani Tripathi <divyamani.tripathi@intel.com>
---
drivers/media/pci/intel/ipu6/ipu6.c | 7 ++++++-
drivers/media/pci/intel/ipu6/ipu6.h | 1 +
drivers/media/pci/intel/ipu6/ipu7-isys-csi-phy.c | 6 ++++--
drivers/media/pci/intel/ipu6/ipu7-isys-csi2-regs.h | 2 ++
4 files changed, 13 insertions(+), 3 deletions(-)
diff --git a/drivers/media/pci/intel/ipu6/ipu6.c b/drivers/media/pci/intel/ipu6/ipu6.c
index 43d951735f72..2ed2a41ac96f 100644
--- a/drivers/media/pci/intel/ipu6/ipu6.c
+++ b/drivers/media/pci/intel/ipu6/ipu6.c
@@ -371,8 +371,13 @@ static void ipu6_internal_pdata_init(struct ipu6_device *isp)
psys_ipdata.hw_variant.spc_offset = IPU6SE_PSYS_SPC_OFFSET;
}
- if (IS_IPU7(isp)) {
+ if (IS_IPU8(isp)) {
+ isys_ipdata.csi2.gpreg = IPU8_IS_IO_CSI2_GPREGS_BASE;
+ isys_ipdata.csi2.gpreg_stride = IPU8_IS_IO_CSI2_GPREGS_STRIDE;
+ isys_ipdata.csi2.nports = 4;
+ } else if (IS_IPU7(isp)) {
isys_ipdata.csi2.gpreg = IPU7_IS_IO_CSI2_GPREGS_BASE;
+ isys_ipdata.csi2.gpreg_stride = IPU7_IS_IO_CSI2_GPREGS_STRIDE;
isys_ipdata.csi2.nports = 4;
}
}
diff --git a/drivers/media/pci/intel/ipu6/ipu6.h b/drivers/media/pci/intel/ipu6/ipu6.h
index 20ffbb4a9934..00fb78a1ec1d 100644
--- a/drivers/media/pci/intel/ipu6/ipu6.h
+++ b/drivers/media/pci/intel/ipu6/ipu6.h
@@ -147,6 +147,7 @@ struct ipu6_isys_internal_csi2_pdata {
u32 fw_access_port_ofs;
/* IPU7-specific field */
u32 gpreg;
+ u32 gpreg_stride;
};
struct ipu6_isys_internal_tpg_pdata {
diff --git a/drivers/media/pci/intel/ipu6/ipu7-isys-csi-phy.c b/drivers/media/pci/intel/ipu6/ipu7-isys-csi-phy.c
index 10273c687faa..ac4f94764407 100644
--- a/drivers/media/pci/intel/ipu6/ipu7-isys-csi-phy.c
+++ b/drivers/media/pci/intel/ipu6/ipu7-isys-csi-phy.c
@@ -167,7 +167,8 @@ static void gpreg_write(struct ipu6_isys *isys, u32 id, u32 addr, u32 data)
{
void __iomem *isys_base = isys->pdata->base;
u32 gpreg = isys->pdata->ipdata->csi2.gpreg;
- void __iomem *base = isys_base + gpreg + 0x1000 * id;
+ void __iomem *base = isys_base + gpreg +
+ isys->pdata->ipdata->csi2.gpreg_stride * id;
struct device *dev = &isys->adev->auxdev.dev;
dev_dbg(dev, "gpreg write: reg 0x%lx = data 0x%08x",
@@ -344,7 +345,8 @@ static int ipu7_isys_phy_ready(struct ipu6_isys *isys, u32 id)
{
void __iomem *isys_base = isys->pdata->base;
u32 gpreg_offset = isys->pdata->ipdata->csi2.gpreg;
- void __iomem *gpreg = isys_base + gpreg_offset + 0x1000 * id;
+ void __iomem *gpreg = isys_base + gpreg_offset +
+ isys->pdata->ipdata->csi2.gpreg_stride * id;
struct device *dev = &isys->adev->auxdev.dev;
u32 phy_ready;
u32 reg, rext;
diff --git a/drivers/media/pci/intel/ipu6/ipu7-isys-csi2-regs.h b/drivers/media/pci/intel/ipu6/ipu7-isys-csi2-regs.h
index 3859401d4802..4f7f33b9d661 100644
--- a/drivers/media/pci/intel/ipu6/ipu7-isys-csi2-regs.h
+++ b/drivers/media/pci/intel/ipu6/ipu7-isys-csi2-regs.h
@@ -968,7 +968,9 @@
/* software config the phy */
#define IPU7_IS_IO_CSI2_GPREGS_BASE (IPU7_IS_IO_BASE + 0x53400)
+#define IPU7_IS_IO_CSI2_GPREGS_STRIDE 0x1000
#define IPU8_IS_IO_CSI2_GPREGS_BASE (IPU7_IS_IO_BASE + 0x40e00)
+#define IPU8_IS_IO_CSI2_GPREGS_STRIDE 0x2000
#define IPU7_CSI_ADAPT_LAYER_SRST 0x0
#define IPU7_MPF_SRST_RST 0x4
#define IPU7_CSI_ERR_IRQ_CTRL_SRST 0x8
--
2.43.0
^ permalink raw reply [flat|nested] 8+ messages in thread* [PATCH 5/7] media: ipu6: add IPU8 isys chip/MMU enablement
2026-09-30 9:01 [PATCH 0/7] media: ipu6: add IPU8 support Divyamani Tripathi
` (3 preceding siblings ...)
2026-09-30 9:01 ` [PATCH 4/7] media: ipu6: make ipu7 gpreg stride configurable as per IPU version Divyamani Tripathi
@ 2026-09-30 9:01 ` Divyamani Tripathi
2026-09-30 9:01 ` [PATCH 6/7] media: ipu6: add IPU8 psys MMU table and PLL power sequencing Divyamani Tripathi
2026-09-30 9:01 ` [PATCH 7/7] media: ipu6: add PCI ID for IPU8 Divyamani Tripathi
6 siblings, 0 replies; 8+ messages in thread
From: Divyamani Tripathi @ 2026-09-30 9:01 UTC (permalink / raw)
To: linux-kernel
Cc: sakari.ailus, antti.laakso, sarang.sapre, manik.bajpai,
Divyamani Tripathi
Complete IPU8 ISYS enablement: add the IPU8 NDE control register, TSC
sync variant, TLBID_HASH bits and ISYS MMU hardware table. Add
IS_IPU8() alongside the existing IS_IPU7() check at each site in
ipu6.c, ipu6-buttress.c, ipu6-isys.c, ipu6-isys-csi2.c, ipu6-cpd.c and
ipu6-mmu.c that needs to follow the IPU7-family codepath, keeping the
two checks independent instead of widening IS_IPU7() to also match
IPU8. Without this IPU8 firmware boot fails with
IA_GOFO_FW_BOOT_STATE_CRIT_UNSPECIFIED (0xdead0001), confirmed on real
hardware. PSYS-specific pieces are intentionally left out here.
Signed-off-by: Divyamani Tripathi <divyamani.tripathi@intel.com>
---
drivers/media/pci/intel/ipu6/ipu6-buttress.c | 44 ++++--
drivers/media/pci/intel/ipu6/ipu6-cpd.c | 2 +-
drivers/media/pci/intel/ipu6/ipu6-isys-csi2.c | 15 +-
drivers/media/pci/intel/ipu6/ipu6-isys.c | 14 +-
drivers/media/pci/intel/ipu6/ipu6-mmu.c | 4 +-
.../intel/ipu6/ipu6-platform-buttress-regs.h | 2 +
drivers/media/pci/intel/ipu6/ipu6.c | 22 +--
drivers/media/pci/intel/ipu6/ipu7-mmu-hw.c | 145 +++++++++++++++++-
drivers/media/pci/intel/ipu6/ipu7-mmu-hw.h | 64 ++++++++
9 files changed, 275 insertions(+), 37 deletions(-)
diff --git a/drivers/media/pci/intel/ipu6/ipu6-buttress.c b/drivers/media/pci/intel/ipu6/ipu6-buttress.c
index 105de1744dff..be07d33a4dab 100644
--- a/drivers/media/pci/intel/ipu6/ipu6-buttress.c
+++ b/drivers/media/pci/intel/ipu6/ipu6-buttress.c
@@ -346,7 +346,7 @@ irqreturn_t ipu6_buttress_isr(int irq, void *isp_ptr)
if (!active)
return IRQ_NONE;
- if (IS_IPU7(isp)) {
+ if (IS_IPU7(isp) || IS_IPU8(isp)) {
u32 pb_irq;
pb_irq = readl(isp->pb_base + IPU7_PB_INTERRUPT_STATUS);
@@ -478,6 +478,9 @@ static int ipu7_isys_d2d_power(struct ipu6_device *isp, bool on)
static void ipu7_nde_control(struct ipu6_device *isp, bool on)
{
+ u32 resvec = IS_IPU8(isp) ? IPU8_NDE_RESVEC : IPU7_NDE_RESVEC;
+ u32 reg = IS_IPU8(isp) ? IPU8_BUTTRESS_REG_NDE_CONTROL :
+ IPU7_BUTTRESS_REG_NDE_CONTROL;
u32 val;
val = FIELD_PREP(IPU7_NDE_VAL_MASK,
@@ -486,8 +489,8 @@ static void ipu7_nde_control(struct ipu6_device *isp, bool on)
on ? IPU7_NDE_SCALE_ACTIVE : IPU7_NDE_SCALE_DEFAULT) |
FIELD_PREP(IPU7_NDE_VALID_MASK,
on ? IPU7_NDE_VALID_ACTIVE : IPU7_NDE_VALID_DEFAULT) |
- FIELD_PREP(IPU7_NDE_RESVEC_MASK, IPU7_NDE_RESVEC);
- writel(val, isp->base + IPU7_BUTTRESS_REG_NDE_CONTROL);
+ FIELD_PREP(IPU7_NDE_RESVEC_MASK, resvec);
+ writel(val, isp->base + reg);
}
static int __ipu7_power_on(struct device *dev,
@@ -612,7 +615,7 @@ int ipu6_buttress_power(struct device *dev,
mutex_lock(&isp->buttress.power_mutex);
- if (IS_IPU7(isp))
+ if (IS_IPU7(isp) || IS_IPU8(isp))
ret = on ? __ipu7_power_on(dev, ctrl) :
__ipu7_power_off(dev, ctrl);
else
@@ -775,7 +778,7 @@ int ipu6_buttress_authenticate(struct ipu6_device *isp)
* Write address of FIT table to FW_SOURCE register
* Let's use fw address. I.e. not using FIT table yet
*/
- if (IS_IPU7(isp)) {
+ if (IS_IPU7(isp) || IS_IPU8(isp)) {
writel(isp->cpd_fw->size,
isp->base + IPU7_BUTTRESS_REG_FW_SOURCE_SIZE);
writel(sg_dma_address(isp->psys->fw_sgt.sgl),
@@ -822,7 +825,7 @@ int ipu6_buttress_authenticate(struct ipu6_device *isp)
goto out_unlock;
}
- void __iomem *base = IS_IPU7(isp) ?
+ void __iomem *base = (IS_IPU7(isp) || IS_IPU8(isp)) ?
isp->base + IPU7_BUTTRESS_REG_FW_BOOT_PARAMS7 :
psys_pdata->base + BOOTLOADER_STATUS_OFFSET;
@@ -922,6 +925,23 @@ static int __ipu7p5_start_tsc_sync(struct ipu6_device *isp)
return -ETIMEDOUT;
}
+static int __ipu8_start_tsc_sync(struct ipu6_device *isp)
+{
+ u32 val;
+
+ for (unsigned int i = 0; i < BUTTRESS_TSC_SYNC_RESET_TRIAL_MAX; i++) {
+ val = readl(isp->base + IPU7_BUTTRESS_REG_PB_TIMESTAMP_VALID);
+ if (val == 1)
+ return 0;
+
+ usleep_range(40, 50);
+ }
+
+ dev_err(&isp->pdev->dev, "TSC sync failed (timeout)\n");
+
+ return -ETIMEDOUT;
+}
+
static int __ipu6_start_tsc_sync(struct ipu6_device *isp)
{
for (unsigned int i = 0; i < BUTTRESS_TSC_SYNC_RESET_TRIAL_MAX; i++) {
@@ -948,6 +968,9 @@ static int __ipu6_start_tsc_sync(struct ipu6_device *isp)
int ipu6_buttress_start_tsc_sync(struct ipu6_device *isp)
{
+ if (IS_IPU8(isp))
+ return __ipu8_start_tsc_sync(isp);
+
if (IS_IPU7P5(isp))
return __ipu7p5_start_tsc_sync(isp);
@@ -1037,7 +1060,10 @@ static void ipu7_buttress_setup(struct ipu6_device *isp)
writel(val, isp->pb_base + IPU7_BAR2_MISC_CONFIG);
- if (IS_IPU7P5(isp)) {
+ if (IS_IPU8(isp)) {
+ writel(BIT(13), isp->pb_base + IPU7_TLBID_HASH_ENABLE_63_32);
+ writel(BIT(9), isp->pb_base + IPU7_TLBID_HASH_ENABLE_95_64);
+ } else if (IS_IPU7P5(isp)) {
writel(BIT(14), isp->pb_base + IPU7_TLBID_HASH_ENABLE_63_32);
writel(BIT(9), isp->pb_base + IPU7_TLBID_HASH_ENABLE_95_64);
} else {
@@ -1057,7 +1083,7 @@ void ipu6_buttress_restore(struct ipu6_device *isp)
{
struct ipu6_buttress *b = &isp->buttress;
- if (IS_IPU7(isp)) {
+ if (IS_IPU7(isp) || IS_IPU8(isp)) {
ipu7_buttress_setup(isp);
} else {
writel(b->regs->irq_all, isp->base + b->regs->irq_clear);
@@ -1085,7 +1111,7 @@ int ipu6_buttress_init(struct ipu6_device *isp)
dev_dbg(&isp->pdev->dev, "IPU in %s mode\n",
isp->secure_mode ? "secure" : "non-secure");
- if (IS_IPU7(isp)) {
+ if (IS_IPU7(isp) || IS_IPU8(isp)) {
ipu7_buttress_setup(isp);
b->ref_clk = 384;
} else {
diff --git a/drivers/media/pci/intel/ipu6/ipu6-cpd.c b/drivers/media/pci/intel/ipu6/ipu6-cpd.c
index 1fadb0f2f6c1..9824a871dfd6 100644
--- a/drivers/media/pci/intel/ipu6/ipu6-cpd.c
+++ b/drivers/media/pci/intel/ipu6/ipu6-cpd.c
@@ -454,7 +454,7 @@ int ipu6_cpd_validate_cpd_file(struct ipu6_device *isp, const void *cpd_file,
return -EINVAL;
}
- if (IS_IPU7(isp))
+ if (IS_IPU7(isp) || IS_IPU8(isp))
return __ipu7_validate_cpd_file(isp, cpd_file, cpd_file_size);
return __ipu6_validate_cpd_file(isp, cpd_file, cpd_file_size);
diff --git a/drivers/media/pci/intel/ipu6/ipu6-isys-csi2.c b/drivers/media/pci/intel/ipu6/ipu6-isys-csi2.c
index 0db6971d8d3e..4a2b3d460782 100644
--- a/drivers/media/pci/intel/ipu6/ipu6-isys-csi2.c
+++ b/drivers/media/pci/intel/ipu6/ipu6-isys-csi2.c
@@ -244,7 +244,8 @@ static void ipu6_isys_csi2_setup_watermark(struct ipu6_isys_csi2 *csi2,
s64 link_freq;
int ret;
- if (IS_IPU7(csi2->asd.isys->adev->isp))
+ if (IS_IPU7(csi2->asd.isys->adev->isp) ||
+ IS_IPU8(csi2->asd.isys->adev->isp))
return;
ret = v4l2_g_ctrl(remote_sd->ctrl_handler, &hb);
@@ -298,7 +299,8 @@ static void ipu6_isys_csi2_setup_watermark(struct ipu6_isys_csi2 *csi2,
static void ipu6_isys_csi2_clear_watermark(struct ipu6_isys_csi2 *csi2)
{
- if (IS_IPU7(csi2->asd.isys->adev->isp))
+ if (IS_IPU7(csi2->asd.isys->adev->isp) ||
+ IS_IPU8(csi2->asd.isys->adev->isp))
return;
csi2->watermark.force_iwake_disable = false;
@@ -680,8 +682,9 @@ static int ipu6_isys_csi2_enable_streams(struct v4l2_subdev *sd,
goto err_requeue_buffers;
if (!csi2->streaming_vc) {
- ret = IS_IPU7(isp) ? ipu7_isys_csi2_stream_enable(csi2) :
- ipu6_isys_csi2_stream_enable(csi2);
+ ret = (IS_IPU7(isp) || IS_IPU8(isp)) ?
+ ipu7_isys_csi2_stream_enable(csi2) :
+ ipu6_isys_csi2_stream_enable(csi2);
if (ret)
goto err_stop_stream_firmware;
}
@@ -696,7 +699,7 @@ static int ipu6_isys_csi2_enable_streams(struct v4l2_subdev *sd,
return 0;
err_stop_stream_csi2:
- if (IS_IPU7(isp))
+ if (IS_IPU7(isp) || IS_IPU8(isp))
ipu7_isys_csi2_stream_disable(csi2);
else
ipu6_isys_csi2_stream_disable(csi2);
@@ -766,7 +769,7 @@ static int ipu6_isys_csi2_disable_streams(struct v4l2_subdev *sd,
ipu6_isys_find_stream_firmware(csi2, vc);
ipu6_isys_stop_stream_firmware(stream);
- if IS_IPU7(isp)
+ if (IS_IPU7(isp) || IS_IPU8(isp))
ipu7_isys_csi2_stream_disable(csi2);
else
ipu6_isys_csi2_stream_disable(csi2);
diff --git a/drivers/media/pci/intel/ipu6/ipu6-isys.c b/drivers/media/pci/intel/ipu6/ipu6-isys.c
index 60f5f9ea2910..34ddef410230 100644
--- a/drivers/media/pci/intel/ipu6/ipu6-isys.c
+++ b/drivers/media/pci/intel/ipu6/ipu6-isys.c
@@ -186,7 +186,7 @@ static int isys_csi2_register_subdevices(struct ipu6_isys *isys)
for (i = 0; i < csi2_pdata->nports; i++) {
void __iomem *base = isys->pdata->base;
- if (IS_IPU7(isys->adev->isp)) {
+ if (IS_IPU7(isys->adev->isp) || IS_IPU8(isys->adev->isp)) {
u32 mask = IS_IPU7_MTL(isys->adev->isp) ?
IPU7_CSI_LEGACY_IRQ_MASK(i) :
IPU7P5_CSI_LEGACY_IRQ_MASK(i);
@@ -633,7 +633,7 @@ static int isys_notifier_init(struct ipu6_isys *isys)
continue;
ret = v4l2_fwnode_endpoint_parse(ep, &vep);
- if (ret && IS_IPU7(isp)) {
+ if (ret && (IS_IPU7(isp) || IS_IPU8(isp))) {
vep.bus_type = V4L2_MBUS_CSI2_CPHY;
ret = v4l2_fwnode_endpoint_parse(ep, &vep);
}
@@ -771,7 +771,7 @@ static int isys_runtime_pm_resume(struct device *dev)
if (ret)
goto err_mmu_hw_cleanup;
- if (IS_IPU7(isp)) {
+ if (IS_IPU7(isp) || IS_IPU8(isp)) {
ipu7_isys_setup_hw(isys);
} else {
ipu6_isys_setup_hw(isys);
@@ -804,7 +804,7 @@ static int isys_runtime_pm_resume(struct device *dev)
isys->phy_termcal_val = 0;
cpu_latency_qos_update_request(&isys->pm_qos, PM_QOS_DEFAULT_VALUE);
- if (!IS_IPU7(isp))
+ if (!IS_IPU7(isp) && !IS_IPU8(isp))
set_iwake_ltrdid(isys, 0, 0, LTR_ISYS_OFF);
err_mmu_hw_cleanup:
@@ -829,7 +829,7 @@ static int isys_runtime_pm_suspend(struct device *dev)
isys->phy_termcal_val = 0;
cpu_latency_qos_update_request(&isys->pm_qos, PM_QOS_DEFAULT_VALUE);
- if (!IS_IPU7(isp))
+ if (!IS_IPU7(isp) && !IS_IPU8(isp))
set_iwake_ltrdid(isys, 0, 0, LTR_ISYS_OFF);
ipu6_mmu_hw_cleanup(adev->mmu);
@@ -986,7 +986,7 @@ static int isys_probe(struct auxiliary_device *auxdev,
if (!isys)
return -ENOMEM;
- adev->auxdrv_data = IS_IPU7(isp) ? &ipu7_isys_auxdrv_data :
+ adev->auxdrv_data = (IS_IPU7(isp) || IS_IPU8(isp)) ? &ipu7_isys_auxdrv_data :
&ipu6_isys_auxdrv_data;
adev->auxdrv = to_auxiliary_drv(auxdev->dev.driver);
isys->adev = adev;
@@ -1023,7 +1023,7 @@ static int isys_probe(struct auxiliary_device *auxdev,
if (ret < 0)
goto out_remove_pkg_dir_shared_buffer;
- if (IS_IPU7(adev->isp))
+ if (IS_IPU7(adev->isp) || IS_IPU8(adev->isp))
isys->phy_set_power = ipu7_isys_csi_phy_set_power;
else if (IS_IPU6SE(adev->isp))
isys->phy_set_power = ipu6_isys_jsl_phy_set_power;
diff --git a/drivers/media/pci/intel/ipu6/ipu6-mmu.c b/drivers/media/pci/intel/ipu6/ipu6-mmu.c
index 243d438786ba..1a564ceb7478 100644
--- a/drivers/media/pci/intel/ipu6/ipu6-mmu.c
+++ b/drivers/media/pci/intel/ipu6/ipu6-mmu.c
@@ -473,7 +473,7 @@ static struct ipu6_mmu_info *ipu6_mmu_alloc(struct ipu6_device *isp)
if (!mmu_info)
return NULL;
- if (IS_IPU7(isp))
+ if (IS_IPU7(isp) || IS_IPU8(isp))
mmu_info->aperture_start = isp->secure_mode ?
IPU7_FW_CODE_REGION_END : IPU7_FW_CODE_REGION_START;
else
@@ -684,7 +684,7 @@ struct ipu6_mmu *ipu6_mmu_init(struct device *dev,
if (!mmu)
return ERR_PTR(-ENOMEM);
- mmu->ops = IS_IPU7(isp) ? &ipu7_mmu_ops : &ipu6_mmu_ops;
+ mmu->ops = (IS_IPU7(isp) || IS_IPU8(isp)) ? &ipu7_mmu_ops : &ipu6_mmu_ops;
mmu->mmid = mmid;
mmu->ready = false;
INIT_LIST_HEAD(&mmu->vma_list);
diff --git a/drivers/media/pci/intel/ipu6/ipu6-platform-buttress-regs.h b/drivers/media/pci/intel/ipu6/ipu6-platform-buttress-regs.h
index 57e661cc2177..a1e00965ac4a 100644
--- a/drivers/media/pci/intel/ipu6/ipu6-platform-buttress-regs.h
+++ b/drivers/media/pci/intel/ipu6/ipu6-platform-buttress-regs.h
@@ -295,6 +295,7 @@ enum {
/* NDE */
#define IPU7_BUTTRESS_REG_NDE_CONTROL 0x21a4
+#define IPU8_BUTTRESS_REG_NDE_CONTROL 0x21a8
#define IPU7_NDE_VAL_MASK GENMASK(9, 0)
#define IPU7_NDE_SCALE_MASK GENMASK(12, 10)
#define IPU7_NDE_VALID_MASK BIT(13)
@@ -306,6 +307,7 @@ enum {
#define IPU7_NDE_SCALE_DEFAULT 2
#define IPU7_NDE_VALID_DEFAULT 0
#define IPU7_NDE_RESVEC 0xe
+#define IPU8_NDE_RESVEC 0x2
/* IS UCX control */
#define IPU7_UCX_CTL_RESET BIT(0)
diff --git a/drivers/media/pci/intel/ipu6/ipu6.c b/drivers/media/pci/intel/ipu6/ipu6.c
index 2ed2a41ac96f..acc492f5cc11 100644
--- a/drivers/media/pci/intel/ipu6/ipu6.c
+++ b/drivers/media/pci/intel/ipu6/ipu6.c
@@ -274,7 +274,7 @@ void ipu6_configure_spc(struct ipu6_device *isp,
void __iomem *spc_regs_base;
u32 val;
- if (IS_IPU7(isp))
+ if (IS_IPU7(isp) || IS_IPU8(isp))
return;
dmem_base = base + hw_variant->dmem_offset;
@@ -371,14 +371,16 @@ static void ipu6_internal_pdata_init(struct ipu6_device *isp)
psys_ipdata.hw_variant.spc_offset = IPU6SE_PSYS_SPC_OFFSET;
}
+ if (IS_IPU7(isp)) {
+ isys_ipdata.csi2.gpreg = IPU7_IS_IO_CSI2_GPREGS_BASE;
+ isys_ipdata.csi2.gpreg_stride = IPU7_IS_IO_CSI2_GPREGS_STRIDE;
+ isys_ipdata.csi2.nports = 4;
+ }
+
if (IS_IPU8(isp)) {
isys_ipdata.csi2.gpreg = IPU8_IS_IO_CSI2_GPREGS_BASE;
isys_ipdata.csi2.gpreg_stride = IPU8_IS_IO_CSI2_GPREGS_STRIDE;
isys_ipdata.csi2.nports = 4;
- } else if (IS_IPU7(isp)) {
- isys_ipdata.csi2.gpreg = IPU7_IS_IO_CSI2_GPREGS_BASE;
- isys_ipdata.csi2.gpreg_stride = IPU7_IS_IO_CSI2_GPREGS_STRIDE;
- isys_ipdata.csi2.nports = 4;
}
}
@@ -503,7 +505,7 @@ static void ipu6_configure_vc_mechanism(struct ipu6_device *isp)
{
u32 val;
- if (IS_IPU7(isp))
+ if (IS_IPU7(isp) || IS_IPU8(isp))
return;
val = readl(isp->base + BUTTRESS_REG_BTRS_CTRL);
@@ -696,7 +698,7 @@ static int ipu6_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)
return dev_err_probe(dev, PTR_ERR(isp->base),
"Failed to I/O mem remapping\n");
- if (IS_IPU7(isp)) {
+ if (IS_IPU7(isp) || IS_IPU8(isp)) {
isp->pb_base = pcim_iomap_region(pdev, IPU7_PCI_PBBAR,
IPU6_NAME);
if (IS_ERR(isp->pb_base))
@@ -768,7 +770,7 @@ static int ipu6_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)
goto out_ipu6_rpm_put;
}
- ret = IS_IPU7(isp) ? ipu7_map_fw(isp) : ipu6_map_fw(isp);
+ ret = (IS_IPU7(isp) || IS_IPU8(isp)) ? ipu7_map_fw(isp) : ipu6_map_fw(isp);
if (ret)
goto out_ipu6_rpm_put;
@@ -811,7 +813,7 @@ static int ipu6_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)
out_ipu6_rpm_put:
pm_runtime_put_sync(&isp->psys->auxdev.dev);
out_ipu6_bus_del_devices:
- dir = IS_IPU7(isp) ? DMA_BIDIRECTIONAL : DMA_TO_DEVICE;
+ dir = (IS_IPU7(isp) || IS_IPU8(isp)) ? DMA_BIDIRECTIONAL : DMA_TO_DEVICE;
if (!IS_ERR_OR_NULL(isp->psys)) {
ipu6_cpd_free_pkg_dir(isp->psys);
if (isp->psys->fw_sgt.nents)
@@ -845,7 +847,7 @@ static void ipu6_pci_remove(struct pci_dev *pdev)
devm_free_irq(&pdev->dev, pdev->irq, isp);
- dir = IS_IPU7(isp) ? DMA_BIDIRECTIONAL : DMA_TO_DEVICE;
+ dir = (IS_IPU7(isp) || IS_IPU8(isp)) ? DMA_BIDIRECTIONAL : DMA_TO_DEVICE;
ipu6_cpd_free_pkg_dir(isp->psys);
ipu6_unmap_fw_region(isp->psys, dir);
diff --git a/drivers/media/pci/intel/ipu6/ipu7-mmu-hw.c b/drivers/media/pci/intel/ipu6/ipu7-mmu-hw.c
index c9b015e89ee6..fecaff5ce032 100644
--- a/drivers/media/pci/intel/ipu6/ipu7-mmu-hw.c
+++ b/drivers/media/pci/intel/ipu6/ipu7-mmu-hw.c
@@ -538,6 +538,127 @@ static struct ipu7_mmu_hw ipu7p5_isys_mmu_hwdata[] = {
},
};
+static struct ipu7_mmu_hw ipu8_isys_mmu_hwdata[] = {
+ {
+ .name = "IS_FW_RD",
+ .offset = IPU8_IS_MMU_FW_RD_OFFSET,
+ .zlx_offset = IPU8_IS_ZLX_UC_RD_OFFSET,
+ .uao_offset = IPU8_IS_UAO_UC_RD_OFFSET,
+ .info_bits = 0x20005101,
+ .refill = 0x00002726,
+ .collapse_en_bitmap = 0x1,
+ .at_sp_arb_cfg = 0x1,
+ .l1_block = IPU8_IS_MMU_FW_RD_L1_BLOCKNR_REG,
+ .l2_block = IPU8_IS_MMU_FW_RD_L2_BLOCKNR_REG,
+ .nr_l1streams = IPU8_IS_MMU_FW_RD_STREAM_NUM,
+ .nr_l2streams = IPU8_IS_MMU_FW_RD_STREAM_NUM,
+ .l1_block_sz = { 0x0, 0x8, 0xa },
+ .l2_block_sz = { 0x0, 0x2, 0x4 },
+ .zlx_nr = IPU8_IS_ZLX_UC_RD_NUM,
+ .zlx_axi_pool = { 0x00000f30 },
+ .zlx_en = { 0, 1, 0, 0 },
+ .zlx_conf = { 0, 2, 0, 0 },
+ .uao_p_num = IPU8_IS_UAO_UC_RD_PLANENUM,
+ .uao_p2tlb = { 0x00000049, 0x0000004c, 0x0000004d, 0x00000000 },
+ },
+ {
+ .name = "IS_FW_WR",
+ .offset = IPU8_IS_MMU_FW_WR_OFFSET,
+ .zlx_offset = IPU8_IS_ZLX_UC_WR_OFFSET,
+ .uao_offset = IPU8_IS_UAO_UC_WR_OFFSET,
+ .info_bits = 0x20005001,
+ .refill = 0x00002524,
+ .collapse_en_bitmap = 0x1,
+ .at_sp_arb_cfg = 0x1,
+ .l1_block = IPU8_IS_MMU_FW_WR_L1_BLOCKNR_REG,
+ .l2_block = IPU8_IS_MMU_FW_WR_L2_BLOCKNR_REG,
+ .nr_l1streams = IPU8_IS_MMU_FW_WR_STREAM_NUM,
+ .nr_l2streams = IPU8_IS_MMU_FW_WR_STREAM_NUM,
+ .l1_block_sz = { 0x0, 0x8, 0xa },
+ .l2_block_sz = { 0x0, 0x2, 0x4 },
+ .zlx_nr = IPU8_IS_ZLX_UC_WR_NUM,
+ .zlx_axi_pool = { 0x00000f20 },
+ .zlx_en = { 0, 1, 1, 0 },
+ .zlx_conf = { 0x0, 0x2, 0x2, 0x0 },
+ .uao_p_num = IPU8_IS_UAO_UC_WR_PLANENUM,
+ .uao_p2tlb = { 0x00000049, 0x0000004a, 0x0000004b, 0x00000000 },
+ },
+ {
+ .name = "IS_DATA_WR_ISOC",
+ .offset = IPU8_IS_MMU_M0_OFFSET,
+ .zlx_offset = IPU8_IS_ZLX_M0_OFFSET,
+ .uao_offset = IPU8_IS_UAO_M0_WR_OFFSET,
+ .info_bits = 0x20004e01,
+ .refill = 0x00002120,
+ .collapse_en_bitmap = 0x1,
+ .at_sp_arb_cfg = 0x1,
+ .l1_block = IPU8_IS_MMU_M0_L1_BLOCKNR_REG,
+ .l2_block = IPU8_IS_MMU_M0_L2_BLOCKNR_REG,
+ .nr_l1streams = IPU8_IS_MMU_M0_STREAM_NUM,
+ .nr_l2streams = IPU8_IS_MMU_M0_STREAM_NUM,
+ .l1_block_sz = { 0x00, 0x02, 0x04, 0x06, 0x08, 0x0a, 0x0c, 0x0e,
+ 0x10, 0x12, 0x14, 0x16, 0x18, 0x1a, 0x1c, 0x1e },
+ .l2_block_sz = { 0x00, 0x02, 0x04, 0x06, 0x08, 0x0a, 0x0c, 0x0e,
+ 0x10, 0x12, 0x14, 0x16, 0x18, 0x1a, 0x1c, 0x1e },
+ .zlx_nr = IPU8_IS_ZLX_M0_NUM,
+ .zlx_axi_pool = { 0x00000f10 },
+ .zlx_en = { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 },
+ .zlx_conf = { 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3,
+ 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3 },
+ .uao_p_num = IPU8_IS_UAO_M0_WR_PLANENUM,
+ .uao_p2tlb = { 0x3b, 0x3c, 0x3d, 0x3e, 0x3b, 0x3c, 0x3d, 0x3e,
+ 0x3b, 0x3c, 0x3d, 0x3e, 0x3b, 0x3c, 0x3d, 0x3e },
+ },
+ {
+ .name = "IS_DATA_WR_SNOOP",
+ .offset = IPU8_IS_MMU_M1_OFFSET,
+ .zlx_offset = IPU8_IS_ZLX_M1_OFFSET,
+ .uao_offset = IPU8_IS_UAO_M1_WR_OFFSET,
+ .info_bits = 0x20004f01,
+ .refill = 0x00002322,
+ .collapse_en_bitmap = 0x1,
+ .at_sp_arb_cfg = 0x1,
+ .l1_block = IPU8_IS_MMU_M1_L1_BLOCKNR_REG,
+ .l2_block = IPU8_IS_MMU_M1_L2_BLOCKNR_REG,
+ .nr_l1streams = IPU8_IS_MMU_M1_STREAM_NUM,
+ .nr_l2streams = IPU8_IS_MMU_M1_STREAM_NUM,
+ .l1_block_sz = { 0x00, 0x02, 0x04, 0x06, 0x08, 0x0a, 0x0c, 0x0e,
+ 0x10, 0x12, 0x14, 0x16, 0x18, 0x1a, 0x1c, 0x1e },
+ .l2_block_sz = { 0x00, 0x02, 0x04, 0x06, 0x08, 0x0a, 0x0c, 0x0e,
+ 0x10, 0x12, 0x14, 0x16, 0x18, 0x1a, 0x1c, 0x1e },
+ .zlx_nr = IPU8_IS_ZLX_M1_NUM,
+ .zlx_axi_pool = { 0x00000f20 },
+ .zlx_en = { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 },
+ .zlx_conf = { 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3,
+ 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3 },
+ .uao_p_num = IPU8_IS_UAO_M1_WR_PLANENUM,
+ .uao_p2tlb = { 0x3f, 0x40, 0x41, 0x42, 0x3f, 0x40, 0x41, 0x42,
+ 0x3f, 0x40, 0x41, 0x42, 0x3f, 0x40, 0x41, 0x42 },
+ },
+ {
+ .name = "IS_UPIPE",
+ .offset = IPU8_IS_MMU_UPIPE_OFFSET,
+ .zlx_offset = IPU8_IS_ZLX_UPIPE_OFFSET,
+ .uao_offset = IPU8_IS_UAO_UPIPE_OFFSET,
+ .info_bits = 0x20005201,
+ .refill = 0x00002928,
+ .collapse_en_bitmap = 0x1,
+ .at_sp_arb_cfg = 0x1,
+ .l1_block = IPU8_IS_MMU_UPIPE_L1_BLOCKNR_REG,
+ .l2_block = IPU8_IS_MMU_UPIPE_L2_BLOCKNR_REG,
+ .nr_l1streams = IPU8_IS_MMU_UPIPE_STREAM_NUM,
+ .nr_l2streams = IPU8_IS_MMU_UPIPE_STREAM_NUM,
+ .l1_block_sz = { 0x0, 0x2, 0x4, 0x6, 0x8, 0xa },
+ .l2_block_sz = { 0x0, 0x2, 0x4, 0x6, 0x8, 0xa },
+ .zlx_nr = IPU8_IS_ZLX_UPIPE_NUM,
+ .zlx_axi_pool = { 0x00000f20 },
+ .zlx_en = { 1, 1, 1, 1, 1, 1 },
+ .zlx_conf = { 0x3, 0x3, 0x3, 0x3, 0x3, 0x3 },
+ .uao_p_num = IPU8_IS_UAO_UPIPE_PLANENUM,
+ .uao_p2tlb = { 0x43, 0x44, 0x45, 0x46, 0x47, 0x48 },
+ },
+};
+
static struct ipu7_mmu_hw ipu7p5_psys_mmu_hwdata[] = {
{
.name = "PS_FW_RD",
@@ -697,6 +818,22 @@ static const struct ipu7_mmu_hwdata ipu7p5_mmu_hwdata_lookup[IPU_SUBSYS_NUM] = {
},
};
+/*
+ * IPU8 has no dedicated psys MMU table upstream (psys pipeline
+ * support is not targeted for this driver); reuse the IPU7P5 psys
+ * table as a placeholder so the psys bus device still initialises.
+ */
+static const struct ipu7_mmu_hwdata ipu8_mmu_hwdata_lookup[IPU_SUBSYS_NUM] = {
+ [IPU_PSYS] = {
+ .hwdata = ipu7p5_psys_mmu_hwdata,
+ .nr_mmus = ARRAY_SIZE(ipu7p5_psys_mmu_hwdata),
+ },
+ [IPU_ISYS] = {
+ .hwdata = ipu8_isys_mmu_hwdata,
+ .nr_mmus = ARRAY_SIZE(ipu8_isys_mmu_hwdata),
+ },
+};
+
static void __ipu7_tlb_invalidate(struct ipu6_mmu *mmu)
{
struct ipu7_mmu_hw *mmu_hw = mmu->ipu7_mmu_hw;
@@ -824,8 +961,12 @@ static int __ipu7_mmu_init_hw_data(struct ipu6_mmu *mmu, struct device *dev,
if (mmu->mmid >= IPU_SUBSYS_NUM)
return -EINVAL;
- lookup = IS_IPU7P5(isp) ? ipu7p5_mmu_hwdata_lookup :
- ipu7_mmu_hwdata_lookup;
+ if (IS_IPU8(isp))
+ lookup = ipu8_mmu_hwdata_lookup;
+ else if (IS_IPU7P5(isp))
+ lookup = ipu7p5_mmu_hwdata_lookup;
+ else
+ lookup = ipu7_mmu_hwdata_lookup;
src = lookup[mmu->mmid].hwdata;
nr_mmus = lookup[mmu->mmid].nr_mmus;
diff --git a/drivers/media/pci/intel/ipu6/ipu7-mmu-hw.h b/drivers/media/pci/intel/ipu6/ipu7-mmu-hw.h
index ba31ed31b245..5c552f4ae4f6 100644
--- a/drivers/media/pci/intel/ipu6/ipu7-mmu-hw.h
+++ b/drivers/media/pci/intel/ipu6/ipu7-mmu-hw.h
@@ -213,6 +213,70 @@
#define IPU7P5_PS_ZLX_FW_RD_NUM 16
#define IPU7P5_PS_ZLX_FW_WR_NUM 10
+/* IPU8 */
+/* IS MMU Cmd RD */
+#define IPU8_IS_MMU_FW_RD_OFFSET 0x270000
+#define IPU8_IS_MMU_FW_RD_STREAM_NUM 3
+#define IPU8_IS_MMU_FW_RD_L1_BLOCKNR_REG 0x54
+#define IPU8_IS_MMU_FW_RD_L2_BLOCKNR_REG 0x60
+
+/* IS MMU Cmd WR */
+#define IPU8_IS_MMU_FW_WR_OFFSET 0x271000
+#define IPU8_IS_MMU_FW_WR_STREAM_NUM 3
+#define IPU8_IS_MMU_FW_WR_L1_BLOCKNR_REG 0x54
+#define IPU8_IS_MMU_FW_WR_L2_BLOCKNR_REG 0x60
+
+/* IS MMU Data WR ISOC */
+#define IPU8_IS_MMU_M0_OFFSET 0x272000
+#define IPU8_IS_MMU_M0_STREAM_NUM 16
+#define IPU8_IS_MMU_M0_L1_BLOCKNR_REG 0x54
+#define IPU8_IS_MMU_M0_L2_BLOCKNR_REG 0x94
+
+/* IS MMU Data WR Snoop */
+#define IPU8_IS_MMU_M1_OFFSET 0x273000
+#define IPU8_IS_MMU_M1_STREAM_NUM 16
+#define IPU8_IS_MMU_M1_L1_BLOCKNR_REG 0x54
+#define IPU8_IS_MMU_M1_L2_BLOCKNR_REG 0x94
+
+/* IS MMU uPipe */
+#define IPU8_IS_MMU_UPIPE_OFFSET 0x274000
+#define IPU8_IS_MMU_UPIPE_STREAM_NUM 6
+#define IPU8_IS_MMU_UPIPE_L1_BLOCKNR_REG 0x54
+#define IPU8_IS_MMU_UPIPE_L2_BLOCKNR_REG 0x6c
+
+/* IS UAO UC RD */
+#define IPU8_IS_UAO_UC_RD_OFFSET 0x27a000
+#define IPU8_IS_UAO_UC_RD_PLANENUM 4
+
+/* IS UAO UC WR */
+#define IPU8_IS_UAO_UC_WR_OFFSET 0x27b000
+#define IPU8_IS_UAO_UC_WR_PLANENUM 4
+
+/* IS UAO M0 WR */
+#define IPU8_IS_UAO_M0_WR_OFFSET 0x27c000
+#define IPU8_IS_UAO_M0_WR_PLANENUM 16
+
+/* IS UAO M1 WR */
+#define IPU8_IS_UAO_M1_WR_OFFSET 0x27d000
+#define IPU8_IS_UAO_M1_WR_PLANENUM 16
+
+/* IS UAO uPipe */
+#define IPU8_IS_UAO_UPIPE_OFFSET 0x27e000
+#define IPU8_IS_UAO_UPIPE_PLANENUM 6
+
+#define IPU8_IS_ZLX_UC_RD_OFFSET 0x275000
+#define IPU8_IS_ZLX_UC_WR_OFFSET 0x276000
+#define IPU8_IS_ZLX_M0_OFFSET 0x277000
+#define IPU8_IS_ZLX_M1_OFFSET 0x278000
+#define IPU8_IS_ZLX_UPIPE_OFFSET 0x279000
+#define IPU8_IS_ZLX_UC_RD_NUM 4
+#define IPU8_IS_ZLX_UC_WR_NUM 4
+#define IPU8_IS_ZLX_M0_NUM 16
+#define IPU8_IS_ZLX_M1_NUM 16
+#define IPU8_IS_ZLX_UPIPE_NUM 6
+
+#define IPU8_IS_MMU_NUM 5U
+
struct ipu7_mmu_hw {
char name[32];
--
2.43.0
^ permalink raw reply [flat|nested] 8+ messages in thread* [PATCH 6/7] media: ipu6: add IPU8 psys MMU table and PLL power sequencing
2026-09-30 9:01 [PATCH 0/7] media: ipu6: add IPU8 support Divyamani Tripathi
` (4 preceding siblings ...)
2026-09-30 9:01 ` [PATCH 5/7] media: ipu6: add IPU8 isys chip/MMU enablement Divyamani Tripathi
@ 2026-09-30 9:01 ` Divyamani Tripathi
2026-09-30 9:01 ` [PATCH 7/7] media: ipu6: add PCI ID for IPU8 Divyamani Tripathi
6 siblings, 0 replies; 8+ messages in thread
From: Divyamani Tripathi @ 2026-09-30 9:01 UTC (permalink / raw)
To: linux-kernel
Cc: sakari.ailus, antti.laakso, sarang.sapre, manik.bajpai,
Divyamani Tripathi
Port the remaining IPU8 psys platform enablement that already exists
upstream in staging ipu7: the psys MMU hardware table and PLL
request/release in the shared power-on/off path. This driver has no
psys pipeline consumer, so it only affects the psys bus device's power
sequencing and MMU setup.
Signed-off-by: Divyamani Tripathi <divyamani.tripathi@intel.com>
---
drivers/media/pci/intel/ipu6/ipu6-buttress.c | 17 +++
.../intel/ipu6/ipu6-platform-buttress-regs.h | 4 +
drivers/media/pci/intel/ipu6/ipu7-mmu-hw.c | 131 +++++++++++++++++-
drivers/media/pci/intel/ipu6/ipu7-mmu-hw.h | 51 +++++++
4 files changed, 196 insertions(+), 7 deletions(-)
diff --git a/drivers/media/pci/intel/ipu6/ipu6-buttress.c b/drivers/media/pci/intel/ipu6/ipu6-buttress.c
index be07d33a4dab..00d504647c29 100644
--- a/drivers/media/pci/intel/ipu6/ipu6-buttress.c
+++ b/drivers/media/pci/intel/ipu6/ipu6-buttress.c
@@ -512,6 +512,17 @@ static int __ipu7_power_on(struct device *dev,
ipu7_nde_control(isp, true);
}
+ /* IPU8 psys needs its PLL running above 400MHz. */
+ if (!is_isys && IS_IPU8(isp) && ctrl->ratio > IPU8_PS_FREQ_CTL_DEFAULT_RATIO) {
+ writel(1, isp->base + IPU7_BUTTRESS_REG_PS_PLL_ENABLE);
+ ret = readl_poll_timeout(isp->base + IPU7_BUTTRESS_REG_SLEEP_LEVEL_STS,
+ val, (val & IPU7_BUTTRESS_OWN_ACK_PS_CLK),
+ 100, BUTTRESS_POWER_TIMEOUT_US);
+ if (ret)
+ dev_warn(&isp->pdev->dev,
+ "ps_pll req ack timeout: 0x%x\n", val);
+ }
+
/* Request clock ownership. */
ovrd_clk = is_isys ? IPU7_BUTTRESS_OVERRIDE_IS_CLK :
IPU7_BUTTRESS_OVERRIDE_PS_CLK;
@@ -569,6 +580,12 @@ static int __ipu7_power_off(struct device *dev,
ipu7_nde_control(isp, false);
}
+ if (ctrl->subsys_id == IPU_PSYS && IS_IPU8(isp)) {
+ val = readl(isp->base + IPU7_BUTTRESS_REG_SLEEP_LEVEL_STS);
+ if (val & IPU7_BUTTRESS_OWN_ACK_PS_CLK)
+ writel(0, isp->base + IPU7_BUTTRESS_REG_PS_PLL_ENABLE);
+ }
+
return 0;
}
diff --git a/drivers/media/pci/intel/ipu6/ipu6-platform-buttress-regs.h b/drivers/media/pci/intel/ipu6/ipu6-platform-buttress-regs.h
index a1e00965ac4a..04d196c49c60 100644
--- a/drivers/media/pci/intel/ipu6/ipu6-platform-buttress-regs.h
+++ b/drivers/media/pci/intel/ipu6/ipu6-platform-buttress-regs.h
@@ -282,6 +282,9 @@ enum {
#define IPU7_BUTTRESS_IS_FREQ_CTL_RATIO_MASK GENMASK(7, 0)
#define IPU7_IS_FREQ_CTL_DEFAULT_RATIO 0x1b
#define IPU7_PS_FREQ_CTL_DEFAULT_RATIO 0x14
+/* IS: 400MHz, PS: 400MHz */
+#define IPU8_IS_FREQ_CTL_DEFAULT_RATIO 0x10
+#define IPU8_PS_FREQ_CTL_DEFAULT_RATIO 0x10
/* D2D power control */
#define IPU7_BUTTRESS_REG_D2D_CTL 0x21d4
@@ -320,6 +323,7 @@ enum {
#define IPU7_BUTTRESS_OWN_ACK_IS_CLK BIT(9)
#define IPU7_BUTTRESS_OVERRIDE_PS_CLK BIT(2)
#define IPU7_BUTTRESS_OWN_ACK_PS_CLK BIT(10)
+#define IPU7_BUTTRESS_REG_PS_PLL_ENABLE 0x21bc
/* PB registers */
#define IPU7_GLOBAL_INTERRUPT_MASK 0x8
diff --git a/drivers/media/pci/intel/ipu6/ipu7-mmu-hw.c b/drivers/media/pci/intel/ipu6/ipu7-mmu-hw.c
index fecaff5ce032..d991f4d29e36 100644
--- a/drivers/media/pci/intel/ipu6/ipu7-mmu-hw.c
+++ b/drivers/media/pci/intel/ipu6/ipu7-mmu-hw.c
@@ -538,6 +538,128 @@ static struct ipu7_mmu_hw ipu7p5_isys_mmu_hwdata[] = {
},
};
+static struct ipu7_mmu_hw ipu8_psys_mmu_hwdata[] = {
+ {
+ .name = "PS_FW_RD",
+ .offset = IPU8_PS_MMU_FW_RD_OFFSET,
+ .zlx_offset = IPU8_PS_ZLX_FW_RD_OFFSET,
+ .uao_offset = IPU8_PS_UAO_FW_RD_OFFSET,
+ .info_bits = 0x20003a01,
+ .refill = 0x00002726,
+ .collapse_en_bitmap = 0x1,
+ .at_sp_arb_cfg = 0x1,
+ .l1_block = IPU8_PS_MMU_FW_RD_L1_BLOCKNR_REG,
+ .l2_block = IPU8_PS_MMU_FW_RD_L2_BLOCKNR_REG,
+ .nr_l1streams = IPU8_PS_MMU_FW_RD_STREAM_NUM,
+ .nr_l2streams = IPU8_PS_MMU_FW_RD_STREAM_NUM,
+ .l1_block_sz = { 0x00, 0x08, 0x0a, 0x0e, 0x10, 0x12, 0x14, 0x16,
+ 0x18, 0x18, 0x18, 0x18 },
+ .l2_block_sz = { 0x00, 0x02, 0x04, 0x06, 0x08, 0x0a, 0x0c, 0x0e,
+ 0x10, 0x12, 0x14, 0x16 },
+ .zlx_nr = IPU8_PS_ZLX_FW_RD_NUM,
+ .zlx_axi_pool = { 0x00000f30 },
+ .zlx_en = { 0, 1, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0 },
+ .zlx_conf = { 0x0, 0x2, 0x0, 0x0, 0x2, 0x2, 0x0, 0x0,
+ 0x0, 0x0, 0x0, 0x0 },
+ .uao_p_num = IPU8_PS_UAO_FW_RD_PLANENUM,
+ .uao_p2tlb = { 0x2d, 0x32, 0x33, 0x30, 0x34, 0x35, 0x36, 0x31,
+ 0x0, 0x0, 0x0, 0x0 },
+ },
+ {
+ .name = "PS_FW_WR",
+ .offset = IPU8_PS_MMU_FW_WR_OFFSET,
+ .zlx_offset = IPU8_PS_ZLX_FW_WR_OFFSET,
+ .uao_offset = IPU8_PS_UAO_FW_WR_OFFSET,
+ .info_bits = 0x20003901,
+ .refill = 0x00002524,
+ .collapse_en_bitmap = 0x1,
+ .at_sp_arb_cfg = 0x1,
+ .l1_block = IPU8_PS_MMU_FW_WR_L1_BLOCKNR_REG,
+ .l2_block = IPU8_PS_MMU_FW_WR_L2_BLOCKNR_REG,
+ .nr_l1streams = IPU8_PS_MMU_FW_WR_STREAM_NUM,
+ .nr_l2streams = IPU8_PS_MMU_FW_WR_STREAM_NUM,
+ .l1_block_sz = { 0x00, 0x08, 0x0a, 0x0c, 0x0e, 0x10, 0x10, 0x10 },
+ .l2_block_sz = { 0x00, 0x02, 0x04, 0x06, 0x08, 0x0a, 0x0c, 0x0e },
+ .zlx_nr = IPU8_PS_ZLX_FW_WR_NUM,
+ .zlx_axi_pool = { 0x00000f20 },
+ .zlx_en = { 0, 1, 1, 0, 0, 0, 0, 0 },
+ .zlx_conf = { 0x0, 0x2, 0x2, 0x0, 0x0, 0x0, 0x0, 0x0 },
+ .uao_p_num = IPU8_PS_UAO_FW_WR_PLANENUM,
+ .uao_p2tlb = { 0x2d, 0x2e, 0x2f, 0x30, 0x31, 0x0, 0x0, 0x0 },
+ },
+ {
+ .name = "PS_DATA_RD",
+ .offset = IPU8_PS_MMU_SRT_RD_OFFSET,
+ .zlx_offset = IPU8_PS_ZLX_DATA_RD_OFFSET,
+ .uao_offset = IPU8_PS_UAO_SRT_RD_OFFSET,
+ .info_bits = 0x20003801,
+ .refill = 0x00002322,
+ .collapse_en_bitmap = 0x1,
+ .at_sp_arb_cfg = 0x1,
+ .l1_block = IPU8_PS_MMU_SRT_RD_L1_BLOCKNR_REG,
+ .l2_block = IPU8_PS_MMU_SRT_RD_L2_BLOCKNR_REG,
+ .nr_l1streams = IPU8_PS_MMU_SRT_RD_STREAM_NUM,
+ .nr_l2streams = IPU8_PS_MMU_SRT_RD_STREAM_NUM,
+ .l1_block_sz = { 0x00, 0x04, 0x06, 0x08, 0x0c, 0x0e, 0x10, 0x14,
+ 0x18, 0x1c, 0x1e, 0x22, 0x24, 0x26, 0x28, 0x2a,
+ 0x2c, 0x2e, 0x30, 0x32, 0x36, 0x3a, 0x3c, 0x3c,
+ 0x3c, 0x3c },
+ .l2_block_sz = { 0x00, 0x02, 0x04, 0x06, 0x08, 0x0a, 0x0c, 0x0e,
+ 0x10, 0x12, 0x14, 0x16, 0x18, 0x1a, 0x1c, 0x1e,
+ 0x20, 0x22, 0x24, 0x26, 0x28, 0x2a, 0x2c, 0x2e,
+ 0x30, 0x32 },
+ .zlx_nr = IPU8_PS_ZLX_DATA_RD_NUM,
+ .zlx_axi_pool = { 0x00000f30 },
+ .zlx_en = { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 0, 0, 0, 0 },
+ .zlx_conf = { 0x6, 0x3, 0x3, 0x6, 0x2, 0x2, 0x6, 0x6,
+ 0x6, 0x3, 0x6, 0x3, 0x3, 0x2, 0x2, 0x2,
+ 0x2, 0x2, 0x2, 0x6, 0x6, 0x3, 0x0, 0x0,
+ 0x0, 0x0 },
+ .uao_p_num = IPU8_PS_UAO_SRT_RD_PLANENUM,
+ .uao_p2tlb = { 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e,
+ 0x1f, 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26,
+ 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x0, 0x0,
+ 0x0, 0x0 },
+ },
+ {
+ .name = "PS_DATA_WR",
+ .offset = IPU8_PS_MMU_SRT_WR_OFFSET,
+ .zlx_offset = IPU8_PS_ZLX_DATA_WR_OFFSET,
+ .uao_offset = IPU8_PS_UAO_SRT_WR_OFFSET,
+ .info_bits = 0x20003701,
+ .refill = 0x00002120,
+ .collapse_en_bitmap = 0x1,
+ .at_sp_arb_cfg = 0x1,
+ .l1_block = IPU8_PS_MMU_SRT_WR_L1_BLOCKNR_REG,
+ .l2_block = IPU8_PS_MMU_SRT_WR_L2_BLOCKNR_REG,
+ .nr_l1streams = IPU8_PS_MMU_SRT_WR_STREAM_NUM,
+ .nr_l2streams = IPU8_PS_MMU_SRT_WR_STREAM_NUM,
+ .l1_block_sz = { 0x00, 0x02, 0x06, 0x08, 0x0a, 0x0c, 0x0e, 0x10,
+ 0x12, 0x14, 0x16, 0x18, 0x1c, 0x1e, 0x22, 0x24,
+ 0x28, 0x2a, 0x2e, 0x30, 0x32, 0x36, 0x38, 0x3a,
+ 0x3a, 0x3a },
+ .l2_block_sz = { 0x00, 0x02, 0x04, 0x06, 0x08, 0x0a, 0x0c, 0x0e,
+ 0x10, 0x12, 0x14, 0x16, 0x18, 0x1a, 0x1c, 0x1e,
+ 0x20, 0x22, 0x24, 0x26, 0x28, 0x2a, 0x2c, 0x2e,
+ 0x30, 0x32 },
+ .zlx_nr = IPU8_PS_ZLX_DATA_WR_NUM,
+ .zlx_axi_pool = { 0x00000f50 },
+ .zlx_en = { 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 0, 0, 0 },
+ .zlx_conf = { 0x3, 0x6, 0x38000002, 0x38000000, 0x3, 0x38000002,
+ 0x38000002, 0x38000002, 0x38000002, 0x38000002,
+ 0x38000002, 0x6, 0x3, 0x6, 0x3, 0x6,
+ 0x3, 0x6, 0x3, 0x3, 0x6, 0x3, 0x3, 0x0,
+ 0x0, 0x0 },
+ .uao_p_num = IPU8_PS_UAO_SRT_WR_PLANENUM,
+ .uao_p2tlb = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+ 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x00,
+ 0x00, 0x00 },
+ },
+};
+
static struct ipu7_mmu_hw ipu8_isys_mmu_hwdata[] = {
{
.name = "IS_FW_RD",
@@ -818,15 +940,10 @@ static const struct ipu7_mmu_hwdata ipu7p5_mmu_hwdata_lookup[IPU_SUBSYS_NUM] = {
},
};
-/*
- * IPU8 has no dedicated psys MMU table upstream (psys pipeline
- * support is not targeted for this driver); reuse the IPU7P5 psys
- * table as a placeholder so the psys bus device still initialises.
- */
static const struct ipu7_mmu_hwdata ipu8_mmu_hwdata_lookup[IPU_SUBSYS_NUM] = {
[IPU_PSYS] = {
- .hwdata = ipu7p5_psys_mmu_hwdata,
- .nr_mmus = ARRAY_SIZE(ipu7p5_psys_mmu_hwdata),
+ .hwdata = ipu8_psys_mmu_hwdata,
+ .nr_mmus = ARRAY_SIZE(ipu8_psys_mmu_hwdata),
},
[IPU_ISYS] = {
.hwdata = ipu8_isys_mmu_hwdata,
diff --git a/drivers/media/pci/intel/ipu6/ipu7-mmu-hw.h b/drivers/media/pci/intel/ipu6/ipu7-mmu-hw.h
index 5c552f4ae4f6..0d3fd7ddea64 100644
--- a/drivers/media/pci/intel/ipu6/ipu7-mmu-hw.h
+++ b/drivers/media/pci/intel/ipu6/ipu7-mmu-hw.h
@@ -277,6 +277,57 @@
#define IPU8_IS_MMU_NUM 5U
+/* PS MMU FW RD */
+#define IPU8_PS_MMU_FW_RD_OFFSET 0x148000
+#define IPU8_PS_MMU_FW_RD_STREAM_NUM 12
+#define IPU8_PS_MMU_FW_RD_L1_BLOCKNR_REG 0x54
+#define IPU8_PS_MMU_FW_RD_L2_BLOCKNR_REG 0x84
+
+/* PS MMU FW WR */
+#define IPU8_PS_MMU_FW_WR_OFFSET 0x149000
+#define IPU8_PS_MMU_FW_WR_STREAM_NUM 8
+#define IPU8_PS_MMU_FW_WR_L1_BLOCKNR_REG 0x54
+#define IPU8_PS_MMU_FW_WR_L2_BLOCKNR_REG 0x74
+
+/* PS MMU FW Data RD VC0 */
+#define IPU8_PS_MMU_SRT_RD_OFFSET 0x14a000
+#define IPU8_PS_MMU_SRT_RD_STREAM_NUM 26
+#define IPU8_PS_MMU_SRT_RD_L1_BLOCKNR_REG 0x54
+#define IPU8_PS_MMU_SRT_RD_L2_BLOCKNR_REG 0xbc
+
+/* PS MMU FW Data WR VC0 */
+#define IPU8_PS_MMU_SRT_WR_OFFSET 0x14b000
+#define IPU8_PS_MMU_SRT_WR_STREAM_NUM 26
+#define IPU8_PS_MMU_SRT_WR_L1_BLOCKNR_REG 0x54
+#define IPU8_PS_MMU_SRT_WR_L2_BLOCKNR_REG 0xbc
+
+/* PS UAO FW RD */
+#define IPU8_PS_UAO_FW_RD_OFFSET 0x156000
+#define IPU8_PS_UAO_FW_RD_PLANENUM 12
+
+/* PS UAO FW WR */
+#define IPU8_PS_UAO_FW_WR_OFFSET 0x157000
+#define IPU8_PS_UAO_FW_WR_PLANENUM 8
+
+/* PS UAO SRT RD */
+#define IPU8_PS_UAO_SRT_RD_OFFSET 0x154000
+#define IPU8_PS_UAO_SRT_RD_PLANENUM 26
+
+/* PS UAO SRT WR */
+#define IPU8_PS_UAO_SRT_WR_OFFSET 0x155000
+#define IPU8_PS_UAO_SRT_WR_PLANENUM 26
+
+#define IPU8_PS_ZLX_DATA_RD_OFFSET 0x14e000
+#define IPU8_PS_ZLX_DATA_WR_OFFSET 0x14f000
+#define IPU8_PS_ZLX_FW_RD_OFFSET 0x150000
+#define IPU8_PS_ZLX_FW_WR_OFFSET 0x151000
+#define IPU8_PS_ZLX_DATA_RD_NUM 26
+#define IPU8_PS_ZLX_DATA_WR_NUM 26
+#define IPU8_PS_ZLX_FW_RD_NUM 12
+#define IPU8_PS_ZLX_FW_WR_NUM 8
+
+#define IPU8_PS_MMU_NUM 4U
+
struct ipu7_mmu_hw {
char name[32];
--
2.43.0
^ permalink raw reply [flat|nested] 8+ messages in thread* [PATCH 7/7] media: ipu6: add PCI ID for IPU8
2026-09-30 9:01 [PATCH 0/7] media: ipu6: add IPU8 support Divyamani Tripathi
` (5 preceding siblings ...)
2026-09-30 9:01 ` [PATCH 6/7] media: ipu6: add IPU8 psys MMU table and PLL power sequencing Divyamani Tripathi
@ 2026-09-30 9:01 ` Divyamani Tripathi
6 siblings, 0 replies; 8+ messages in thread
From: Divyamani Tripathi @ 2026-09-30 9:01 UTC (permalink / raw)
To: linux-kernel
Cc: sakari.ailus, antti.laakso, sarang.sapre, manik.bajpai,
Divyamani Tripathi
Add the IPU8 PCI ID and probe wiring. IPU8 reuses the IPU7P5 buttress
register map (unvalidated against IPU8's hardware spec) but needs its
own default control ratio (0x10), so add dedicated
ipu8_{isys,psys}_buttress_ctrl structs instead of reusing IPU7's.
Signed-off-by: Divyamani Tripathi <divyamani.tripathi@intel.com>
---
drivers/media/pci/intel/ipu6/ipu6.c | 40 ++++++++++++++++++++++++++++-
include/media/ipu6-pci-table.h | 2 ++
2 files changed, 41 insertions(+), 1 deletion(-)
diff --git a/drivers/media/pci/intel/ipu6/ipu6.c b/drivers/media/pci/intel/ipu6/ipu6.c
index acc492f5cc11..17e659230149 100644
--- a/drivers/media/pci/intel/ipu6/ipu6.c
+++ b/drivers/media/pci/intel/ipu6/ipu6.c
@@ -140,6 +140,28 @@ static const struct ipu6_buttress_ctrl ipu7_psys_buttress_ctrl = {
.pwr_sts_off = IPU6_BUTTRESS_PWR_STATE_DN_DONE,
};
+static const struct ipu6_buttress_ctrl ipu8_isys_buttress_ctrl = {
+ .subsys_id = IPU_ISYS,
+ .ratio = IPU8_IS_FREQ_CTL_DEFAULT_RATIO,
+ .qos_floor = 0,
+ .freq_ctl = IPU7_BUTTRESS_REG_IS_WORKPOINT_REQ,
+ .pwr_sts_shift = IPU7_BUTTRESS_PWR_STATE_IS_PWR_SHIFT,
+ .pwr_sts_mask = IPU7_BUTTRESS_PWR_STATE_IS_PWR_MASK,
+ .pwr_sts_on = IPU6_BUTTRESS_PWR_STATE_UP_DONE,
+ .pwr_sts_off = IPU6_BUTTRESS_PWR_STATE_DN_DONE,
+};
+
+static const struct ipu6_buttress_ctrl ipu8_psys_buttress_ctrl = {
+ .subsys_id = IPU_PSYS,
+ .ratio = IPU8_PS_FREQ_CTL_DEFAULT_RATIO,
+ .qos_floor = 0,
+ .freq_ctl = IPU7_BUTTRESS_REG_PS_WORKPOINT_REQ,
+ .pwr_sts_shift = IPU7_BUTTRESS_PWR_STATE_PS_PWR_SHIFT,
+ .pwr_sts_mask = IPU7_BUTTRESS_PWR_STATE_PS_PWR_MASK,
+ .pwr_sts_on = IPU6_BUTTRESS_PWR_STATE_UP_DONE,
+ .pwr_sts_off = IPU6_BUTTRESS_PWR_STATE_DN_DONE,
+};
+
static const struct ipu6_buttress_registers ipu6_buttress_regs = {
/* Registers */
.irq_status = BUTTRESS_REG_ISR_STATUS,
@@ -624,7 +646,8 @@ static int ipu6_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)
int ret;
if ((id->device == PCI_DEVICE_ID_INTEL_IPU7 ||
- id->device == PCI_DEVICE_ID_INTEL_IPU7P5) && force_no_probe_ipu7)
+ id->device == PCI_DEVICE_ID_INTEL_IPU7P5 ||
+ id->device == PCI_DEVICE_ID_INTEL_IPU8) && force_no_probe_ipu7)
return -ENODEV;
isp = devm_kzalloc(dev, sizeof(*isp), GFP_KERNEL);
@@ -677,6 +700,21 @@ static int ipu6_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)
isys_ctrl = &ipu7_isys_buttress_ctrl;
psys_ctrl = &ipu7_psys_buttress_ctrl;
break;
+ case PCI_DEVICE_ID_INTEL_IPU8:
+ /*
+ * IPU8 reuses the IPU7P5 buttress register map,
+ * matching staging ipu7 (no dedicated ipu8_buttress_regs
+ * there either). isys/psys control ratios use IPU8's own
+ * 0x10 default, unlike IPU7/IPU7P5.
+ * TODO: confirm buttress register map against IPU8 hw spec.
+ */
+ isp->hw_ver = IPU_VERSION_8;
+ isp->cpd_fw_name = IPU8_FIRMWARE_NAME;
+ isp->model_name = IPU8_MEDIA_DEV_MODEL_NAME;
+ isp->buttress.regs = &ipu7p5_buttress_regs;
+ isys_ctrl = &ipu8_isys_buttress_ctrl;
+ psys_ctrl = &ipu8_psys_buttress_ctrl;
+ break;
default:
return dev_err_probe(dev, -ENODEV,
"Unsupported IPU6 device %x\n",
diff --git a/include/media/ipu6-pci-table.h b/include/media/ipu6-pci-table.h
index cacb8a3170d0..4c7e724ea15e 100644
--- a/include/media/ipu6-pci-table.h
+++ b/include/media/ipu6-pci-table.h
@@ -16,6 +16,7 @@
#define PCI_DEVICE_ID_INTEL_IPU6EP_MTL 0x7d19
#define PCI_DEVICE_ID_INTEL_IPU7 0x645d
#define PCI_DEVICE_ID_INTEL_IPU7P5 0xb05d
+#define PCI_DEVICE_ID_INTEL_IPU8 0xd719
static const struct pci_device_id ipu6_pci_tbl[] = {
{ PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_IPU6) },
@@ -26,6 +27,7 @@ static const struct pci_device_id ipu6_pci_tbl[] = {
{ PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_IPU6EP_MTL) },
{ PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_IPU7) },
{ PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_IPU7P5) },
+ { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_IPU8) },
{ }
};
--
2.43.0
^ permalink raw reply [flat|nested] 8+ messages in thread