FILE
ipu7-buttress.c
File preview with syntax highlighting.
linux-6.19.14/drivers/staging/media/ipu7/ipu7-buttress.c
1// SPDX-License-Identifier: GPL-2.0-only 2/* 3 * Copyright (C) 2013 - 2025 Intel Corporation 4 */ 5 6#include <asm/cpu_device_id.h> 7#include <linux/bitfield.h> 8#include <linux/bits.h> 9#include <linux/completion.h> 10#include <linux/device.h> 11#include <linux/dma-mapping.h> 12#include <linux/firmware.h> 13#include <linux/interrupt.h> 14#include <linux/iopoll.h> 15#include <linux/math64.h> 16#include <linux/mm.h> 17#include <linux/mutex.h> 18#include <linux/module.h> 19#include <linux/pci.h> 20#include <linux/pm_runtime.h> 21#include <linux/scatterlist.h> 22#include <linux/types.h> 23 24#include "ipu7.h" 25#include "ipu7-bus.h" 26#include "ipu7-buttress.h" 27#include "ipu7-buttress-regs.h" 28 29#define BOOTLOADER_STATUS_OFFSET BUTTRESS_REG_FW_BOOT_PARAMS7 30 31#define BOOTLOADER_MAGIC_KEY 0xb00710adU 32 33#define ENTRY BUTTRESS_IU2CSECSR_IPC_PEER_COMP_ACTIONS_RST_PHASE1 34#define EXIT BUTTRESS_IU2CSECSR_IPC_PEER_COMP_ACTIONS_RST_PHASE2 35#define QUERY BUTTRESS_IU2CSECSR_IPC_PEER_QUERIED_IP_COMP_ACTIONS_RST_PHASE 36 37#define BUTTRESS_TSC_SYNC_RESET_TRIAL_MAX 10U 38 39#define BUTTRESS_POWER_TIMEOUT_US (200 * USEC_PER_MSEC) 40 41#define BUTTRESS_CSE_BOOTLOAD_TIMEOUT_US (5 * USEC_PER_SEC) 42#define BUTTRESS_CSE_AUTHENTICATE_TIMEOUT_US (10 * USEC_PER_SEC) 43#define BUTTRESS_CSE_FWRESET_TIMEOUT_US (100 * USEC_PER_MSEC) 44 45#define BUTTRESS_IPC_TX_TIMEOUT_MS MSEC_PER_SEC 46#define BUTTRESS_IPC_RX_TIMEOUT_MS MSEC_PER_SEC 47#define BUTTRESS_IPC_VALIDITY_TIMEOUT_US (1 * USEC_PER_SEC) 48#define BUTTRESS_TSC_SYNC_TIMEOUT_US (5 * USEC_PER_MSEC) 49 50#define BUTTRESS_IPC_RESET_RETRY 2000U 51#define BUTTRESS_CSE_IPC_RESET_RETRY 4U 52#define BUTTRESS_IPC_CMD_SEND_RETRY 1U 53 54struct ipu7_ipc_buttress_msg { 55 u32 cmd; 56 u32 expected_resp; 57 bool require_resp; 58 u8 cmd_size; 59}; 60 61static const u32 ipu7_adev_irq_mask[2] = { 62 BUTTRESS_IRQ_IS_IRQ, 63 BUTTRESS_IRQ_PS_IRQ 64}; 65 66int ipu_buttress_ipc_reset(struct ipu7_device *isp, 67 struct ipu_buttress_ipc *ipc) 68{ 69 unsigned int retries = BUTTRESS_IPC_RESET_RETRY; 70 struct ipu_buttress *b = &isp->buttress; 71 struct device *dev = &isp->pdev->dev; 72 u32 val = 0, csr_in_clr; 73 74 if (!isp->secure_mode) { 75 dev_dbg(dev, "Skip IPC reset for non-secure mode\n"); 76 return 0; 77 } 78 79 mutex_lock(&b->ipc_mutex); 80 81 /* Clear-by-1 CSR (all bits), corresponding internal states. */ 82 val = readl(isp->base + ipc->csr_in); 83 writel(val, isp->base + ipc->csr_in); 84 85 /* Set peer CSR bit IPC_PEER_COMP_ACTIONS_RST_PHASE1 */ 86 writel(ENTRY, isp->base + ipc->csr_out); 87 /* 88 * Clear-by-1 all CSR bits EXCEPT following 89 * bits: 90 * A. IPC_PEER_COMP_ACTIONS_RST_PHASE1. 91 * B. IPC_PEER_COMP_ACTIONS_RST_PHASE2. 92 * C. Possibly custom bits, depending on 93 * their role. 94 */ 95 csr_in_clr = BUTTRESS_IU2CSECSR_IPC_PEER_DEASSERTED_REG_VALID_REQ | 96 BUTTRESS_IU2CSECSR_IPC_PEER_ACKED_REG_VALID | 97 BUTTRESS_IU2CSECSR_IPC_PEER_ASSERTED_REG_VALID_REQ | QUERY; 98 99 do { 100 usleep_range(400, 500); 101 val = readl(isp->base + ipc->csr_in); 102 switch (val) { 103 case ENTRY | EXIT: 104 case ENTRY | EXIT | QUERY: 105 /* 106 * 1) Clear-by-1 CSR bits 107 * (IPC_PEER_COMP_ACTIONS_RST_PHASE1, 108 * IPC_PEER_COMP_ACTIONS_RST_PHASE2). 109 * 2) Set peer CSR bit 110 * IPC_PEER_QUERIED_IP_COMP_ACTIONS_RST_PHASE. 111 */ 112 writel(ENTRY | EXIT, isp->base + ipc->csr_in); 113 writel(QUERY, isp->base + ipc->csr_out); 114 break; 115 case ENTRY: 116 case ENTRY | QUERY: 117 /* 118 * 1) Clear-by-1 CSR bits 119 * (IPC_PEER_COMP_ACTIONS_RST_PHASE1, 120 * IPC_PEER_QUERIED_IP_COMP_ACTIONS_RST_PHASE). 121 * 2) Set peer CSR bit 122 * IPC_PEER_COMP_ACTIONS_RST_PHASE1. 123 */ 124 writel(ENTRY | QUERY, isp->base + ipc->csr_in); 125 writel(ENTRY, isp->base + ipc->csr_out); 126 break; 127 case EXIT: 128 case EXIT | QUERY: 129 /* 130 * Clear-by-1 CSR bit 131 * IPC_PEER_COMP_ACTIONS_RST_PHASE2. 132 * 1) Clear incoming doorbell. 133 * 2) Clear-by-1 all CSR bits EXCEPT following 134 * bits: 135 * A. IPC_PEER_COMP_ACTIONS_RST_PHASE1. 136 * B. IPC_PEER_COMP_ACTIONS_RST_PHASE2. 137 * C. Possibly custom bits, depending on 138 * their role. 139 * 3) Set peer CSR bit 140 * IPC_PEER_COMP_ACTIONS_RST_PHASE2. 141 */ 142 writel(EXIT, isp->base + ipc->csr_in); 143 writel(0, isp->base + ipc->db0_in); 144 writel(csr_in_clr, isp->base + ipc->csr_in); 145 writel(EXIT, isp->base + ipc->csr_out); 146 147 /* 148 * Read csr_in again to make sure if RST_PHASE2 is done. 149 * If csr_in is QUERY, it should be handled again. 150 */ 151 usleep_range(200, 300); 152 val = readl(isp->base + ipc->csr_in); 153 if (val & QUERY) { 154 dev_dbg(dev, 155 "RST_PHASE2 retry csr_in = %x\n", val); 156 break; 157 } 158 mutex_unlock(&b->ipc_mutex); 159 return 0; 160 case QUERY: 161 /* 162 * 1) Clear-by-1 CSR bit 163 * IPC_PEER_QUERIED_IP_COMP_ACTIONS_RST_PHASE. 164 * 2) Set peer CSR bit 165 * IPC_PEER_COMP_ACTIONS_RST_PHASE1 166 */ 167 writel(QUERY, isp->base + ipc->csr_in); 168 writel(ENTRY, isp->base + ipc->csr_out); 169 break; 170 default: 171 dev_dbg_ratelimited(dev, "Unexpected CSR 0x%x\n", val); 172 break; 173 } 174 } while (retries--); 175 176 mutex_unlock(&b->ipc_mutex); 177 dev_err(dev, "Timed out while waiting for CSE\n"); 178 179 return -ETIMEDOUT; 180} 181 182static void ipu_buttress_ipc_validity_close(struct ipu7_device *isp, 183 struct ipu_buttress_ipc *ipc) 184{ 185 writel(BUTTRESS_IU2CSECSR_IPC_PEER_DEASSERTED_REG_VALID_REQ, 186 isp->base + ipc->csr_out); 187} 188 189static int 190ipu_buttress_ipc_validity_open(struct ipu7_device *isp, 191 struct ipu_buttress_ipc *ipc) 192{ 193 unsigned int mask = BUTTRESS_IU2CSECSR_IPC_PEER_ACKED_REG_VALID; 194 void __iomem *addr; 195 int ret; 196 u32 val; 197 198 writel(BUTTRESS_IU2CSECSR_IPC_PEER_ASSERTED_REG_VALID_REQ, 199 isp->base + ipc->csr_out); 200 201 addr = isp->base + ipc->csr_in; 202 ret = readl_poll_timeout(addr, val, val & mask, 200, 203 BUTTRESS_IPC_VALIDITY_TIMEOUT_US); 204 if (ret) { 205 dev_err(&isp->pdev->dev, "CSE validity timeout 0x%x\n", val); 206 ipu_buttress_ipc_validity_close(isp, ipc); 207 } 208 209 return ret; 210} 211 212static void ipu_buttress_ipc_recv(struct ipu7_device *isp, 213 struct ipu_buttress_ipc *ipc, u32 *ipc_msg) 214{ 215 if (ipc_msg) 216 *ipc_msg = readl(isp->base + ipc->data0_in); 217 writel(0, isp->base + ipc->db0_in); 218} 219 220static int ipu_buttress_ipc_send_msg(struct ipu7_device *isp, 221 struct ipu7_ipc_buttress_msg *msg) 222{ 223 unsigned long tx_timeout_jiffies, rx_timeout_jiffies; 224 unsigned int retry = BUTTRESS_IPC_CMD_SEND_RETRY; 225 struct ipu_buttress *b = &isp->buttress; 226 struct ipu_buttress_ipc *ipc = &b->cse; 227 struct device *dev = &isp->pdev->dev; 228 int tout; 229 u32 val; 230 int ret; 231 232 mutex_lock(&b->ipc_mutex); 233 234 ret = ipu_buttress_ipc_validity_open(isp, ipc); 235 if (ret) { 236 dev_err(dev, "IPC validity open failed\n"); 237 goto out; 238 } 239 240 tx_timeout_jiffies = msecs_to_jiffies(BUTTRESS_IPC_TX_TIMEOUT_MS); 241 rx_timeout_jiffies = msecs_to_jiffies(BUTTRESS_IPC_RX_TIMEOUT_MS); 242 243try: 244 reinit_completion(&ipc->send_complete); 245 if (msg->require_resp) 246 reinit_completion(&ipc->recv_complete); 247 248 dev_dbg(dev, "IPC command: 0x%x\n", msg->cmd); 249 writel(msg->cmd, isp->base + ipc->data0_out); 250 val = BUTTRESS_IU2CSEDB0_BUSY | msg->cmd_size; 251 writel(val, isp->base + ipc->db0_out); 252 253 tout = wait_for_completion_timeout(&ipc->send_complete, 254 tx_timeout_jiffies); 255 if (!tout) { 256 dev_err(dev, "send IPC response timeout\n"); 257 if (!retry--) { 258 ret = -ETIMEDOUT; 259 goto out; 260 } 261 262 /* Try again if CSE is not responding on first try */ 263 writel(0, isp->base + ipc->db0_out); 264 goto try; 265 } 266 267 if (!msg->require_resp) { 268 ret = -EIO; 269 goto out; 270 } 271 272 tout = wait_for_completion_timeout(&ipc->recv_complete, 273 rx_timeout_jiffies); 274 if (!tout) { 275 dev_err(dev, "recv IPC response timeout\n"); 276 ret = -ETIMEDOUT; 277 goto out; 278 } 279 280 if (ipc->nack_mask && 281 (ipc->recv_data & ipc->nack_mask) == ipc->nack) { 282 dev_err(dev, "IPC NACK for cmd 0x%x\n", msg->cmd); 283 ret = -EIO; 284 goto out; 285 } 286 287 if (ipc->recv_data != msg->expected_resp) { 288 dev_err(dev, 289 "expected resp: 0x%x, IPC response: 0x%x\n", 290 msg->expected_resp, ipc->recv_data); 291 ret = -EIO; 292 goto out; 293 } 294 295 dev_dbg(dev, "IPC commands done\n"); 296 297out: 298 ipu_buttress_ipc_validity_close(isp, ipc); 299 mutex_unlock(&b->ipc_mutex); 300 301 return ret; 302} 303 304static int ipu_buttress_ipc_send(struct ipu7_device *isp, 305 u32 ipc_msg, u32 size, bool require_resp, 306 u32 expected_resp) 307{ 308 struct ipu7_ipc_buttress_msg msg = { 309 .cmd = ipc_msg, 310 .cmd_size = size, 311 .require_resp = require_resp, 312 .expected_resp = expected_resp, 313 }; 314 315 return ipu_buttress_ipc_send_msg(isp, &msg); 316} 317 318static irqreturn_t ipu_buttress_call_isr(struct ipu7_bus_device *adev) 319{ 320 irqreturn_t ret = IRQ_WAKE_THREAD; 321 322 if (!adev || !adev->auxdrv || !adev->auxdrv_data) 323 return IRQ_NONE; 324 325 if (adev->auxdrv_data->isr) 326 ret = adev->auxdrv_data->isr(adev); 327 328 if (ret == IRQ_WAKE_THREAD && !adev->auxdrv_data->isr_threaded) 329 ret = IRQ_NONE; 330 331 return ret; 332} 333 334irqreturn_t ipu_buttress_isr(int irq, void *isp_ptr) 335{ 336 struct ipu7_device *isp = isp_ptr; 337 struct ipu7_bus_device *adev[] = { isp->isys, isp->psys }; 338 struct ipu_buttress *b = &isp->buttress; 339 struct device *dev = &isp->pdev->dev; 340 irqreturn_t ret = IRQ_NONE; 341 u32 pb_irq, pb_local_irq; 342 u32 disable_irqs = 0; 343 u32 irq_status; 344 unsigned int i; 345 int active; 346 347 active = pm_runtime_get_if_active(dev); 348 if (active <= 0) 349 return IRQ_NONE; 350 351 pb_irq = readl(isp->pb_base + INTERRUPT_STATUS); 352 writel(pb_irq, isp->pb_base + INTERRUPT_STATUS); 353 354 /* check btrs ATS, CFI and IMR errors, BIT(0) is unused for IPU */ 355 pb_local_irq = readl(isp->pb_base + BTRS_LOCAL_INTERRUPT_MASK); 356 if (pb_local_irq == 0xffffffff) { 357 dev_warn_once(dev, "invalid PB irq status\n"); 358 pm_runtime_put_noidle(dev); 359 return IRQ_NONE; 360 } 361 362 if (pb_local_irq & ~BIT(0)) { 363 dev_warn(dev, "PB interrupt status 0x%x local 0x%x\n", pb_irq, 364 pb_local_irq); 365 dev_warn(dev, "Details: %x %x %x %x %x %x %x %x\n", 366 readl(isp->pb_base + ATS_ERROR_LOG1), 367 readl(isp->pb_base + ATS_ERROR_LOG2), 368 readl(isp->pb_base + CFI_0_ERROR_LOG), 369 readl(isp->pb_base + CFI_1_ERROR_LOGGING), 370 readl(isp->pb_base + IMR_ERROR_LOGGING_LOW), 371 readl(isp->pb_base + IMR_ERROR_LOGGING_HIGH), 372 readl(isp->pb_base + IMR_ERROR_LOGGING_CFI_1_LOW), 373 readl(isp->pb_base + IMR_ERROR_LOGGING_CFI_1_HIGH)); 374 } 375 376 irq_status = readl(isp->base + BUTTRESS_REG_IRQ_STATUS); 377 if (!irq_status) { 378 pm_runtime_put_noidle(dev); 379 return IRQ_NONE; 380 } 381 382 if (irq_status == 0xffffffff) { 383 dev_warn_once(dev, "invalid irq status 0x%08x\n", irq_status); 384 pm_runtime_put_noidle(dev); 385 return IRQ_NONE; 386 } 387 388 do { 389 writel(irq_status, isp->base + BUTTRESS_REG_IRQ_CLEAR); 390 391 for (i = 0; i < ARRAY_SIZE(ipu7_adev_irq_mask); i++) { 392 irqreturn_t r = ipu_buttress_call_isr(adev[i]); 393 394 if (!(irq_status & ipu7_adev_irq_mask[i])) 395 continue; 396 397 if (r == IRQ_WAKE_THREAD) { 398 ret = IRQ_WAKE_THREAD; 399 disable_irqs |= ipu7_adev_irq_mask[i]; 400 } else if (ret == IRQ_NONE && r == IRQ_HANDLED) { 401 ret = IRQ_HANDLED; 402 } 403 } 404 405 if (irq_status & (BUTTRESS_IRQS | BUTTRESS_IRQ_SAI_VIOLATION) && 406 ret == IRQ_NONE) 407 ret = IRQ_HANDLED; 408 409 if (irq_status & BUTTRESS_IRQ_IPC_FROM_CSE_IS_WAITING) { 410 dev_dbg(dev, "BUTTRESS_IRQ_IPC_FROM_CSE_IS_WAITING\n"); 411 ipu_buttress_ipc_recv(isp, &b->cse, &b->cse.recv_data); 412 complete(&b->cse.recv_complete); 413 } 414 415 if (irq_status & BUTTRESS_IRQ_CSE_CSR_SET) 416 dev_dbg(dev, "BUTTRESS_IRQ_CSE_CSR_SET\n"); 417 418 if (irq_status & BUTTRESS_IRQ_IPC_EXEC_DONE_BY_CSE) { 419 dev_dbg(dev, "BUTTRESS_IRQ_IPC_EXEC_DONE_BY_CSE\n"); 420 complete(&b->cse.send_complete); 421 } 422 423 if (irq_status & BUTTRESS_IRQ_PUNIT_2_IUNIT_IRQ) 424 dev_dbg(dev, "BUTTRESS_IRQ_PUNIT_2_IUNIT_IRQ\n"); 425 426 if (irq_status & BUTTRESS_IRQ_SAI_VIOLATION && 427 ipu_buttress_get_secure_mode(isp)) 428 dev_err(dev, "BUTTRESS_IRQ_SAI_VIOLATION\n"); 429 430 irq_status = readl(isp->base + BUTTRESS_REG_IRQ_STATUS); 431 } while (irq_status); 432 433 if (disable_irqs) 434 writel(BUTTRESS_IRQS & ~disable_irqs, 435 isp->base + BUTTRESS_REG_IRQ_ENABLE); 436 437 pm_runtime_put(dev); 438 439 return ret; 440} 441 442irqreturn_t ipu_buttress_isr_threaded(int irq, void *isp_ptr) 443{ 444 struct ipu7_device *isp = isp_ptr; 445 struct ipu7_bus_device *adev[] = { isp->isys, isp->psys }; 446 const struct ipu7_auxdrv_data *drv_data = NULL; 447 irqreturn_t ret = IRQ_NONE; 448 unsigned int i; 449 450 for (i = 0; i < ARRAY_SIZE(ipu7_adev_irq_mask) && adev[i]; i++) { 451 drv_data = adev[i]->auxdrv_data; 452 if (!drv_data) 453 continue; 454 455 if (drv_data->wake_isr_thread && 456 drv_data->isr_threaded(adev[i]) == IRQ_HANDLED) 457 ret = IRQ_HANDLED; 458 } 459 460 writel(BUTTRESS_IRQS, isp->base + BUTTRESS_REG_IRQ_ENABLE); 461 462 return ret; 463} 464 465static int isys_d2d_power(struct device *dev, bool on) 466{ 467 struct ipu7_device *isp = to_ipu7_bus_device(dev)->isp; 468 int ret = 0; 469 u32 target = on ? BUTTRESS_D2D_PWR_ACK : 0U; 470 u32 val; 471 472 dev_dbg(dev, "power %s isys d2d.\n", on ? "UP" : "DOWN"); 473 val = readl(isp->base + BUTTRESS_REG_D2D_CTL); 474 if ((val & BUTTRESS_D2D_PWR_ACK) == target) { 475 dev_info(dev, "d2d already in %s state.\n", 476 on ? "UP" : "DOWN"); 477 return 0; 478 } 479 480 val = on ? val | BUTTRESS_D2D_PWR_EN : val & (~BUTTRESS_D2D_PWR_EN); 481 writel(val, isp->base + BUTTRESS_REG_D2D_CTL); 482 ret = readl_poll_timeout(isp->base + BUTTRESS_REG_D2D_CTL, 483 val, (val & BUTTRESS_D2D_PWR_ACK) == target, 484 100, BUTTRESS_POWER_TIMEOUT_US); 485 if (ret) 486 dev_err(dev, "power %s d2d timeout. status: 0x%x\n", 487 on ? "UP" : "DOWN", val); 488 489 return ret; 490} 491 492static void isys_nde_control(struct device *dev, bool on) 493{ 494 struct ipu7_device *isp = to_ipu7_bus_device(dev)->isp; 495 u32 val, value, scale, valid, resvec; 496 u32 nde_reg; 497 498 if (on) { 499 value = BUTTRESS_NDE_VAL_ACTIVE; 500 scale = BUTTRESS_NDE_SCALE_ACTIVE; 501 valid = BUTTRESS_NDE_VALID_ACTIVE; 502 } else { 503 value = BUTTRESS_NDE_VAL_DEFAULT; 504 scale = BUTTRESS_NDE_SCALE_DEFAULT; 505 valid = BUTTRESS_NDE_VALID_DEFAULT; 506 } 507 508 /* only set the fabrics resource ownership for ipu8 */ 509 nde_reg = is_ipu8(isp->hw_ver) ? IPU8_BUTTRESS_REG_NDE_CONTROL : 510 IPU7_BUTTRESS_REG_NDE_CONTROL; 511 resvec = is_ipu8(isp->hw_ver) ? 0x2 : 0xe; 512 val = FIELD_PREP(NDE_VAL_MASK, value) | 513 FIELD_PREP(NDE_SCALE_MASK, scale) | 514 FIELD_PREP(NDE_VALID_MASK, valid) | 515 FIELD_PREP(NDE_RESVEC_MASK, resvec); 516 517 writel(val, isp->base + nde_reg); 518} 519 520static int ipu7_buttress_powerup(struct device *dev, 521 const struct ipu_buttress_ctrl *ctrl) 522{ 523 struct ipu7_device *isp = to_ipu7_bus_device(dev)->isp; 524 u32 val, exp_sts; 525 int ret = 0; 526 527 if (!ctrl) 528 return 0; 529 530 mutex_lock(&isp->buttress.power_mutex); 531 532 exp_sts = ctrl->pwr_sts_on << ctrl->pwr_sts_shift; 533 if (ctrl->subsys_id == IPU_IS) { 534 ret = isys_d2d_power(dev, true); 535 if (ret) 536 goto out_power; 537 isys_nde_control(dev, true); 538 } 539 540 /* request clock resource ownership */ 541 val = readl(isp->base + BUTTRESS_REG_SLEEP_LEVEL_CFG); 542 val |= ctrl->ovrd_clk; 543 writel(val, isp->base + BUTTRESS_REG_SLEEP_LEVEL_CFG); 544 ret = readl_poll_timeout(isp->base + BUTTRESS_REG_SLEEP_LEVEL_STS, 545 val, (val & ctrl->own_clk_ack), 546 100, BUTTRESS_POWER_TIMEOUT_US); 547 if (ret) 548 dev_warn(dev, "request clk ownership timeout. status 0x%x\n", 549 val); 550 551 val = ctrl->ratio << ctrl->ratio_shift | ctrl->cdyn << ctrl->cdyn_shift; 552 553 dev_dbg(dev, "set 0x%x to %s_WORKPOINT_REQ.\n", val, 554 ctrl->subsys_id == IPU_IS ? "IS" : "PS"); 555 writel(val, isp->base + ctrl->freq_ctl); 556 557 ret = readl_poll_timeout(isp->base + BUTTRESS_REG_PWR_STATUS, 558 val, ((val & ctrl->pwr_sts_mask) == exp_sts), 559 100, BUTTRESS_POWER_TIMEOUT_US); 560 if (ret) { 561 dev_err(dev, "%s power up timeout with status: 0x%x\n", 562 ctrl->subsys_id == IPU_IS ? "IS" : "PS", val); 563 goto out_power; 564 } 565 566 dev_dbg(dev, "%s power up successfully. status: 0x%x\n", 567 ctrl->subsys_id == IPU_IS ? "IS" : "PS", val); 568 569 /* release clock resource ownership */ 570 val = readl(isp->base + BUTTRESS_REG_SLEEP_LEVEL_CFG); 571 val &= ~ctrl->ovrd_clk; 572 writel(val, isp->base + BUTTRESS_REG_SLEEP_LEVEL_CFG); 573 574out_power: 575 mutex_unlock(&isp->buttress.power_mutex); 576 577 return ret; 578} 579 580static int ipu7_buttress_powerdown(struct device *dev, 581 const struct ipu_buttress_ctrl *ctrl) 582{ 583 struct ipu7_device *isp = to_ipu7_bus_device(dev)->isp; 584 u32 val, exp_sts; 585 int ret = 0; 586 587 if (!ctrl) 588 return 0; 589 590 mutex_lock(&isp->buttress.power_mutex); 591 592 exp_sts = ctrl->pwr_sts_off << ctrl->pwr_sts_shift; 593 val = 0x8U << ctrl->ratio_shift; 594 595 dev_dbg(dev, "set 0x%x to %s_WORKPOINT_REQ.\n", val, 596 ctrl->subsys_id == IPU_IS ? "IS" : "PS"); 597 writel(val, isp->base + ctrl->freq_ctl); 598 ret = readl_poll_timeout(isp->base + BUTTRESS_REG_PWR_STATUS, 599 val, ((val & ctrl->pwr_sts_mask) == exp_sts), 600 100, BUTTRESS_POWER_TIMEOUT_US); 601 if (ret) { 602 dev_err(dev, "%s power down timeout with status: 0x%x\n", 603 ctrl->subsys_id == IPU_IS ? "IS" : "PS", val); 604 goto out_power; 605 } 606 607 dev_dbg(dev, "%s power down successfully. status: 0x%x\n", 608 ctrl->subsys_id == IPU_IS ? "IS" : "PS", val); 609out_power: 610 if (ctrl->subsys_id == IPU_IS && !ret) { 611 isys_d2d_power(dev, false); 612 isys_nde_control(dev, false); 613 } 614 615 mutex_unlock(&isp->buttress.power_mutex); 616 617 return ret; 618} 619 620static int ipu8_buttress_powerup(struct device *dev, 621 const struct ipu_buttress_ctrl *ctrl) 622{ 623 struct ipu7_device *isp = to_ipu7_bus_device(dev)->isp; 624 u32 sleep_level_reg = BUTTRESS_REG_SLEEP_LEVEL_STS; 625 u32 val, exp_sts; 626 int ret = 0; 627 628 if (!ctrl) 629 return 0; 630 631 mutex_lock(&isp->buttress.power_mutex); 632 exp_sts = ctrl->pwr_sts_on << ctrl->pwr_sts_shift; 633 if (ctrl->subsys_id == IPU_IS) { 634 ret = isys_d2d_power(dev, true); 635 if (ret) 636 goto out_power; 637 isys_nde_control(dev, true); 638 } 639 640 /* request ps_pll when psys freq > 400Mhz */ 641 if (ctrl->subsys_id == IPU_PS && ctrl->ratio > 0x10) { 642 writel(1, isp->base + BUTTRESS_REG_PS_PLL_ENABLE); 643 ret = readl_poll_timeout(isp->base + sleep_level_reg, 644 val, (val & ctrl->own_clk_ack), 645 100, BUTTRESS_POWER_TIMEOUT_US); 646 if (ret) 647 dev_warn(dev, "ps_pll req ack timeout. status 0x%x\n", 648 val); 649 } 650 651 val = ctrl->ratio << ctrl->ratio_shift | ctrl->cdyn << ctrl->cdyn_shift; 652 dev_dbg(dev, "set 0x%x to %s_WORKPOINT_REQ.\n", val, 653 ctrl->subsys_id == IPU_IS ? "IS" : "PS"); 654 writel(val, isp->base + ctrl->freq_ctl); 655 ret = readl_poll_timeout(isp->base + BUTTRESS_REG_PWR_STATUS, 656 val, ((val & ctrl->pwr_sts_mask) == exp_sts), 657 100, BUTTRESS_POWER_TIMEOUT_US); 658 if (ret) { 659 dev_err(dev, "%s power up timeout with status: 0x%x\n", 660 ctrl->subsys_id == IPU_IS ? "IS" : "PS", val); 661 goto out_power; 662 } 663 664 dev_dbg(dev, "%s power up successfully. status: 0x%x\n", 665 ctrl->subsys_id == IPU_IS ? "IS" : "PS", val); 666out_power: 667 mutex_unlock(&isp->buttress.power_mutex); 668 669 return ret; 670} 671 672static int ipu8_buttress_powerdown(struct device *dev, 673 const struct ipu_buttress_ctrl *ctrl) 674{ 675 struct ipu7_device *isp = to_ipu7_bus_device(dev)->isp; 676 u32 val, exp_sts; 677 int ret = 0; 678 679 if (!ctrl) 680 return 0; 681 682 mutex_lock(&isp->buttress.power_mutex); 683 exp_sts = ctrl->pwr_sts_off << ctrl->pwr_sts_shift; 684 685 if (ctrl->subsys_id == IPU_PS) 686 val = 0x10U << ctrl->ratio_shift; 687 else 688 val = 0x8U << ctrl->ratio_shift; 689 690 dev_dbg(dev, "set 0x%x to %s_WORKPOINT_REQ.\n", val, 691 ctrl->subsys_id == IPU_IS ? "IS" : "PS"); 692 writel(val, isp->base + ctrl->freq_ctl); 693 ret = readl_poll_timeout(isp->base + BUTTRESS_REG_PWR_STATUS, 694 val, ((val & ctrl->pwr_sts_mask) == exp_sts), 695 100, BUTTRESS_POWER_TIMEOUT_US); 696 if (ret) { 697 dev_err(dev, "%s power down timeout with status: 0x%x\n", 698 ctrl->subsys_id == IPU_IS ? "IS" : "PS", val); 699 goto out_power; 700 } 701 702 dev_dbg(dev, "%s power down successfully. status: 0x%x\n", 703 ctrl->subsys_id == IPU_IS ? "IS" : "PS", val); 704out_power: 705 if (ctrl->subsys_id == IPU_IS && !ret) { 706 isys_d2d_power(dev, false); 707 isys_nde_control(dev, false); 708 } 709 710 if (ctrl->subsys_id == IPU_PS) { 711 val = readl(isp->base + BUTTRESS_REG_SLEEP_LEVEL_STS); 712 if (val & ctrl->own_clk_ack) 713 writel(0, isp->base + BUTTRESS_REG_PS_PLL_ENABLE); 714 } 715 mutex_unlock(&isp->buttress.power_mutex); 716 717 return ret; 718} 719 720int ipu_buttress_powerup(struct device *dev, 721 const struct ipu_buttress_ctrl *ctrl) 722{ 723 struct ipu7_device *isp = to_ipu7_bus_device(dev)->isp; 724 725 if (is_ipu8(isp->hw_ver)) 726 return ipu8_buttress_powerup(dev, ctrl); 727 728 return ipu7_buttress_powerup(dev, ctrl); 729} 730 731int ipu_buttress_powerdown(struct device *dev, 732 const struct ipu_buttress_ctrl *ctrl) 733{ 734 struct ipu7_device *isp = to_ipu7_bus_device(dev)->isp; 735 736 if (is_ipu8(isp->hw_ver)) 737 return ipu8_buttress_powerdown(dev, ctrl); 738 739 return ipu7_buttress_powerdown(dev, ctrl); 740} 741 742bool ipu_buttress_get_secure_mode(struct ipu7_device *isp) 743{ 744 u32 val; 745 746 val = readl(isp->base + BUTTRESS_REG_SECURITY_CTL); 747 748 return val & BUTTRESS_SECURITY_CTL_FW_SECURE_MODE; 749} 750 751bool ipu_buttress_auth_done(struct ipu7_device *isp) 752{ 753 u32 val; 754 755 if (!isp->secure_mode) 756 return true; 757 758 val = readl(isp->base + BUTTRESS_REG_SECURITY_CTL); 759 val = FIELD_GET(BUTTRESS_SECURITY_CTL_FW_SETUP_MASK, val); 760 761 return val == BUTTRESS_SECURITY_CTL_AUTH_DONE; 762} 763EXPORT_SYMBOL_NS_GPL(ipu_buttress_auth_done, "INTEL_IPU7"); 764 765int ipu_buttress_get_isys_freq(struct ipu7_device *isp, u32 *freq) 766{ 767 u32 reg_val; 768 int ret; 769 770 ret = pm_runtime_get_sync(&isp->isys->auxdev.dev); 771 if (ret < 0) { 772 pm_runtime_put(&isp->isys->auxdev.dev); 773 dev_err(&isp->pdev->dev, "Runtime PM failed (%d)\n", ret); 774 return ret; 775 } 776 777 reg_val = readl(isp->base + BUTTRESS_REG_IS_WORKPOINT_REQ); 778 779 pm_runtime_put(&isp->isys->auxdev.dev); 780 781 if (is_ipu8(isp->hw_ver)) 782 *freq = (reg_val & BUTTRESS_IS_FREQ_CTL_RATIO_MASK) * 25; 783 else 784 *freq = (reg_val & BUTTRESS_IS_FREQ_CTL_RATIO_MASK) * 50 / 3; 785 786 return 0; 787} 788EXPORT_SYMBOL_NS_GPL(ipu_buttress_get_isys_freq, "INTEL_IPU7"); 789 790int ipu_buttress_get_psys_freq(struct ipu7_device *isp, u32 *freq) 791{ 792 u32 reg_val; 793 int ret; 794 795 ret = pm_runtime_get_sync(&isp->psys->auxdev.dev); 796 if (ret < 0) { 797 pm_runtime_put(&isp->psys->auxdev.dev); 798 dev_err(&isp->pdev->dev, "Runtime PM failed (%d)\n", ret); 799 return ret; 800 } 801 802 reg_val = readl(isp->base + BUTTRESS_REG_PS_WORKPOINT_REQ); 803 804 pm_runtime_put(&isp->psys->auxdev.dev); 805 806 reg_val &= BUTTRESS_PS_FREQ_CTL_RATIO_MASK; 807 *freq = BUTTRESS_PS_FREQ_RATIO_STEP * reg_val; 808 809 return 0; 810} 811EXPORT_SYMBOL_NS_GPL(ipu_buttress_get_psys_freq, "INTEL_IPU7"); 812 813int ipu_buttress_reset_authentication(struct ipu7_device *isp) 814{ 815 struct device *dev = &isp->pdev->dev; 816 int ret; 817 u32 val; 818 819 if (!isp->secure_mode) { 820 dev_dbg(dev, "Skip auth for non-secure mode\n"); 821 return 0; 822 } 823 824 writel(BUTTRESS_FW_RESET_CTL_START, isp->base + 825 BUTTRESS_REG_FW_RESET_CTL); 826 827 ret = readl_poll_timeout(isp->base + BUTTRESS_REG_FW_RESET_CTL, val, 828 val & BUTTRESS_FW_RESET_CTL_DONE, 500, 829 BUTTRESS_CSE_FWRESET_TIMEOUT_US); 830 if (ret) { 831 dev_err(dev, "Time out while resetting authentication state\n"); 832 return ret; 833 } 834 835 dev_dbg(dev, "FW reset for authentication done\n"); 836 writel(0, isp->base + BUTTRESS_REG_FW_RESET_CTL); 837 /* leave some time for HW restore */ 838 usleep_range(800, 1000); 839 840 return 0; 841} 842 843int ipu_buttress_authenticate(struct ipu7_device *isp) 844{ 845 struct ipu_buttress *b = &isp->buttress; 846 struct device *dev = &isp->pdev->dev; 847 u32 data, mask, done, fail; 848 int ret; 849 850 if (!isp->secure_mode) { 851 dev_dbg(dev, "Skip auth for non-secure mode\n"); 852 return 0; 853 } 854 855 mutex_lock(&b->auth_mutex); 856 857 if (ipu_buttress_auth_done(isp)) { 858 ret = 0; 859 goto out_unlock; 860 } 861 862 /* 863 * BUTTRESS_REG_FW_SOURCE_BASE needs to be set with FW CPD 864 * package address for secure mode. 865 */ 866 867 writel(isp->cpd_fw->size, isp->base + BUTTRESS_REG_FW_SOURCE_SIZE); 868 writel(sg_dma_address(isp->psys->fw_sgt.sgl), 869 isp->base + BUTTRESS_REG_FW_SOURCE_BASE); 870 871 /* 872 * Write boot_load into IU2CSEDATA0 873 * Write sizeof(boot_load) | 0x2 << CLIENT_ID to 874 * IU2CSEDB.IU2CSECMD and set IU2CSEDB.IU2CSEBUSY as 875 */ 876 dev_info(dev, "Sending BOOT_LOAD to CSE\n"); 877 ret = ipu_buttress_ipc_send(isp, BUTTRESS_IU2CSEDATA0_IPC_BOOT_LOAD, 878 1, true, 879 BUTTRESS_CSE2IUDATA0_IPC_BOOT_LOAD_DONE); 880 if (ret) { 881 dev_err(dev, "CSE boot_load failed\n"); 882 goto out_unlock; 883 } 884 885 mask = BUTTRESS_SECURITY_CTL_FW_SETUP_MASK; 886 done = BUTTRESS_SECURITY_CTL_FW_SETUP_DONE; 887 fail = BUTTRESS_SECURITY_CTL_AUTH_FAILED; 888 ret = readl_poll_timeout(isp->base + BUTTRESS_REG_SECURITY_CTL, data, 889 ((data & mask) == done || 890 (data & mask) == fail), 500, 891 BUTTRESS_CSE_BOOTLOAD_TIMEOUT_US); 892 if (ret) { 893 dev_err(dev, "CSE boot_load timeout\n"); 894 goto out_unlock; 895 } 896 897 if ((data & mask) == fail) { 898 dev_err(dev, "CSE auth failed\n"); 899 ret = -EINVAL; 900 goto out_unlock; 901 } 902 903 ret = readl_poll_timeout(isp->base + BOOTLOADER_STATUS_OFFSET, 904 data, data == BOOTLOADER_MAGIC_KEY, 500, 905 BUTTRESS_CSE_BOOTLOAD_TIMEOUT_US); 906 if (ret) { 907 dev_err(dev, "Unexpected magic number 0x%x\n", data); 908 goto out_unlock; 909 } 910 911 /* 912 * Write authenticate_run into IU2CSEDATA0 913 * Write sizeof(boot_load) | 0x2 << CLIENT_ID to 914 * IU2CSEDB.IU2CSECMD and set IU2CSEDB.IU2CSEBUSY as 915 */ 916 dev_info(dev, "Sending AUTHENTICATE_RUN to CSE\n"); 917 ret = ipu_buttress_ipc_send(isp, BUTTRESS_IU2CSEDATA0_IPC_AUTH_RUN, 918 1, true, 919 BUTTRESS_CSE2IUDATA0_IPC_AUTH_RUN_DONE); 920 if (ret) { 921 dev_err(dev, "CSE authenticate_run failed\n"); 922 goto out_unlock; 923 } 924 925 done = BUTTRESS_SECURITY_CTL_AUTH_DONE; 926 ret = readl_poll_timeout(isp->base + BUTTRESS_REG_SECURITY_CTL, data, 927 ((data & mask) == done || 928 (data & mask) == fail), 500, 929 BUTTRESS_CSE_AUTHENTICATE_TIMEOUT_US); 930 if (ret) { 931 dev_err(dev, "CSE authenticate timeout\n"); 932 goto out_unlock; 933 } 934 935 if ((data & mask) == fail) { 936 dev_err(dev, "CSE boot_load failed\n"); 937 ret = -EINVAL; 938 goto out_unlock; 939 } 940 941 dev_info(dev, "CSE authenticate_run done\n"); 942 943out_unlock: 944 mutex_unlock(&b->auth_mutex); 945 946 return ret; 947} 948 949static int ipu_buttress_send_tsc_request(struct ipu7_device *isp) 950{ 951 u32 val, mask, done; 952 int ret; 953 954 mask = BUTTRESS_PWR_STATUS_HH_STATUS_MASK; 955 956 writel(BUTTRESS_TSC_CMD_START_TSC_SYNC, 957 isp->base + BUTTRESS_REG_TSC_CMD); 958 959 val = readl(isp->base + BUTTRESS_REG_PWR_STATUS); 960 val = FIELD_GET(mask, val); 961 if (val == BUTTRESS_PWR_STATUS_HH_STATE_ERR) { 962 dev_err(&isp->pdev->dev, "Start tsc sync failed\n"); 963 return -EINVAL; 964 } 965 966 done = BUTTRESS_PWR_STATUS_HH_STATE_DONE; 967 ret = readl_poll_timeout(isp->base + BUTTRESS_REG_PWR_STATUS, val, 968 FIELD_GET(mask, val) == done, 500, 969 BUTTRESS_TSC_SYNC_TIMEOUT_US); 970 if (ret) 971 dev_err(&isp->pdev->dev, "Start tsc sync timeout\n"); 972 973 return ret; 974} 975 976int ipu_buttress_start_tsc_sync(struct ipu7_device *isp) 977{ 978 void __iomem *base = isp->base; 979 unsigned int i; 980 u32 val; 981 982 if (is_ipu8(isp->hw_ver)) { 983 for (i = 0; i < BUTTRESS_TSC_SYNC_RESET_TRIAL_MAX; i++) { 984 val = readl(base + BUTTRESS_REG_PB_TIMESTAMP_VALID); 985 if (val == 1) 986 return 0; 987 usleep_range(40, 50); 988 } 989 990 dev_err(&isp->pdev->dev, "PB HH sync failed (valid %u)\n", val); 991 return -ETIMEDOUT; 992 } 993 994 if (is_ipu7p5(isp->hw_ver)) { 995 val = readl(base + BUTTRESS_REG_TSC_CTL); 996 val |= BUTTRESS_SEL_PB_TIMESTAMP; 997 writel(val, base + BUTTRESS_REG_TSC_CTL); 998 999 for (i = 0; i < BUTTRESS_TSC_SYNC_RESET_TRIAL_MAX; i++) { 1000 val = readl(base + BUTTRESS_REG_PB_TIMESTAMP_VALID); 1001 if (val == 1) 1002 return 0; 1003 usleep_range(40, 50); 1004 } 1005 1006 dev_err(&isp->pdev->dev, "PB HH sync failed (valid %u)\n", val); 1007 1008 return -ETIMEDOUT; 1009 } 1010 1011 for (i = 0; i < BUTTRESS_TSC_SYNC_RESET_TRIAL_MAX; i++) { 1012 int ret; 1013 1014 ret = ipu_buttress_send_tsc_request(isp); 1015 if (ret != -ETIMEDOUT) 1016 return ret; 1017 1018 val = readl(base + BUTTRESS_REG_TSC_CTL); 1019 val = val | BUTTRESS_TSW_WA_SOFT_RESET; 1020 writel(val, base + BUTTRESS_REG_TSC_CTL); 1021 val = val & (~BUTTRESS_TSW_WA_SOFT_RESET); 1022 writel(val, base + BUTTRESS_REG_TSC_CTL); 1023 } 1024 1025 dev_err(&isp->pdev->dev, "TSC sync failed (timeout)\n"); 1026 1027 return -ETIMEDOUT; 1028} 1029EXPORT_SYMBOL_NS_GPL(ipu_buttress_start_tsc_sync, "INTEL_IPU7"); 1030 1031void ipu_buttress_tsc_read(struct ipu7_device *isp, u64 *val) 1032{ 1033 unsigned long flags; 1034 u32 tsc_hi, tsc_lo; 1035 1036 local_irq_save(flags); 1037 if (is_ipu7(isp->hw_ver)) { 1038 tsc_lo = readl(isp->base + BUTTRESS_REG_TSC_LO); 1039 tsc_hi = readl(isp->base + BUTTRESS_REG_TSC_HI); 1040 } else { 1041 tsc_lo = readl(isp->base + BUTTRESS_REG_PB_TIMESTAMP_LO); 1042 tsc_hi = readl(isp->base + BUTTRESS_REG_PB_TIMESTAMP_HI); 1043 } 1044 *val = (u64)tsc_hi << 32 | tsc_lo; 1045 local_irq_restore(flags); 1046} 1047EXPORT_SYMBOL_NS_GPL(ipu_buttress_tsc_read, "INTEL_IPU7"); 1048 1049u64 ipu_buttress_tsc_ticks_to_ns(u64 ticks, const struct ipu7_device *isp) 1050{ 1051 u64 ns = ticks * 10000; 1052 1053 /* 1054 * converting TSC tick count to ns is calculated by: 1055 * Example (TSC clock frequency is 19.2MHz): 1056 * ns = ticks * 1000 000 000 / 19.2Mhz 1057 * = ticks * 1000 000 000 / 19200000Hz 1058 * = ticks * 10000 / 192 ns 1059 */ 1060 return div_u64(ns, isp->buttress.ref_clk); 1061} 1062EXPORT_SYMBOL_NS_GPL(ipu_buttress_tsc_ticks_to_ns, "INTEL_IPU7"); 1063 1064/* trigger uc control to wakeup fw */ 1065void ipu_buttress_wakeup_is_uc(const struct ipu7_device *isp) 1066{ 1067 u32 val; 1068 1069 val = readl(isp->base + BUTTRESS_REG_DRV_IS_UCX_CONTROL_STATUS); 1070 val |= UCX_CTL_WAKEUP; 1071 writel(val, isp->base + BUTTRESS_REG_DRV_IS_UCX_CONTROL_STATUS); 1072} 1073EXPORT_SYMBOL_NS_GPL(ipu_buttress_wakeup_is_uc, "INTEL_IPU7"); 1074 1075void ipu_buttress_wakeup_ps_uc(const struct ipu7_device *isp) 1076{ 1077 u32 val; 1078 1079 val = readl(isp->base + BUTTRESS_REG_DRV_PS_UCX_CONTROL_STATUS); 1080 val |= UCX_CTL_WAKEUP; 1081 writel(val, isp->base + BUTTRESS_REG_DRV_PS_UCX_CONTROL_STATUS); 1082} 1083EXPORT_SYMBOL_NS_GPL(ipu_buttress_wakeup_ps_uc, "INTEL_IPU7"); 1084 1085static const struct x86_cpu_id ipu_misc_cfg_exclusion[] = { 1086 X86_MATCH_VFM_STEPS(INTEL_PANTHERLAKE_L, 0x1, 0x1, 0), 1087 {}, 1088}; 1089 1090static void ipu_buttress_setup(struct ipu7_device *isp) 1091{ 1092 struct device *dev = &isp->pdev->dev; 1093 u32 val; 1094 1095 /* program PB BAR */ 1096#define WRXREQOP_OVRD_VAL_MASK GENMASK(22, 19) 1097 writel(0, isp->pb_base + GLOBAL_INTERRUPT_MASK); 1098 val = readl(isp->pb_base + BAR2_MISC_CONFIG); 1099 if (is_ipu7(isp->hw_ver) || x86_match_cpu(ipu_misc_cfg_exclusion)) 1100 val |= 0x100U; 1101 else 1102 val |= FIELD_PREP(WRXREQOP_OVRD_VAL_MASK, 0xf) | 1103 BIT(18) | 0x100U; 1104 1105 writel(val, isp->pb_base + BAR2_MISC_CONFIG); 1106 val = readl(isp->pb_base + BAR2_MISC_CONFIG); 1107 1108 if (is_ipu8(isp->hw_ver)) { 1109 writel(BIT(13), isp->pb_base + TLBID_HASH_ENABLE_63_32); 1110 writel(BIT(9), isp->pb_base + TLBID_HASH_ENABLE_95_64); 1111 dev_dbg(dev, "IPU8 TLBID_HASH %x %x\n", 1112 readl(isp->pb_base + TLBID_HASH_ENABLE_63_32), 1113 readl(isp->pb_base + TLBID_HASH_ENABLE_95_64)); 1114 } else if (is_ipu7p5(isp->hw_ver)) { 1115 writel(BIT(14), isp->pb_base + TLBID_HASH_ENABLE_63_32); 1116 writel(BIT(9), isp->pb_base + TLBID_HASH_ENABLE_95_64); 1117 dev_dbg(dev, "IPU7P5 TLBID_HASH %x %x\n", 1118 readl(isp->pb_base + TLBID_HASH_ENABLE_63_32), 1119 readl(isp->pb_base + TLBID_HASH_ENABLE_95_64)); 1120 } else { 1121 writel(BIT(22), isp->pb_base + TLBID_HASH_ENABLE_63_32); 1122 writel(BIT(1), isp->pb_base + TLBID_HASH_ENABLE_127_96); 1123 dev_dbg(dev, "TLBID_HASH %x %x\n", 1124 readl(isp->pb_base + TLBID_HASH_ENABLE_63_32), 1125 readl(isp->pb_base + TLBID_HASH_ENABLE_127_96)); 1126 } 1127 1128 writel(BUTTRESS_IRQS, isp->base + BUTTRESS_REG_IRQ_CLEAR); 1129 writel(BUTTRESS_IRQS, isp->base + BUTTRESS_REG_IRQ_MASK); 1130 writel(BUTTRESS_IRQS, isp->base + BUTTRESS_REG_IRQ_ENABLE); 1131 /* LNL SW workaround for PS PD hang when PS sub-domain during PD */ 1132 writel(PS_FSM_CG, isp->base + BUTTRESS_REG_CG_CTRL_BITS); 1133} 1134 1135void ipu_buttress_restore(struct ipu7_device *isp) 1136{ 1137 struct ipu_buttress *b = &isp->buttress; 1138 1139 ipu_buttress_setup(isp); 1140 1141 writel(b->wdt_cached_value, isp->base + BUTTRESS_REG_IDLE_WDT); 1142} 1143 1144int ipu_buttress_init(struct ipu7_device *isp) 1145{ 1146 int ret, ipc_reset_retry = BUTTRESS_CSE_IPC_RESET_RETRY; 1147 struct ipu_buttress *b = &isp->buttress; 1148 struct device *dev = &isp->pdev->dev; 1149 u32 val; 1150 1151 mutex_init(&b->power_mutex); 1152 mutex_init(&b->auth_mutex); 1153 mutex_init(&b->cons_mutex); 1154 mutex_init(&b->ipc_mutex); 1155 init_completion(&b->cse.send_complete); 1156 init_completion(&b->cse.recv_complete); 1157 1158 b->cse.nack = BUTTRESS_CSE2IUDATA0_IPC_NACK; 1159 b->cse.nack_mask = BUTTRESS_CSE2IUDATA0_IPC_NACK_MASK; 1160 b->cse.csr_in = BUTTRESS_REG_CSE2IUCSR; 1161 b->cse.csr_out = BUTTRESS_REG_IU2CSECSR; 1162 b->cse.db0_in = BUTTRESS_REG_CSE2IUDB0; 1163 b->cse.db0_out = BUTTRESS_REG_IU2CSEDB0; 1164 b->cse.data0_in = BUTTRESS_REG_CSE2IUDATA0; 1165 b->cse.data0_out = BUTTRESS_REG_IU2CSEDATA0; 1166 1167 isp->secure_mode = ipu_buttress_get_secure_mode(isp); 1168 val = readl(isp->base + BUTTRESS_REG_IPU_SKU); 1169 dev_info(dev, "IPU%u SKU %u in %s mode mask 0x%x\n", val & 0xfU, 1170 (val >> 4) & 0x7U, isp->secure_mode ? "secure" : "non-secure", 1171 readl(isp->base + BUTTRESS_REG_CAMERA_MASK)); 1172 b->wdt_cached_value = readl(isp->base + BUTTRESS_REG_IDLE_WDT); 1173 b->ref_clk = 384; 1174 1175 ipu_buttress_setup(isp); 1176 1177 /* Retry couple of times in case of CSE initialization is delayed */ 1178 do { 1179 ret = ipu_buttress_ipc_reset(isp, &b->cse); 1180 if (ret) { 1181 dev_warn(dev, "IPC reset protocol failed, retrying\n"); 1182 } else { 1183 dev_dbg(dev, "IPC reset done\n"); 1184 return 0; 1185 } 1186 } while (ipc_reset_retry--); 1187 1188 dev_err(dev, "IPC reset protocol failed\n"); 1189 1190 mutex_destroy(&b->power_mutex); 1191 mutex_destroy(&b->auth_mutex); 1192 mutex_destroy(&b->cons_mutex); 1193 mutex_destroy(&b->ipc_mutex); 1194 1195 return ret; 1196} 1197 1198void ipu_buttress_exit(struct ipu7_device *isp) 1199{ 1200 struct ipu_buttress *b = &isp->buttress; 1201 1202 writel(0, isp->base + BUTTRESS_REG_IRQ_ENABLE); 1203 mutex_destroy(&b->power_mutex); 1204 mutex_destroy(&b->auth_mutex); 1205 mutex_destroy(&b->cons_mutex); 1206 mutex_destroy(&b->ipc_mutex); 1207}
~/
Read-only file preview.