blob: 2b54700425fe0f8b0991833a6bc2462de8d10d1b [file] [log] [blame]
Konstantin Porotchkin01c84d42018-02-26 16:01:57 +02001/*
2 * Copyright (C) 2018 Marvell International Ltd.
3 *
4 * SPDX-License-Identifier: BSD-3-Clause
5 * https://spdx.org/licenses
6 */
7
8/* MCI bus driver for Marvell ARMADA 8K and 8K+ SoCs */
9
Antonio Nino Diaze0f90632018-12-14 00:18:21 +000010#include <common/debug.h>
11#include <drivers/delay_timer.h>
12#include <drivers/marvell/mci.h>
13#include <lib/mmio.h>
14
Konstantin Porotchkin01c84d42018-02-26 16:01:57 +020015#include <mvebu.h>
16#include <mvebu_def.h>
17#include <plat_marvell.h>
18
19/* /HB /Units /Direct_regs /Direct regs
20 * /Configuration Register Write/Read Data Register
21 */
22#define MCI_WRITE_READ_DATA_REG(mci_index) \
23 MVEBU_MCI_REG_BASE_REMAP(mci_index)
24/* /HB /Units /Direct_regs /Direct regs
25 * /Configuration Register Access Command Register
26 */
27#define MCI_ACCESS_CMD_REG(mci_index) \
28 (MVEBU_MCI_REG_BASE_REMAP(mci_index) + 0x4)
29
30/* Access Command fields :
31 * bit[3:0] - Sub command: 1 => Peripheral Config Register Read,
32 * 0 => Peripheral Config Register Write,
33 * 2 => Peripheral Assign ID request,
34 * 3 => Circular Config Write
35 * bit[5] - 1 => Local (same chip access) 0 => Remote
36 * bit[15:8] - Destination hop ID. Put Global ID (GID) here (see scheme below).
37 * bit[23:22] - 0x3 IHB PHY REG address space, 0x0 IHB Controller space
38 * bit[21:16] - Low 6 bits of offset. Hight 2 bits are taken from bit[28:27]
39 * of IHB_PHY_CTRL
40 * (must be set before any PHY register access occurs):
41 * /IHB_REG /IHB_REGInterchip Hopping Bus Registers
42 * /IHB Version Control Register
43 *
44 * ixi_ihb_top IHB PHY
45 * AXI ----------------------------- -------------
46 * <--| axi_hb_top | ihb_pipe_top |-->| |
47 * -->| GID=1 | GID=0 |<--| |
48 * ----------------------------- -------------
49 */
50#define MCI_INDIRECT_CTRL_READ_CMD 0x1
51#define MCI_INDIRECT_CTRL_ASSIGN_CMD 0x2
52#define MCI_INDIRECT_CTRL_CIRCULAR_CMD 0x3
53#define MCI_INDIRECT_CTRL_LOCAL_PKT (1 << 5)
54#define MCI_INDIRECT_CTRL_CMD_DONE_OFFSET 6
55#define MCI_INDIRECT_CTRL_CMD_DONE \
56 (1 << MCI_INDIRECT_CTRL_CMD_DONE_OFFSET)
57#define MCI_INDIRECT_CTRL_DATA_READY_OFFSET 7
58#define MCI_INDIRECT_CTRL_DATA_READY \
59 (1 << MCI_INDIRECT_CTRL_DATA_READY_OFFSET)
60#define MCI_INDIRECT_CTRL_HOPID_OFFSET 8
61#define MCI_INDIRECT_CTRL_HOPID(id) \
62 (((id) & 0xFF) << MCI_INDIRECT_CTRL_HOPID_OFFSET)
63#define MCI_INDIRECT_CTRL_REG_CHIPID_OFFSET 16
64#define MCI_INDIRECT_REG_CTRL_ADDR(reg_num) \
65 (reg_num << MCI_INDIRECT_CTRL_REG_CHIPID_OFFSET)
66
67/* Hop ID values */
68#define GID_IHB_PIPE 0
69#define GID_AXI_HB 1
70#define GID_IHB_EXT 2
71
72#define MCI_DID_GLOBAL_ASSIGNMENT_REQUEST_REG 0x2
73/* Target MCi Local ID (LID, which is = self DID) */
74#define MCI_DID_GLOBAL_ASSIGN_REQ_MCI_LOCAL_ID(val) (((val) & 0xFF) << 16)
75/* Bits [15:8]: Number of MCis on chip of target MCi */
76#define MCI_DID_GLOBAL_ASSIGN_REQ_MCI_COUNT(val) (((val) & 0xFF) << 8)
77/* Bits [7:0]: Number of hops on chip of target MCi */
78#define MCI_DID_GLOBAL_ASSIGN_REQ_HOPS_NUM(val) (((val) & 0xFF) << 0)
79
80/* IHB_REG domain registers */
81/* /HB /Units /IHB_REG /IHB_REGInterchip Hopping Bus Registers/
82 * Rx Memory Configuration Register (RX_MEM_CFG)
83 */
84#define MCI_CTRL_RX_MEM_CFG_REG_NUM 0x0
85#define MCI_CTRL_RX_TX_MEM_CFG_RQ_THRESH(val) (((val) & 0xFF) << 24)
86#define MCI_CTRL_RX_TX_MEM_CFG_PQ_THRESH(val) (((val) & 0xFF) << 16)
87#define MCI_CTRL_RX_TX_MEM_CFG_NQ_THRESH(val) (((val) & 0xFF) << 8)
88#define MCI_CTRL_RX_TX_MEM_CFG_DELTA_THRESH(val) (((val) & 0xF) << 4)
89#define MCI_CTRL_RX_TX_MEM_CFG_RTC(val) (((val) & 0x3) << 2)
90#define MCI_CTRL_RX_TX_MEM_CFG_WTC(val) (((val) & 0x3) << 0)
91#define MCI_CTRL_RX_MEM_CFG_REG_DEF_CP_VAL \
92 (MCI_CTRL_RX_TX_MEM_CFG_RQ_THRESH(0x07) | \
93 MCI_CTRL_RX_TX_MEM_CFG_PQ_THRESH(0x3f) | \
94 MCI_CTRL_RX_TX_MEM_CFG_NQ_THRESH(0x3f) | \
95 MCI_CTRL_RX_TX_MEM_CFG_DELTA_THRESH(0xf) | \
96 MCI_CTRL_RX_TX_MEM_CFG_RTC(1) | \
97 MCI_CTRL_RX_TX_MEM_CFG_WTC(1))
98
99#define MCI_CTRL_RX_MEM_CFG_REG_DEF_AP_VAL \
100 (MCI_CTRL_RX_TX_MEM_CFG_RQ_THRESH(0x3f) | \
101 MCI_CTRL_RX_TX_MEM_CFG_PQ_THRESH(0x03) | \
102 MCI_CTRL_RX_TX_MEM_CFG_NQ_THRESH(0x3f) | \
103 MCI_CTRL_RX_TX_MEM_CFG_DELTA_THRESH(0xf) | \
104 MCI_CTRL_RX_TX_MEM_CFG_RTC(1) | \
105 MCI_CTRL_RX_TX_MEM_CFG_WTC(1))
106
107
108/* /HB /Units /IHB_REG /IHB_REGInterchip Hopping Bus Registers/
109 * Tx Memory Configuration Register (TX_MEM_CFG)
110 */
111#define MCI_CTRL_TX_MEM_CFG_REG_NUM 0x1
112/* field mapping for TX mem config register
113 * are the same as for RX register - see register above
114 */
115#define MCI_CTRL_TX_MEM_CFG_REG_DEF_VAL \
116 (MCI_CTRL_RX_TX_MEM_CFG_RQ_THRESH(0x20) | \
117 MCI_CTRL_RX_TX_MEM_CFG_PQ_THRESH(0x20) | \
118 MCI_CTRL_RX_TX_MEM_CFG_NQ_THRESH(0x20) | \
119 MCI_CTRL_RX_TX_MEM_CFG_DELTA_THRESH(2) | \
120 MCI_CTRL_RX_TX_MEM_CFG_RTC(1) | \
121 MCI_CTRL_RX_TX_MEM_CFG_WTC(1))
122
123/* /HB /Units /IHB_REG /IHB_REGInterchip Hopping Bus Registers
124 * /IHB Link CRC Control
125 */
126/* MCi Link CRC Control Register (MCi_CRC_CTRL) */
127#define MCI_LINK_CRC_CTRL_REG_NUM 0x4
128
129/* /HB /Units /IHB_REG /IHB_REGInterchip Hopping Bus Registers
130 * /IHB Status Register
131 */
132/* MCi Status Register (MCi_STS) */
133#define MCI_CTRL_STATUS_REG_NUM 0x5
134#define MCI_CTRL_STATUS_REG_PHY_READY (1 << 12)
135#define MCI_CTRL_STATUS_REG_LINK_PRESENT (1 << 15)
136#define MCI_CTRL_STATUS_REG_PHY_CID_VIO_OFFSET 24
137#define MCI_CTRL_STATUS_REG_PHY_CID_VIO_MASK \
138 (0xF << MCI_CTRL_STATUS_REG_PHY_CID_VIO_OFFSET)
139/* Expected successful Link result, including reserved bit */
140#define MCI_CTRL_PHY_READY (MCI_CTRL_STATUS_REG_PHY_READY | \
141 MCI_CTRL_STATUS_REG_LINK_PRESENT | \
142 MCI_CTRL_STATUS_REG_PHY_CID_VIO_MASK)
143
144/* /HB /Units /IHB_REG /IHB_REGInterchip Hopping Bus Registers/
145 * MCi PHY Speed Settings Register (MCi_PHY_SETTING)
146 */
147#define MCI_CTRL_MCI_PHY_SETTINGS_REG_NUM 0x8
148#define MCI_CTRL_MCI_PHY_SET_DLO_FIFO_FULL_TRESH(val) (((val) & 0xF) << 28)
149#define MCI_CTRL_MCI_PHY_SET_PHY_MAX_SPEED(val) (((val) & 0xF) << 12)
150#define MCI_CTRL_MCI_PHY_SET_PHYCLK_SEL(val) (((val) & 0xF) << 8)
151#define MCI_CTRL_MCI_PHY_SET_REFCLK_FREQ_SEL(val) (((val) & 0xF) << 4)
152#define MCI_CTRL_MCI_PHY_SET_AUTO_LINK_EN(val) (((val) & 0x1) << 1)
153#define MCI_CTRL_MCI_PHY_SET_REG_DEF_VAL \
154 (MCI_CTRL_MCI_PHY_SET_DLO_FIFO_FULL_TRESH(0x3) | \
155 MCI_CTRL_MCI_PHY_SET_PHY_MAX_SPEED(0x3) | \
156 MCI_CTRL_MCI_PHY_SET_PHYCLK_SEL(0x2) | \
157 MCI_CTRL_MCI_PHY_SET_REFCLK_FREQ_SEL(0x1))
158#define MCI_CTRL_MCI_PHY_SET_REG_DEF_VAL2 \
159 (MCI_CTRL_MCI_PHY_SET_DLO_FIFO_FULL_TRESH(0x3) | \
160 MCI_CTRL_MCI_PHY_SET_PHY_MAX_SPEED(0x3) | \
161 MCI_CTRL_MCI_PHY_SET_PHYCLK_SEL(0x5) | \
162 MCI_CTRL_MCI_PHY_SET_REFCLK_FREQ_SEL(0x1))
163
164/* /HB /Units /IHB_REG /IHB_REGInterchip Hopping Bus Registers
165 * /IHB Mode Config
166 */
167#define MCI_CTRL_IHB_MODE_CFG_REG_NUM 0x25
168#define MCI_CTRL_IHB_MODE_HBCLK_DIV(val) ((val) & 0xFF)
169#define MCI_CTRL_IHB_MODE_CHUNK_MOD_OFFSET 8
170#define MCI_CTRL_IHB_MODE_CHUNK_MOD \
171 (1 << MCI_CTRL_IHB_MODE_CHUNK_MOD_OFFSET)
172#define MCI_CTRL_IHB_MODE_FWD_MOD_OFFSET 9
173#define MCI_CTRL_IHB_MODE_FWD_MOD \
174 (1 << MCI_CTRL_IHB_MODE_FWD_MOD_OFFSET)
175#define MCI_CTRL_IHB_MODE_SEQFF_FINE_MOD(val) (((val) & 0xF) << 12)
176#define MCI_CTRL_IHB_MODE_RX_COMB_THRESH(val) (((val) & 0xFF) << 16)
177#define MCI_CTRL_IHB_MODE_TX_COMB_THRESH(val) (((val) & 0xFF) << 24)
178
179#define MCI_CTRL_IHB_MODE_CFG_REG_DEF_VAL \
180 (MCI_CTRL_IHB_MODE_HBCLK_DIV(6) | \
181 MCI_CTRL_IHB_MODE_FWD_MOD | \
182 MCI_CTRL_IHB_MODE_SEQFF_FINE_MOD(0xF) | \
183 MCI_CTRL_IHB_MODE_RX_COMB_THRESH(0x3f) | \
184 MCI_CTRL_IHB_MODE_TX_COMB_THRESH(0x40))
185/* AXI_HB registers */
186#define MCI_AXI_ACCESS_DATA_REG_NUM 0x0
187#define MCI_AXI_ACCESS_PCIE_MODE 1
188#define MCI_AXI_ACCESS_CACHE_CHECK_OFFSET 5
189#define MCI_AXI_ACCESS_CACHE_CHECK \
190 (1 << MCI_AXI_ACCESS_CACHE_CHECK_OFFSET)
191#define MCI_AXI_ACCESS_FORCE_POST_WR_OFFSET 6
192#define MCI_AXI_ACCESS_FORCE_POST_WR \
193 (1 << MCI_AXI_ACCESS_FORCE_POST_WR_OFFSET)
194#define MCI_AXI_ACCESS_DISABLE_CLK_GATING_OFFSET 9
195#define MCI_AXI_ACCESS_DISABLE_CLK_GATING \
196 (1 << MCI_AXI_ACCESS_DISABLE_CLK_GATING_OFFSET)
197
198/* /HB /Units /HB_REG /HB_REGHopping Bus Registers
199 * /Window 0 Address Mask Register
200 */
201#define MCI_HB_CTRL_WIN0_ADDRESS_MASK_REG_NUM 0x2
202
203/* /HB /Units /HB_REG /HB_REGHopping Bus Registers
204 * /Window 0 Destination Register
205 */
206#define MCI_HB_CTRL_WIN0_DESTINATION_REG_NUM 0x3
207#define MCI_HB_CTRL_WIN0_DEST_VALID_FLAG(val) (((val) & 0x1) << 16)
208#define MCI_HB_CTRL_WIN0_DEST_ID(val) (((val) & 0xFF) << 0)
209
210/* /HB /Units /HB_REG /HB_REGHopping Bus Registers /Tx Control Register */
211#define MCI_HB_CTRL_TX_CTRL_REG_NUM 0xD
212#define MCI_HB_CTRL_TX_CTRL_PCIE_MODE_OFFSET 24
213#define MCI_HB_CTRL_TX_CTRL_PCIE_MODE \
214 (1 << MCI_HB_CTRL_TX_CTRL_PCIE_MODE_OFFSET)
215#define MCI_HB_CTRL_TX_CTRL_PRI_TH_QOS(val) (((val) & 0xF) << 12)
216#define MCI_HB_CTRL_TX_CTRL_MAX_RD_CNT(val) (((val) & 0x1F) << 6)
217#define MCI_HB_CTRL_TX_CTRL_MAX_WR_CNT(val) (((val) & 0x1F) << 0)
218
219/* /HB /Units /IHB_REG /IHB_REGInterchip Hopping Bus Registers
220 * /IHB Version Control Register
221 */
222#define MCI_PHY_CTRL_REG_NUM 0x7
223#define MCI_PHY_CTRL_MCI_MINOR 0x8 /* BITS [3:0] */
224#define MCI_PHY_CTRL_MCI_MAJOR_OFFSET 4
225#define MCI_PHY_CTRL_MCI_MAJOR \
226 (1 << MCI_PHY_CTRL_MCI_MAJOR_OFFSET)
227#define MCI_PHY_CTRL_MCI_SLEEP_REQ_OFFSET 11
228#define MCI_PHY_CTRL_MCI_SLEEP_REQ \
229 (1 << MCI_PHY_CTRL_MCI_SLEEP_REQ_OFFSET)
230/* Host=1 / Device=0 PHY mode */
231#define MCI_PHY_CTRL_MCI_PHY_MODE_OFFSET 24
232#define MCI_PHY_CTRL_MCI_PHY_MODE_HOST \
233 (1 << MCI_PHY_CTRL_MCI_PHY_MODE_OFFSET)
234/* Register=1 / PWM=0 interface */
235#define MCI_PHY_CTRL_MCI_PHY_REG_IF_MODE_OFFSET 25
236#define MCI_PHY_CTRL_MCI_PHY_REG_IF_MODE \
237 (1 << MCI_PHY_CTRL_MCI_PHY_REG_IF_MODE_OFFSET)
238 /* PHY code InReset=1 */
239#define MCI_PHY_CTRL_MCI_PHY_RESET_CORE_OFFSET 26
240#define MCI_PHY_CTRL_MCI_PHY_RESET_CORE \
241 (1 << MCI_PHY_CTRL_MCI_PHY_RESET_CORE_OFFSET)
242#define MCI_PHY_CTRL_PHY_ADDR_MSB_OFFSET 27
243#define MCI_PHY_CTRL_PHY_ADDR_MSB(addr) \
244 (((addr) & 0x3) << \
245 MCI_PHY_CTRL_PHY_ADDR_MSB_OFFSET)
246#define MCI_PHY_CTRL_PIDI_MODE_OFFSET 31
247#define MCI_PHY_CTRL_PIDI_MODE \
Justin Chadwellfed41a12019-07-03 14:04:33 +0100248 (1U << MCI_PHY_CTRL_PIDI_MODE_OFFSET)
Konstantin Porotchkin01c84d42018-02-26 16:01:57 +0200249
250/* Number of times to wait for the MCI link ready after MCI configurations
251 * Normally takes 34-35 successive reads
252 */
253#define LINK_READY_TIMEOUT 100
254
255enum mci_register_type {
256 MCI_REG_TYPE_PHY = 0,
257 MCI_REG_TYPE_CTRL,
258};
259
260enum {
261 MCI_CMD_WRITE,
262 MCI_CMD_READ
263};
264
265/* Write wrapper callback for debug:
266 * will print written data in case LOG_LEVEL >= 40
267 */
268static void mci_mmio_write_32(uintptr_t addr, uint32_t value)
269{
270 VERBOSE("Write:\t0x%x = 0x%x\n", (uint32_t)addr, value);
271 mmio_write_32(addr, value);
272}
273/* Read wrapper callback for debug:
274 * will print read data in case LOG_LEVEL >= 40
275 */
276static uint32_t mci_mmio_read_32(uintptr_t addr)
277{
278 uint32_t value;
279
280 value = mmio_read_32(addr);
281 VERBOSE("Read:\t0x%x = 0x%x\n", (uint32_t)addr, value);
282 return value;
283}
284
285/* MCI indirect access command completion polling:
286 * Each write/read command done via MCI indirect registers must be polled
287 * for command completions status.
288 *
289 * Returns 1 in case of error
290 * Returns 0 in case of command completed successfully.
291 */
292static int mci_poll_command_completion(int mci_index, int command_type)
293{
294 uint32_t mci_cmd_value = 0, retry_count = 100, ret = 0;
295 uint32_t completion_flags = MCI_INDIRECT_CTRL_CMD_DONE;
296
297 debug_enter();
298 /* Read commands require validating that requested data is ready */
299 if (command_type == MCI_CMD_READ)
300 completion_flags |= MCI_INDIRECT_CTRL_DATA_READY;
301
302 do {
303 /* wait 1 ms before each polling */
304 mdelay(1);
305 mci_cmd_value = mci_mmio_read_32(MCI_ACCESS_CMD_REG(mci_index));
306 } while (((mci_cmd_value & completion_flags) != completion_flags) &&
307 (retry_count-- > 0));
308
309 if (retry_count == 0) {
310 ERROR("%s: MCI command timeout (command status = 0x%x)\n",
311 __func__, mci_cmd_value);
312 ret = 1;
313 }
314
315 debug_exit();
316 return ret;
317}
318
319int mci_read(int mci_idx, uint32_t cmd, uint32_t *value)
320{
321 int rval;
322
323 mci_mmio_write_32(MCI_ACCESS_CMD_REG(mci_idx), cmd);
324
325 rval = mci_poll_command_completion(mci_idx, MCI_CMD_READ);
326
327 *value = mci_mmio_read_32(MCI_WRITE_READ_DATA_REG(mci_idx));
328
329 return rval;
330}
331
332int mci_write(int mci_idx, uint32_t cmd, uint32_t data)
333{
334 mci_mmio_write_32(MCI_WRITE_READ_DATA_REG(mci_idx), data);
335 mci_mmio_write_32(MCI_ACCESS_CMD_REG(mci_idx), cmd);
336
337 return mci_poll_command_completion(mci_idx, MCI_CMD_WRITE);
338}
339
340/* Perform 3 configurations in one command: PCI mode,
341 * queues separation and cache bit
342 */
343static int mci_axi_set_pcie_mode(int mci_index)
344{
345 uint32_t reg_data, ret = 1;
346
347 debug_enter();
348 /* This configuration makes MCI IP behave consistently with AXI protocol
349 * It should be configured at one side only (for example locally at AP).
350 * The IP takes care of performing the same configurations at MCI on
351 * another side (for example remotely at CP).
352 */
353 mci_mmio_write_32(MCI_WRITE_READ_DATA_REG(mci_index),
354 MCI_AXI_ACCESS_PCIE_MODE |
355 MCI_AXI_ACCESS_CACHE_CHECK |
356 MCI_AXI_ACCESS_FORCE_POST_WR |
357 MCI_AXI_ACCESS_DISABLE_CLK_GATING);
358 mci_mmio_write_32(MCI_ACCESS_CMD_REG(mci_index),
359 MCI_INDIRECT_REG_CTRL_ADDR(
360 MCI_AXI_ACCESS_DATA_REG_NUM) |
361 MCI_INDIRECT_CTRL_HOPID(GID_AXI_HB) |
362 MCI_INDIRECT_CTRL_LOCAL_PKT |
363 MCI_INDIRECT_CTRL_CIRCULAR_CMD);
364
365 /* if Write command was successful, verify PCIe mode */
366 if (mci_poll_command_completion(mci_index, MCI_CMD_WRITE) == 0) {
367 /* Verify the PCIe mode selected */
368 mci_mmio_write_32(MCI_ACCESS_CMD_REG(mci_index),
369 MCI_INDIRECT_REG_CTRL_ADDR(
370 MCI_HB_CTRL_TX_CTRL_REG_NUM) |
371 MCI_INDIRECT_CTRL_HOPID(GID_AXI_HB) |
372 MCI_INDIRECT_CTRL_LOCAL_PKT |
373 MCI_INDIRECT_CTRL_READ_CMD);
374 /* if read was completed, verify PCIe mode */
375 if (mci_poll_command_completion(mci_index, MCI_CMD_READ) == 0) {
376 reg_data = mci_mmio_read_32(
377 MCI_WRITE_READ_DATA_REG(mci_index));
378 if (reg_data & MCI_HB_CTRL_TX_CTRL_PCIE_MODE)
379 ret = 0;
380 }
381 }
382
383 debug_exit();
384 return ret;
385}
386
387/* Reduce sequence FIFO timer expiration threshold */
388static int mci_axi_set_fifo_thresh(int mci_index)
389{
390 uint32_t reg_data, ret = 0;
391
392 debug_enter();
393 /* This configuration reduces sequence FIFO timer expiration threshold
394 * (to 0x7 instead of 0xA).
395 * In MCI 1.6 version this configuration prevents possible functional
396 * issues.
397 * In version 1.82 the configuration prevents performance degradation
398 */
399
400 /* Configure local AP side */
401 reg_data = MCI_PHY_CTRL_PIDI_MODE |
402 MCI_PHY_CTRL_MCI_PHY_REG_IF_MODE |
403 MCI_PHY_CTRL_MCI_PHY_MODE_HOST |
404 MCI_PHY_CTRL_MCI_MAJOR |
405 MCI_PHY_CTRL_MCI_MINOR;
406 mci_mmio_write_32(MCI_WRITE_READ_DATA_REG(mci_index), reg_data);
407 mci_mmio_write_32(MCI_ACCESS_CMD_REG(mci_index),
408 MCI_INDIRECT_REG_CTRL_ADDR(MCI_PHY_CTRL_REG_NUM) |
409 MCI_INDIRECT_CTRL_LOCAL_PKT);
410 ret |= mci_poll_command_completion(mci_index, MCI_CMD_WRITE);
411
412 /* Reduce the threshold */
413 mci_mmio_write_32(MCI_WRITE_READ_DATA_REG(mci_index),
414 MCI_CTRL_IHB_MODE_CFG_REG_DEF_VAL);
415
416 mci_mmio_write_32(MCI_ACCESS_CMD_REG(mci_index),
417 MCI_INDIRECT_REG_CTRL_ADDR(
418 MCI_CTRL_IHB_MODE_CFG_REG_NUM) |
419 MCI_INDIRECT_CTRL_LOCAL_PKT);
420 ret |= mci_poll_command_completion(mci_index, MCI_CMD_WRITE);
421
422 /* Exit PIDI mode */
423 reg_data = MCI_PHY_CTRL_MCI_PHY_REG_IF_MODE |
424 MCI_PHY_CTRL_MCI_PHY_MODE_HOST |
425 MCI_PHY_CTRL_MCI_MAJOR |
426 MCI_PHY_CTRL_MCI_MINOR;
427 mci_mmio_write_32(MCI_WRITE_READ_DATA_REG(mci_index), reg_data);
428 mci_mmio_write_32(MCI_ACCESS_CMD_REG(mci_index),
429 MCI_INDIRECT_REG_CTRL_ADDR(MCI_PHY_CTRL_REG_NUM) |
430 MCI_INDIRECT_CTRL_LOCAL_PKT);
431 ret |= mci_poll_command_completion(mci_index, MCI_CMD_WRITE);
432
433 /* Configure remote CP side */
434 reg_data = MCI_PHY_CTRL_PIDI_MODE |
435 MCI_PHY_CTRL_MCI_MAJOR |
436 MCI_PHY_CTRL_MCI_MINOR |
437 MCI_PHY_CTRL_MCI_PHY_REG_IF_MODE;
438 mci_mmio_write_32(MCI_WRITE_READ_DATA_REG(mci_index), reg_data);
439 mci_mmio_write_32(MCI_ACCESS_CMD_REG(mci_index),
440 MCI_INDIRECT_REG_CTRL_ADDR(MCI_PHY_CTRL_REG_NUM) |
441 MCI_CTRL_IHB_MODE_FWD_MOD);
442 ret |= mci_poll_command_completion(mci_index, MCI_CMD_WRITE);
443
444 /* Reduce the threshold */
445 mci_mmio_write_32(MCI_WRITE_READ_DATA_REG(mci_index),
446 MCI_CTRL_IHB_MODE_CFG_REG_DEF_VAL);
447 mci_mmio_write_32(MCI_ACCESS_CMD_REG(mci_index),
448 MCI_INDIRECT_REG_CTRL_ADDR(
449 MCI_CTRL_IHB_MODE_CFG_REG_NUM) |
450 MCI_INDIRECT_CTRL_HOPID(GID_IHB_EXT));
451 ret |= mci_poll_command_completion(mci_index, MCI_CMD_WRITE);
452
453 /* Exit PIDI mode */
454 reg_data = MCI_PHY_CTRL_MCI_MAJOR |
455 MCI_PHY_CTRL_MCI_MINOR |
456 MCI_PHY_CTRL_MCI_PHY_REG_IF_MODE;
457 mci_mmio_write_32(MCI_WRITE_READ_DATA_REG(mci_index), reg_data);
458 mci_mmio_write_32(MCI_ACCESS_CMD_REG(mci_index),
459 MCI_INDIRECT_REG_CTRL_ADDR(MCI_PHY_CTRL_REG_NUM) |
460 MCI_CTRL_IHB_MODE_FWD_MOD);
461
462 ret |= mci_poll_command_completion(mci_index, MCI_CMD_WRITE);
463
464 debug_exit();
465 return ret;
466}
467
468/* Configure:
469 * 1. AP & CP TX thresholds and delta configurations
470 * 2. DLO & DLI FIFO full threshold
471 * 3. RX thresholds and delta configurations
472 * 4. CP AR and AW outstanding
473 * 5. AP AR and AW outstanding
474 */
475static int mci_axi_set_fifo_rx_tx_thresh(int mci_index)
476{
477 uint32_t ret = 0;
478
479 debug_enter();
480 /* AP TX thresholds and delta configurations (IHB_reg 0x1) */
481 mci_mmio_write_32(MCI_WRITE_READ_DATA_REG(mci_index),
482 MCI_CTRL_TX_MEM_CFG_REG_DEF_VAL);
483 mci_mmio_write_32(MCI_ACCESS_CMD_REG(mci_index),
484 MCI_INDIRECT_REG_CTRL_ADDR(
485 MCI_CTRL_TX_MEM_CFG_REG_NUM) |
486 MCI_INDIRECT_CTRL_LOCAL_PKT);
487 ret |= mci_poll_command_completion(mci_index, MCI_CMD_WRITE);
488
489 /* CP TX thresholds and delta configurations (IHB_reg 0x1) */
490 mci_mmio_write_32(MCI_WRITE_READ_DATA_REG(mci_index),
491 MCI_CTRL_TX_MEM_CFG_REG_DEF_VAL);
492 mci_mmio_write_32(MCI_ACCESS_CMD_REG(mci_index),
493 MCI_INDIRECT_REG_CTRL_ADDR(
494 MCI_CTRL_TX_MEM_CFG_REG_NUM) |
495 MCI_INDIRECT_CTRL_HOPID(GID_IHB_EXT));
496 ret |= mci_poll_command_completion(mci_index, MCI_CMD_WRITE);
497
498 /* AP DLO & DLI FIFO full threshold & Auto-Link enable (IHB_reg 0x8) */
499 mci_mmio_write_32(MCI_WRITE_READ_DATA_REG(mci_index),
500 MCI_CTRL_MCI_PHY_SET_REG_DEF_VAL |
501 MCI_CTRL_MCI_PHY_SET_AUTO_LINK_EN(1));
502 mci_mmio_write_32(MCI_ACCESS_CMD_REG(mci_index),
503 MCI_INDIRECT_REG_CTRL_ADDR(
504 MCI_CTRL_MCI_PHY_SETTINGS_REG_NUM) |
505 MCI_INDIRECT_CTRL_LOCAL_PKT);
506 ret |= mci_poll_command_completion(mci_index, MCI_CMD_WRITE);
507
508 /* CP DLO & DLI FIFO full threshold (IHB_reg 0x8) */
509 mci_mmio_write_32(MCI_WRITE_READ_DATA_REG(mci_index),
510 MCI_CTRL_MCI_PHY_SET_REG_DEF_VAL);
511 mci_mmio_write_32(MCI_ACCESS_CMD_REG(mci_index),
512 MCI_INDIRECT_REG_CTRL_ADDR(
513 MCI_CTRL_MCI_PHY_SETTINGS_REG_NUM) |
514 MCI_INDIRECT_CTRL_HOPID(GID_IHB_EXT));
515 ret |= mci_poll_command_completion(mci_index, MCI_CMD_WRITE);
516
517 /* AP RX thresholds and delta configurations (IHB_reg 0x0) */
518 mci_mmio_write_32(MCI_WRITE_READ_DATA_REG(mci_index),
519 MCI_CTRL_RX_MEM_CFG_REG_DEF_AP_VAL);
520 mci_mmio_write_32(MCI_ACCESS_CMD_REG(mci_index),
521 MCI_INDIRECT_REG_CTRL_ADDR(
522 MCI_CTRL_RX_MEM_CFG_REG_NUM) |
523 MCI_INDIRECT_CTRL_LOCAL_PKT);
524 ret |= mci_poll_command_completion(mci_index, MCI_CMD_WRITE);
525
526 /* CP RX thresholds and delta configurations (IHB_reg 0x0) */
527 mci_mmio_write_32(MCI_WRITE_READ_DATA_REG(mci_index),
528 MCI_CTRL_RX_MEM_CFG_REG_DEF_CP_VAL);
529 mci_mmio_write_32(MCI_ACCESS_CMD_REG(mci_index),
530 MCI_INDIRECT_REG_CTRL_ADDR(
531 MCI_CTRL_RX_MEM_CFG_REG_NUM) |
532 MCI_INDIRECT_CTRL_HOPID(GID_IHB_EXT));
533 ret |= mci_poll_command_completion(mci_index, MCI_CMD_WRITE);
534
535 /* AP AR & AW maximum AXI outstanding request cfg (HB_reg 0xd) */
536 mci_mmio_write_32(MCI_WRITE_READ_DATA_REG(mci_index),
537 MCI_HB_CTRL_TX_CTRL_PRI_TH_QOS(8) |
538 MCI_HB_CTRL_TX_CTRL_MAX_RD_CNT(3) |
539 MCI_HB_CTRL_TX_CTRL_MAX_WR_CNT(3));
540 mci_mmio_write_32(MCI_ACCESS_CMD_REG(mci_index),
541 MCI_INDIRECT_REG_CTRL_ADDR(
542 MCI_HB_CTRL_TX_CTRL_REG_NUM) |
543 MCI_INDIRECT_CTRL_HOPID(GID_AXI_HB) |
544 MCI_INDIRECT_CTRL_LOCAL_PKT);
545 ret |= mci_poll_command_completion(mci_index, MCI_CMD_WRITE);
546
547 /* CP AR & AW maximum AXI outstanding request cfg (HB_reg 0xd) */
548 mci_mmio_write_32(MCI_WRITE_READ_DATA_REG(mci_index),
549 MCI_HB_CTRL_TX_CTRL_PRI_TH_QOS(8) |
550 MCI_HB_CTRL_TX_CTRL_MAX_RD_CNT(0xB) |
551 MCI_HB_CTRL_TX_CTRL_MAX_WR_CNT(0x11));
552 mci_mmio_write_32(MCI_ACCESS_CMD_REG(mci_index),
553 MCI_INDIRECT_REG_CTRL_ADDR(
554 MCI_HB_CTRL_TX_CTRL_REG_NUM) |
555 MCI_INDIRECT_CTRL_HOPID(GID_IHB_EXT) |
556 MCI_INDIRECT_CTRL_HOPID(GID_AXI_HB));
557 ret |= mci_poll_command_completion(mci_index, MCI_CMD_WRITE);
558
559 debug_exit();
560 return ret;
561}
562
563/* configure MCI to allow read & write transactions to arrive at the same time.
564 * Without the below configuration, MCI won't sent response to CPU for
565 * transactions which arrived simultaneously and will lead to CPU hang.
566 * The below will configure MCI to be able to pass transactions from/to CP/AP.
567 */
568static int mci_enable_simultaneous_transactions(int mci_index)
569{
570 uint32_t ret = 0;
571
572 debug_enter();
573 /* ID assignment (assigning global ID offset to CP) */
Grzegorz Jaszczyk582fdfd2019-02-06 14:16:51 +0100574 mci_mmio_write_32(MCI_WRITE_READ_DATA_REG(mci_index),
Konstantin Porotchkin01c84d42018-02-26 16:01:57 +0200575 MCI_DID_GLOBAL_ASSIGN_REQ_MCI_LOCAL_ID(2) |
576 MCI_DID_GLOBAL_ASSIGN_REQ_MCI_COUNT(2) |
577 MCI_DID_GLOBAL_ASSIGN_REQ_HOPS_NUM(2));
Grzegorz Jaszczyk582fdfd2019-02-06 14:16:51 +0100578 mci_mmio_write_32(MCI_ACCESS_CMD_REG(mci_index),
Konstantin Porotchkin01c84d42018-02-26 16:01:57 +0200579 MCI_INDIRECT_REG_CTRL_ADDR(
580 MCI_DID_GLOBAL_ASSIGNMENT_REQUEST_REG) |
581 MCI_INDIRECT_CTRL_ASSIGN_CMD);
582 ret |= mci_poll_command_completion(mci_index, MCI_CMD_WRITE);
583
584 /* Assigning dest. ID=3 to all transactions entering from AXI at AP */
Grzegorz Jaszczyk582fdfd2019-02-06 14:16:51 +0100585 mci_mmio_write_32(MCI_WRITE_READ_DATA_REG(mci_index),
Konstantin Porotchkin01c84d42018-02-26 16:01:57 +0200586 MCI_HB_CTRL_WIN0_DEST_VALID_FLAG(1) |
587 MCI_HB_CTRL_WIN0_DEST_ID(3));
Grzegorz Jaszczyk582fdfd2019-02-06 14:16:51 +0100588 mci_mmio_write_32(MCI_ACCESS_CMD_REG(mci_index),
Konstantin Porotchkin01c84d42018-02-26 16:01:57 +0200589 MCI_INDIRECT_REG_CTRL_ADDR(
590 MCI_HB_CTRL_WIN0_DESTINATION_REG_NUM) |
591 MCI_INDIRECT_CTRL_HOPID(GID_AXI_HB) |
592 MCI_INDIRECT_CTRL_LOCAL_PKT);
593 ret |= mci_poll_command_completion(mci_index, MCI_CMD_WRITE);
594
595 /* Assigning dest. ID=1 to all transactions entering from AXI at CP */
Grzegorz Jaszczyk582fdfd2019-02-06 14:16:51 +0100596 mci_mmio_write_32(MCI_WRITE_READ_DATA_REG(mci_index),
Konstantin Porotchkin01c84d42018-02-26 16:01:57 +0200597 MCI_HB_CTRL_WIN0_DEST_VALID_FLAG(1) |
598 MCI_HB_CTRL_WIN0_DEST_ID(1));
Grzegorz Jaszczyk582fdfd2019-02-06 14:16:51 +0100599 mci_mmio_write_32(MCI_ACCESS_CMD_REG(mci_index),
Konstantin Porotchkin01c84d42018-02-26 16:01:57 +0200600 MCI_INDIRECT_REG_CTRL_ADDR(
601 MCI_HB_CTRL_WIN0_DESTINATION_REG_NUM) |
602 MCI_INDIRECT_CTRL_HOPID(GID_IHB_EXT) |
603 MCI_INDIRECT_CTRL_HOPID(GID_AXI_HB));
604 ret |= mci_poll_command_completion(mci_index, MCI_CMD_WRITE);
605
606 /* End address to all transactions entering from AXI at AP.
607 * This will lead to get match for any AXI address
608 * and receive destination ID=3
609 */
Grzegorz Jaszczyk582fdfd2019-02-06 14:16:51 +0100610 mci_mmio_write_32(MCI_WRITE_READ_DATA_REG(mci_index), 0xffffffff);
611 mci_mmio_write_32(MCI_ACCESS_CMD_REG(mci_index),
Konstantin Porotchkin01c84d42018-02-26 16:01:57 +0200612 MCI_INDIRECT_REG_CTRL_ADDR(
613 MCI_HB_CTRL_WIN0_ADDRESS_MASK_REG_NUM) |
614 MCI_INDIRECT_CTRL_HOPID(GID_AXI_HB) |
615 MCI_INDIRECT_CTRL_LOCAL_PKT);
616 ret |= mci_poll_command_completion(mci_index, MCI_CMD_WRITE);
617
618 /* End address to all transactions entering from AXI at CP.
619 * This will lead to get match for any AXI address
620 * and receive destination ID=1
621 */
Grzegorz Jaszczyk582fdfd2019-02-06 14:16:51 +0100622 mci_mmio_write_32(MCI_WRITE_READ_DATA_REG(mci_index), 0xffffffff);
623 mci_mmio_write_32(MCI_ACCESS_CMD_REG(mci_index),
Konstantin Porotchkin01c84d42018-02-26 16:01:57 +0200624 MCI_INDIRECT_REG_CTRL_ADDR(
625 MCI_HB_CTRL_WIN0_ADDRESS_MASK_REG_NUM) |
626 MCI_INDIRECT_CTRL_HOPID(GID_IHB_EXT) |
627 MCI_INDIRECT_CTRL_HOPID(GID_AXI_HB));
628 ret |= mci_poll_command_completion(mci_index, MCI_CMD_WRITE);
629
630 debug_exit();
631 return ret;
632}
633
634/* Check if MCI simultaneous transaction was already enabled.
635 * Currently bootrom does this mci configuration only when the boot source is
636 * SAR_MCIX4, in other cases it should be done at this stage.
637 * It is worth noticing that in case of booting from uart, the bootrom
638 * flow is different and this mci initialization is skipped even if boot
639 * source is SAR_MCIX4. Therefore new verification bases on appropriate mci's
640 * register content: if the appropriate reg contains 0x0 it means that the
641 * bootrom didn't perform required mci configuration.
642 *
643 * Returns:
644 * 0 - configuration already done
645 * 1 - configuration missing
646 */
647static _Bool mci_simulatenous_trans_missing(int mci_index)
648{
649 uint32_t reg, ret;
650
651 /* read 'Window 0 Destination ID assignment' from HB register 0x3
652 * (TX_CFG_W0_DST_ID) to check whether ID assignment was already
653 * performed by BootROM.
654 */
655 debug_enter();
Grzegorz Jaszczyk582fdfd2019-02-06 14:16:51 +0100656 mci_mmio_write_32(MCI_ACCESS_CMD_REG(mci_index),
Konstantin Porotchkin01c84d42018-02-26 16:01:57 +0200657 MCI_INDIRECT_REG_CTRL_ADDR(
658 MCI_HB_CTRL_WIN0_DESTINATION_REG_NUM) |
659 MCI_INDIRECT_CTRL_HOPID(GID_AXI_HB) |
660 MCI_INDIRECT_CTRL_LOCAL_PKT |
661 MCI_INDIRECT_CTRL_READ_CMD);
662 ret = mci_poll_command_completion(mci_index, MCI_CMD_READ);
663
664 reg = mci_mmio_read_32(MCI_WRITE_READ_DATA_REG(mci_index));
665
666 if (ret)
667 ERROR("Failed to verify MCI simultaneous read/write status\n");
668
669 debug_exit();
670 /* default ID assignment is 0, so if register doesn't contain zeros
671 * it means that bootrom already performed required configuration.
672 */
673 if (reg != 0)
674 return 0;
675
676 return 1;
677}
678
679/* For A1 revision, configure the MCI link for performance improvement:
680 * - set MCI to support read/write transactions to arrive at the same time
681 * - Switch AXI to PCIe mode
682 * - Reduce sequence FIFO threshold
683 * - Configure RX/TX FIFO thresholds
684 *
685 * Note:
686 * We don't exit on error code from any sub routine, to try (best effort) to
687 * complete the MCI configuration.
688 * (If we exit - Bootloader will surely fail to boot)
689 */
690int mci_configure(int mci_index)
691{
692 int rval;
693
694 debug_enter();
695 /* According to design guidelines the MCI simultaneous transaction
696 * shouldn't be enabled more then once - therefore make sure that it
697 * wasn't already enabled in bootrom.
698 */
699 if (mci_simulatenous_trans_missing(mci_index)) {
Grzegorz Jaszczyk582fdfd2019-02-06 14:16:51 +0100700 VERBOSE("Enabling MCI simultaneous transaction for mci%d\n",
701 mci_index);
Konstantin Porotchkin01c84d42018-02-26 16:01:57 +0200702 /* set MCI to support read/write transactions
703 * to arrive at the same time
704 */
705 rval = mci_enable_simultaneous_transactions(mci_index);
706 if (rval)
707 ERROR("Failed to set MCI simultaneous read/write\n");
708 } else
709 VERBOSE("Skip MCI ID assignment - already done by bootrom\n");
710
711 /* Configure MCI for more consistent behavior with AXI protocol */
712 rval = mci_axi_set_pcie_mode(mci_index);
713 if (rval)
714 ERROR("Failed to set MCI to AXI PCIe mode\n");
715
716 /* reduce FIFO global threshold */
717 rval = mci_axi_set_fifo_thresh(mci_index);
718 if (rval)
719 ERROR("Failed to set MCI FIFO global threshold\n");
720
721 /* configure RX/TX FIFO thresholds */
722 rval = mci_axi_set_fifo_rx_tx_thresh(mci_index);
723 if (rval)
724 ERROR("Failed to set MCI RX/TX FIFO threshold\n");
725
726 debug_exit();
727 return 1;
728}
729
730int mci_get_link_status(void)
731{
732 uint32_t cmd, data;
733
734 cmd = (MCI_INDIRECT_REG_CTRL_ADDR(MCI_CTRL_STATUS_REG_NUM) |
735 MCI_INDIRECT_CTRL_LOCAL_PKT | MCI_INDIRECT_CTRL_READ_CMD);
736 if (mci_read(0, cmd, &data)) {
737 ERROR("Failed to read status register\n");
738 return -1;
739 }
740
741 /* Check if the link is ready */
742 if (data != MCI_CTRL_PHY_READY) {
743 ERROR("Bad link status %x\n", data);
744 return -1;
745 }
746
747 return 0;
748}
749
750void mci_turn_link_down(void)
751{
752 uint32_t cmd, data;
753 int rval = 0;
754
755 debug_enter();
756
757 /* Turn off auto-link */
758 cmd = (MCI_INDIRECT_REG_CTRL_ADDR(MCI_CTRL_MCI_PHY_SETTINGS_REG_NUM) |
759 MCI_INDIRECT_CTRL_LOCAL_PKT);
760 data = (MCI_CTRL_MCI_PHY_SET_REG_DEF_VAL2 |
761 MCI_CTRL_MCI_PHY_SET_AUTO_LINK_EN(0));
762 rval = mci_write(0, cmd, data);
763 if (rval)
764 ERROR("Failed to turn off auto-link\n");
765
766 /* Reset AP PHY */
767 cmd = (MCI_INDIRECT_REG_CTRL_ADDR(MCI_PHY_CTRL_REG_NUM) |
768 MCI_INDIRECT_CTRL_LOCAL_PKT);
769 data = (MCI_PHY_CTRL_MCI_MINOR |
770 MCI_PHY_CTRL_MCI_MAJOR |
771 MCI_PHY_CTRL_MCI_PHY_MODE_HOST |
772 MCI_PHY_CTRL_MCI_PHY_RESET_CORE);
773 rval = mci_write(0, cmd, data);
774 if (rval)
775 ERROR("Failed to reset AP PHY\n");
776
777 /* Clear all status & CRC values */
778 cmd = (MCI_INDIRECT_REG_CTRL_ADDR(MCI_LINK_CRC_CTRL_REG_NUM) |
779 MCI_INDIRECT_CTRL_LOCAL_PKT);
780 data = 0x0;
781 mci_write(0, cmd, data);
782 cmd = (MCI_INDIRECT_REG_CTRL_ADDR(MCI_CTRL_STATUS_REG_NUM) |
783 MCI_INDIRECT_CTRL_LOCAL_PKT);
784 data = 0x0;
785 rval = mci_write(0, cmd, data);
786 if (rval)
787 ERROR("Failed to reset AP PHY\n");
788
789 /* Wait 5ms before un-reset the PHY */
790 mdelay(5);
791
792 /* Un-reset AP PHY */
793 cmd = (MCI_INDIRECT_REG_CTRL_ADDR(MCI_PHY_CTRL_REG_NUM) |
794 MCI_INDIRECT_CTRL_LOCAL_PKT);
795 data = (MCI_PHY_CTRL_MCI_MINOR | MCI_PHY_CTRL_MCI_MAJOR |
796 MCI_PHY_CTRL_MCI_PHY_MODE_HOST);
797 rval = mci_write(0, cmd, data);
798 if (rval)
799 ERROR("Failed to un-reset AP PHY\n");
800
801 debug_exit();
802}
803
804void mci_turn_link_on(void)
805{
806 uint32_t cmd, data;
807 int rval = 0;
808
809 debug_enter();
810 /* Turn on auto-link */
811 cmd = (MCI_INDIRECT_REG_CTRL_ADDR(MCI_CTRL_MCI_PHY_SETTINGS_REG_NUM) |
812 MCI_INDIRECT_CTRL_LOCAL_PKT);
813 data = (MCI_CTRL_MCI_PHY_SET_REG_DEF_VAL2 |
814 MCI_CTRL_MCI_PHY_SET_AUTO_LINK_EN(1));
815 rval = mci_write(0, cmd, data);
816 if (rval)
817 ERROR("Failed to turn on auto-link\n");
818
819 debug_exit();
820}
821
822/* Initialize MCI for performance improvements */
Grzegorz Jaszczyk106eb822019-02-07 15:15:14 +0100823int mci_link_tune(int mci_index)
Konstantin Porotchkin01c84d42018-02-26 16:01:57 +0200824{
825 int ret;
826
827 debug_enter();
828 INFO("MCI%d initialization:\n", mci_index);
829
830 ret = mci_configure(mci_index);
831
832 debug_exit();
833 return ret;
834}