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