coreboot
coreboot is an Open Source project aimed at replacing the proprietary BIOS found in most computers.
qupv3_config.c
Go to the documentation of this file.
1 /* SPDX-License-Identifier: GPL-2.0-only */
2 
3 #include <cbfs.h>
4 #include <string.h>
6 #include <console/console.h>
8 #include <soc/qcom_qup_se.h>
9 #include <soc/addressmap.h>
10 
12 
13 void qupv3_se_fw_load_and_init(unsigned int bus, unsigned int protocol,
14  unsigned int mode)
15 {
16  uint32_t i;
18  const uint8_t *cfg_idx_arr;
19  const uint32_t *cfg_val_arr;
20  const uint32_t *fw_val_arr;
21  struct elf_se_hdr *hdr;
22  struct qup_regs *regs = qup[bus].regs;
23  static const char * const filename[] = {
24  [SE_PROTOCOL_SPI] = "fallback/spi_fw",
25  [SE_PROTOCOL_UART] = "fallback/uart_fw",
26  [SE_PROTOCOL_I2C] = "fallback/i2c_fw",
27  };
28 
29  if (protocol >= SE_PROTOCOL_MAX || !filename[protocol])
30  die("*ERROR* * INVALID PROTOCOL ***\n");
31 
32  if (!fw_list[protocol]) {
33  fw_list[protocol] = cbfs_map(filename[protocol], NULL);
34  if (!fw_list[protocol])
35  die("*ERROR* * cbfs_map failed ***\n");
36  }
37 
38  hdr = fw_list[protocol];
40 
41  cfg_idx_arr = (const uint8_t *)hdr + hdr->cfg_idx_offset;
42  cfg_val_arr = (const uint32_t *)((uint8_t *)hdr + hdr->cfg_val_offset);
43  fw_val_arr = (const uint32_t *)((uint8_t *)hdr + hdr->fw_offset);
44 
45  /* Unlock SE for FW loading */
46  write32(&regs->se_geni_fw_multilock_protns, 0x0);
47  write32(&regs->se_geni_fw_multilock_msa, 0x0);
48 
49  /* First, ensure GENI FW is disabled */
50  write32(&regs->geni_output_ctrl, 0x0);
54  write32(&regs->se_geni_clk_ctrl, 0x0);
57 
58 
59  /* HPG section 3.1.7.1 */
60  if (protocol != SE_PROTOCOL_UART) {
61  setbits_le32(&regs->geni_dfs_if_cfg,
63  /* configure clock dfsr */
65  }
66 
67  /* HPG section 3.1.7.2 */
68  /* No Init Required */
69 
70  /* HPG section 3.1.7.3 */
71  write32(&regs->dma_general_cfg,
76  write32(&regs->geni_cgc_ctrl, DEFAULT_CGC_EN);
77 
78  /* HPG section 3.1.7.4 */
79  write32(&regs->geni_init_cfg_revision, hdr->cfg_version);
80  write32(&regs->geni_s_init_cfg_revision, hdr->cfg_version);
81 
82  assert(cfg_idx_arr[hdr->cfg_size_in_items - 1] * sizeof(uint32_t) <=
84 
85  for (i = 0; i < hdr->cfg_size_in_items; i++)
86  write32(&regs->geni_cfg_reg0 + cfg_idx_arr[i],
87  cfg_val_arr[i]);
88 
89  /* HPG section 3.1.7.9 */
90  /* non-UART configuration, UART driver can configure as desired for UART
91  */
92  write32(&regs->geni_rx_rfr_watermark_reg, FIFO_DEPTH - 2);
93 
94  /* HPG section 3.1.7.5 */
95  /* Don't change any SPI polarity, client driver will handle this */
96  setbits_le32(&regs->geni_output_ctrl, DEFAULT_IO_OUTPUT_CTRL_MSK);
97 
98  /* HPG section 3.1.7.6 */
99  reg_value = read32(&regs->geni_dma_mode_en);
100  if (mode == GSI) {
102  write32(&regs->geni_dma_mode_en, reg_value);
103  write32(&regs->se_irq_en, 0x0);
104  write32(&regs->se_gsi_event_en, SE_GSI_EVENT_EN_BMSK);
105  } else if (mode == FIFO) {
107  write32(&regs->geni_dma_mode_en, reg_value);
108  write32(&regs->se_irq_en, SE_IRQ_EN_RMSK);
109  write32(&regs->se_gsi_event_en, 0x0);
110  } else if (mode == CPU_DMA) {
112  write32(&regs->geni_dma_mode_en, reg_value);
113  write32(&regs->se_irq_en, SE_IRQ_EN_RMSK);
114  write32(&regs->se_gsi_event_en, 0x0);
115  }
116 
117  /* HPG section 3.1.7.7 */
118  write32(&regs->geni_m_irq_enable,
125  write32(&regs->geni_s_irq_enable, reg_value);
126 
127  /* HPG section 3.1.7.8 */
128  /* GPI/DMA mode */
132  write32(&regs->dma_tx_irq_en_set, reg_value);
133 
138  write32(&regs->dma_rx_irq_en_set, reg_value);
139 
140  /* HPG section 3.1.7.10 */
142  (hdr->fw_version & 0xFF <<
144  write32(&regs->se_geni_fw_revision, reg_value);
145 
146  reg_value =
148  (hdr->fw_version & 0xFF <<
150  write32(&regs->se_s_fw_revision, reg_value);
151 
153 
154  memcpy((&regs->se_geni_cfg_ramn), fw_val_arr,
155  hdr->fw_size_in_items * sizeof(uint32_t));
156 
157  /* HPG section 3.1.7.12 */
158  write32(&regs->geni_force_default_reg, 0x1);
161  setbits_le32(&regs->se_geni_clk_ctrl, GENI_CLK_CTRL_SER_CLK_SEL_BMSK);
162  clrbits_le32(&regs->geni_cgc_ctrl,
165 
166  /* HPG section 3.1.7.13 */
167  /* GSI/DMA mode */
168  setbits_le32(&regs->se_dma_if_en, DMA_IF_EN_DMA_IF_EN_BMSK);
169 
170  /* HPG section 3.1.7.14 */
171  reg_value = read32(&regs->se_fifo_if_disable);
172  if ((mode == MIXED) || (mode == FIFO))
174  else
176  write32(&regs->se_fifo_if_disable, reg_value);
177  write32(&regs->se_geni_clk_ctrl, 0x1);
178 
179  /* Lock SE from FW loading */
180  write32(&regs->se_geni_fw_multilock_protns, 0x1);
181  write32(&regs->se_geni_fw_multilock_msa, 0x1);
182 }
183 
185 {
186  uint32_t i;
187  uint32_t regVal = 0;
188  struct gsi_fw_hdr *gsi_hdr;
189  struct gsi_fw_iep *fwIep;
190  struct gsi_fw_iram *fwIRam;
191  struct gsi_regs *regs = (struct gsi_regs *)(uintptr_t) addr;
192  static const char * const filename = "fallback/gsi_fw";
193 
194  /* Assign firmware header base */
195  gsi_hdr = cbfs_map(filename, NULL);
196  if (!gsi_hdr)
197  die("*ERROR* * cbfs_map() failed ***\n");
198 
199  assert(gsi_hdr->magic == GSI_FW_MAGIC_HEADER)
200 
201  /* Assign IEP entry base */
202  fwIep = (struct gsi_fw_iep *)(((uint8_t *)gsi_hdr) +
203  gsi_hdr->iep_offset);
204  /* Assign firmware IRAM entry base */
205  fwIRam = (struct gsi_fw_iram *)(((uint8_t *)gsi_hdr) +
206  gsi_hdr->fw_offset);
207 
209  write32(&regs->gsi_periph_base_lsb, 0);
210  write32(&regs->gsi_periph_base_msb, 0);
211 
212  /* Load IEP */
213  for (i = 0; i < gsi_hdr->iep_size_in_items; i++) {
214  /* Check if offset does not exceed GSI address space size */
215  if (fwIep[i].offset < GSI_REG_BASE_SIZE)
216  write32((void *)&regs->gsi_cfg + fwIep[i].offset,
217  fwIep[i].value);
218  }
219 
220  /* Load firmware in IRAM */
221  assert((gsi_hdr->fw_size_in_items * 2) < (GSI_INST_RAM_n_MAX_n + 1))
222 
223  /* Program Firmware version */
224  write32(&regs->gsi_manager_mcs_code_ver, fwIRam->iram_dword0);
225 
226  memcpy((&regs->gsi_inst_ramn), (void *)fwIRam,
231 
232  write32(&regs->gsi_ee_n_scratch_0_addr, 0x0);
233  write32(&regs->ee_n_gsi_ee_generic_cmd, 0x81);
234 
235  do {
236  regVal = read32(&regs->gsi_ee_n_scratch_0_addr);
237  } while (regVal > 1);
238 }
239 
240 static void qup_common_init(int addr)
241 {
242  struct qupv3_common_reg *qupv3_common;
243  /* HPG section 3.1.2 */
244  qupv3_common = (struct qupv3_common_reg *)(uintptr_t) addr;
245  setbits32(&qupv3_common->qupv3_common_cfg_reg,
247 
248  /* HPG section 3.1.7.3 */
249  setbits32(&qupv3_common->qupv3_se_ahb_m_cfg_reg,
251 }
252 
253 void qupv3_fw_init(void)
254 {
255  uint8_t i;
256 
257  /* Turn on all QUP clocks */
258  for (i = 0; i < QUPV3_SE_MAX; i++)
259  clock_enable_qup(i);
260 
263 }
static void write32(void *addr, uint32_t val)
Definition: mmio.h:40
static uint32_t read32(const void *addr)
Definition: mmio.h:22
void * memcpy(void *dest, const void *src, size_t n)
Definition: memcpy.c:7
#define assert(statement)
Definition: assert.h:74
static void * cbfs_map(const char *name, size_t *size_out)
Definition: cbfs.h:246
static u32 addr
Definition: cirrus.c:14
void __noreturn die(const char *fmt,...)
Definition: die.c:17
static size_t offset
Definition: flashconsole.c:16
#define setbits32(addr, set)
Definition: mmio.h:21
#define setbits_le32(addr, set)
Definition: endian.h:58
#define clrbits_le32(addr, clear)
Definition: endian.h:51
#define S_RX_FIFO_WR_ERR_EN
#define S_ILLEGAL_CMD_EN
#define GENI_DFS_IF_CFG_DFS_IF_EN_BMSK
#define S_RX_FIFO_RD_ERR_EN
#define S_GP_IRQ_3_EN
#define S_GP_IRQ_0_EN
#define S_CMD_OVERRUN_EN
#define S_GP_IRQ_2_EN
#define FW_REV_PROTOCOL_SHFT
#define S_CMD_CANCEL_EN
#define DEFAULT_CGC_EN
#define FIFO_DEPTH
#define M_COMMON_GENI_M_IRQ_EN
#define DEFAULT_IO_OUTPUT_CTRL_MSK
#define S_GP_IRQ_1_EN
#define FW_REV_VERSION_SHFT
#define S_CMD_ABORT_EN
@ SE_PROTOCOL_MAX
@ SE_PROTOCOL_I2C
@ SE_PROTOCOL_UART
@ SE_PROTOCOL_SPI
#define FIFO_IF_DISABLE
static struct elf_se_hdr * fw_list[SE_PROTOCOL_MAX]
Definition: qupv3_config.c:11
void qupv3_fw_init(void)
Definition: qupv3_config.c:253
void gpi_firmware_load(int addr)
Definition: qupv3_config.c:184
static void qup_common_init(int addr)
Definition: qupv3_config.c:240
void qupv3_se_fw_load_and_init(unsigned int bus, unsigned int protocol, unsigned int mode)
Definition: qupv3_config.c:13
#define GENI_CGC_CTRL_PROG_RAM_HCLK_OFF_BMSK
#define GSI_INST_RAM_n_MAX_n
#define DMA_GENERAL_CFG_AHB_SEC_SLV_CLK_CGC_ON_BMSK
#define GENI_DMA_MODE_EN_GENI_DMA_MODE_EN_BMSK
#define DMA_GENERAL_CFG_DMA_TX_CLK_CGC_ON_BMSK
#define DMA_IF_EN_DMA_IF_EN_BMSK
#define SE_IRQ_EN_RMSK
#define SIZE_GENI_FW_RAM
#define GSI_FW_MAGIC_HEADER
#define GENI_CGC_CTRL_PROG_RAM_SCLK_OFF_BMSK
#define GSI_MCS_CFG_MCS_ENABLE_BMSK
#define DMA_TX_IRQ_EN_SET_RESET_DONE_EN_SET_BMSK
#define GSI_CFG_GSI_ENABLE_BMSK
#define QUPV3_COMMON_CFG_FAST_SWITCH_TO_HIGH_DISABLE_BMSK
#define GSI_CGC_CTRL_REGION_2_HW_CGC_EN_BMSK
#define DMA_RX_IRQ_EN_SET_SBE_EN_SET_BMSK
#define DMA_GENERAL_CFG_DMA_RX_CLK_CGC_ON_BMSK
#define GSI_FW_BYTES_PER_LINE
#define GENI_CLK_CTRL_SER_CLK_SEL_BMSK
#define DMA_RX_IRQ_EN_SET_RESET_DONE_EN_SET_BMSK
#define DMA_GENERAL_CFG_DMA_AHB_SLV_CLK_CGC_ON_BMSK
#define SE_GSI_EVENT_EN_BMSK
#define DMA_RX_IRQ_EN_SET_FLUSH_DONE_EN_SET_BMSK
#define GSI_CFG_DOUBLE_MCS_CLK_FREQ_BMSK
#define DMA_TX_IRQ_EN_SET_DMA_DONE_EN_SET_BMSK
#define QUPV3_SE_AHB_M_CFG_AHB_M_CLK_CGC_ON_BMSK
#define GSI_REG_BASE_SIZE
#define SEFW_MAGIC_HEADER
#define DMA_RX_IRQ_EN_SET_DMA_DONE_EN_SET_BMSK
#define DMA_TX_IRQ_EN_SET_SBE_EN_SET_BMSK
@ QUPV3_SE_MAX
Definition: qcom_qup_se.h:25
#define MAX_OFFSET_CFG_REG
Definition: qcom_qup_se.h:36
void clock_enable_qup(int qup)
Definition: clock.c:132
void clock_configure_dfsr(int qup)
Definition: clock.c:126
#define QUP_WRAP1_BASE
Definition: addressmap.h:35
#define QUP_WRAP0_BASE
Definition: addressmap.h:26
#define NULL
Definition: stddef.h:19
unsigned int uint32_t
Definition: stdint.h:14
unsigned long uintptr_t
Definition: stdint.h:21
unsigned char uint8_t
Definition: stdint.h:8
Definition: device.h:76
uint16_t fw_offset
uint16_t cfg_size_in_items
uint16_t fw_version
uint16_t fw_size_in_items
uint16_t cfg_idx_offset
uint16_t serial_protocol
uint16_t cfg_val_offset
uint16_t cfg_version
uint16_t fw_size_in_items
uint16_t fw_offset
uint16_t iep_size_in_items
uint16_t iep_offset
uint32_t iram_dword0
struct qup_regs * regs
Definition: qcom_qup_se.h:29