src/soc/qualcomm: Remove unused <stdlib.h>
[coreboot.git] / src / soc / qualcomm / sc7180 / qspi.c
blob30dc1c3387cdec3c35e69e844910d95ce2e8ffb9
1 /*
2 * This file is part of the coreboot project.
4 * Copyright (C) 2019, The Linux Foundation. All rights reserved.
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 2 and
8 * only version 2 as published by the Free Software Foundation.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
16 #include <spi-generic.h>
17 #include <spi_flash.h>
18 #include <arch/cache.h>
19 #include <device/mmio.h>
20 #include <soc/addressmap.h>
21 #include <soc/qspi.h>
22 #include <soc/gpio.h>
23 #include <soc/clock.h>
24 #include <symbols.h>
25 #include <assert.h>
26 #include <gpio.h>
27 #include <string.h>
29 #define CACHE_LINE_SIZE 64
31 static int curr_desc_idx = -1;
33 struct cmd_desc {
34 uint32_t data_address;
35 uint32_t next_descriptor;
36 uint32_t direction:1;
37 uint32_t multi_io_mode:3;
38 uint32_t reserved1:4;
39 uint32_t fragment:1;
40 uint32_t reserved2:7;
41 uint32_t length:16;
42 //------------------------//
43 uint32_t bounce_src;
44 uint32_t bounce_dst;
45 uint32_t bounce_length;
46 uint64_t padding[5];
49 enum qspi_mode {
50 SDR_1BIT = 1,
51 SDR_2BIT = 2,
52 SDR_4BIT = 3,
53 DDR_1BIT = 5,
54 DDR_2BIT = 6,
55 DDR_4BIT = 7,
58 enum cs_state {
59 CS_DEASSERT,
60 CS_ASSERT
63 struct xfer_cfg {
64 enum qspi_mode mode;
67 enum bus_xfer_direction {
68 MASTER_READ = 0,
69 MASTER_WRITE = 1,
72 struct {
73 struct cmd_desc descriptors[3];
74 uint8_t buffers[3][CACHE_LINE_SIZE];
75 } *dma = (void *)_dma_coherent;
77 static void dma_transfer_chain(struct cmd_desc *chain)
79 uint32_t mstr_int_status;
81 write32(&sc7180_qspi->mstr_int_sts, 0xFFFFFFFF);
82 write32(&sc7180_qspi->next_dma_desc_addr, (uint32_t)(uintptr_t) chain);
84 while (1) {
85 mstr_int_status = read32(&sc7180_qspi->mstr_int_sts);
86 if (mstr_int_status & DMA_CHAIN_DONE)
87 break;
91 static void flush_chain(void)
93 struct cmd_desc *desc = &dma->descriptors[0];
94 uint8_t *src;
95 uint8_t *dst;
97 dma_transfer_chain(desc);
99 while (desc) {
100 if (desc->direction == MASTER_READ) {
101 if (desc->bounce_length == 0)
102 dcache_invalidate_by_mva(
103 (void *)(uintptr_t) desc->data_address,
104 desc->length);
105 else {
106 src = (void *)(uintptr_t) desc->bounce_src;
107 dst = (void *)(uintptr_t) desc->bounce_dst;
108 memcpy(dst, src, desc->bounce_length);
111 desc = (void *)(uintptr_t) desc->next_descriptor;
113 curr_desc_idx = -1;
116 static struct cmd_desc *allocate_descriptor(void)
118 struct cmd_desc *current;
119 struct cmd_desc *next;
120 uint8_t index;
122 current = (curr_desc_idx == -1) ?
123 NULL : &dma->descriptors[curr_desc_idx];
125 index = ++curr_desc_idx;
126 next = &dma->descriptors[index];
128 next->data_address = (uint32_t) (uintptr_t) dma->buffers[index];
130 next->next_descriptor = 0;
131 next->direction = MASTER_READ;
132 next->multi_io_mode = 0;
133 next->reserved1 = 0;
134 next->fragment = 0;
135 next->reserved2 = 0;
136 next->length = 0;
137 next->bounce_src = 0;
138 next->bounce_dst = 0;
139 next->bounce_length = 0;
141 if (current) {
142 current->next_descriptor = (uint32_t)(uintptr_t) next;
143 current->fragment = 1;
146 return next;
149 static void cs_change(enum cs_state state)
151 gpio_set(GPIO(68), state == CS_DEASSERT);
154 static void configure_gpios(void)
156 gpio_output(GPIO(68), 1);
158 gpio_configure(GPIO(64), GPIO64_FUNC_QSPI_DATA_0,
159 GPIO_NO_PULL, GPIO_2MA, GPIO_OUTPUT_ENABLE);
161 gpio_configure(GPIO(65), GPIO65_FUNC_QSPI_DATA_1,
162 GPIO_NO_PULL, GPIO_2MA, GPIO_OUTPUT_ENABLE);
164 gpio_configure(GPIO(63), GPIO63_FUNC_QSPI_CLK,
165 GPIO_NO_PULL, GPIO_2MA, GPIO_OUTPUT_ENABLE);
168 static void queue_bounce_data(uint8_t *data, uint32_t data_bytes,
169 enum qspi_mode data_mode, bool write)
171 struct cmd_desc *desc;
172 uint8_t *ptr;
174 desc = allocate_descriptor();
175 desc->direction = write;
176 desc->multi_io_mode = data_mode;
177 ptr = (void *)(uintptr_t) desc->data_address;
179 if (write) {
180 memcpy(ptr, data, data_bytes);
181 } else {
182 desc->bounce_src = (uint32_t)(uintptr_t) ptr;
183 desc->bounce_dst = (uint32_t)(uintptr_t) data;
184 desc->bounce_length = data_bytes;
187 desc->length = data_bytes;
190 static void queue_direct_data(uint8_t *data, uint32_t data_bytes,
191 enum qspi_mode data_mode, bool write)
193 struct cmd_desc *desc;
195 desc = allocate_descriptor();
196 desc->direction = write;
197 desc->multi_io_mode = data_mode;
198 desc->data_address = (uint32_t)(uintptr_t) data;
199 desc->length = data_bytes;
201 if (write)
202 dcache_clean_by_mva(data, data_bytes);
203 else
204 dcache_invalidate_by_mva(data, data_bytes);
207 static void queue_data(uint8_t *data, uint32_t data_bytes,
208 enum qspi_mode data_mode, bool write)
210 uint8_t *aligned_ptr;
211 uint8_t *epilog_ptr;
212 uint32_t prolog_bytes, aligned_bytes, epilog_bytes;
214 if (data_bytes == 0)
215 return;
217 aligned_ptr =
218 (uint8_t *)ALIGN_UP((uintptr_t)data, CACHE_LINE_SIZE);
220 prolog_bytes = MIN(data_bytes, aligned_ptr - data);
221 aligned_bytes = ALIGN_DOWN(data_bytes - prolog_bytes, CACHE_LINE_SIZE);
222 epilog_bytes = data_bytes - prolog_bytes - aligned_bytes;
224 epilog_ptr = data + prolog_bytes + aligned_bytes;
226 if (prolog_bytes)
227 queue_bounce_data(data, prolog_bytes, data_mode, write);
228 if (aligned_bytes)
229 queue_direct_data(aligned_ptr, aligned_bytes, data_mode, write);
230 if (epilog_bytes)
231 queue_bounce_data(epilog_ptr, epilog_bytes, data_mode, write);
234 static void reg_init(void)
236 uint32_t spi_mode;
237 uint32_t tx_data_oe_delay, tx_data_delay;
238 uint32_t mstr_config;
240 spi_mode = 0;
242 tx_data_oe_delay = 0;
243 tx_data_delay = 0;
245 mstr_config = (tx_data_oe_delay << TX_DATA_OE_DELAY_SHIFT) |
246 (tx_data_delay << TX_DATA_DELAY_SHIFT) | (SBL_EN) |
247 (spi_mode << SPI_MODE_SHIFT) |
248 (PIN_HOLDN) |
249 (FB_CLK_EN) |
250 (DMA_ENABLE) |
251 (FULL_CYCLE_MODE);
253 write32(&sc7180_qspi->mstr_cfg, mstr_config);
254 write32(&sc7180_qspi->ahb_mstr_cfg, 0xA42);
255 write32(&sc7180_qspi->mstr_int_en, 0x0);
256 write32(&sc7180_qspi->mstr_int_sts, 0xFFFFFFFF);
257 write32(&sc7180_qspi->rd_fifo_cfg, 0x0);
258 write32(&sc7180_qspi->rd_fifo_rst, RESET_FIFO);
261 void quadspi_init(uint32_t hz)
263 assert(dcache_line_bytes() == CACHE_LINE_SIZE);
264 clock_configure_qspi(hz * 4);
265 configure_gpios();
266 reg_init();
269 int sc7180_claim_bus(const struct spi_slave *slave)
271 cs_change(CS_ASSERT);
272 return 0;
275 void sc7180_release_bus(const struct spi_slave *slave)
277 cs_change(CS_DEASSERT);
280 static int xfer(enum qspi_mode mode, const void *dout, size_t out_bytes,
281 void *din, size_t in_bytes)
283 if ((out_bytes && !dout) || (in_bytes && !din) ||
284 (in_bytes && out_bytes)) {
285 return -1;
288 queue_data((uint8_t *) (out_bytes ? dout : din),
289 in_bytes | out_bytes, mode, !!out_bytes);
291 flush_chain();
293 return 0;
296 int sc7180_xfer(const struct spi_slave *slave, const void *dout,
297 size_t out_bytes, void *din, size_t in_bytes)
299 return xfer(SDR_1BIT, dout, out_bytes, din, in_bytes);
302 int sc7180_xfer_dual(const struct spi_slave *slave, const void *dout,
303 size_t out_bytes, void *din, size_t in_bytes)
305 return xfer(SDR_2BIT, dout, out_bytes, din, in_bytes);