[PATCH v2 09/44] media: ipu6: Prepare buttress for ipu7 support
Antti Laakso <[email protected]>
| Newsgroups | org.kernel.vger.linux-media |
|---|---|
| Message-ID | <[email protected]> |
Introduce a struct to hold buttress registers and bitmasks that vary across hardware versions beyond ipu6 to simplify support for future hardware versions. Signed-off-by: Antti Laakso <[email protected]> --- drivers/media/pci/intel/ipu6/ipu6-buttress.c | 96 ++++++++++--------- drivers/media/pci/intel/ipu6/ipu6-buttress.h | 25 +++++ .../intel/ipu6/ipu6-platform-buttress-regs.h | 2 +- drivers/media/pci/intel/ipu6/ipu6.c | 26 +++++ 4 files changed, 101 insertions(+), 48 deletions(-) diff --git a/drivers/media/pci/intel/ipu6/ipu6-buttress.c b/drivers/media/pci/intel/ipu6/ipu6-buttress.c index cbe356589a9d..3c5f4e407b7c 100644 --- a/drivers/media/pci/intel/ipu6/ipu6-buttress.c +++ b/drivers/media/pci/intel/ipu6/ipu6-buttress.c @@ -55,11 +55,6 @@ #define BUTTRESS_MAX_CONSECUTIVE_IRQS 100 -static const u32 ipu6_adev_irq_mask[2] = { - BUTTRESS_ISR_IS_IRQ, - BUTTRESS_ISR_PS_IRQ -}; - int ipu6_buttress_ipc_reset(struct ipu6_device *isp, struct ipu6_buttress_ipc *ipc) { @@ -337,7 +332,8 @@ irqreturn_t ipu6_buttress_isr(int irq, void *isp_ptr) struct ipu6_device *isp = isp_ptr; struct ipu6_bus_device *adev[] = { isp->isys, isp->psys }; struct ipu6_buttress *b = &isp->buttress; - u32 reg_irq_sts = BUTTRESS_REG_ISR_STATUS; + const struct ipu6_buttress_registers *regs = b->regs; + const u32 adev_irq_mask[] = { regs->irq_is, regs->irq_ps }; irqreturn_t ret = IRQ_NONE; u32 disable_irqs = 0; u32 irq_status; @@ -348,7 +344,7 @@ irqreturn_t ipu6_buttress_isr(int irq, void *isp_ptr) if (!active) return IRQ_NONE; - irq_status = readl(isp->base + reg_irq_sts); + irq_status = readl(isp->base + regs->irq_status); if (irq_status == 0 || WARN_ON_ONCE(irq_status == 0xffffffffu)) { if (active > 0) pm_runtime_put_noidle(&isp->pdev->dev); @@ -356,26 +352,26 @@ irqreturn_t ipu6_buttress_isr(int irq, void *isp_ptr) } do { - writel(irq_status, isp->base + BUTTRESS_REG_ISR_CLEAR); + writel(irq_status, isp->base + regs->irq_clear); - for (i = 0; i < ARRAY_SIZE(ipu6_adev_irq_mask); i++) { + for (i = 0; i < ARRAY_SIZE(adev_irq_mask); i++) { irqreturn_t r = ipu6_buttress_call_isr(adev[i]); - if (!(irq_status & ipu6_adev_irq_mask[i])) + if (!(irq_status & adev_irq_mask[i])) continue; if (r == IRQ_WAKE_THREAD) { ret = IRQ_WAKE_THREAD; - disable_irqs |= ipu6_adev_irq_mask[i]; + disable_irqs |= adev_irq_mask[i]; } else if (ret == IRQ_NONE && r == IRQ_HANDLED) { ret = IRQ_HANDLED; } } - if ((irq_status & BUTTRESS_EVENT) && ret == IRQ_NONE) + if ((irq_status & regs->irq_events) && ret == IRQ_NONE) ret = IRQ_HANDLED; - if (irq_status & BUTTRESS_ISR_IPC_FROM_CSE_IS_WAITING) { + if (irq_status & regs->irq_cse_ipc) { dev_dbg(&isp->pdev->dev, "BUTTRESS_ISR_IPC_FROM_CSE_IS_WAITING\n"); @@ -383,13 +379,13 @@ irqreturn_t ipu6_buttress_isr(int irq, void *isp_ptr) complete(&b->ipc.recv_complete); } - if (irq_status & BUTTRESS_ISR_IPC_EXEC_DONE_BY_CSE) { + if (irq_status & regs->irq_exec_done) { dev_dbg(&isp->pdev->dev, "BUTTRESS_ISR_IPC_EXEC_DONE_BY_CSE\n"); complete(&b->ipc.send_complete); } - if (irq_status & BUTTRESS_ISR_SAI_VIOLATION && + if (irq_status & regs->irq_sai && ipu6_buttress_get_secure_mode(isp)) dev_err(&isp->pdev->dev, "BUTTRESS_ISR_SAI_VIOLATION\n"); @@ -408,12 +404,12 @@ irqreturn_t ipu6_buttress_isr(int irq, void *isp_ptr) break; } - irq_status = readl(isp->base + reg_irq_sts); + irq_status = readl(isp->base + regs->irq_status); } while (irq_status); if (disable_irqs) - writel(BUTTRESS_IRQS & ~disable_irqs, - isp->base + BUTTRESS_REG_ISR_ENABLE); + writel(regs->irq_all & ~disable_irqs, + isp->base + regs->irq_enable); if (active > 0) pm_runtime_put(&isp->pdev->dev); @@ -424,12 +420,13 @@ irqreturn_t ipu6_buttress_isr(int irq, void *isp_ptr) irqreturn_t ipu6_buttress_isr_threaded(int irq, void *isp_ptr) { struct ipu6_device *isp = isp_ptr; + const struct ipu6_buttress_registers *regs = isp->buttress.regs; struct ipu6_bus_device *adev[] = { isp->isys, isp->psys }; const struct ipu6_auxdrv_data *drv_data = NULL; irqreturn_t ret = IRQ_NONE; unsigned int i; - for (i = 0; i < ARRAY_SIZE(ipu6_adev_irq_mask) && adev[i]; i++) { + for (i = 0; i < ARRAY_SIZE(adev) && adev[i]; i++) { drv_data = adev[i]->auxdrv_data; if (!drv_data) continue; @@ -439,7 +436,7 @@ irqreturn_t ipu6_buttress_isr_threaded(int irq, void *isp_ptr) ret = IRQ_HANDLED; } - writel(BUTTRESS_IRQS, isp->base + BUTTRESS_REG_ISR_ENABLE); + writel(regs->irq_all, isp->base + regs->irq_enable); return ret; } @@ -472,7 +469,7 @@ int ipu6_buttress_power(struct device *dev, writel(val, isp->base + ctrl->freq_ctl); - ret = readl_poll_timeout(isp->base + BUTTRESS_REG_PWR_STATE, + ret = readl_poll_timeout(isp->base + isp->buttress.regs->pwr_status, val, (val & ctrl->pwr_sts_mask) == pwr_sts, 100, BUTTRESS_POWER_TIMEOUT_US); if (ret) @@ -488,7 +485,7 @@ bool ipu6_buttress_get_secure_mode(struct ipu6_device *isp) { u32 val; - val = readl(isp->base + BUTTRESS_REG_SECURITY_CTL); + val = readl(isp->base + isp->buttress.regs->security_ctl); return val & BUTTRESS_SECURITY_CTL_FW_SECURE_MODE; } @@ -500,7 +497,7 @@ bool ipu6_buttress_auth_done(struct ipu6_device *isp) if (!isp->secure_mode) return true; - val = readl(isp->base + BUTTRESS_REG_SECURITY_CTL); + val = readl(isp->base + isp->buttress.regs->security_ctl); val = FIELD_GET(BUTTRESS_SECURITY_CTL_FW_SETUP_MASK, val); return val == BUTTRESS_SECURITY_CTL_AUTH_DONE; @@ -518,10 +515,10 @@ int ipu6_buttress_reset_authentication(struct ipu6_device *isp) } writel(BUTTRESS_FW_RESET_CTL_START, isp->base + - BUTTRESS_REG_FW_RESET_CTL); + isp->buttress.regs->fw_reset_ctl); - ret = readl_poll_timeout(isp->base + BUTTRESS_REG_FW_RESET_CTL, val, - val & BUTTRESS_FW_RESET_CTL_DONE, 500, + ret = readl_poll_timeout(isp->base + isp->buttress.regs->fw_reset_ctl, + val, val & BUTTRESS_FW_RESET_CTL_DONE, 500, BUTTRESS_CSE_FWRESET_TIMEOUT_US); if (ret) { dev_err(&isp->pdev->dev, @@ -530,7 +527,8 @@ int ipu6_buttress_reset_authentication(struct ipu6_device *isp) } dev_dbg(&isp->pdev->dev, "FW reset for authentication done\n"); - writel(0, isp->base + BUTTRESS_REG_FW_RESET_CTL); + writel(0, isp->base + isp->buttress.regs->fw_reset_ctl); + /* leave some time for HW restore */ usleep_range(800, 1000); @@ -660,7 +658,7 @@ int ipu6_buttress_authenticate(struct ipu6_device *isp) mask = BUTTRESS_SECURITY_CTL_FW_SETUP_MASK; done = BUTTRESS_SECURITY_CTL_FW_SETUP_DONE; fail = BUTTRESS_SECURITY_CTL_AUTH_FAILED; - ret = readl_poll_timeout(isp->base + BUTTRESS_REG_SECURITY_CTL, data, + ret = readl_poll_timeout(isp->base + b->regs->security_ctl, data, ((data & mask) == done || (data & mask) == fail), 500, BUTTRESS_CSE_BOOTLOAD_TIMEOUT_US); @@ -700,7 +698,7 @@ int ipu6_buttress_authenticate(struct ipu6_device *isp) } done = BUTTRESS_SECURITY_CTL_AUTH_DONE; - ret = readl_poll_timeout(isp->base + BUTTRESS_REG_SECURITY_CTL, data, + ret = readl_poll_timeout(isp->base + b->regs->security_ctl, data, ((data & mask) == done || (data & mask) == fail), 500, BUTTRESS_CSE_AUTHENTICATE_TIMEOUT_US); @@ -725,15 +723,16 @@ int ipu6_buttress_authenticate(struct ipu6_device *isp) static int ipu6_buttress_send_tsc_request(struct ipu6_device *isp) { + const struct ipu6_buttress_registers *regs = isp->buttress.regs; u32 val, mask, done; int ret; mask = BUTTRESS_PWR_STATE_HH_STATUS_MASK; writel(BUTTRESS_FABRIC_CMD_START_TSC_SYNC, - isp->base + BUTTRESS_REG_FABRIC_CMD); + isp->base + regs->fabric_cmd); - val = readl(isp->base + BUTTRESS_REG_PWR_STATE); + val = readl(isp->base + regs->pwr_status); val = FIELD_GET(mask, val); if (val == BUTTRESS_PWR_STATE_HH_STATE_ERR) { dev_err(&isp->pdev->dev, "Start tsc sync failed\n"); @@ -741,8 +740,8 @@ static int ipu6_buttress_send_tsc_request(struct ipu6_device *isp) } done = BUTTRESS_PWR_STATE_HH_STATE_DONE; - ret = readl_poll_timeout(isp->base + BUTTRESS_REG_PWR_STATE, val, - FIELD_GET(mask, val) == done, 500, + ret = readl_poll_timeout(isp->base + regs->pwr_status, + val, FIELD_GET(mask, val) == done, 500, BUTTRESS_TSC_SYNC_TIMEOUT_US); if (ret) dev_err(&isp->pdev->dev, "Start tsc sync timeout\n"); @@ -762,11 +761,13 @@ int ipu6_buttress_start_tsc_sync(struct ipu6_device *isp) if (ret != -ETIMEDOUT) return ret; - val = readl(isp->base + BUTTRESS_REG_TSW_CTL); + u32 tsw_ctl = isp->buttress.regs->tsw_ctl; + + val = readl(isp->base + tsw_ctl); val = val | BUTTRESS_TSW_CTL_SOFT_RESET; - writel(val, isp->base + BUTTRESS_REG_TSW_CTL); + writel(val, isp->base + tsw_ctl); val = val & ~BUTTRESS_TSW_CTL_SOFT_RESET; - writel(val, isp->base + BUTTRESS_REG_TSW_CTL); + writel(val, isp->base + tsw_ctl); } dev_err(&isp->pdev->dev, "TSC sync failed (timeout)\n"); @@ -777,13 +778,14 @@ EXPORT_SYMBOL_NS_GPL(ipu6_buttress_start_tsc_sync, "INTEL_IPU6"); void ipu6_buttress_tsc_read(struct ipu6_device *isp, u64 *val) { + void __iomem *tsc = isp->base + isp->buttress.regs->tsc_lo; u32 tsc_hi_1, tsc_hi_2, tsc_lo; unsigned long flags; local_irq_save(flags); - tsc_hi_1 = readl(isp->base + BUTTRESS_REG_TSC_HI); - tsc_lo = readl(isp->base + BUTTRESS_REG_TSC_LO); - tsc_hi_2 = readl(isp->base + BUTTRESS_REG_TSC_HI); + tsc_hi_1 = readl(tsc + BUTTRESS_TSC_HI_OFFSET); + tsc_lo = readl(tsc); + tsc_hi_2 = readl(tsc + BUTTRESS_TSC_HI_OFFSET); if (tsc_hi_1 == tsc_hi_2) { *val = (u64)tsc_hi_1 << 32 | tsc_lo; } else { @@ -816,9 +818,9 @@ void ipu6_buttress_restore(struct ipu6_device *isp) { struct ipu6_buttress *b = &isp->buttress; - writel(BUTTRESS_IRQS, isp->base + BUTTRESS_REG_ISR_CLEAR); - writel(BUTTRESS_IRQS, isp->base + BUTTRESS_REG_ISR_ENABLE); - writel(b->wdt_cached_value, isp->base + BUTTRESS_REG_WDT); + writel(b->regs->irq_all, isp->base + b->regs->irq_clear); + writel(b->regs->irq_all, isp->base + b->regs->irq_enable); + writel(b->wdt_cached_value, isp->base + b->regs->wdt); } int ipu6_buttress_init(struct ipu6_device *isp) @@ -851,12 +853,12 @@ int ipu6_buttress_init(struct ipu6_device *isp) readl(isp->base + BUTTRESS_REG_SECURITY_TOUCH), readl(isp->base + BUTTRESS_REG_CAMERA_MASK)); - b->wdt_cached_value = readl(isp->base + BUTTRESS_REG_WDT); - writel(BUTTRESS_IRQS, isp->base + BUTTRESS_REG_ISR_CLEAR); - writel(BUTTRESS_IRQS, isp->base + BUTTRESS_REG_ISR_ENABLE); + b->wdt_cached_value = readl(isp->base + b->regs->wdt); + writel(b->regs->irq_all, isp->base + b->regs->irq_clear); + writel(b->regs->irq_all, isp->base + b->regs->irq_enable); /* get ref_clk frequency by reading the indication in btrs control */ - val = readl(isp->base + BUTTRESS_REG_BTRS_CTRL); + val = readl(isp->base + b->regs->btrs_ctrl); val = FIELD_GET(BUTTRESS_REG_BTRS_CTRL_REF_CLK_IND, val); switch (val) { @@ -902,7 +904,7 @@ void ipu6_buttress_exit(struct ipu6_device *isp) { struct ipu6_buttress *b = &isp->buttress; - writel(0, isp->base + BUTTRESS_REG_ISR_ENABLE); + writel(0, isp->base + b->regs->irq_enable); mutex_destroy(&b->power_mutex); mutex_destroy(&b->auth_mutex); diff --git a/drivers/media/pci/intel/ipu6/ipu6-buttress.h b/drivers/media/pci/intel/ipu6/ipu6-buttress.h index b1c1a10e3e6d..68586a32fda3 100644 --- a/drivers/media/pci/intel/ipu6/ipu6-buttress.h +++ b/drivers/media/pci/intel/ipu6/ipu6-buttress.h @@ -42,9 +42,34 @@ struct ipu6_buttress_ipc { u32 data0_in; }; +struct ipu6_buttress_registers { + /* Registers */ + u32 irq_status; + u32 irq_clear; + u32 irq_enable; + u32 pwr_status; + u32 security_ctl; + u32 fw_reset_ctl; + u32 fabric_cmd; + u32 tsw_ctl; + u32 tsc_lo; + u32 wdt; + u32 btrs_ctrl; + + /* Bitmasks */ + u32 irq_is; + u32 irq_ps; + u32 irq_all; + u32 irq_events; + u32 irq_cse_ipc; + u32 irq_exec_done; + u32 irq_sai; +}; + struct ipu6_buttress { struct mutex power_mutex, auth_mutex, cons_mutex, ipc_mutex; struct ipu6_buttress_ipc ipc; + const struct ipu6_buttress_registers *regs; struct list_head constraints; u32 wdt_cached_value; bool force_suspend; 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 efd65e494c16..5006cce74b23 100644 --- a/drivers/media/pci/intel/ipu6/ipu6-platform-buttress-regs.h +++ b/drivers/media/pci/intel/ipu6/ipu6-platform-buttress-regs.h @@ -212,7 +212,7 @@ enum { #define BUTTRESS_TSW_CTL_SOFT_RESET BIT(8) #define BUTTRESS_REG_TSC_LO 0x164 -#define BUTTRESS_REG_TSC_HI 0x168 +#define BUTTRESS_TSC_HI_OFFSET 4 #define BUTTRESS_IRQS (BUTTRESS_ISR_IPC_FROM_CSE_IS_WAITING | \ BUTTRESS_ISR_IPC_EXEC_DONE_BY_CSE | \ diff --git a/drivers/media/pci/intel/ipu6/ipu6.c b/drivers/media/pci/intel/ipu6/ipu6.c index efb58bc4d127..55e660fda421 100644 --- a/drivers/media/pci/intel/ipu6/ipu6.c +++ b/drivers/media/pci/intel/ipu6/ipu6.c @@ -228,6 +228,30 @@ static const struct ipu6_buttress_ctrl psys_buttress_ctrl = { .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, + .irq_clear = BUTTRESS_REG_ISR_CLEAR, + .irq_enable = BUTTRESS_REG_ISR_ENABLE, + .pwr_status = BUTTRESS_REG_PWR_STATE, + .security_ctl = BUTTRESS_REG_SECURITY_CTL, + .fw_reset_ctl = BUTTRESS_REG_FW_RESET_CTL, + .fabric_cmd = BUTTRESS_REG_FABRIC_CMD, + .tsw_ctl = BUTTRESS_REG_TSW_CTL, + .tsc_lo = BUTTRESS_REG_TSC_LO, + .wdt = BUTTRESS_REG_WDT, + .btrs_ctrl = BUTTRESS_REG_BTRS_CTRL, + + /* Bitmasks */ + .irq_is = BUTTRESS_ISR_IS_IRQ, + .irq_ps = BUTTRESS_ISR_PS_IRQ, + .irq_all = BUTTRESS_IRQS, + .irq_events = BUTTRESS_EVENT, + .irq_cse_ipc = BUTTRESS_ISR_IPC_FROM_CSE_IS_WAITING, + .irq_exec_done = BUTTRESS_ISR_IPC_EXEC_DONE_BY_CSE, + .irq_sai = BUTTRESS_ISR_SAI_VIOLATION, +}; + static void ipu6_pkg_dir_configure_spc(struct ipu6_device *isp, const struct ipu6_hw_variants *hw_variant, @@ -522,6 +546,8 @@ static int ipu6_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id) pci_set_master(pdev); isp->cpd_metadata_cmpnt_size = sizeof(struct ipu6_cpd_metadata_cmpnt); + isp->buttress.regs = &ipu6_buttress_regs; + switch (id->device) { case PCI_DEVICE_ID_INTEL_IPU6: isp->hw_ver = IPU_VERSION_6; -- 2.55.0