blob: 4a353130e1e73b8db68dd2b6688b261687fc494f [file] [log] [blame]
Vadim Bendebury3afa03e2014-04-10 14:20:39 -07001/*
2 * Copyright (c) 2012 The Linux Foundation. All rights reserved.
3 */
4
Vadim Bendeburydffd8922014-04-30 13:25:12 -07005#include <arch/io.h>
6#include <delay.h>
Julius Wernereaa9c452014-09-24 15:40:49 -07007#include <gpio.h>
Julius Werner73d1ed62014-10-20 13:20:49 -07008#include <soc/iomap.h>
9#include <soc/spi.h>
Vadim Bendeburydffd8922014-04-30 13:25:12 -070010#include <stdlib.h>
11#include <string.h>
Vadim Bendebury3afa03e2014-04-10 14:20:39 -070012
13#define SUCCESS 0
14
15#define DUMMY_DATA_VAL 0
16#define TIMEOUT_CNT 100
17#define CS_ASSERT 1
18#define CS_DEASSERT 0
19#define NUM_PORTS 3
20#define NUM_GSBI_PINS 3
21#define TLMM_ARGS 6
22#define NUM_CS 4
23#define GSBI_PIN_IDX 0
24#define FUNC_SEL_IDX 1
25#define GPIO_DIR_IDX 2
26#define PULL_CONF_IDX 3
27#define DRV_STR_IDX 4
28#define GPIO_EN_IDX 5
29
Vadim Bendeburydffd8922014-04-30 13:25:12 -070030/* Arbitrarily assigned error code values */
31#define ETIMEDOUT -10
32#define EINVAL -11
33#define EIO -12
34
Vadim Bendebury3afa03e2014-04-10 14:20:39 -070035#define GSBI_IDX_TO_GSBI(idx) (idx + 5)
36
David Hendricks68ec2fc2014-07-25 12:59:48 -070037
38/* MX_INPUT_COUNT and MX_OUTPUT_COUNT are 16-bits. Zero has a special meaning
39 * (count function disabled) and does not hold significance in the count. */
40#define MAX_PACKET_COUNT ((64 * KiB) - 1)
41
Vadim Bendebury3afa03e2014-04-10 14:20:39 -070042/*
43 * TLMM Configuration for SPI NOR
44 * gsbi_pin_conf[bus_num][GPIO_NUM, FUNC_SEL, I/O,
45 * PULL UP/DOWN, DRV_STR, GPIO_FUNC]
46 * gsbi_pin_conf[0][x][y] -- GSBI5
47 * gsbi_pin_conf[1][x][y] -- GSBI6
48 * gsbi_pin_conf[2][x][y] -- GSBI7
49*/
50static unsigned int gsbi_pin_conf[NUM_PORTS][NUM_GSBI_PINS][TLMM_ARGS] = {
51 {
52 /* GSBI5 CLK */
53 {
54 GSBI5_SPI_CLK, FUNC_SEL_1, GPIO_INPUT,
55 GPIO_PULL_DOWN, GPIO_DRV_STR_11MA, GPIO_FUNC_DISABLE
56 },
57 /* GSBI5 MISO */
58 {
59 GSBI5_SPI_MISO, FUNC_SEL_1, GPIO_INPUT,
60 GPIO_PULL_DOWN, GPIO_DRV_STR_10MA, GPIO_FUNC_DISABLE
61 },
62 /* GSBI5 MOSI */
63 {
64 GSBI5_SPI_MOSI, FUNC_SEL_1, GPIO_INPUT,
65 GPIO_PULL_DOWN, GPIO_DRV_STR_10MA, GPIO_FUNC_DISABLE
66 }
67 },
68 {
69 /* GSBI6 CLK */
70 {
71 GSBI6_SPI_CLK, FUNC_SEL_3, GPIO_INPUT,
72 GPIO_PULL_DOWN, GPIO_DRV_STR_11MA, GPIO_FUNC_DISABLE
73 },
74 /* GSBI6 MISO */
75 {
76 GSBI6_SPI_MISO, FUNC_SEL_3, GPIO_INPUT,
77 GPIO_PULL_DOWN, GPIO_DRV_STR_10MA, GPIO_FUNC_DISABLE
78 },
79 /* GSBI6 MOSI */
80 {
81 GSBI6_SPI_MOSI, FUNC_SEL_3, GPIO_INPUT,
82 GPIO_PULL_DOWN, GPIO_DRV_STR_10MA, GPIO_FUNC_DISABLE
83 }
84 },
85 {
86 /* GSBI7 CLK */
87 {
88 GSBI7_SPI_CLK, FUNC_SEL_1, GPIO_INPUT,
89 GPIO_PULL_DOWN, GPIO_DRV_STR_11MA, GPIO_FUNC_DISABLE
90 },
91 /* GSBI7 MISO */
92 {
93 GSBI7_SPI_MISO, FUNC_SEL_1, GPIO_INPUT,
94 GPIO_PULL_DOWN, GPIO_DRV_STR_10MA, GPIO_FUNC_DISABLE
95 },
96 /* GSBI7 MOSI */
97 {
98 GSBI7_SPI_MOSI, FUNC_SEL_1, GPIO_INPUT,
99 GPIO_PULL_DOWN, GPIO_DRV_STR_10MA, GPIO_FUNC_DISABLE
100 }
101 }
102};
103
104/*
105 * CS GPIO number array cs_gpio_array[port_num][cs_num]
106 * cs_gpio_array[0][x] -- GSBI5
107 * cs_gpio_array[1][x] -- GSBI6
108 * cs_gpio_array[2][x] -- GSBI7
109 */
110static unsigned int cs_gpio_array[NUM_PORTS][NUM_CS] = {
111 {
112 GSBI5_SPI_CS_0, GSBI5_SPI_CS_1, GSBI5_SPI_CS_2, GSBI5_SPI_CS_3
113 },
114 {
115 GSBI6_SPI_CS_0, 0, 0, 0
116 },
117 {
118 GSBI7_SPI_CS_0, 0, 0, 0
119 }
120};
121
122/*
123 * GSBI HCLK state register bit
124 * hclk_state[0] -- GSBI5
125 * hclk_state[1] -- GSBI6
126 * hclk_state[2] -- GSBI7
127*/
128static unsigned int hclk_state[NUM_PORTS] = {
129 GSBI5_HCLK,
130 GSBI6_HCLK,
131 GSBI7_HCLK
132};
133
134/*
135 * GSBI QUP_APPS_CLK state register bit
136 * qup_apps_clk_state[0] -- GSBI5
137 * qup_apps_clk_state[1] -- GSBI6
138 * qup_apps_clk_state[2] -- GSBI7
139*/
140static unsigned int qup_apps_clk_state[NUM_PORTS] = {
141 GSBI5_QUP_APPS_CLK,
142 GSBI6_QUP_APPS_CLK,
143 GSBI7_QUP_APPS_CLK
144};
145
146
147static int check_bit_state(uint32_t reg_addr, int bit_num, int val, int us_delay)
148{
149 unsigned int count = TIMEOUT_CNT;
Vadim Bendeburydffd8922014-04-30 13:25:12 -0700150 unsigned int bit_val = ((readl_i(reg_addr) >> bit_num) & 0x01);
Vadim Bendebury3afa03e2014-04-10 14:20:39 -0700151
152 while (bit_val != val) {
153 count--;
154 if (count == 0)
155 return -ETIMEDOUT;
156 udelay(us_delay);
Vadim Bendeburydffd8922014-04-30 13:25:12 -0700157 bit_val = ((readl_i(reg_addr) >> bit_num) & 0x01);
Vadim Bendebury3afa03e2014-04-10 14:20:39 -0700158 }
159
160 return SUCCESS;
161}
162
163/*
164 * Check whether GSBIn_QUP State is valid
165 */
166static int check_qup_state_valid(struct ipq_spi_slave *ds)
167{
168
169 return check_bit_state(ds->regs->qup_state, QUP_STATE_VALID_BIT,
170 QUP_STATE_VALID, 1);
171
172}
173
174/*
175 * Configure GSBIn Core state
176 */
177static int config_spi_state(struct ipq_spi_slave *ds, unsigned int state)
178{
179 uint32_t val;
Vadim Bendeburydffd8922014-04-30 13:25:12 -0700180 int ret;
181 uint32_t new_state;
Vadim Bendebury3afa03e2014-04-10 14:20:39 -0700182
183 ret = check_qup_state_valid(ds);
184 if (ret != SUCCESS)
185 return ret;
186
187 switch (state) {
188 case SPI_RUN_STATE:
Vadim Bendeburydffd8922014-04-30 13:25:12 -0700189 new_state = QUP_STATE_RUN_STATE;
Vadim Bendebury3afa03e2014-04-10 14:20:39 -0700190 break;
Vadim Bendeburydffd8922014-04-30 13:25:12 -0700191
Vadim Bendebury3afa03e2014-04-10 14:20:39 -0700192 case SPI_RESET_STATE:
Vadim Bendeburydffd8922014-04-30 13:25:12 -0700193 new_state = QUP_STATE_RESET_STATE;
Vadim Bendebury3afa03e2014-04-10 14:20:39 -0700194 break;
Vadim Bendeburydffd8922014-04-30 13:25:12 -0700195
196 case SPI_PAUSE_STATE:
197 new_state = QUP_STATE_PAUSE_STATE;
198 break;
199
Vadim Bendebury3afa03e2014-04-10 14:20:39 -0700200 default:
Vadim Bendeburydffd8922014-04-30 13:25:12 -0700201 printk(BIOS_ERR,
202 "err: unsupported GSBI SPI state : %d\n", state);
203 return -EINVAL;
Vadim Bendebury3afa03e2014-04-10 14:20:39 -0700204 }
205
Vadim Bendeburydffd8922014-04-30 13:25:12 -0700206 /* Set the state as requested */
207 val = (readl_i(ds->regs->qup_state) & ~QUP_STATE_MASK)
208 | new_state;
209 writel_i(val, ds->regs->qup_state);
210 return check_qup_state_valid(ds);
Vadim Bendebury3afa03e2014-04-10 14:20:39 -0700211}
212
213/*
214 * Set GSBIn SPI Mode
215 */
216static void spi_set_mode(struct ipq_spi_slave *ds, unsigned int mode)
217{
218 unsigned int clk_idle_state;
219 unsigned int input_first_mode;
220 uint32_t val;
221
222 switch (mode) {
223 case GSBI_SPI_MODE_0:
224 clk_idle_state = 0;
225 input_first_mode = SPI_INPUT_FIRST_MODE;
226 break;
227 case GSBI_SPI_MODE_1:
228 clk_idle_state = 0;
229 input_first_mode = 0;
230 break;
231 case GSBI_SPI_MODE_2:
232 clk_idle_state = 1;
233 input_first_mode = SPI_INPUT_FIRST_MODE;
234 break;
235 case GSBI_SPI_MODE_3:
236 clk_idle_state = 1;
237 input_first_mode = 0;
238 break;
239 default:
Vadim Bendeburydffd8922014-04-30 13:25:12 -0700240 printk(BIOS_ERR,
241 "err : unsupported spi mode : %d\n", mode);
Vadim Bendebury3afa03e2014-04-10 14:20:39 -0700242 return;
243 }
244
Vadim Bendeburydffd8922014-04-30 13:25:12 -0700245 val = readl_i(ds->regs->spi_config);
Vadim Bendebury3afa03e2014-04-10 14:20:39 -0700246 val |= input_first_mode;
Vadim Bendeburydffd8922014-04-30 13:25:12 -0700247 writel_i(val, ds->regs->spi_config);
Vadim Bendebury3afa03e2014-04-10 14:20:39 -0700248
Vadim Bendeburydffd8922014-04-30 13:25:12 -0700249 val = readl_i(ds->regs->io_control);
Vadim Bendebury3afa03e2014-04-10 14:20:39 -0700250 if (clk_idle_state)
251 val |= SPI_IO_CONTROL_CLOCK_IDLE_HIGH;
252 else
253 val &= ~SPI_IO_CONTROL_CLOCK_IDLE_HIGH;
254
Vadim Bendeburydffd8922014-04-30 13:25:12 -0700255 writel_i(val, ds->regs->io_control);
Vadim Bendebury3afa03e2014-04-10 14:20:39 -0700256}
257
258/*
259 * Check for HCLK state
260 */
261static int check_hclk_state(unsigned int core_num, int enable)
262{
Vadim Bendebury3afa03e2014-04-10 14:20:39 -0700263 return check_bit_state(CLK_HALT_CFPB_STATEB_REG,
264 hclk_state[core_num], enable, 5);
265}
266
267/*
268 * Check for QUP APPS CLK state
269 */
270static int check_qup_clk_state(unsigned int core_num, int enable)
271{
Vadim Bendebury3afa03e2014-04-10 14:20:39 -0700272 return check_bit_state(CLK_HALT_CFPB_STATEB_REG,
273 qup_apps_clk_state[core_num], enable, 5);
274}
275
276/*
277 * Function to assert and De-assert chip select
278 */
279static void CS_change(int port_num, int cs_num, int enable)
280{
281 unsigned int cs_gpio = cs_gpio_array[port_num][cs_num];
Vadim Bendeburyd36ef6a2014-07-25 17:34:42 -0700282 void *addr = GPIO_IN_OUT_ADDR(cs_gpio);
Vadim Bendeburydffd8922014-04-30 13:25:12 -0700283 uint32_t val = readl_i(addr);
Vadim Bendebury3afa03e2014-04-10 14:20:39 -0700284
Vadim Bendebury0b70bd12014-06-23 10:41:38 -0700285 val &= (~(1 << GPIO_OUTPUT));
Vadim Bendebury3afa03e2014-04-10 14:20:39 -0700286 if (!enable)
Vadim Bendebury0b70bd12014-06-23 10:41:38 -0700287 val |= (1 << GPIO_OUTPUT);
Julius Werner2f37bd62015-02-19 14:51:15 -0800288 write32(addr, val);
Vadim Bendebury3afa03e2014-04-10 14:20:39 -0700289}
290
291/*
292 * GSBIn TLMM configuration
293 */
294static void gsbi_pin_config(unsigned int port_num, int cs_num)
295{
296 unsigned int gpio;
297 unsigned int i;
298 /* Hold the GSBIn (core_num) core in reset */
Vadim Bendeburydffd8922014-04-30 13:25:12 -0700299 clrsetbits_le32_i(GSBIn_RESET_REG(GSBI_IDX_TO_GSBI(port_num)),
Vadim Bendebury3afa03e2014-04-10 14:20:39 -0700300 GSBI1_RESET_MSK, GSBI1_RESET);
301
302 /*
303 * Configure SPI_CLK, SPI_MISO and SPI_MOSI
304 */
305 for (i = 0; i < NUM_GSBI_PINS; i++) {
306 unsigned int func_sel;
307 unsigned int io_config;
308 unsigned int pull_config;
309 unsigned int drv_strength;
310 unsigned int gpio_en;
311 unsigned int *ptr;
312
313 ptr = gsbi_pin_conf[port_num][i];
314 gpio = *(ptr + GSBI_PIN_IDX);
315 func_sel = *(ptr + FUNC_SEL_IDX);
316 io_config = *(ptr + GPIO_DIR_IDX);
317 pull_config = *(ptr + PULL_CONF_IDX);
318 drv_strength = *(ptr + DRV_STR_IDX);
319 gpio_en = *(ptr + GPIO_EN_IDX);
320
321 gpio_tlmm_config(gpio, func_sel, io_config,
322 pull_config, drv_strength, gpio_en);
323 }
324
325 gpio = cs_gpio_array[port_num][cs_num];
326 /* configure CS */
327 gpio_tlmm_config(gpio, FUNC_SEL_GPIO, GPIO_OUTPUT, GPIO_PULL_UP,
328 GPIO_DRV_STR_10MA, GPIO_FUNC_ENABLE);
329 CS_change(port_num, cs_num, CS_DEASSERT);
330}
331
332/*
333 * Clock configuration for GSBIn Core
334 */
335static int gsbi_clock_init(struct ipq_spi_slave *ds)
336{
337 int ret;
338
339 /* Hold the GSBIn (core_num) core in reset */
Vadim Bendeburydffd8922014-04-30 13:25:12 -0700340 clrsetbits_le32_i(GSBIn_RESET_REG(GSBI_IDX_TO_GSBI(ds->slave.bus)),
Vadim Bendebury3afa03e2014-04-10 14:20:39 -0700341 GSBI1_RESET_MSK, GSBI1_RESET);
342
343 /* Disable GSBIn (core_num) QUP core clock branch */
Vadim Bendeburydffd8922014-04-30 13:25:12 -0700344 clrsetbits_le32_i(ds->regs->qup_ns_reg, QUP_CLK_BRANCH_ENA_MSK,
Vadim Bendebury3afa03e2014-04-10 14:20:39 -0700345 QUP_CLK_BRANCH_DIS);
346
347 ret = check_qup_clk_state(ds->slave.bus, 1);
348 if (ret) {
Vadim Bendeburydffd8922014-04-30 13:25:12 -0700349 printk(BIOS_ERR,
350 "QUP Clock Halt For GSBI%d failed!\n", ds->slave.bus);
Vadim Bendebury3afa03e2014-04-10 14:20:39 -0700351 return ret;
352 }
353
354 /* Disable M/N:D counter and hold M/N:D counter in reset */
Vadim Bendeburydffd8922014-04-30 13:25:12 -0700355 clrsetbits_le32_i(ds->regs->qup_ns_reg, (MNCNTR_MSK | MNCNTR_RST_MSK),
Vadim Bendebury3afa03e2014-04-10 14:20:39 -0700356 (MNCNTR_RST_ENA | MNCNTR_DIS));
357
358 /* Disable GSBIn (core_num) QUP core clock root */
Vadim Bendeburydffd8922014-04-30 13:25:12 -0700359 clrsetbits_le32_i(ds->regs->qup_ns_reg, CLK_ROOT_ENA_MSK, CLK_ROOT_DIS);
Vadim Bendebury3afa03e2014-04-10 14:20:39 -0700360
Vadim Bendeburydffd8922014-04-30 13:25:12 -0700361 clrsetbits_le32_i(ds->regs->qup_ns_reg, GSBIn_PLL_SRC_MSK,
Vadim Bendebury3afa03e2014-04-10 14:20:39 -0700362 GSBIn_PLL_SRC_PLL8);
Vadim Bendeburydffd8922014-04-30 13:25:12 -0700363 clrsetbits_le32_i(ds->regs->qup_ns_reg, GSBIn_PRE_DIV_SEL_MSK,
Vadim Bendebury3afa03e2014-04-10 14:20:39 -0700364 (0 << GSBI_PRE_DIV_SEL_SHFT));
365
366 /* Program M/N:D values for GSBIn_QUP_APPS_CLK @50MHz */
Vadim Bendeburydffd8922014-04-30 13:25:12 -0700367 clrsetbits_le32_i(ds->regs->qup_md_reg, GSBIn_M_VAL_MSK,
Vadim Bendebury3afa03e2014-04-10 14:20:39 -0700368 (0x01 << GSBI_M_VAL_SHFT));
Vadim Bendeburydffd8922014-04-30 13:25:12 -0700369 clrsetbits_le32_i(ds->regs->qup_md_reg, GSBIn_D_VAL_MSK,
Vadim Bendebury3afa03e2014-04-10 14:20:39 -0700370 (0xF7 << GSBI_D_VAL_SHFT));
Vadim Bendeburydffd8922014-04-30 13:25:12 -0700371 clrsetbits_le32_i(ds->regs->qup_ns_reg, GSBIn_N_VAL_MSK,
Vadim Bendebury3afa03e2014-04-10 14:20:39 -0700372 (0xF8 << GSBI_N_VAL_SHFT));
373
374 /* Set MNCNTR_MODE = 0: Bypass mode */
Vadim Bendeburydffd8922014-04-30 13:25:12 -0700375 clrsetbits_le32_i(ds->regs->qup_ns_reg, MNCNTR_MODE_MSK,
Vadim Bendebury3afa03e2014-04-10 14:20:39 -0700376 MNCNTR_MODE_DUAL_EDGE);
377
378 /* De-assert the M/N:D counter reset */
Vadim Bendeburydffd8922014-04-30 13:25:12 -0700379 clrsetbits_le32_i(ds->regs->qup_ns_reg, MNCNTR_RST_MSK, MNCNTR_RST_DIS);
380 clrsetbits_le32_i(ds->regs->qup_ns_reg, MNCNTR_MSK, MNCNTR_EN);
Vadim Bendebury3afa03e2014-04-10 14:20:39 -0700381
382 /*
383 * Enable the GSBIn (core_num) QUP core clock root.
384 * Keep MND counter disabled
385 */
Vadim Bendeburydffd8922014-04-30 13:25:12 -0700386 clrsetbits_le32_i(ds->regs->qup_ns_reg, CLK_ROOT_ENA_MSK, CLK_ROOT_ENA);
Vadim Bendebury3afa03e2014-04-10 14:20:39 -0700387
388 /* Enable GSBIn (core_num) QUP core clock branch */
Vadim Bendeburydffd8922014-04-30 13:25:12 -0700389 clrsetbits_le32_i(ds->regs->qup_ns_reg, QUP_CLK_BRANCH_ENA_MSK,
Vadim Bendebury3afa03e2014-04-10 14:20:39 -0700390 QUP_CLK_BRANCH_ENA);
391
392 ret = check_qup_clk_state(ds->slave.bus, 0);
393 if (ret) {
Vadim Bendeburydffd8922014-04-30 13:25:12 -0700394 printk(BIOS_ERR,
395 "QUP Clock Enable For GSBI%d"
Vadim Bendebury3afa03e2014-04-10 14:20:39 -0700396 " failed!\n", ds->slave.bus);
397 return ret;
398 }
399
400 /* Enable GSBIn (core_num) core clock branch */
Vadim Bendeburydffd8922014-04-30 13:25:12 -0700401 clrsetbits_le32_i(GSBIn_HCLK_CTL_REG(GSBI_IDX_TO_GSBI(ds->slave.bus)),
Vadim Bendebury3afa03e2014-04-10 14:20:39 -0700402 GSBI_CLK_BRANCH_ENA_MSK, GSBI_CLK_BRANCH_ENA);
403
404 ret = check_hclk_state(ds->slave.bus, 0);
405 if (ret) {
Vadim Bendeburydffd8922014-04-30 13:25:12 -0700406 printk(BIOS_ERR,
407 "HCLK Enable For GSBI%d failed!\n", ds->slave.bus);
Vadim Bendebury3afa03e2014-04-10 14:20:39 -0700408 return ret;
409 }
410
411 /* Release GSBIn (core_num) core from reset */
Vadim Bendeburydffd8922014-04-30 13:25:12 -0700412 clrsetbits_le32_i(GSBIn_RESET_REG(GSBI_IDX_TO_GSBI(ds->slave.bus)),
Vadim Bendebury3afa03e2014-04-10 14:20:39 -0700413 GSBI1_RESET_MSK, 0);
414 udelay(50);
415
416 return SUCCESS;
417}
418
419/*
420 * Reset entire QUP and all mini cores
421 */
422static void spi_reset(struct ipq_spi_slave *ds)
423{
Vadim Bendeburydffd8922014-04-30 13:25:12 -0700424 writel_i(0x1, ds->regs->qup_sw_reset);
Vadim Bendebury3afa03e2014-04-10 14:20:39 -0700425 udelay(5);
426}
427
Vadim Bendeburydffd8922014-04-30 13:25:12 -0700428static const struct gsbi_spi spi_reg[] = {
429 /* GSBI5 registers for SPI interface */
430 {
431 GSBI5_SPI_CONFIG_REG,
432 GSBI5_SPI_IO_CONTROL_REG,
433 GSBI5_SPI_ERROR_FLAGS_REG,
434 GSBI5_SPI_ERROR_FLAGS_EN_REG,
435 GSBI5_GSBI_CTRL_REG_REG,
436 GSBI5_QUP_CONFIG_REG,
437 GSBI5_QUP_ERROR_FLAGS_REG,
438 GSBI5_QUP_ERROR_FLAGS_EN_REG,
439 GSBI5_QUP_OPERATIONAL_REG,
440 GSBI5_QUP_IO_MODES_REG,
441 GSBI5_QUP_STATE_REG,
442 GSBI5_QUP_INPUT_FIFOc_REG(0),
443 GSBI5_QUP_OUTPUT_FIFOc_REG(0),
444 GSBI5_QUP_MX_INPUT_COUNT_REG,
445 GSBI5_QUP_MX_OUTPUT_COUNT_REG,
446 GSBI5_QUP_SW_RESET_REG,
447 GSBIn_QUP_APPS_NS_REG(5),
448 GSBIn_QUP_APPS_MD_REG(5),
449 },
450 /* GSBI6 registers for SPI interface */
451 {
452 GSBI6_SPI_CONFIG_REG,
453 GSBI6_SPI_IO_CONTROL_REG,
454 GSBI6_SPI_ERROR_FLAGS_REG,
455 GSBI6_SPI_ERROR_FLAGS_EN_REG,
456 GSBI6_GSBI_CTRL_REG_REG,
457 GSBI6_QUP_CONFIG_REG,
458 GSBI6_QUP_ERROR_FLAGS_REG,
459 GSBI6_QUP_ERROR_FLAGS_EN_REG,
460 GSBI6_QUP_OPERATIONAL_REG,
461 GSBI6_QUP_IO_MODES_REG,
462 GSBI6_QUP_STATE_REG,
463 GSBI6_QUP_INPUT_FIFOc_REG(0),
464 GSBI6_QUP_OUTPUT_FIFOc_REG(0),
465 GSBI6_QUP_MX_INPUT_COUNT_REG,
466 GSBI6_QUP_MX_OUTPUT_COUNT_REG,
467 GSBI6_QUP_SW_RESET_REG,
468 GSBIn_QUP_APPS_NS_REG(6),
469 GSBIn_QUP_APPS_MD_REG(6),
470 },
471 /* GSBI7 registers for SPI interface */
472 {
473 GSBI7_SPI_CONFIG_REG,
474 GSBI7_SPI_IO_CONTROL_REG,
475 GSBI7_SPI_ERROR_FLAGS_REG,
476 GSBI7_SPI_ERROR_FLAGS_EN_REG,
477 GSBI7_GSBI_CTRL_REG_REG,
478 GSBI7_QUP_CONFIG_REG,
479 GSBI7_QUP_ERROR_FLAGS_REG,
480 GSBI7_QUP_ERROR_FLAGS_EN_REG,
481 GSBI7_QUP_OPERATIONAL_REG,
482 GSBI7_QUP_IO_MODES_REG,
483 GSBI7_QUP_STATE_REG,
484 GSBI7_QUP_INPUT_FIFOc_REG(0),
485 GSBI7_QUP_OUTPUT_FIFOc_REG(0),
486 GSBI7_QUP_MX_INPUT_COUNT_REG,
487 GSBI7_QUP_MX_OUTPUT_COUNT_REG,
488 GSBI7_QUP_SW_RESET_REG,
489 GSBIn_QUP_APPS_NS_REG(7),
490 GSBIn_QUP_APPS_MD_REG(7),
491 }
492};
493static struct ipq_spi_slave spi_slave_pool[2];
494
Vadim Bendebury3afa03e2014-04-10 14:20:39 -0700495void spi_init()
496{
Vadim Bendeburydffd8922014-04-30 13:25:12 -0700497 /* just in case */
498 memset(spi_slave_pool, 0, sizeof(spi_slave_pool));
Vadim Bendebury3afa03e2014-04-10 14:20:39 -0700499}
500
Vadim Bendeburydffd8922014-04-30 13:25:12 -0700501struct spi_slave *spi_setup_slave(unsigned int bus, unsigned int cs)
Vadim Bendebury3afa03e2014-04-10 14:20:39 -0700502{
Vadim Bendeburydffd8922014-04-30 13:25:12 -0700503 struct ipq_spi_slave *ds = NULL;
504 int i;
Vadim Bendebury3afa03e2014-04-10 14:20:39 -0700505
506 /*
507 * IPQ GSBI (Generic Serial Bus Interface) supports SPI Flash
508 * on different GSBI5, GSBI6 and GSBI7
509 * with different number of chip selects (CS, channels):
510 */
511 if ((bus < GSBI5_SPI) || (bus > GSBI7_SPI)
512 || ((bus == GSBI5_SPI) && (cs > 3))
513 || ((bus == GSBI6_SPI) && (cs > 0))
514 || ((bus == GSBI7_SPI) && (cs > 0))) {
Vadim Bendeburydffd8922014-04-30 13:25:12 -0700515 printk(BIOS_ERR, "SPI error: unsupported bus %d "
Vadim Bendebury3afa03e2014-04-10 14:20:39 -0700516 "(Supported busses 0,1 and 2) or chipselect\n", bus);
Vadim Bendebury3afa03e2014-04-10 14:20:39 -0700517 }
Vadim Bendebury3afa03e2014-04-10 14:20:39 -0700518
Vadim Bendeburydffd8922014-04-30 13:25:12 -0700519 for (i = 0; i < ARRAY_SIZE(spi_slave_pool); i++) {
520 if (spi_slave_pool[i].allocated)
521 continue;
522 ds = spi_slave_pool + i;
523 ds->slave.bus = bus;
524 ds->slave.cs = cs;
525 ds->regs = &spi_reg[bus];
Vadim Bendebury3afa03e2014-04-10 14:20:39 -0700526
Vadim Bendeburydffd8922014-04-30 13:25:12 -0700527 /*
528 * TODO(vbendeb):
529 * hardcoded frequency and mode - we might need to find a way
530 * to configure this
531 */
532 ds->freq = 10000000;
533 ds->mode = GSBI_SPI_MODE_0;
534 ds->allocated = 1;
535
536 return &ds->slave;
Vadim Bendebury3afa03e2014-04-10 14:20:39 -0700537 }
Vadim Bendebury3afa03e2014-04-10 14:20:39 -0700538
Vadim Bendeburydffd8922014-04-30 13:25:12 -0700539 printk(BIOS_ERR, "SPI error: all %d pools busy\n", i);
Vadim Bendebury3afa03e2014-04-10 14:20:39 -0700540 return NULL;
541}
542
Vadim Bendebury3afa03e2014-04-10 14:20:39 -0700543/*
544 * GSBIn SPI Hardware Initialisation
545 */
546static int spi_hw_init(struct ipq_spi_slave *ds)
547{
548 int ret;
549
Vadim Bendeburydffd8922014-04-30 13:25:12 -0700550 if (ds->initialized)
551 return 0;
Vadim Bendebury3afa03e2014-04-10 14:20:39 -0700552
553 /* GSBI module configuration */
554 spi_reset(ds);
555
556 /* Set the GSBIn QUP state */
557 ret = config_spi_state(ds, SPI_RESET_STATE);
558 if (ret)
559 return ret;
560
561 /* Configure GSBI_CTRL register to set protocol_mode to SPI:011 */
Vadim Bendeburydffd8922014-04-30 13:25:12 -0700562 clrsetbits_le32_i(ds->regs->gsbi_ctrl, PROTOCOL_CODE_MSK,
Vadim Bendebury3afa03e2014-04-10 14:20:39 -0700563 PROTOCOL_CODE_SPI);
564
565 /*
566 * Configure Mini core to SPI core with Input Output enabled,
567 * SPI master, N = 8 bits
568 */
Vadim Bendeburydffd8922014-04-30 13:25:12 -0700569 clrsetbits_le32_i(ds->regs->qup_config, (QUP_CONFIG_MINI_CORE_MSK |
Vadim Bendebury3afa03e2014-04-10 14:20:39 -0700570 SPI_QUP_CONF_INPUT_MSK |
571 SPI_QUP_CONF_OUTPUT_MSK |
572 SPI_BIT_WORD_MSK),
573 (QUP_CONFIG_MINI_CORE_SPI |
Vadim Bendeburydffd8922014-04-30 13:25:12 -0700574 SPI_QUP_CONF_NO_INPUT |
575 SPI_QUP_CONF_NO_OUTPUT |
Vadim Bendebury3afa03e2014-04-10 14:20:39 -0700576 SPI_8_BIT_WORD));
577
578 /*
579 * Configure Input first SPI protocol,
580 * SPI master mode and no loopback
581 */
Vadim Bendeburydffd8922014-04-30 13:25:12 -0700582 clrsetbits_le32_i(ds->regs->spi_config, (LOOP_BACK_MSK |
Vadim Bendebury3afa03e2014-04-10 14:20:39 -0700583 SLAVE_OPERATION_MSK),
584 (NO_LOOP_BACK |
585 SLAVE_OPERATION));
586
587 /*
588 * Configure SPI IO Control Register
589 * CLK_ALWAYS_ON = 0
590 * MX_CS_MODE = 0
591 * NO_TRI_STATE = 1
592 */
Vadim Bendeburydffd8922014-04-30 13:25:12 -0700593 writel_i((CLK_ALWAYS_ON | MX_CS_MODE | NO_TRI_STATE),
Vadim Bendebury3afa03e2014-04-10 14:20:39 -0700594 ds->regs->io_control);
595
596 /*
597 * Configure SPI IO Modes.
598 * OUTPUT_BIT_SHIFT_EN = 1
599 * INPUT_MODE = Block Mode
600 * OUTPUT MODE = Block Mode
601 */
Vadim Bendeburydffd8922014-04-30 13:25:12 -0700602 clrsetbits_le32_i(ds->regs->qup_io_modes, (OUTPUT_BIT_SHIFT_MSK |
Vadim Bendebury3afa03e2014-04-10 14:20:39 -0700603 INPUT_BLOCK_MODE_MSK |
604 OUTPUT_BLOCK_MODE_MSK),
605 (OUTPUT_BIT_SHIFT_EN |
606 INPUT_BLOCK_MODE |
607 OUTPUT_BLOCK_MODE));
608
609 spi_set_mode(ds, ds->mode);
610
611 /* Disable Error mask */
Vadim Bendeburydffd8922014-04-30 13:25:12 -0700612 writel_i(0, ds->regs->error_flags_en);
613 writel_i(0, ds->regs->qup_error_flags_en);
Vadim Bendebury3afa03e2014-04-10 14:20:39 -0700614
615 ds->initialized = 1;
616
617 return SUCCESS;
618}
619
620int spi_claim_bus(struct spi_slave *slave)
621{
622 struct ipq_spi_slave *ds = to_ipq_spi(slave);
623 unsigned int ret;
624
Vadim Bendeburydffd8922014-04-30 13:25:12 -0700625 if (ds->initialized)
626 return SUCCESS;
627
Vadim Bendebury3afa03e2014-04-10 14:20:39 -0700628 /* GPIO Configuration for SPI port */
629 gsbi_pin_config(ds->slave.bus, ds->slave.cs);
630
631 /* Clock configuration */
632 ret = gsbi_clock_init(ds);
633 if (ret)
634 return ret;
635
636 ret = spi_hw_init(ds);
637 if (ret)
638 return -EIO;
639
640 return SUCCESS;
641}
642
643void spi_release_bus(struct spi_slave *slave)
644{
645 struct ipq_spi_slave *ds = to_ipq_spi(slave);
646
647 /* Reset the SPI hardware */
648 spi_reset(ds);
649 ds->initialized = 0;
650}
651
David Hendricks68ec2fc2014-07-25 12:59:48 -0700652static int spi_xfer_tx_packet(struct ipq_spi_slave *ds,
653 const uint8_t *dout, unsigned out_bytes)
654{
655 int ret;
656
657 writel_i(out_bytes, ds->regs->qup_mx_output_count);
658
659 ret = config_spi_state(ds, SPI_RUN_STATE);
660 if (ret)
661 return ret;
662
663 while (out_bytes) {
664 if (readl_i(ds->regs->qup_operational) & QUP_OUTPUT_FIFO_FULL)
665 continue;
666
667 writel_i(*dout++, ds->regs->qup_output_fifo);
668 out_bytes--;
669
670 /* Wait for output FIFO to drain. */
671 if (!out_bytes)
672 while (readl_i(ds->regs->qup_operational) &
673 QUP_OUTPUT_FIFO_NOT_EMPTY)
674 ;
675 }
676
677 return config_spi_state(ds, SPI_RESET_STATE);
678}
679
680static int spi_xfer_rx_packet(struct ipq_spi_slave *ds,
681 uint8_t *din, unsigned in_bytes)
682{
683 int ret;
684
685 writel_i(in_bytes, ds->regs->qup_mx_input_count);
686 writel_i(in_bytes, ds->regs->qup_mx_output_count);
687
688 ret = config_spi_state(ds, SPI_RUN_STATE);
689 if (ret)
690 return ret;
691
692 /* Seed clocking */
693 writel_i(0xff, ds->regs->qup_output_fifo);
694 while (in_bytes) {
695 if (!(readl_i(ds->regs->qup_operational) &
696 QUP_INPUT_FIFO_NOT_EMPTY))
697 continue;
698 /* Keep it clocking */
699 writel_i(0xff, ds->regs->qup_output_fifo);
700
701 *din++ = readl_i(ds->regs->qup_input_fifo) & 0xff;
702 in_bytes--;
703 }
704
705 return config_spi_state(ds, SPI_RESET_STATE);
706}
707
Patrick Georgi3b1c2382015-04-16 17:15:02 +0200708unsigned int spi_crop_chunk(unsigned int cmd_len, unsigned int buf_len)
709{
710 return min(MAX_PACKET_COUNT, buf_len);
711}
712
Vadim Bendeburydffd8922014-04-30 13:25:12 -0700713int spi_xfer(struct spi_slave *slave, const void *dout,
714 unsigned out_bytes, void *din, unsigned in_bytes)
Vadim Bendebury3afa03e2014-04-10 14:20:39 -0700715{
Vadim Bendebury3afa03e2014-04-10 14:20:39 -0700716 int ret;
Vadim Bendeburydffd8922014-04-30 13:25:12 -0700717 struct ipq_spi_slave *ds = to_ipq_spi(slave);
Vadim Bendebury3afa03e2014-04-10 14:20:39 -0700718
Vadim Bendeburydffd8922014-04-30 13:25:12 -0700719 /* Assert the chip select */
720 CS_change(ds->slave.bus, ds->slave.cs, CS_ASSERT);
721
722 ret = config_spi_state(ds, SPI_RESET_STATE);
723 if (ret)
724 goto out;
725
726 if (!out_bytes)
727 goto spi_receive;
728
729 /*
730 * Let's do the write side of the transaction first. Enable output
731 * FIFO.
732 */
733 clrsetbits_le32_i(ds->regs->qup_config, SPI_QUP_CONF_OUTPUT_MSK,
734 SPI_QUP_CONF_OUTPUT_ENA);
735
Vadim Bendeburydffd8922014-04-30 13:25:12 -0700736 while (out_bytes) {
David Hendricks68ec2fc2014-07-25 12:59:48 -0700737 unsigned todo = MIN(out_bytes, MAX_PACKET_COUNT);
Vadim Bendeburydffd8922014-04-30 13:25:12 -0700738
David Hendricks68ec2fc2014-07-25 12:59:48 -0700739 ret = spi_xfer_tx_packet(ds, dout, todo);
740 if (ret)
741 break;
Vadim Bendeburydffd8922014-04-30 13:25:12 -0700742
David Hendricks68ec2fc2014-07-25 12:59:48 -0700743 out_bytes -= todo;
744 dout += todo;
Vadim Bendebury3afa03e2014-04-10 14:20:39 -0700745 }
746
Vadim Bendeburydffd8922014-04-30 13:25:12 -0700747 if (ret)
748 goto out;
Vadim Bendebury3afa03e2014-04-10 14:20:39 -0700749
Vadim Bendeburydffd8922014-04-30 13:25:12 -0700750spi_receive:
751 if (!in_bytes) /* Nothing to read. */
752 goto out;
753
754 /* Enable input FIFO */
755 clrsetbits_le32_i(ds->regs->qup_config, SPI_QUP_CONF_INPUT_MSK,
756 SPI_QUP_CONF_INPUT_ENA);
757
Vadim Bendeburydffd8922014-04-30 13:25:12 -0700758 while (in_bytes) {
David Hendricks68ec2fc2014-07-25 12:59:48 -0700759 unsigned todo = MIN(in_bytes, MAX_PACKET_COUNT);
Vadim Bendeburydffd8922014-04-30 13:25:12 -0700760
David Hendricks68ec2fc2014-07-25 12:59:48 -0700761 ret = spi_xfer_rx_packet(ds, din, todo);
762 if (ret)
763 break;
764
765 in_bytes -= todo;
766 din += todo;
Vadim Bendebury3afa03e2014-04-10 14:20:39 -0700767 }
768
David Hendricks68ec2fc2014-07-25 12:59:48 -0700769out:
Vadim Bendeburydffd8922014-04-30 13:25:12 -0700770 /* Deassert CS */
771 CS_change(ds->slave.bus, ds->slave.cs, CS_DEASSERT);
Vadim Bendebury3afa03e2014-04-10 14:20:39 -0700772
Vadim Bendeburydffd8922014-04-30 13:25:12 -0700773 /*
774 * Put the SPI Core back in the Reset State
775 * to end the transfer
776 */
777 (void)config_spi_state(ds, SPI_RESET_STATE);
Vadim Bendebury3afa03e2014-04-10 14:20:39 -0700778
779 return ret;
780}