Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 /*
0003  * Copyright (C) 2020-21 Intel Corporation.
0004  */
0005 
0006 #include <linux/delay.h>
0007 #include <linux/device.h>
0008 #include <linux/io.h>
0009 #include <linux/io-64-nonatomic-lo-hi.h>
0010 #include <linux/slab.h>
0011 
0012 #include "iosm_ipc_mmio.h"
0013 #include "iosm_ipc_mux.h"
0014 
0015 /* Definition of MMIO offsets
0016  * note that MMIO_CI offsets are relative to end of chip info structure
0017  */
0018 
0019 /* MMIO chip info size in bytes */
0020 #define MMIO_CHIP_INFO_SIZE 60
0021 
0022 /* CP execution stage */
0023 #define MMIO_OFFSET_EXECUTION_STAGE 0x00
0024 
0025 /* Boot ROM Chip Info struct */
0026 #define MMIO_OFFSET_CHIP_INFO 0x04
0027 
0028 #define MMIO_OFFSET_ROM_EXIT_CODE 0x40
0029 
0030 #define MMIO_OFFSET_PSI_ADDRESS 0x54
0031 
0032 #define MMIO_OFFSET_PSI_SIZE 0x5C
0033 
0034 #define MMIO_OFFSET_IPC_STATUS 0x60
0035 
0036 #define MMIO_OFFSET_CONTEXT_INFO 0x64
0037 
0038 #define MMIO_OFFSET_BASE_ADDR 0x6C
0039 
0040 #define MMIO_OFFSET_END_ADDR 0x74
0041 
0042 #define MMIO_OFFSET_CP_VERSION 0xF0
0043 
0044 #define MMIO_OFFSET_CP_CAPABILITIES 0xF4
0045 
0046 /* Timeout in 50 msec to wait for the modem boot code to write a valid
0047  * execution stage into mmio area
0048  */
0049 #define IPC_MMIO_EXEC_STAGE_TIMEOUT 50
0050 
0051 /* check if exec stage has one of the valid values */
0052 static bool ipc_mmio_is_valid_exec_stage(enum ipc_mem_exec_stage stage)
0053 {
0054     switch (stage) {
0055     case IPC_MEM_EXEC_STAGE_BOOT:
0056     case IPC_MEM_EXEC_STAGE_PSI:
0057     case IPC_MEM_EXEC_STAGE_EBL:
0058     case IPC_MEM_EXEC_STAGE_RUN:
0059     case IPC_MEM_EXEC_STAGE_CRASH:
0060     case IPC_MEM_EXEC_STAGE_CD_READY:
0061         return true;
0062     default:
0063         return false;
0064     }
0065 }
0066 
0067 void ipc_mmio_update_cp_capability(struct iosm_mmio *ipc_mmio)
0068 {
0069     u32 cp_cap;
0070     unsigned int ver;
0071 
0072     ver = ipc_mmio_get_cp_version(ipc_mmio);
0073     cp_cap = ioread32(ipc_mmio->base + ipc_mmio->offset.cp_capability);
0074 
0075     ipc_mmio->mux_protocol = ((ver >= IOSM_CP_VERSION) && (cp_cap &
0076                  (UL_AGGR | DL_AGGR))) ? MUX_AGGREGATION
0077                  : MUX_LITE;
0078 
0079     ipc_mmio->has_ul_flow_credit =
0080         (ver >= IOSM_CP_VERSION) && (cp_cap & UL_FLOW_CREDIT);
0081 }
0082 
0083 struct iosm_mmio *ipc_mmio_init(void __iomem *mmio, struct device *dev)
0084 {
0085     struct iosm_mmio *ipc_mmio = kzalloc(sizeof(*ipc_mmio), GFP_KERNEL);
0086     int retries = IPC_MMIO_EXEC_STAGE_TIMEOUT;
0087     enum ipc_mem_exec_stage stage;
0088 
0089     if (!ipc_mmio)
0090         return NULL;
0091 
0092     ipc_mmio->dev = dev;
0093 
0094     ipc_mmio->base = mmio;
0095 
0096     ipc_mmio->offset.exec_stage = MMIO_OFFSET_EXECUTION_STAGE;
0097 
0098     /* Check for a valid execution stage to make sure that the boot code
0099      * has correctly initialized the MMIO area.
0100      */
0101     do {
0102         stage = ipc_mmio_get_exec_stage(ipc_mmio);
0103         if (ipc_mmio_is_valid_exec_stage(stage))
0104             break;
0105 
0106         msleep(20);
0107     } while (retries-- > 0);
0108 
0109     if (!retries) {
0110         dev_err(ipc_mmio->dev, "invalid exec stage %X", stage);
0111         goto init_fail;
0112     }
0113 
0114     ipc_mmio->offset.chip_info = MMIO_OFFSET_CHIP_INFO;
0115 
0116     /* read chip info size and version from chip info structure */
0117     ipc_mmio->chip_info_version =
0118         ioread8(ipc_mmio->base + ipc_mmio->offset.chip_info);
0119 
0120     /* Increment of 2 is needed as the size value in the chip info
0121      * excludes the version and size field, which are always present
0122      */
0123     ipc_mmio->chip_info_size =
0124         ioread8(ipc_mmio->base + ipc_mmio->offset.chip_info + 1) + 2;
0125 
0126     if (ipc_mmio->chip_info_size != MMIO_CHIP_INFO_SIZE) {
0127         dev_err(ipc_mmio->dev, "Unexpected Chip Info");
0128         goto init_fail;
0129     }
0130 
0131     ipc_mmio->offset.rom_exit_code = MMIO_OFFSET_ROM_EXIT_CODE;
0132 
0133     ipc_mmio->offset.psi_address = MMIO_OFFSET_PSI_ADDRESS;
0134     ipc_mmio->offset.psi_size = MMIO_OFFSET_PSI_SIZE;
0135     ipc_mmio->offset.ipc_status = MMIO_OFFSET_IPC_STATUS;
0136     ipc_mmio->offset.context_info = MMIO_OFFSET_CONTEXT_INFO;
0137     ipc_mmio->offset.ap_win_base = MMIO_OFFSET_BASE_ADDR;
0138     ipc_mmio->offset.ap_win_end = MMIO_OFFSET_END_ADDR;
0139 
0140     ipc_mmio->offset.cp_version = MMIO_OFFSET_CP_VERSION;
0141     ipc_mmio->offset.cp_capability = MMIO_OFFSET_CP_CAPABILITIES;
0142 
0143     return ipc_mmio;
0144 
0145 init_fail:
0146     kfree(ipc_mmio);
0147     return NULL;
0148 }
0149 
0150 enum ipc_mem_exec_stage ipc_mmio_get_exec_stage(struct iosm_mmio *ipc_mmio)
0151 {
0152     if (!ipc_mmio)
0153         return IPC_MEM_EXEC_STAGE_INVALID;
0154 
0155     return (enum ipc_mem_exec_stage)ioread32(ipc_mmio->base +
0156                          ipc_mmio->offset.exec_stage);
0157 }
0158 
0159 void ipc_mmio_copy_chip_info(struct iosm_mmio *ipc_mmio, void *dest,
0160                  size_t size)
0161 {
0162     if (ipc_mmio && dest)
0163         memcpy_fromio(dest, ipc_mmio->base + ipc_mmio->offset.chip_info,
0164                   size);
0165 }
0166 
0167 enum ipc_mem_device_ipc_state ipc_mmio_get_ipc_state(struct iosm_mmio *ipc_mmio)
0168 {
0169     if (!ipc_mmio)
0170         return IPC_MEM_DEVICE_IPC_INVALID;
0171 
0172     return (enum ipc_mem_device_ipc_state)ioread32(ipc_mmio->base +
0173                                ipc_mmio->offset.ipc_status);
0174 }
0175 
0176 enum rom_exit_code ipc_mmio_get_rom_exit_code(struct iosm_mmio *ipc_mmio)
0177 {
0178     if (!ipc_mmio)
0179         return IMEM_ROM_EXIT_FAIL;
0180 
0181     return (enum rom_exit_code)ioread32(ipc_mmio->base +
0182                         ipc_mmio->offset.rom_exit_code);
0183 }
0184 
0185 void ipc_mmio_config(struct iosm_mmio *ipc_mmio)
0186 {
0187     if (!ipc_mmio)
0188         return;
0189 
0190     /* AP memory window (full window is open and active so that modem checks
0191      * each AP address) 0 means don't check on modem side.
0192      */
0193     iowrite64(0, ipc_mmio->base + ipc_mmio->offset.ap_win_base);
0194     iowrite64(0, ipc_mmio->base + ipc_mmio->offset.ap_win_end);
0195 
0196     iowrite64(ipc_mmio->context_info_addr,
0197           ipc_mmio->base + ipc_mmio->offset.context_info);
0198 }
0199 
0200 void ipc_mmio_set_psi_addr_and_size(struct iosm_mmio *ipc_mmio, dma_addr_t addr,
0201                     u32 size)
0202 {
0203     if (!ipc_mmio)
0204         return;
0205 
0206     iowrite64(addr, ipc_mmio->base + ipc_mmio->offset.psi_address);
0207     iowrite32(size, ipc_mmio->base + ipc_mmio->offset.psi_size);
0208 }
0209 
0210 void ipc_mmio_set_contex_info_addr(struct iosm_mmio *ipc_mmio, phys_addr_t addr)
0211 {
0212     if (!ipc_mmio)
0213         return;
0214 
0215     /* store context_info address. This will be stored in the mmio area
0216      * during IPC_MEM_DEVICE_IPC_INIT state via ipc_mmio_config()
0217      */
0218     ipc_mmio->context_info_addr = addr;
0219 }
0220 
0221 int ipc_mmio_get_cp_version(struct iosm_mmio *ipc_mmio)
0222 {
0223     if (ipc_mmio)
0224         return ioread32(ipc_mmio->base + ipc_mmio->offset.cp_version);
0225 
0226     return -EFAULT;
0227 }