LCOV - code coverage report
Current view: top level - ipu4 - ipu6-buttress.c (source / functions) Coverage Total Hit
Test: ipu4.info Lines: 46.2 % 338 156
Test Date: 2026-05-12 04:57:36 Functions: 60.0 % 20 12

            Line data    Source code
       1              : // SPDX-License-Identifier: GPL-2.0-only
       2              : /*
       3              :  * Copyright (C) 2013--2024 Intel Corporation
       4              :  */
       5              : 
       6              : #include <linux/bitfield.h>
       7              : #include <linux/bits.h>
       8              : #include <linux/completion.h>
       9              : #include <linux/delay.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/pci.h>
      19              : #include <linux/pfn.h>
      20              : #include <linux/pm_runtime.h>
      21              : #include <linux/scatterlist.h>
      22              : #include <linux/slab.h>
      23              : #include <linux/time64.h>
      24              : 
      25              : #include "ipu6.h"
      26              : #include "ipu6-bus.h"
      27              : #include "ipu6-dma.h"
      28              : #include "ipu6-buttress.h"
      29              : #include "ipu6-platform-buttress-regs.h"
      30              : 
      31              : #include "ipu4-compat.h"
      32              : 
      33              : #define IPU4_BOOTLOADER_STATUS_OFFSET   0x8000
      34              : #define IPU6_BOOTLOADER_STATUS_OFFSET   0x15c
      35              : 
      36              : #define BOOTLOADER_MAGIC_KEY            0xb00710ad
      37              : 
      38              : #define ENTRY   BUTTRESS_IU2CSECSR_IPC_PEER_COMP_ACTIONS_RST_PHASE1
      39              : #define EXIT    BUTTRESS_IU2CSECSR_IPC_PEER_COMP_ACTIONS_RST_PHASE2
      40              : #define QUERY   BUTTRESS_IU2CSECSR_IPC_PEER_QUERIED_IP_COMP_ACTIONS_RST_PHASE
      41              : 
      42              : #define IPU4_BUTTRESS_TSC_CLOCK_FREQUENCY       192
      43              : #define BUTTRESS_TSC_SYNC_RESET_TRIAL_MAX       10
      44              : 
      45              : #define BUTTRESS_POWER_TIMEOUT_US               (200 * USEC_PER_MSEC)
      46              : 
      47              : #define BUTTRESS_CSE_BOOTLOAD_TIMEOUT_US        (5 * USEC_PER_SEC)
      48              : #define BUTTRESS_CSE_AUTHENTICATE_TIMEOUT_US    (10 * USEC_PER_SEC)
      49              : #define BUTTRESS_CSE_FWRESET_TIMEOUT_US         (100 * USEC_PER_MSEC)
      50              : 
      51              : #define BUTTRESS_IPC_TX_TIMEOUT_MS              MSEC_PER_SEC
      52              : #define BUTTRESS_IPC_RX_TIMEOUT_MS              MSEC_PER_SEC
      53              : #define BUTTRESS_IPC_VALIDITY_TIMEOUT_US        (1 * USEC_PER_SEC)
      54              : #define BUTTRESS_TSC_SYNC_TIMEOUT_US            (5 * USEC_PER_MSEC)
      55              : 
      56              : #define BUTTRESS_IPC_RESET_RETRY                2000
      57              : #define BUTTRESS_CSE_IPC_RESET_RETRY    4
      58              : #define BUTTRESS_IPC_CMD_SEND_RETRY     1
      59              : 
      60              : #define BUTTRESS_MAX_CONSECUTIVE_IRQS   100
      61              : 
      62              : static const u32 ipu6_adev_irq_mask[2] = {
      63              :         BUTTRESS_ISR_IS_IRQ,
      64              :         BUTTRESS_ISR_PS_IRQ
      65              : };
      66              : 
      67            1 : int ipu6_buttress_ipc_reset(struct ipu6_device *isp,
      68              :                             struct ipu6_buttress_ipc *ipc)
      69              : {
      70              :         unsigned int retries = BUTTRESS_IPC_RESET_RETRY;
      71              :         struct ipu6_buttress *b = &isp->buttress;
      72              :         u32 val = 0, csr_in_clr;
      73              : 
      74            1 :         if (!isp->secure_mode) {
      75            0 :                 dev_dbg(&isp->pdev->dev, "Skip IPC reset for non-secure mode");
      76            0 :                 return 0;
      77              :         }
      78              : 
      79            1 :         mutex_lock(&b->ipc_mutex);
      80              : 
      81              :         /* Clear-by-1 CSR (all bits), corresponding internal states. */
      82            1 :         val = readl(isp->base + ipc->csr_in);
      83            1 :         writel(val, isp->base + ipc->csr_in);
      84              : 
      85              :         /* Set peer CSR bit IPC_PEER_COMP_ACTIONS_RST_PHASE1 */
      86            1 :         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            1 :                 val = readl(isp->base + ipc->csr_in);
     102            1 :                 switch (val) {
     103            0 :                 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            0 :                         writel(ENTRY | EXIT, isp->base + ipc->csr_in);
     113            0 :                         writel(QUERY, isp->base + ipc->csr_out);
     114              :                         break;
     115            0 :                 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            0 :                         writel(ENTRY | QUERY, isp->base + ipc->csr_in);
     125            0 :                         writel(ENTRY, isp->base + ipc->csr_out);
     126              :                         break;
     127            1 :                 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            1 :                         writel(EXIT, isp->base + ipc->csr_in);
     143            1 :                         writel(0, isp->base + ipc->db0_in);
     144            1 :                         writel(csr_in_clr, isp->base + ipc->csr_in);
     145            1 :                         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            1 :                         val = readl(isp->base + ipc->csr_in);
     153            1 :                         if (val & QUERY) {
     154            0 :                                 dev_dbg(&isp->pdev->dev,
     155              :                                         "RST_PHASE2 retry csr_in = %x\n", val);
     156              :                                 break;
     157              :                         }
     158            1 :                         mutex_unlock(&b->ipc_mutex);
     159            1 :                         return 0;
     160            0 :                 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            0 :                         writel(QUERY, isp->base + ipc->csr_in);
     168            0 :                         writel(ENTRY, isp->base + ipc->csr_out);
     169              :                         break;
     170              :                 default:
     171            0 :                         dev_dbg_ratelimited(&isp->pdev->dev,
     172              :                                             "Unexpected CSR 0x%x\n", val);
     173              :                         break;
     174              :                 }
     175            0 :         } while (retries--);
     176              : 
     177            0 :         mutex_unlock(&b->ipc_mutex);
     178            0 :         dev_err(&isp->pdev->dev, "Timed out while waiting for CSE\n");
     179              : 
     180            0 :         return -ETIMEDOUT;
     181              : }
     182              : 
     183              : static void ipu6_buttress_ipc_validity_close(struct ipu6_device *isp,
     184              :                                              struct ipu6_buttress_ipc *ipc)
     185              : {
     186              :         writel(BUTTRESS_IU2CSECSR_IPC_PEER_DEASSERTED_REG_VALID_REQ,
     187            0 :                isp->base + ipc->csr_out);
     188            0 : }
     189              : 
     190              : static int
     191            0 : ipu6_buttress_ipc_validity_open(struct ipu6_device *isp,
     192              :                                 struct ipu6_buttress_ipc *ipc)
     193              : {
     194              :         unsigned int mask = BUTTRESS_IU2CSECSR_IPC_PEER_ACKED_REG_VALID;
     195              :         void __iomem *addr;
     196              :         int ret;
     197              :         u32 val;
     198              : 
     199              :         writel(BUTTRESS_IU2CSECSR_IPC_PEER_ASSERTED_REG_VALID_REQ,
     200            0 :                isp->base + ipc->csr_out);
     201              : 
     202            0 :         addr = isp->base + ipc->csr_in;
     203            0 :         ret = readl_poll_timeout(addr, val, val & mask, 200,
     204              :                                  BUTTRESS_IPC_VALIDITY_TIMEOUT_US);
     205              :         if (ret) {
     206            0 :                 dev_err(&isp->pdev->dev, "CSE validity timeout 0x%x\n", val);
     207              :                 ipu6_buttress_ipc_validity_close(isp, ipc);
     208              :         }
     209              : 
     210            0 :         return ret;
     211              : }
     212              : 
     213              : static void ipu6_buttress_ipc_recv(struct ipu6_device *isp,
     214              :                                    struct ipu6_buttress_ipc *ipc, u32 *ipc_msg)
     215              : {
     216            0 :         if (ipc_msg)
     217            0 :                 *ipc_msg = readl(isp->base + ipc->data0_in);
     218            0 :         writel(0, isp->base + ipc->db0_in);
     219              : }
     220              : 
     221            0 : static int ipu6_buttress_ipc_send_bulk(struct ipu6_device *isp,
     222              :                                        struct ipu6_ipc_buttress_bulk_msg *msgs,
     223              :                                        u32 size)
     224              : {
     225              :         unsigned long tx_timeout_jiffies, rx_timeout_jiffies;
     226              :         unsigned int i, retry = BUTTRESS_IPC_CMD_SEND_RETRY;
     227              :         struct ipu6_buttress *b = &isp->buttress;
     228            0 :         struct ipu6_buttress_ipc *ipc = &b->cse;
     229              :         u32 val;
     230              :         int ret;
     231              :         int tout;
     232              : 
     233            0 :         mutex_lock(&b->ipc_mutex);
     234              : 
     235            0 :         ret = ipu6_buttress_ipc_validity_open(isp, ipc);
     236            0 :         if (ret) {
     237            0 :                 dev_err(&isp->pdev->dev, "IPC validity open failed\n");
     238            0 :                 goto out;
     239              :         }
     240              : 
     241              :         tx_timeout_jiffies = msecs_to_jiffies(BUTTRESS_IPC_TX_TIMEOUT_MS);
     242              :         rx_timeout_jiffies = msecs_to_jiffies(BUTTRESS_IPC_RX_TIMEOUT_MS);
     243              : 
     244            0 :         for (i = 0; i < size; i++) {
     245              :                 reinit_completion(&ipc->send_complete);
     246            0 :                 if (msgs[i].require_resp)
     247              :                         reinit_completion(&ipc->recv_complete);
     248              : 
     249            0 :                 dev_dbg(&isp->pdev->dev, "bulk IPC command: 0x%x\n",
     250              :                         msgs[i].cmd);
     251            0 :                 writel(msgs[i].cmd, isp->base + ipc->data0_out);
     252            0 :                 val = BUTTRESS_IU2CSEDB0_BUSY | msgs[i].cmd_size;
     253            0 :                 writel(val, isp->base + ipc->db0_out);
     254              : 
     255            0 :                 tout = wait_for_completion_timeout(&ipc->send_complete,
     256              :                                                    tx_timeout_jiffies);
     257            0 :                 if (!tout) {
     258            0 :                         dev_err(&isp->pdev->dev, "send IPC response timeout\n");
     259            0 :                         if (!retry--) {
     260              :                                 ret = -ETIMEDOUT;
     261            0 :                                 goto out;
     262              :                         }
     263              : 
     264              :                         /* Try again if CSE is not responding on first try */
     265            0 :                         writel(0, isp->base + ipc->db0_out);
     266            0 :                         i--;
     267            0 :                         continue;
     268              :                 }
     269              : 
     270              :                 retry = BUTTRESS_IPC_CMD_SEND_RETRY;
     271              : 
     272            0 :                 if (!msgs[i].require_resp)
     273            0 :                         continue;
     274              : 
     275            0 :                 tout = wait_for_completion_timeout(&ipc->recv_complete,
     276              :                                                    rx_timeout_jiffies);
     277            0 :                 if (!tout) {
     278            0 :                         dev_err(&isp->pdev->dev, "recv IPC response timeout\n");
     279              :                         ret = -ETIMEDOUT;
     280            0 :                         goto out;
     281              :                 }
     282              : 
     283            0 :                 if (ipc->nack_mask &&
     284            0 :                     (ipc->recv_data & ipc->nack_mask) == ipc->nack) {
     285            0 :                         dev_err(&isp->pdev->dev,
     286              :                                 "IPC NACK for cmd 0x%x\n", msgs[i].cmd);
     287              :                         ret = -EIO;
     288            0 :                         goto out;
     289              :                 }
     290              : 
     291            0 :                 if (ipc->recv_data != msgs[i].expected_resp) {
     292            0 :                         dev_err(&isp->pdev->dev,
     293              :                                 "expected resp: 0x%x, IPC response: 0x%x ",
     294              :                                 msgs[i].expected_resp, ipc->recv_data);
     295              :                         ret = -EIO;
     296            0 :                         goto out;
     297              :                 }
     298              :         }
     299              : 
     300            0 :         dev_dbg(&isp->pdev->dev, "bulk IPC commands done\n");
     301              : 
     302            0 : out:
     303              :         ipu6_buttress_ipc_validity_close(isp, ipc);
     304            0 :         mutex_unlock(&b->ipc_mutex);
     305            0 :         return ret;
     306              : }
     307              : 
     308              : static int
     309              : ipu6_buttress_ipc_send(struct ipu6_device *isp,
     310              :                        u32 ipc_msg, u32 size, bool require_resp,
     311              :                        u32 expected_resp)
     312              : {
     313            0 :         struct ipu6_ipc_buttress_bulk_msg msg = {
     314              :                 .cmd = ipc_msg,
     315              :                 .cmd_size = size,
     316              :                 .require_resp = require_resp,
     317              :                 .expected_resp = expected_resp,
     318              :         };
     319              : 
     320            0 :         return ipu6_buttress_ipc_send_bulk(isp, &msg, 1);
     321              : }
     322              : 
     323           10 : static irqreturn_t ipu6_buttress_call_isr(struct ipu6_bus_device *adev)
     324              : {
     325              :         irqreturn_t ret = IRQ_WAKE_THREAD;
     326              : 
     327           10 :         if (!adev || !adev->auxdrv || !adev->auxdrv_data)
     328              :                 return IRQ_NONE;
     329              : 
     330            5 :         if (adev->auxdrv_data->isr)
     331            5 :                 ret = adev->auxdrv_data->isr(adev);
     332              : 
     333            5 :         if (ret == IRQ_WAKE_THREAD && !adev->auxdrv_data->isr_threaded)
     334              :                 ret = IRQ_NONE;
     335              : 
     336              :         return ret;
     337              : }
     338              : 
     339            5 : irqreturn_t ipu6_buttress_isr(int irq, void *isp_ptr)
     340              : {
     341              :         struct ipu6_device *isp = isp_ptr;
     342            5 :         struct ipu6_bus_device *adev[] = { isp->isys, isp->psys };
     343              :         struct ipu6_buttress *b = &isp->buttress;
     344              :         irqreturn_t ret = IRQ_NONE;
     345              :         u32 disable_irqs = 0;
     346              :         u32 irq_status;
     347              :         u32 i, count = 0;
     348              :         int active;
     349              : 
     350            5 :         active = pm_runtime_get_if_active(&isp->pdev->dev);
     351            5 :         if (!active)
     352              :                 return IRQ_NONE;
     353              : 
     354            5 :         irq_status = readl(isp->base + b->reg_irq_sts);
     355            5 :         if (irq_status == 0 || WARN_ON_ONCE(irq_status == 0xffffffffu)) {
     356            0 :                 if (active > 0)
     357            0 :                         pm_runtime_put_noidle(&isp->pdev->dev);
     358            0 :                 return IRQ_NONE;
     359              :         }
     360              : 
     361              :         do {
     362            5 :                 writel(irq_status, isp->base + BUTTRESS_REG_ISR_CLEAR);
     363              : 
     364           15 :                 for (i = 0; i < ARRAY_SIZE(ipu6_adev_irq_mask); i++) {
     365           10 :                         irqreturn_t r = ipu6_buttress_call_isr(adev[i]);
     366              : 
     367           10 :                         if (!(irq_status & ipu6_adev_irq_mask[i]))
     368            5 :                                 continue;
     369              : 
     370            5 :                         if (r == IRQ_WAKE_THREAD) {
     371              :                                 ret = IRQ_WAKE_THREAD;
     372            0 :                                 disable_irqs |= ipu6_adev_irq_mask[i];
     373            5 :                         } else if (ret == IRQ_NONE && r == IRQ_HANDLED) {
     374              :                                 ret = IRQ_HANDLED;
     375              :                         }
     376              :                 }
     377              : 
     378            5 :                 if ((irq_status & BUTTRESS_EVENT) && ret == IRQ_NONE)
     379              :                         ret = IRQ_HANDLED;
     380              : 
     381            5 :                 if (irq_status & BUTTRESS_ISR_IPC_FROM_CSE_IS_WAITING) {
     382            0 :                         dev_dbg(&isp->pdev->dev,
     383              :                                 "BUTTRESS_ISR_IPC_FROM_CSE_IS_WAITING\n");
     384            0 :                         ipu6_buttress_ipc_recv(isp, &b->cse, &b->cse.recv_data);
     385            0 :                         complete(&b->cse.recv_complete);
     386              :                 }
     387              : 
     388            5 :                 if (irq_status & BUTTRESS_ISR_IPC_EXEC_DONE_BY_CSE) {
     389            0 :                         dev_dbg(&isp->pdev->dev,
     390              :                                 "BUTTRESS_ISR_IPC_EXEC_DONE_BY_CSE\n");
     391            0 :                         complete(&b->cse.send_complete);
     392              :                 }
     393              : 
     394            5 :                 if (irq_status & BUTTRESS_ISR_SAI_VIOLATION &&
     395              :                     ipu6_buttress_get_secure_mode(isp))
     396            0 :                         dev_err(&isp->pdev->dev,
     397              :                                 "BUTTRESS_ISR_SAI_VIOLATION\n");
     398              : 
     399            5 :                 if (irq_status & (BUTTRESS_ISR_IS_FATAL_MEM_ERR |
     400              :                                   BUTTRESS_ISR_PS_FATAL_MEM_ERR))
     401            0 :                         dev_err(&isp->pdev->dev,
     402              :                                 "BUTTRESS_ISR_FATAL_MEM_ERR\n");
     403              : 
     404            5 :                 if (irq_status & BUTTRESS_ISR_UFI_ERROR)
     405            0 :                         dev_err(&isp->pdev->dev, "BUTTRESS_ISR_UFI_ERROR\n");
     406              : 
     407            5 :                 if (++count == BUTTRESS_MAX_CONSECUTIVE_IRQS) {
     408            0 :                         dev_err(&isp->pdev->dev, "too many consecutive IRQs\n");
     409              :                         ret = IRQ_NONE;
     410            0 :                         break;
     411              :                 }
     412              : 
     413            5 :                 irq_status = readl(isp->base + b->reg_irq_sts);
     414            5 :         } while (irq_status);
     415              : 
     416            5 :         if (disable_irqs)
     417            0 :                 writel(BUTTRESS_IRQS & ~disable_irqs,
     418            0 :                        isp->base + BUTTRESS_REG_ISR_ENABLE);
     419              : 
     420            5 :         if (active > 0)
     421            5 :                 pm_runtime_put(&isp->pdev->dev);
     422              : 
     423              :         return ret;
     424              : }
     425              : 
     426            0 : irqreturn_t ipu6_buttress_isr_threaded(int irq, void *isp_ptr)
     427              : {
     428              :         struct ipu6_device *isp = isp_ptr;
     429            0 :         struct ipu6_bus_device *adev[] = { isp->isys, isp->psys };
     430              :         const struct ipu6_auxdrv_data *drv_data = NULL;
     431              :         irqreturn_t ret = IRQ_NONE;
     432              :         unsigned int i;
     433              : 
     434            0 :         for (i = 0; i < ARRAY_SIZE(ipu6_adev_irq_mask) && adev[i]; i++) {
     435            0 :                 drv_data = adev[i]->auxdrv_data;
     436            0 :                 if (!drv_data)
     437            0 :                         continue;
     438              : 
     439            0 :                 if (drv_data->wake_isr_thread &&
     440            0 :                     drv_data->isr_threaded(adev[i]) == IRQ_HANDLED)
     441              :                         ret = IRQ_HANDLED;
     442              :         }
     443              : 
     444            0 :         writel(BUTTRESS_IRQS, isp->base + BUTTRESS_REG_ISR_ENABLE);
     445              : 
     446            0 :         return ret;
     447              : }
     448              : 
     449            8 : int ipu6_buttress_power(struct device *dev,
     450              :                         const struct ipu6_buttress_ctrl *ctrl, bool on)
     451              : {
     452            8 :         struct ipu6_device *isp = to_ipu6_bus_device(dev)->isp;
     453              :         u32 pwr_sts, val;
     454              :         int ret;
     455              : 
     456            8 :         if (!ctrl)
     457              :                 return 0;
     458              : 
     459            8 :         mutex_lock(&isp->buttress.power_mutex);
     460              : 
     461            8 :         if (!on) {
     462              :                 val = 0;
     463            4 :                 pwr_sts = ctrl->pwr_sts_off << ctrl->pwr_sts_shift;
     464              :         } else {
     465            4 :                 val = BUTTRESS_FREQ_CTL_START |
     466            4 :                         FIELD_PREP(BUTTRESS_FREQ_CTL_RATIO_MASK,
     467            4 :                                    ctrl->ratio) |
     468            4 :                         FIELD_PREP(BUTTRESS_FREQ_CTL_QOS_FLOOR_MASK,
     469              :                                    ctrl->qos_floor) |
     470              :                         IPU4_BUTTRESS_FREQ_CTL_ICCMAX_LEVEL;
     471              : 
     472            4 :                 pwr_sts = ctrl->pwr_sts_on << ctrl->pwr_sts_shift;
     473              :         }
     474              : 
     475            8 :         writel(val, isp->base + ctrl->freq_ctl);
     476              : 
     477           16 :         ret = readl_poll_timeout(isp->base + BUTTRESS_REG_PWR_STATE,
     478              :                                  val, (val & ctrl->pwr_sts_mask) == pwr_sts,
     479              :                                  100, BUTTRESS_POWER_TIMEOUT_US);
     480              :         if (ret)
     481            0 :                 dev_err(&isp->pdev->dev,
     482              :                         "Change power status timeout with 0x%x\n", val);
     483              : 
     484            8 :         mutex_unlock(&isp->buttress.power_mutex);
     485              : 
     486            8 :         return ret;
     487              : }
     488              : 
     489            0 : bool ipu6_buttress_get_secure_mode(struct ipu6_device *isp)
     490              : {
     491              :         u32 val;
     492              : 
     493            0 :         val = readl(isp->base + BUTTRESS_REG_SECURITY_CTL);
     494              : 
     495            1 :         return val & BUTTRESS_SECURITY_CTL_FW_SECURE_MODE;
     496              : }
     497              : 
     498            0 : bool ipu6_buttress_auth_done(struct ipu6_device *isp)
     499              : {
     500              :         u32 val;
     501              : 
     502            2 :         if (!isp->secure_mode)
     503              :                 return true;
     504              : 
     505            2 :         val = readl(isp->base + BUTTRESS_REG_SECURITY_CTL);
     506              :         val = FIELD_GET(BUTTRESS_SECURITY_CTL_FW_SETUP_MASK, val);
     507              : 
     508            0 :         return val == BUTTRESS_SECURITY_CTL_AUTH_DONE;
     509              : }
     510              : EXPORT_SYMBOL_NS_GPL(ipu6_buttress_auth_done, INTEL_IPU6);
     511              : 
     512            0 : int ipu6_buttress_reset_authentication(struct ipu6_device *isp)
     513              : {
     514              :         int ret;
     515              :         u32 val;
     516              : 
     517            0 :         if (!isp->secure_mode) {
     518            0 :                 dev_dbg(&isp->pdev->dev, "Skip auth for non-secure mode\n");
     519            0 :                 return 0;
     520              :         }
     521              : 
     522            0 :         writel(BUTTRESS_FW_RESET_CTL_START, isp->base +
     523              :                BUTTRESS_REG_FW_RESET_CTL);
     524              : 
     525            0 :         ret = readl_poll_timeout(isp->base + BUTTRESS_REG_FW_RESET_CTL, val,
     526              :                                  val & BUTTRESS_FW_RESET_CTL_DONE, 500,
     527              :                                  BUTTRESS_CSE_FWRESET_TIMEOUT_US);
     528              :         if (ret) {
     529            0 :                 dev_err(&isp->pdev->dev,
     530              :                         "Time out while resetting authentication state\n");
     531            0 :                 return ret;
     532              :         }
     533              : 
     534            0 :         dev_dbg(&isp->pdev->dev, "FW reset for authentication done\n");
     535            0 :         writel(0, isp->base + BUTTRESS_REG_FW_RESET_CTL);
     536              :         /* leave some time for HW restore */
     537              :         usleep_range(800, 1000);
     538              : 
     539            0 :         return 0;
     540              : }
     541              : 
     542            1 : int ipu6_buttress_map_fw_image(struct ipu6_bus_device *sys,
     543              :                                const struct firmware *fw, struct sg_table *sgt)
     544              : {
     545            1 :         bool is_vmalloc = is_vmalloc_addr(fw->data);
     546            1 :         struct pci_dev *pdev = sys->isp->pdev;
     547              :         struct page **pages;
     548              :         const void *addr;
     549              :         unsigned long n_pages;
     550              :         unsigned int i;
     551              :         int ret;
     552              : 
     553            1 :         if (!is_vmalloc && !virt_addr_valid(fw->data))
     554              :                 return -EDOM;
     555              : 
     556            1 :         n_pages = PFN_UP(fw->size);
     557              : 
     558            1 :         pages = kmalloc_array(n_pages, sizeof(*pages), GFP_KERNEL);
     559            1 :         if (!pages)
     560              :                 return -ENOMEM;
     561              : 
     562            1 :         addr = fw->data;
     563            2 :         for (i = 0; i < n_pages; i++) {
     564              :                 struct page *p = is_vmalloc ?
     565            1 :                         vmalloc_to_page(addr) : virt_to_page(addr);
     566              : 
     567            1 :                 if (!p) {
     568              :                         ret = -ENOMEM;
     569            0 :                         goto out;
     570              :                 }
     571            1 :                 pages[i] = p;
     572            1 :                 addr += PAGE_SIZE;
     573              :         }
     574              : 
     575            1 :         ret = sg_alloc_table_from_pages(sgt, pages, n_pages, 0, fw->size,
     576              :                                         GFP_KERNEL);
     577            1 :         if (ret) {
     578              :                 ret = -ENOMEM;
     579            0 :                 goto out;
     580              :         }
     581              : 
     582            1 :         ret = dma_map_sgtable(&pdev->dev, sgt, DMA_TO_DEVICE, 0);
     583            1 :         if (ret) {
     584            0 :                 sg_free_table(sgt);
     585            0 :                 goto out;
     586              :         }
     587              : 
     588            1 :         ret = ipu6_dma_map_sgtable(sys, sgt, DMA_TO_DEVICE, 0);
     589            1 :         if (ret) {
     590              :                 dma_unmap_sgtable(&pdev->dev, sgt, DMA_TO_DEVICE, 0);
     591            0 :                 sg_free_table(sgt);
     592            0 :                 goto out;
     593              :         }
     594              : 
     595            1 :         ipu6_dma_sync_sgtable(sys, sgt);
     596              : 
     597            1 : out:
     598            1 :         kfree(pages);
     599              : 
     600            1 :         return ret;
     601              : }
     602              : EXPORT_SYMBOL_NS_GPL(ipu6_buttress_map_fw_image, INTEL_IPU6);
     603              : 
     604            0 : void ipu6_buttress_unmap_fw_image(struct ipu6_bus_device *sys,
     605              :                                   struct sg_table *sgt)
     606              : {
     607            0 :         struct pci_dev *pdev = sys->isp->pdev;
     608              : 
     609            0 :         ipu6_dma_unmap_sgtable(sys, sgt, DMA_TO_DEVICE, 0);
     610            0 :         dma_unmap_sgtable(&pdev->dev, sgt, DMA_TO_DEVICE, 0);
     611            0 :         sg_free_table(sgt);
     612            0 : }
     613              : EXPORT_SYMBOL_NS_GPL(ipu6_buttress_unmap_fw_image, INTEL_IPU6);
     614              : 
     615            2 : int ipu6_buttress_authenticate(struct ipu6_device *isp)
     616              : {
     617              :         struct ipu6_buttress *b = &isp->buttress;
     618              :         struct ipu6_psys_pdata *psys_pdata;
     619              :         u32 data, mask, done, fail;
     620              :         int ret;
     621            2 :         u32 bootloader_status_offset = is_ipu4(isp->hw_ver) ?
     622            2 :                 IPU4_BOOTLOADER_STATUS_OFFSET : IPU6_BOOTLOADER_STATUS_OFFSET;
     623              : 
     624            2 :         if (!isp->secure_mode) {
     625            0 :                 dev_dbg(&isp->pdev->dev, "Skip auth for non-secure mode\n");
     626            0 :                 return 0;
     627              :         }
     628              : 
     629            2 :         psys_pdata = isp->psys->pdata;
     630              : 
     631            2 :         mutex_lock(&b->auth_mutex);
     632              : 
     633            2 :         ret = pm_runtime_resume_and_get(&isp->pdev->dev);
     634            2 :         if (ret < 0)
     635            0 :                 goto out_unlock;
     636              : 
     637            2 :         if (ipu6_buttress_auth_done(isp)) {
     638              :                 ret = 0;
     639            2 :                 goto out_pm_put;
     640              :         }
     641              : 
     642              :         /*
     643              :          * Write address of FIT table to FW_SOURCE register
     644              :          * Let's use fw address. I.e. not using FIT table yet
     645              :          */
     646            0 :         data = lower_32_bits(isp->psys->pkg_dir_dma_addr);
     647            0 :         writel(data, isp->base + BUTTRESS_REG_FW_SOURCE_BASE_LO);
     648              : 
     649            0 :         data = upper_32_bits(isp->psys->pkg_dir_dma_addr);
     650            0 :         writel(data, isp->base + BUTTRESS_REG_FW_SOURCE_BASE_HI);
     651              : 
     652              :         /*
     653              :          * Write boot_load into IU2CSEDATA0
     654              :          * Write sizeof(boot_load) | 0x2 << CLIENT_ID to
     655              :          * IU2CSEDB.IU2CSECMD and set IU2CSEDB.IU2CSEBUSY as
     656              :          */
     657            0 :         dev_info(&isp->pdev->dev, "Sending BOOT_LOAD to CSE\n");
     658              : 
     659              :         ret = ipu6_buttress_ipc_send(isp,
     660              :                                      BUTTRESS_IU2CSEDATA0_IPC_BOOT_LOAD,
     661              :                                      1, true,
     662              :                                      BUTTRESS_CSE2IUDATA0_IPC_BOOT_LOAD_DONE);
     663            0 :         if (ret) {
     664            0 :                 dev_err(&isp->pdev->dev, "CSE boot_load failed\n");
     665            0 :                 goto out_pm_put;
     666              :         }
     667              : 
     668              :         mask = BUTTRESS_SECURITY_CTL_FW_SETUP_MASK;
     669              :         done = BUTTRESS_SECURITY_CTL_FW_SETUP_DONE;
     670              :         fail = BUTTRESS_SECURITY_CTL_AUTH_FAILED;
     671            0 :         ret = readl_poll_timeout(isp->base + BUTTRESS_REG_SECURITY_CTL, data,
     672              :                                  ((data & mask) == done ||
     673              :                                   (data & mask) == fail), 500,
     674              :                                  BUTTRESS_CSE_BOOTLOAD_TIMEOUT_US);
     675              :         if (ret) {
     676            0 :                 dev_err(&isp->pdev->dev, "CSE boot_load timeout\n");
     677            0 :                 goto out_pm_put;
     678              :         }
     679              : 
     680            0 :         if ((data & mask) == fail) {
     681            0 :                 dev_err(&isp->pdev->dev, "CSE auth failed\n");
     682              :                 ret = -EINVAL;
     683            0 :                 goto out_pm_put;
     684              :         }
     685              : 
     686            0 :         ret = readl_poll_timeout(psys_pdata->base + bootloader_status_offset,
     687              :                                  data, data == BOOTLOADER_MAGIC_KEY, 500,
     688              :                                  BUTTRESS_CSE_BOOTLOAD_TIMEOUT_US);
     689              :         if (ret) {
     690            0 :                 dev_err(&isp->pdev->dev, "Unexpected magic number 0x%x\n",
     691              :                         data);
     692            0 :                 goto out_pm_put;
     693              :         }
     694              : 
     695              :         /*
     696              :          * Write authenticate_run into IU2CSEDATA0
     697              :          * Write sizeof(boot_load) | 0x2 << CLIENT_ID to
     698              :          * IU2CSEDB.IU2CSECMD and set IU2CSEDB.IU2CSEBUSY as
     699              :          */
     700            0 :         dev_info(&isp->pdev->dev, "Sending AUTHENTICATE_RUN to CSE\n");
     701              :         ret = ipu6_buttress_ipc_send(isp,
     702              :                                      BUTTRESS_IU2CSEDATA0_IPC_AUTH_RUN,
     703              :                                      1, true,
     704              :                                      BUTTRESS_CSE2IUDATA0_IPC_AUTH_RUN_DONE);
     705            0 :         if (ret) {
     706            0 :                 dev_err(&isp->pdev->dev, "CSE authenticate_run failed\n");
     707            0 :                 goto out_pm_put;
     708              :         }
     709              : 
     710              :         done = BUTTRESS_SECURITY_CTL_AUTH_DONE;
     711            0 :         ret = readl_poll_timeout(isp->base + BUTTRESS_REG_SECURITY_CTL, data,
     712              :                                  ((data & mask) == done ||
     713              :                                   (data & mask) == fail), 500,
     714              :                                  BUTTRESS_CSE_AUTHENTICATE_TIMEOUT_US);
     715              :         if (ret) {
     716            0 :                 dev_err(&isp->pdev->dev, "CSE authenticate timeout\n");
     717            0 :                 goto out_pm_put;
     718              :         }
     719              : 
     720            0 :         if ((data & mask) == fail) {
     721            0 :                 dev_err(&isp->pdev->dev, "CSE boot_load failed\n");
     722              :                 ret = -EINVAL;
     723            0 :                 goto out_pm_put;
     724              :         }
     725              : 
     726            0 :         dev_info(&isp->pdev->dev, "CSE authenticate_run done\n");
     727              : 
     728            2 : out_pm_put:
     729            2 :         pm_runtime_put(&isp->pdev->dev);
     730            2 : out_unlock:
     731            2 :         mutex_unlock(&b->auth_mutex);
     732              : 
     733            2 :         return ret;
     734              : }
     735              : EXPORT_SYMBOL_NS_GPL(ipu6_buttress_authenticate, INTEL_IPU6);
     736              : 
     737            1 : static int ipu6_buttress_send_tsc_request(struct ipu6_device *isp)
     738              : {
     739              :         u32 val, mask, done;
     740              :         int ret;
     741              : 
     742              :         mask = IPU4_BUTTRESS_PWR_STATE_HH_STATUS_MASK;
     743              : 
     744              :         writel(BUTTRESS_FABRIC_CMD_START_TSC_SYNC,
     745            1 :                isp->base + BUTTRESS_REG_FABRIC_CMD);
     746              : 
     747            1 :         val = readl(isp->base + BUTTRESS_REG_PWR_STATE);
     748              :         val = FIELD_GET(mask, val);
     749            1 :         if (val == BUTTRESS_PWR_STATE_HH_STATE_ERR) {
     750            0 :                 dev_err(&isp->pdev->dev, "Start tsc sync failed\n");
     751            0 :                 return -EINVAL;
     752              :         }
     753              : 
     754              :         done = BUTTRESS_PWR_STATE_HH_STATE_DONE;
     755            2 :         ret = readl_poll_timeout(isp->base + BUTTRESS_REG_PWR_STATE, val,
     756              :                                  FIELD_GET(mask, val) == done, 500,
     757              :                                  BUTTRESS_TSC_SYNC_TIMEOUT_US);
     758              :         if (ret)
     759            0 :                 dev_err(&isp->pdev->dev, "Start tsc sync timeout\n");
     760              : 
     761              :         return ret;
     762              : }
     763              : 
     764            1 : int ipu6_buttress_start_tsc_sync(struct ipu6_device *isp)
     765              : {
     766              :         unsigned int i;
     767              : 
     768            1 :         for (i = 0; i < BUTTRESS_TSC_SYNC_RESET_TRIAL_MAX; i++) {
     769              :                 u32 val;
     770              :                 int ret;
     771              : 
     772            1 :                 ret = ipu6_buttress_send_tsc_request(isp);
     773            1 :                 if (ret != -ETIMEDOUT)
     774            1 :                         return ret;
     775              : 
     776            0 :                 val = readl(isp->base + BUTTRESS_REG_TSW_CTL);
     777            0 :                 val = val | BUTTRESS_TSW_CTL_SOFT_RESET;
     778            0 :                 writel(val, isp->base + BUTTRESS_REG_TSW_CTL);
     779              :                 val = val & ~BUTTRESS_TSW_CTL_SOFT_RESET;
     780            0 :                 writel(val, isp->base + BUTTRESS_REG_TSW_CTL);
     781              :         }
     782              : 
     783            0 :         dev_err(&isp->pdev->dev, "TSC sync failed (timeout)\n");
     784              : 
     785            0 :         return -ETIMEDOUT;
     786              : }
     787              : EXPORT_SYMBOL_NS_GPL(ipu6_buttress_start_tsc_sync, INTEL_IPU6);
     788              : 
     789            2 : void ipu6_buttress_tsc_read(struct ipu6_device *isp, u64 *val)
     790              : {
     791              :         u32 tsc_hi_1, tsc_hi_2, tsc_lo;
     792              :         unsigned long flags;
     793              : 
     794              :         local_irq_save(flags);
     795            2 :         tsc_hi_1 = readl(isp->base + BUTTRESS_REG_TSC_HI);
     796            2 :         tsc_lo = readl(isp->base + BUTTRESS_REG_TSC_LO);
     797            2 :         tsc_hi_2 = readl(isp->base + BUTTRESS_REG_TSC_HI);
     798            2 :         if (tsc_hi_1 == tsc_hi_2) {
     799            2 :                 *val = (u64)tsc_hi_1 << 32 | tsc_lo;
     800              :         } else {
     801              :                 /* Check if TSC has rolled over */
     802            0 :                 if (tsc_lo & BIT(31))
     803            0 :                         *val = (u64)tsc_hi_1 << 32 | tsc_lo;
     804              :                 else
     805            0 :                         *val = (u64)tsc_hi_2 << 32 | tsc_lo;
     806              :         }
     807              :         local_irq_restore(flags);
     808            2 : }
     809              : EXPORT_SYMBOL_NS_GPL(ipu6_buttress_tsc_read, INTEL_IPU6);
     810              : 
     811            2 : u64 ipu6_buttress_tsc_ticks_to_ns(u64 ticks, const struct ipu6_device *isp)
     812              : {
     813            2 :         u64 ns = ticks * 10000;
     814              : 
     815              :         /*
     816              :          * converting TSC tick count to ns is calculated by:
     817              :          * Example (TSC clock frequency is 19.2MHz):
     818              :          * ns = ticks * 1000 000 000 / 19.2Mhz
     819              :          *    = ticks * 1000 000 000 / 19200000Hz
     820              :          *    = ticks * 10000 / 192 ns
     821              :          */
     822            2 :         return div_u64(ns, IPU4_BUTTRESS_TSC_CLOCK_FREQUENCY);
     823              : }
     824              : EXPORT_SYMBOL_NS_GPL(ipu6_buttress_tsc_ticks_to_ns, INTEL_IPU6);
     825              : 
     826            3 : void ipu6_buttress_restore(struct ipu6_device *isp)
     827              : {
     828              :         struct ipu6_buttress *b = &isp->buttress;
     829              : 
     830            3 :         writel(BUTTRESS_IRQS, isp->base + BUTTRESS_REG_ISR_CLEAR);
     831            3 :         writel(BUTTRESS_IRQS, isp->base + BUTTRESS_REG_ISR_ENABLE);
     832            3 :         writel(b->wdt_cached_value, isp->base + BUTTRESS_REG_WDT);
     833            3 : }
     834              : 
     835            1 : int ipu6_buttress_init(struct ipu6_device *isp)
     836              : {
     837              :         int ret, ipc_reset_retry = BUTTRESS_CSE_IPC_RESET_RETRY;
     838              :         struct ipu6_buttress *b = &isp->buttress;
     839              :         u32 val;
     840              : 
     841            1 :         mutex_init(&b->power_mutex);
     842            1 :         mutex_init(&b->auth_mutex);
     843            1 :         mutex_init(&b->cons_mutex);
     844            1 :         mutex_init(&b->ipc_mutex);
     845              :         init_completion(&b->cse.send_complete);
     846              :         init_completion(&b->cse.recv_complete);
     847              : 
     848            1 :         b->cse.nack = BUTTRESS_CSE2IUDATA0_IPC_NACK;
     849            1 :         b->cse.nack_mask = BUTTRESS_CSE2IUDATA0_IPC_NACK_MASK;
     850            1 :         b->cse.csr_in = BUTTRESS_REG_CSE2IUCSR;
     851            1 :         b->cse.csr_out = BUTTRESS_REG_IU2CSECSR;
     852            1 :         b->cse.db0_in = BUTTRESS_REG_CSE2IUDB0;
     853            1 :         b->cse.db0_out = BUTTRESS_REG_IU2CSEDB0;
     854            1 :         b->cse.data0_in = BUTTRESS_REG_CSE2IUDATA0;
     855            1 :         b->cse.data0_out = BUTTRESS_REG_IU2CSEDATA0;
     856              : 
     857              : 
     858            1 :         isp->secure_mode = ipu6_buttress_get_secure_mode(isp);
     859            1 :         dev_dbg(&isp->pdev->dev, "IPU6 in %s mode touch 0x%x mask 0x%x\n",
     860              :                 isp->secure_mode ? "secure" : "non-secure",
     861              :                 readl(isp->base + BUTTRESS_REG_SECURITY_TOUCH),
     862              :                 readl(isp->base + BUTTRESS_REG_CAMERA_MASK));
     863              : 
     864            1 :         b->wdt_cached_value = readl(isp->base + BUTTRESS_REG_WDT);
     865            1 :         writel(BUTTRESS_IRQS, isp->base + BUTTRESS_REG_ISR_CLEAR);
     866            1 :         writel(BUTTRESS_IRQS, isp->base + BUTTRESS_REG_ISR_ENABLE);
     867              : 
     868              :         /* get ref_clk frequency by reading the indication in btrs control */
     869            1 :         val = readl(isp->base + BUTTRESS_REG_BTRS_CTRL);
     870            1 :         val = FIELD_GET(BUTTRESS_REG_BTRS_CTRL_REF_CLK_IND, val);
     871              : 
     872            1 :         switch (val) {
     873            1 :         case 0x0:
     874            1 :                 b->ref_clk = 240;
     875            1 :                 break;
     876            0 :         case 0x1:
     877            0 :                 b->ref_clk = 192;
     878            0 :                 break;
     879            0 :         case 0x2:
     880            0 :                 b->ref_clk = 384;
     881            0 :                 break;
     882            0 :         default:
     883            0 :                 dev_warn(&isp->pdev->dev,
     884              :                          "Unsupported ref clock, use 19.2Mhz by default.\n");
     885            0 :                 b->ref_clk = 192;
     886            0 :                 break;
     887              :         }
     888              : 
     889              :         /* Retry couple of times in case of CSE initialization is delayed */
     890              :         do {
     891            1 :                 ret = ipu6_buttress_ipc_reset(isp, &b->cse);
     892            1 :                 if (ret) {
     893            0 :                         dev_warn(&isp->pdev->dev,
     894              :                                  "IPC reset protocol failed, retrying\n");
     895              :                 } else {
     896            1 :                         dev_dbg(&isp->pdev->dev, "IPC reset done\n");
     897            1 :                         return 0;
     898              :                 }
     899            0 :         } while (ipc_reset_retry--);
     900              : 
     901            0 :         dev_err(&isp->pdev->dev, "IPC reset protocol failed\n");
     902              : 
     903              :         mutex_destroy(&b->power_mutex);
     904              :         mutex_destroy(&b->auth_mutex);
     905              :         mutex_destroy(&b->cons_mutex);
     906              :         mutex_destroy(&b->ipc_mutex);
     907              : 
     908            0 :         return ret;
     909              : }
     910              : 
     911            0 : void ipu6_buttress_exit(struct ipu6_device *isp)
     912              : {
     913              :         struct ipu6_buttress *b = &isp->buttress;
     914              : 
     915            0 :         writel(0, isp->base + BUTTRESS_REG_ISR_ENABLE);
     916              : 
     917              :         mutex_destroy(&b->power_mutex);
     918              :         mutex_destroy(&b->auth_mutex);
     919              :         mutex_destroy(&b->cons_mutex);
     920              :         mutex_destroy(&b->ipc_mutex);
     921            0 : }
        

Generated by: LCOV version 2.0-1