coreboot
coreboot is an Open Source project aimed at replacing the proprietary BIOS found in most computers.
qup_se_handler.c
Go to the documentation of this file.
1 /* SPDX-License-Identifier: GPL-2.0-only */
2 
3 #include <console/console.h>
5 #include <soc/qcom_qup_se.h>
6 
7 u32 qup_wait_for_m_irq(unsigned int bus)
8 {
9  struct stopwatch sw;
10  unsigned int m_irq = 0;
11  struct qup_regs *regs = qup[bus].regs;
12 
14  while (!stopwatch_expired(&sw)) {
15  m_irq = read32(&regs->geni_m_irq_status);
16  if (m_irq)
17  break;
18  }
19  return m_irq;
20 }
21 
22 u32 qup_wait_for_s_irq(unsigned int bus)
23 {
24  struct stopwatch sw;
25  unsigned int s_irq = 0;
26  struct qup_regs *regs = qup[bus].regs;
27 
29  while (!stopwatch_expired(&sw)) {
30  s_irq = read32(&regs->geni_s_irq_status);
31  if (s_irq)
32  break;
33  }
34  return s_irq;
35 }
36 
37 static int handle_tx(unsigned int bus, const u8 *dout,
38  unsigned int tx_rem_bytes)
39 {
40  int max_bytes = 0;
41  struct qup_regs *regs = qup[bus].regs;
42 
44  max_bytes = MIN(tx_rem_bytes, max_bytes);
45 
46  buffer_to_fifo32((void *)dout, max_bytes, &regs->geni_tx_fifon,
48 
49  if (tx_rem_bytes == max_bytes)
50  write32(&regs->geni_tx_watermark_reg, 0);
51  return max_bytes;
52 }
53 
54 static int handle_rx(unsigned int bus, u8 *din, unsigned int rx_rem_bytes)
55 {
56  struct qup_regs *regs = qup[bus].regs;
57  u32 rx_fifo_status = read32(&regs->geni_rx_fifo_status);
58  int rx_bytes = 0;
59 
60  rx_bytes = (rx_fifo_status & RX_FIFO_WC_MSK) * BYTES_PER_FIFO_WORD;
61  rx_bytes = MIN(rx_rem_bytes, rx_bytes);
62 
63  buffer_from_fifo32(din, rx_bytes, &regs->geni_rx_fifon,
65  return rx_bytes;
66 }
67 
68 void qup_m_cancel_and_abort(unsigned int bus)
69 {
70  struct qup_regs *regs = qup[bus].regs;
71  struct stopwatch sw;
72  unsigned int m_irq;
73 
74  write32(&regs->geni_tx_watermark_reg, 0);
75  write32(&regs->geni_m_cmd_ctrl_reg, M_GENI_CMD_CANCEL);
76 
78  do {
79  m_irq = qup_wait_for_m_irq(bus);
80  if (m_irq & M_CMD_CANCEL_EN) {
81  write32(&regs->geni_m_irq_clear, m_irq);
82  break;
83  }
84  write32(&regs->geni_m_irq_clear, m_irq);
85  } while (!stopwatch_expired(&sw));
86 
87  if (!(m_irq & M_CMD_CANCEL_EN)) {
88  printk(BIOS_INFO, "%s:Cancel failed, Abort the operation\n",
89  __func__);
90 
91  write32(&regs->geni_m_cmd_ctrl_reg, M_GENI_CMD_ABORT);
93  do {
94  m_irq = qup_wait_for_m_irq(bus);
95  if (m_irq & M_CMD_ABORT_EN) {
96  write32(&regs->geni_m_irq_clear, m_irq);
97  break;
98  }
99  write32(&regs->geni_m_irq_clear, m_irq);
100  } while (!stopwatch_expired(&sw));
101 
102  if (!(m_irq & M_CMD_ABORT_EN))
103  printk(BIOS_INFO, "%s:Abort failed\n", __func__);
104  }
105 }
106 
107 void qup_s_cancel_and_abort(unsigned int bus)
108 {
109  struct qup_regs *regs = qup[bus].regs;
110  struct stopwatch sw;
111  unsigned int s_irq;
112  u32 rx_fifo_status;
113  u8 buf[64]; /* FIFO size */
114 
115  write32(&regs->geni_tx_watermark_reg, 0);
116  write32(&regs->geni_s_cmd_ctrl_reg, S_GENI_CMD_CANCEL);
117 
118  stopwatch_init_msecs_expire(&sw, 100);
119  do {
120  s_irq = qup_wait_for_s_irq(bus);
121  rx_fifo_status = read32(&regs->geni_rx_fifo_status);
122  if (rx_fifo_status & RX_LAST)
123  /* Read whatever data available in FIFO */
124  handle_rx(bus, buf, 64);
125  if (s_irq & S_CMD_CANCEL_EN) {
126  write32(&regs->geni_s_irq_clear, s_irq);
127  break;
128  }
129  write32(&regs->geni_s_irq_clear, s_irq);
130  } while (!stopwatch_expired(&sw));
131 
132  if (!(s_irq & S_CMD_CANCEL_EN)) {
133  printk(BIOS_INFO, "%s:Cancel failed, Abort the operation\n",
134  __func__);
135 
136  write32(&regs->geni_s_cmd_ctrl_reg, S_GENI_CMD_ABORT);
137  stopwatch_init_msecs_expire(&sw, 100);
138  do {
139  s_irq = qup_wait_for_s_irq(bus);
140  if (s_irq & S_CMD_ABORT_EN) {
141  write32(&regs->geni_s_irq_clear, s_irq);
142  break;
143  }
144  write32(&regs->geni_s_irq_clear, s_irq);
145  } while (!stopwatch_expired(&sw));
146 
147  if (!(s_irq & S_CMD_ABORT_EN))
148  printk(BIOS_INFO, "%s:Abort failed\n", __func__);
149  }
150 }
151 
152 int qup_handle_transfer(unsigned int bus, const void *dout, void *din, int size,
153  struct stopwatch *timeout)
154 {
155  unsigned int m_irq;
156  unsigned int rx_rem_bytes = din ? size : 0;
157  unsigned int tx_rem_bytes = dout ? size : 0;
158  struct qup_regs *regs = qup[bus].regs;
159 
160  do {
161  m_irq = qup_wait_for_m_irq(bus);
162  if ((m_irq & M_RX_FIFO_WATERMARK_EN) ||
163  (m_irq & M_RX_FIFO_LAST_EN))
164  rx_rem_bytes -= handle_rx(bus, din + size
165  - rx_rem_bytes, rx_rem_bytes);
166  if (m_irq & M_TX_FIFO_WATERMARK_EN)
167  tx_rem_bytes -= handle_tx(bus, dout + size
168  - tx_rem_bytes, tx_rem_bytes);
169  if (m_irq & M_CMD_DONE_EN) {
170  write32(&regs->geni_m_irq_clear, m_irq);
171  break;
172  }
173  write32(&regs->geni_m_irq_clear, m_irq);
174  } while (!stopwatch_expired(timeout));
175 
176  if (!(m_irq & M_CMD_DONE_EN) || tx_rem_bytes || rx_rem_bytes) {
177  printk(BIOS_INFO, "%s:Error: Transfer failed\n", __func__);
179  return -1;
180  }
181  return 0;
182 }
static void write32(void *addr, uint32_t val)
Definition: mmio.h:40
static uint32_t read32(const void *addr)
Definition: mmio.h:22
#define MIN(a, b)
Definition: helpers.h:37
#define printk(level,...)
Definition: stdlib.h:16
void buffer_from_fifo32(void *buffer, size_t size, void *fifo, int fifo_stride, int fifo_width)
Definition: mmio.c:8
static void buffer_to_fifo32(const void *buffer, size_t size, void *fifo, int fifo_stride, int fifo_width)
Definition: mmio.h:54
static int stopwatch_expired(struct stopwatch *sw)
Definition: timer.h:152
static void stopwatch_init_msecs_expire(struct stopwatch *sw, long ms)
Definition: timer.h:133
static void stopwatch_init_usecs_expire(struct stopwatch *sw, long us)
Definition: timer.h:127
#define BIOS_INFO
BIOS_INFO - Expected events.
Definition: loglevel.h:113
static uint8_t * buf
Definition: uart.c:7
static int handle_tx(unsigned int bus, const u8 *dout, unsigned int tx_rem_bytes)
u32 qup_wait_for_s_irq(unsigned int bus)
static int handle_rx(unsigned int bus, u8 *din, unsigned int rx_rem_bytes)
void qup_m_cancel_and_abort(unsigned int bus)
u32 qup_wait_for_m_irq(unsigned int bus)
Definition: qup_se_handler.c:7
int qup_handle_transfer(unsigned int bus, const void *dout, void *din, int size, struct stopwatch *timeout)
void qup_s_cancel_and_abort(unsigned int bus)
#define M_TX_FIFO_WATERMARK_EN
#define RX_FIFO_WC_MSK
#define TX_WATERMARK
#define S_GENI_CMD_ABORT
#define RX_LAST
#define S_GENI_CMD_CANCEL
#define M_CMD_CANCEL_EN
#define M_CMD_ABORT_EN
#define S_CMD_CANCEL_EN
#define M_CMD_DONE_EN
#define FIFO_DEPTH
#define M_RX_FIFO_WATERMARK_EN
#define M_RX_FIFO_LAST_EN
#define M_GENI_CMD_ABORT
#define BYTES_PER_FIFO_WORD
#define S_CMD_ABORT_EN
#define M_GENI_CMD_CANCEL
uint32_t u32
Definition: stdint.h:51
uint8_t u8
Definition: stdint.h:45
Definition: device.h:76
struct qup_regs * regs
Definition: qcom_qup_se.h:29