xref: /aosp_15_r20/external/coreboot/src/soc/qualcomm/common/qupv3_spi.c (revision b9411a12aaaa7e1e6a6fb7c5e057f44ee179a49c)
1 /* SPDX-License-Identifier: GPL-2.0-only */
2 
3 #include <assert.h>
4 #include <console/console.h>
5 #include <lib.h>
6 #include <soc/clock.h>
7 #include <soc/gpio.h>
8 #include <soc/qcom_qup_se.h>
9 #include <soc/qup_se_handlers_common.h>
10 #include <soc/qupv3_config_common.h>
11 #include <soc/qupv3_spi_common.h>
12 #include <types.h>
13 
14 /* SE_SPI_LOOPBACK register fields */
15 #define LOOPBACK_ENABLE	0x1
16 
17 /* SE_SPI_WORD_LEN register fields */
18 #define WORD_LEN_MSK	QC_GENMASK(9, 0)
19 #define MIN_WORD_LEN	4
20 
21 /* SPI_TX/SPI_RX_TRANS_LEN fields */
22 #define TRANS_LEN_MSK	QC_GENMASK(23, 0)
23 
24 /* M_CMD OP codes for SPI */
25 #define SPI_TX_ONLY	1
26 #define SPI_RX_ONLY	2
27 #define SPI_FULL_DUPLEX	3
28 #define SPI_TX_RX	7
29 #define SPI_CS_ASSERT	8
30 #define SPI_CS_DEASSERT	9
31 #define SPI_SCK_ONLY	10
32 
33 /* M_CMD params for SPI */
34 /* If fragmentation bit is set then CS will not toggle after each transfer */
35 #define M_CMD_FRAGMENTATION	BIT(2)
36 
37 #define BITS_PER_BYTE	8
38 #define BITS_PER_WORD	8
39 #define TX_WATERMARK	1
40 
41 #define IRQ_TRIGGER (M_RX_FIFO_WATERMARK_EN | M_RX_FIFO_LAST_EN | \
42 	M_TX_FIFO_WATERMARK_EN | M_CMD_DONE_EN | \
43 	M_CMD_CANCEL_EN | M_CMD_ABORT_EN)
44 
setup_fifo_params(const struct spi_slave * slave)45 static void setup_fifo_params(const struct spi_slave *slave)
46 {
47 	unsigned int se_bus = slave->bus;
48 	struct qup_regs *regs = qup[se_bus].regs;
49 	u32 word_len = 0;
50 
51 	/* Disable loopback mode */
52 	write32(&regs->proto_loopback_cfg, 0);
53 
54 	write32(&regs->spi_demux_sel, slave->cs);
55 	word_len = ((BITS_PER_WORD - MIN_WORD_LEN) & WORD_LEN_MSK);
56 	write32(&regs->spi_word_len, word_len);
57 
58 	/* FIFO PACKING CONFIGURATION */
59 	write32(&regs->geni_tx_packing_cfg0, PACK_VECTOR0
60 						| (PACK_VECTOR1 << 10));
61 	write32(&regs->geni_tx_packing_cfg1, PACK_VECTOR2
62 						| (PACK_VECTOR3 << 10));
63 	write32(&regs->geni_rx_packing_cfg0, PACK_VECTOR0
64 						| (PACK_VECTOR1 << 10));
65 	write32(&regs->geni_rx_packing_cfg1, PACK_VECTOR2
66 						| (PACK_VECTOR3 << 10));
67 	write32(&regs->geni_byte_granularity, (log2(BITS_PER_WORD) - 3));
68 }
69 
qup_setup_m_cmd(unsigned int se_bus,u32 cmd,u32 params)70 static void qup_setup_m_cmd(unsigned int se_bus, u32 cmd, u32 params)
71 {
72 	struct qup_regs *regs = qup[se_bus].regs;
73 	u32 m_cmd = (cmd << M_OPCODE_SHFT);
74 
75 	m_cmd |= (params & M_PARAMS_MSK);
76 	write32(&regs->geni_m_cmd0, m_cmd);
77 }
78 
qup_spi_xfer(const struct spi_slave * slave,const void * dout,size_t bytes_out,void * din,size_t bytes_in)79 int qup_spi_xfer(const struct spi_slave *slave, const void *dout,
80 	size_t bytes_out, void *din, size_t bytes_in)
81 {
82 	u32 m_cmd = 0;
83 	u32 m_param = M_CMD_FRAGMENTATION;
84 	int size;
85 	unsigned int se_bus = slave->bus;
86 	struct qup_regs *regs = qup[se_bus].regs;
87 	struct stopwatch timeout;
88 
89 	if ((bytes_in == 0) && (bytes_out == 0))
90 		return 0;
91 
92 	setup_fifo_params(slave);
93 
94 	if (!bytes_out) {
95 		size = bytes_in;
96 		m_cmd = SPI_RX_ONLY;
97 		dout = NULL;
98 	} else if (!bytes_in) {
99 		size = bytes_out;
100 		m_cmd = SPI_TX_ONLY;
101 		din = NULL;
102 	} else {
103 		size = MIN(bytes_in, bytes_out);
104 		m_cmd = SPI_FULL_DUPLEX;
105 	}
106 
107 	/* Check for maximum permissible transfer length */
108 	assert(!(size & ~TRANS_LEN_MSK));
109 
110 	if (bytes_out) {
111 		write32(&regs->spi_tx_trans_len, size);
112 		write32(&regs->geni_tx_watermark_reg, TX_WATERMARK);
113 	}
114 	if (bytes_in)
115 		write32(&regs->spi_rx_trans_len, size);
116 
117 	qup_setup_m_cmd(se_bus, m_cmd, m_param);
118 
119 	stopwatch_init_msecs_expire(&timeout, 1000);
120 	if (qup_handle_transfer(se_bus, dout, din, size, &timeout))
121 		return -1;
122 
123 	qup_spi_xfer(slave, dout + size, MAX((int)bytes_out - size, 0),
124 			din + size, MAX((int)bytes_in - size, 0));
125 
126 	return 0;
127 }
128 
spi_qup_set_cs(const struct spi_slave * slave,bool enable)129 static int spi_qup_set_cs(const struct spi_slave *slave, bool enable)
130 {
131 	u32 m_cmd = 0;
132 	u32 m_irq = 0;
133 	unsigned int se_bus = slave->bus;
134 	struct stopwatch sw;
135 
136 	m_cmd = (enable) ? SPI_CS_ASSERT : SPI_CS_DEASSERT;
137 	qup_setup_m_cmd(se_bus, m_cmd, 0);
138 
139 	stopwatch_init_usecs_expire(&sw, 100);
140 	do {
141 		m_irq = qup_wait_for_m_irq(se_bus);
142 		if (m_irq & M_CMD_DONE_EN) {
143 			write32(&qup[se_bus].regs->geni_m_irq_clear, m_irq);
144 			break;
145 		}
146 		write32(&qup[se_bus].regs->geni_m_irq_clear, m_irq);
147 	} while (!stopwatch_expired(&sw));
148 
149 	if (!(m_irq & M_CMD_DONE_EN)) {
150 		printk(BIOS_INFO, "%s:Failed to %s chip\n", __func__,
151 					(enable) ? "Assert" : "Deassert");
152 		qup_m_cancel_and_abort(se_bus);
153 		return -1;
154 	}
155 	return 0;
156 }
157 
qup_spi_init(unsigned int bus,unsigned int speed_hz)158 void qup_spi_init(unsigned int bus, unsigned int speed_hz)
159 {
160 	u32 m_clk_cfg = 0, div = DEFAULT_SE_CLK / speed_hz;
161 	struct qup_regs *regs = qup[bus].regs;
162 
163 	/* Make sure div can hit target frequency within +/- 1KHz range */
164 	assert(((DEFAULT_SE_CLK - speed_hz * div) <= div * KHz) && (div > 0));
165 	qupv3_se_fw_load_and_init(bus, SE_PROTOCOL_SPI, MIXED);
166 	clock_enable_qup(bus);
167 	m_clk_cfg |= ((div << CLK_DIV_SHFT) | SER_CLK_EN);
168 	write32(&regs->geni_ser_m_clk_cfg, m_clk_cfg);
169 	/* Mode:0, cpha=0, cpol=0 */
170 	write32(&regs->spi_cpha, 0);
171 	write32(&regs->spi_cpol, 0);
172 
173 	/* Serial engine IO initialization */
174 	write32(&regs->geni_cgc_ctrl, DEFAULT_CGC_EN);
175 	write32(&regs->dma_general_cfg,
176 		(AHB_SEC_SLV_CLK_CGC_ON | DMA_AHB_SLV_CFG_ON
177 		| DMA_TX_CLK_CGC_ON | DMA_RX_CLK_CGC_ON));
178 	write32(&regs->geni_output_ctrl,
179 			DEFAULT_IO_OUTPUT_CTRL_MSK);
180 	write32(&regs->geni_force_default_reg, FORCE_DEFAULT);
181 
182 	/* Serial engine IO set mode */
183 	write32(&regs->se_irq_en, (GENI_M_IRQ_EN |
184 			GENI_S_IRQ_EN | DMA_TX_IRQ_EN | DMA_RX_IRQ_EN));
185 	write32(&regs->se_gsi_event_en, 0);
186 
187 	/* Set RX and RFR watermark */
188 	write32(&regs->geni_rx_watermark_reg, 0);
189 	write32(&regs->geni_rx_rfr_watermark_reg, FIFO_DEPTH - 2);
190 
191 	/* GPIO Configuration */
192 	gpio_configure(qup[bus].pin[0], qup[bus].func[0], GPIO_NO_PULL,
193 				GPIO_6MA, GPIO_INPUT);   /* MISO */
194 	gpio_configure(qup[bus].pin[1], qup[bus].func[1], GPIO_NO_PULL,
195 				GPIO_6MA, GPIO_OUTPUT);  /* MOSI */
196 	gpio_configure(qup[bus].pin[2], qup[bus].func[2], GPIO_NO_PULL,
197 				GPIO_6MA, GPIO_OUTPUT);  /* CLK */
198 	gpio_configure(qup[bus].pin[3], qup[bus].func[3], GPIO_NO_PULL,
199 				GPIO_6MA, GPIO_OUTPUT);  /* CS */
200 
201 	/* Select and setup FIFO mode */
202 	write32(&regs->geni_m_irq_clear, 0xFFFFFFFF);
203 	write32(&regs->geni_s_irq_clear, 0xFFFFFFFF);
204 	write32(&regs->dma_tx_irq_clr, 0xFFFFFFFF);
205 	write32(&regs->dma_rx_irq_clr, 0xFFFFFFFF);
206 	write32(&regs->geni_m_irq_enable, (M_COMMON_GENI_M_IRQ_EN |
207 			M_CMD_DONE_EN |	M_TX_FIFO_WATERMARK_EN |
208 			M_RX_FIFO_WATERMARK_EN | M_RX_FIFO_LAST_EN));
209 	write32(&regs->geni_s_irq_enable, (S_COMMON_GENI_S_IRQ_EN
210 						| S_CMD_DONE_EN));
211 	clrbits32(&regs->geni_dma_mode_en, GENI_DMA_MODE_EN);
212 }
213 
qup_spi_claim_bus(const struct spi_slave * slave)214 int qup_spi_claim_bus(const struct spi_slave *slave)
215 {
216 	return spi_qup_set_cs(slave, 1);
217 }
218 
qup_spi_release_bus(const struct spi_slave * slave)219 void qup_spi_release_bus(const struct spi_slave *slave)
220 {
221 	spi_qup_set_cs(slave, 0);
222 }
223