Elyes HAOUAS | 231b251 | 2020-05-07 07:29:44 +0200 | [diff] [blame] | 1 | /* SPDX-License-Identifier: GPL-2.0-only */ |
T Michael Turney | cea0d9c | 2019-11-27 19:28:23 -0800 | [diff] [blame] | 2 | |
Elyes HAOUAS | 32661c7 | 2020-06-16 06:51:58 +0200 | [diff] [blame] | 3 | #include <cbfs.h> |
| 4 | #include <string.h> |
Ravi Kumar Bokka | 34960d4 | 2021-07-27 21:02:54 +0530 | [diff] [blame] | 5 | #include <soc/qupv3_config_common.h> |
| 6 | #include <console/console.h> |
| 7 | #include <soc/qup_se_handlers_common.h> |
| 8 | #include <soc/qcom_qup_se.h> |
| 9 | #include <soc/addressmap.h> |
T Michael Turney | cea0d9c | 2019-11-27 19:28:23 -0800 | [diff] [blame] | 10 | |
| 11 | static struct elf_se_hdr *fw_list[SE_PROTOCOL_MAX]; |
Sudheer Kumar Amrabadi | 0d30a86 | 2023-01-16 08:48:15 +0530 | [diff] [blame^] | 12 | static struct gsi_fw_hdr *gsi_hdr; |
T Michael Turney | cea0d9c | 2019-11-27 19:28:23 -0800 | [diff] [blame] | 13 | |
| 14 | void qupv3_se_fw_load_and_init(unsigned int bus, unsigned int protocol, |
| 15 | unsigned int mode) |
| 16 | { |
| 17 | uint32_t i; |
| 18 | uint32_t reg_value; |
| 19 | const uint8_t *cfg_idx_arr; |
| 20 | const uint32_t *cfg_val_arr; |
| 21 | const uint32_t *fw_val_arr; |
| 22 | struct elf_se_hdr *hdr; |
| 23 | struct qup_regs *regs = qup[bus].regs; |
| 24 | static const char * const filename[] = { |
| 25 | [SE_PROTOCOL_SPI] = "fallback/spi_fw", |
| 26 | [SE_PROTOCOL_UART] = "fallback/uart_fw", |
| 27 | [SE_PROTOCOL_I2C] = "fallback/i2c_fw", |
| 28 | }; |
| 29 | |
| 30 | if (protocol >= SE_PROTOCOL_MAX || !filename[protocol]) |
| 31 | die("*ERROR* * INVALID PROTOCOL ***\n"); |
| 32 | |
| 33 | if (!fw_list[protocol]) { |
Julius Werner | 834b3ec | 2020-03-04 16:52:08 -0800 | [diff] [blame] | 34 | fw_list[protocol] = cbfs_map(filename[protocol], NULL); |
T Michael Turney | cea0d9c | 2019-11-27 19:28:23 -0800 | [diff] [blame] | 35 | if (!fw_list[protocol]) |
Ravi Kumar Bokka | 34960d4 | 2021-07-27 21:02:54 +0530 | [diff] [blame] | 36 | die("*ERROR* * cbfs_map failed ***\n"); |
T Michael Turney | cea0d9c | 2019-11-27 19:28:23 -0800 | [diff] [blame] | 37 | } |
| 38 | |
| 39 | hdr = fw_list[protocol]; |
| 40 | assert(hdr->magic == SEFW_MAGIC_HEADER) |
| 41 | |
| 42 | cfg_idx_arr = (const uint8_t *)hdr + hdr->cfg_idx_offset; |
| 43 | cfg_val_arr = (const uint32_t *)((uint8_t *)hdr + hdr->cfg_val_offset); |
| 44 | fw_val_arr = (const uint32_t *)((uint8_t *)hdr + hdr->fw_offset); |
| 45 | |
| 46 | /* Unlock SE for FW loading */ |
| 47 | write32(®s->se_geni_fw_multilock_protns, 0x0); |
| 48 | write32(®s->se_geni_fw_multilock_msa, 0x0); |
| 49 | |
| 50 | /* First, ensure GENI FW is disabled */ |
| 51 | write32(®s->geni_output_ctrl, 0x0); |
| 52 | clrbits_le32(®s->geni_dfs_if_cfg, GENI_DFS_IF_CFG_DFS_IF_EN_BMSK); |
| 53 | setbits_le32(®s->geni_cgc_ctrl, GENI_CGC_CTRL_PROG_RAM_SCLK_OFF_BMSK |
| 54 | | GENI_CGC_CTRL_PROG_RAM_HCLK_OFF_BMSK); |
| 55 | write32(®s->se_geni_clk_ctrl, 0x0); |
| 56 | clrbits_le32(®s->geni_cgc_ctrl, GENI_CGC_CTRL_PROG_RAM_SCLK_OFF_BMSK |
| 57 | | GENI_CGC_CTRL_PROG_RAM_HCLK_OFF_BMSK); |
| 58 | |
Ravi Kumar Bokka | 34960d4 | 2021-07-27 21:02:54 +0530 | [diff] [blame] | 59 | |
T Michael Turney | cea0d9c | 2019-11-27 19:28:23 -0800 | [diff] [blame] | 60 | /* HPG section 3.1.7.1 */ |
Roja Rani Yarubandi | dcf80ab0 | 2020-05-07 16:28:29 +0530 | [diff] [blame] | 61 | if (protocol != SE_PROTOCOL_UART) { |
T Michael Turney | cea0d9c | 2019-11-27 19:28:23 -0800 | [diff] [blame] | 62 | setbits_le32(®s->geni_dfs_if_cfg, |
| 63 | GENI_DFS_IF_CFG_DFS_IF_EN_BMSK); |
| 64 | /* configure clock dfsr */ |
| 65 | clock_configure_dfsr(bus); |
| 66 | } |
| 67 | |
| 68 | /* HPG section 3.1.7.2 */ |
| 69 | /* No Init Required */ |
| 70 | |
| 71 | /* HPG section 3.1.7.3 */ |
| 72 | write32(®s->dma_general_cfg, |
| 73 | DMA_GENERAL_CFG_AHB_SEC_SLV_CLK_CGC_ON_BMSK | |
| 74 | DMA_GENERAL_CFG_DMA_AHB_SLV_CLK_CGC_ON_BMSK | |
| 75 | DMA_GENERAL_CFG_DMA_TX_CLK_CGC_ON_BMSK | |
| 76 | DMA_GENERAL_CFG_DMA_RX_CLK_CGC_ON_BMSK); |
| 77 | write32(®s->geni_cgc_ctrl, DEFAULT_CGC_EN); |
| 78 | |
| 79 | /* HPG section 3.1.7.4 */ |
| 80 | write32(®s->geni_init_cfg_revision, hdr->cfg_version); |
| 81 | write32(®s->geni_s_init_cfg_revision, hdr->cfg_version); |
| 82 | |
| 83 | assert(cfg_idx_arr[hdr->cfg_size_in_items - 1] * sizeof(uint32_t) <= |
| 84 | MAX_OFFSET_CFG_REG); |
| 85 | |
Ravi Kumar Bokka | 34960d4 | 2021-07-27 21:02:54 +0530 | [diff] [blame] | 86 | for (i = 0; i < hdr->cfg_size_in_items; i++) |
T Michael Turney | cea0d9c | 2019-11-27 19:28:23 -0800 | [diff] [blame] | 87 | write32(®s->geni_cfg_reg0 + cfg_idx_arr[i], |
Ravi Kumar Bokka | 34960d4 | 2021-07-27 21:02:54 +0530 | [diff] [blame] | 88 | cfg_val_arr[i]); |
T Michael Turney | cea0d9c | 2019-11-27 19:28:23 -0800 | [diff] [blame] | 89 | |
| 90 | /* HPG section 3.1.7.9 */ |
| 91 | /* non-UART configuration, UART driver can configure as desired for UART |
| 92 | */ |
| 93 | write32(®s->geni_rx_rfr_watermark_reg, FIFO_DEPTH - 2); |
| 94 | |
| 95 | /* HPG section 3.1.7.5 */ |
| 96 | /* Don't change any SPI polarity, client driver will handle this */ |
| 97 | setbits_le32(®s->geni_output_ctrl, DEFAULT_IO_OUTPUT_CTRL_MSK); |
| 98 | |
| 99 | /* HPG section 3.1.7.6 */ |
| 100 | reg_value = read32(®s->geni_dma_mode_en); |
| 101 | if (mode == GSI) { |
| 102 | reg_value |= GENI_DMA_MODE_EN_GENI_DMA_MODE_EN_BMSK; |
| 103 | write32(®s->geni_dma_mode_en, reg_value); |
| 104 | write32(®s->se_irq_en, 0x0); |
| 105 | write32(®s->se_gsi_event_en, SE_GSI_EVENT_EN_BMSK); |
| 106 | } else if (mode == FIFO) { |
| 107 | reg_value &= ~GENI_DMA_MODE_EN_GENI_DMA_MODE_EN_BMSK; |
| 108 | write32(®s->geni_dma_mode_en, reg_value); |
| 109 | write32(®s->se_irq_en, SE_IRQ_EN_RMSK); |
| 110 | write32(®s->se_gsi_event_en, 0x0); |
| 111 | } else if (mode == CPU_DMA) { |
| 112 | reg_value |= GENI_DMA_MODE_EN_GENI_DMA_MODE_EN_BMSK; |
| 113 | write32(®s->geni_dma_mode_en, reg_value); |
| 114 | write32(®s->se_irq_en, SE_IRQ_EN_RMSK); |
| 115 | write32(®s->se_gsi_event_en, 0x0); |
| 116 | } |
| 117 | |
| 118 | /* HPG section 3.1.7.7 */ |
| 119 | write32(®s->geni_m_irq_enable, |
| 120 | M_COMMON_GENI_M_IRQ_EN); |
| 121 | reg_value = S_CMD_OVERRUN_EN | S_ILLEGAL_CMD_EN | |
| 122 | S_CMD_CANCEL_EN | S_CMD_ABORT_EN | |
| 123 | S_GP_IRQ_0_EN | S_GP_IRQ_1_EN | |
| 124 | S_GP_IRQ_2_EN | S_GP_IRQ_3_EN | |
| 125 | S_RX_FIFO_WR_ERR_EN | S_RX_FIFO_RD_ERR_EN; |
| 126 | write32(®s->geni_s_irq_enable, reg_value); |
| 127 | |
| 128 | /* HPG section 3.1.7.8 */ |
| 129 | /* GPI/DMA mode */ |
| 130 | reg_value = DMA_TX_IRQ_EN_SET_RESET_DONE_EN_SET_BMSK | |
| 131 | DMA_TX_IRQ_EN_SET_SBE_EN_SET_BMSK | |
| 132 | DMA_TX_IRQ_EN_SET_DMA_DONE_EN_SET_BMSK; |
| 133 | write32(®s->dma_tx_irq_en_set, reg_value); |
| 134 | |
| 135 | reg_value = DMA_RX_IRQ_EN_SET_FLUSH_DONE_EN_SET_BMSK | |
| 136 | DMA_RX_IRQ_EN_SET_RESET_DONE_EN_SET_BMSK | |
| 137 | DMA_RX_IRQ_EN_SET_SBE_EN_SET_BMSK | |
| 138 | DMA_RX_IRQ_EN_SET_DMA_DONE_EN_SET_BMSK; |
| 139 | write32(®s->dma_rx_irq_en_set, reg_value); |
| 140 | |
| 141 | /* HPG section 3.1.7.10 */ |
| 142 | reg_value = (hdr->serial_protocol << FW_REV_PROTOCOL_SHFT) | |
| 143 | (hdr->fw_version & 0xFF << |
| 144 | FW_REV_VERSION_SHFT); |
| 145 | write32(®s->se_geni_fw_revision, reg_value); |
| 146 | |
| 147 | reg_value = |
| 148 | (hdr->serial_protocol << FW_REV_PROTOCOL_SHFT) | |
| 149 | (hdr->fw_version & 0xFF << |
| 150 | FW_REV_VERSION_SHFT); |
| 151 | write32(®s->se_s_fw_revision, reg_value); |
| 152 | |
| 153 | assert(hdr->fw_size_in_items <= SIZE_GENI_FW_RAM); |
| 154 | |
| 155 | memcpy((®s->se_geni_cfg_ramn), fw_val_arr, |
| 156 | hdr->fw_size_in_items * sizeof(uint32_t)); |
| 157 | |
| 158 | /* HPG section 3.1.7.12 */ |
| 159 | write32(®s->geni_force_default_reg, 0x1); |
| 160 | setbits_le32(®s->geni_cgc_ctrl, GENI_CGC_CTRL_PROG_RAM_SCLK_OFF_BMSK |
| 161 | |GENI_CGC_CTRL_PROG_RAM_HCLK_OFF_BMSK); |
| 162 | setbits_le32(®s->se_geni_clk_ctrl, GENI_CLK_CTRL_SER_CLK_SEL_BMSK); |
| 163 | clrbits_le32(®s->geni_cgc_ctrl, |
| 164 | (GENI_CGC_CTRL_PROG_RAM_SCLK_OFF_BMSK | |
| 165 | GENI_CGC_CTRL_PROG_RAM_HCLK_OFF_BMSK)); |
| 166 | |
| 167 | /* HPG section 3.1.7.13 */ |
| 168 | /* GSI/DMA mode */ |
| 169 | setbits_le32(®s->se_dma_if_en, DMA_IF_EN_DMA_IF_EN_BMSK); |
| 170 | |
| 171 | /* HPG section 3.1.7.14 */ |
| 172 | reg_value = read32(®s->se_fifo_if_disable); |
| 173 | if ((mode == MIXED) || (mode == FIFO)) |
| 174 | reg_value &= ~FIFO_IF_DISABLE; |
| 175 | else |
| 176 | reg_value |= FIFO_IF_DISABLE; |
| 177 | write32(®s->se_fifo_if_disable, reg_value); |
| 178 | write32(®s->se_geni_clk_ctrl, 0x1); |
| 179 | |
| 180 | /* Lock SE from FW loading */ |
| 181 | write32(®s->se_geni_fw_multilock_protns, 0x1); |
| 182 | write32(®s->se_geni_fw_multilock_msa, 0x1); |
| 183 | } |
| 184 | |
Ravi Kumar Bokka | 34960d4 | 2021-07-27 21:02:54 +0530 | [diff] [blame] | 185 | void gpi_firmware_load(int addr) |
| 186 | { |
| 187 | uint32_t i; |
| 188 | uint32_t regVal = 0; |
Ravi Kumar Bokka | 34960d4 | 2021-07-27 21:02:54 +0530 | [diff] [blame] | 189 | struct gsi_fw_iep *fwIep; |
| 190 | struct gsi_fw_iram *fwIRam; |
Elyes Haouas | 9776738 | 2022-11-18 15:08:13 +0100 | [diff] [blame] | 191 | struct gsi_regs *regs = (struct gsi_regs *)(uintptr_t)addr; |
Ravi Kumar Bokka | 34960d4 | 2021-07-27 21:02:54 +0530 | [diff] [blame] | 192 | static const char * const filename = "fallback/gsi_fw"; |
| 193 | |
| 194 | /* Assign firmware header base */ |
Sudheer Kumar Amrabadi | 0d30a86 | 2023-01-16 08:48:15 +0530 | [diff] [blame^] | 195 | if (!gsi_hdr) { |
| 196 | gsi_hdr = cbfs_map(filename, NULL); |
| 197 | if (!gsi_hdr) |
| 198 | die("*ERROR* * cbfs_map() failed ***\n"); |
| 199 | } |
Ravi Kumar Bokka | 34960d4 | 2021-07-27 21:02:54 +0530 | [diff] [blame] | 200 | |
| 201 | assert(gsi_hdr->magic == GSI_FW_MAGIC_HEADER) |
| 202 | |
| 203 | /* Assign IEP entry base */ |
| 204 | fwIep = (struct gsi_fw_iep *)(((uint8_t *)gsi_hdr) + |
| 205 | gsi_hdr->iep_offset); |
| 206 | /* Assign firmware IRAM entry base */ |
| 207 | fwIRam = (struct gsi_fw_iram *)(((uint8_t *)gsi_hdr) + |
| 208 | gsi_hdr->fw_offset); |
| 209 | |
| 210 | clrbits_le32(®s->gsi_cgc_ctrl, GSI_CGC_CTRL_REGION_2_HW_CGC_EN_BMSK); |
| 211 | write32(®s->gsi_periph_base_lsb, 0); |
| 212 | write32(®s->gsi_periph_base_msb, 0); |
| 213 | |
| 214 | /* Load IEP */ |
| 215 | for (i = 0; i < gsi_hdr->iep_size_in_items; i++) { |
| 216 | /* Check if offset does not exceed GSI address space size */ |
| 217 | if (fwIep[i].offset < GSI_REG_BASE_SIZE) |
| 218 | write32((void *)®s->gsi_cfg + fwIep[i].offset, |
| 219 | fwIep[i].value); |
| 220 | } |
| 221 | |
| 222 | /* Load firmware in IRAM */ |
| 223 | assert((gsi_hdr->fw_size_in_items * 2) < (GSI_INST_RAM_n_MAX_n + 1)) |
| 224 | |
| 225 | /* Program Firmware version */ |
| 226 | write32(®s->gsi_manager_mcs_code_ver, fwIRam->iram_dword0); |
| 227 | |
| 228 | memcpy((®s->gsi_inst_ramn), (void *)fwIRam, |
| 229 | gsi_hdr->fw_size_in_items * GSI_FW_BYTES_PER_LINE); |
| 230 | setbits_le32(®s->gsi_mcs_cfg, GSI_MCS_CFG_MCS_ENABLE_BMSK); |
| 231 | setbits_le32(®s->gsi_cfg, GSI_CFG_DOUBLE_MCS_CLK_FREQ_BMSK |
| 232 | | GSI_CFG_GSI_ENABLE_BMSK); |
| 233 | |
| 234 | write32(®s->gsi_ee_n_scratch_0_addr, 0x0); |
| 235 | write32(®s->ee_n_gsi_ee_generic_cmd, 0x81); |
| 236 | |
| 237 | do { |
| 238 | regVal = read32(®s->gsi_ee_n_scratch_0_addr); |
| 239 | } while (regVal > 1); |
| 240 | } |
| 241 | |
T Michael Turney | cea0d9c | 2019-11-27 19:28:23 -0800 | [diff] [blame] | 242 | static void qup_common_init(int addr) |
| 243 | { |
| 244 | struct qupv3_common_reg *qupv3_common; |
| 245 | /* HPG section 3.1.2 */ |
Elyes Haouas | 9776738 | 2022-11-18 15:08:13 +0100 | [diff] [blame] | 246 | qupv3_common = (struct qupv3_common_reg *)(uintptr_t)addr; |
T Michael Turney | cea0d9c | 2019-11-27 19:28:23 -0800 | [diff] [blame] | 247 | setbits32(&qupv3_common->qupv3_common_cfg_reg, |
| 248 | QUPV3_COMMON_CFG_FAST_SWITCH_TO_HIGH_DISABLE_BMSK); |
| 249 | |
| 250 | /* HPG section 3.1.7.3 */ |
| 251 | setbits32(&qupv3_common->qupv3_se_ahb_m_cfg_reg, |
| 252 | QUPV3_SE_AHB_M_CFG_AHB_M_CLK_CGC_ON_BMSK); |
| 253 | } |
| 254 | |
| 255 | void qupv3_fw_init(void) |
| 256 | { |
| 257 | uint8_t i; |
| 258 | |
| 259 | /* Turn on all QUP clocks */ |
| 260 | for (i = 0; i < QUPV3_SE_MAX; i++) |
| 261 | clock_enable_qup(i); |
| 262 | |
| 263 | qup_common_init(QUP_WRAP0_BASE); |
| 264 | qup_common_init(QUP_WRAP1_BASE); |
| 265 | } |