0001
0002
0003
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
0016
0017
0018
0019
0020 #define MMIO_CHIP_INFO_SIZE 60
0021
0022
0023 #define MMIO_OFFSET_EXECUTION_STAGE 0x00
0024
0025
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
0047
0048
0049 #define IPC_MMIO_EXEC_STAGE_TIMEOUT 50
0050
0051
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
0099
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
0117 ipc_mmio->chip_info_version =
0118 ioread8(ipc_mmio->base + ipc_mmio->offset.chip_info);
0119
0120
0121
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
0191
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
0216
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 }