blob: 055dd61fbe5a991a09e0b279106156e1a19f4364 [file] [log] [blame]
Tom Rini10e47792018-05-06 17:58:06 -04001// SPDX-License-Identifier: GPL-2.0+
Kumar Gala2683c532011-04-13 08:37:44 -05002/*
3 * Copyright 2009-2011 Freescale Semiconductor, Inc.
4 * Dave Liu <daveliu@freescale.com>
Kumar Gala2683c532011-04-13 08:37:44 -05005 */
6#include <common.h>
Simon Glass313112a2019-08-01 09:46:46 -06007#include <env.h>
Sean Anderson9a2c7732022-09-07 13:44:55 +08008#include <image.h>
Kumar Gala2683c532011-04-13 08:37:44 -05009#include <malloc.h>
10#include <asm/io.h>
Masahiro Yamada56a931c2016-09-21 11:28:55 +090011#include <linux/errno.h>
Simon Glass48b6c6b2019-11-14 12:57:16 -070012#include <u-boot/crc.h>
Madalin Bucurb76b0a62020-04-23 16:25:19 +030013#include <dm.h>
Kumar Gala2683c532011-04-13 08:37:44 -050014
15#include "fm.h"
Qianyu Gongae6a7582016-02-18 13:01:59 +080016#include <fsl_qe.h> /* For struct qe_firmware */
Kumar Gala2683c532011-04-13 08:37:44 -050017
Kumar Gala2683c532011-04-13 08:37:44 -050018#include <nand.h>
Kumar Gala2683c532011-04-13 08:37:44 -050019#include <spi_flash.h>
Kumar Gala2683c532011-04-13 08:37:44 -050020#include <mmc.h>
Rajesh Bhagat1dec9612018-11-05 18:02:23 +000021
22#ifdef CONFIG_ARM64
23#include <asm/armv8/mmu.h>
24#include <asm/arch/cpu.h>
Kumar Gala2683c532011-04-13 08:37:44 -050025#endif
26
Tom Rini0a2bac72022-11-16 13:10:29 -050027struct fm_muram muram[CFG_SYS_NUM_FMAN];
Kumar Gala2683c532011-04-13 08:37:44 -050028
Hou Zhiqiangea52d332015-10-26 19:47:44 +080029void *fm_muram_base(int fm_idx)
Kumar Gala2683c532011-04-13 08:37:44 -050030{
31 return muram[fm_idx].base;
32}
33
Hou Zhiqiangea52d332015-10-26 19:47:44 +080034void *fm_muram_alloc(int fm_idx, size_t size, ulong align)
Kumar Gala2683c532011-04-13 08:37:44 -050035{
Hou Zhiqiangea52d332015-10-26 19:47:44 +080036 void *ret;
37 ulong align_mask;
38 size_t off;
39 void *save;
Kumar Gala2683c532011-04-13 08:37:44 -050040
41 align_mask = align - 1;
42 save = muram[fm_idx].alloc;
43
Hou Zhiqiangea52d332015-10-26 19:47:44 +080044 off = (ulong)save & align_mask;
Kumar Gala2683c532011-04-13 08:37:44 -050045 if (off != 0)
46 muram[fm_idx].alloc += (align - off);
47 off = size & align_mask;
48 if (off != 0)
49 size += (align - off);
50 if ((muram[fm_idx].alloc + size) >= muram[fm_idx].top) {
51 muram[fm_idx].alloc = save;
52 printf("%s: run out of ram.\n", __func__);
Hou Zhiqiangea52d332015-10-26 19:47:44 +080053 return NULL;
Kumar Gala2683c532011-04-13 08:37:44 -050054 }
55
56 ret = muram[fm_idx].alloc;
57 muram[fm_idx].alloc += size;
58 memset((void *)ret, 0, size);
59
60 return ret;
61}
62
63static void fm_init_muram(int fm_idx, void *reg)
64{
Hou Zhiqiangea52d332015-10-26 19:47:44 +080065 void *base = reg;
Kumar Gala2683c532011-04-13 08:37:44 -050066
67 muram[fm_idx].base = base;
Tom Rini6a5dccc2022-11-16 13:10:41 -050068 muram[fm_idx].size = CFG_SYS_FM_MURAM_SIZE;
Kumar Gala2683c532011-04-13 08:37:44 -050069 muram[fm_idx].alloc = base + FM_MURAM_RES_SIZE;
Tom Rini6a5dccc2022-11-16 13:10:41 -050070 muram[fm_idx].top = base + CFG_SYS_FM_MURAM_SIZE;
Kumar Gala2683c532011-04-13 08:37:44 -050071}
72
73/*
74 * fm_upload_ucode - Fman microcode upload worker function
75 *
76 * This function does the actual uploading of an Fman microcode
77 * to an Fman.
78 */
79static void fm_upload_ucode(int fm_idx, struct fm_imem *imem,
80 u32 *ucode, unsigned int size)
81{
82 unsigned int i;
83 unsigned int timeout = 1000000;
84
85 /* enable address auto increase */
86 out_be32(&imem->iadd, IRAM_IADD_AIE);
87 /* write microcode to IRAM */
88 for (i = 0; i < size / 4; i++)
Hou Zhiqiang3a25ece2015-10-26 19:47:43 +080089 out_be32(&imem->idata, (be32_to_cpu(ucode[i])));
Kumar Gala2683c532011-04-13 08:37:44 -050090
91 /* verify if the writing is over */
92 out_be32(&imem->iadd, 0);
Hou Zhiqiang3a25ece2015-10-26 19:47:43 +080093 while ((in_be32(&imem->idata) != be32_to_cpu(ucode[0])) && --timeout)
Kumar Gala2683c532011-04-13 08:37:44 -050094 ;
95 if (!timeout)
96 printf("Fman%u: microcode upload timeout\n", fm_idx + 1);
97
98 /* enable microcode from IRAM */
99 out_be32(&imem->iready, IRAM_READY);
100}
101
102/*
103 * Upload an Fman firmware
104 *
105 * This function is similar to qe_upload_firmware(), exception that it uploads
106 * a microcode to the Fman instead of the QE.
107 *
108 * Because the process for uploading a microcode to the Fman is similar for
109 * that of the QE, the QE firmware binary format is used for Fman microcode.
110 * It should be possible to unify these two functions, but for now we keep them
111 * separate.
112 */
113static int fman_upload_firmware(int fm_idx,
114 struct fm_imem *fm_imem,
115 const struct qe_firmware *firmware)
116{
117 unsigned int i;
118 u32 crc;
119 size_t calc_size = sizeof(struct qe_firmware);
120 size_t length;
121 const struct qe_header *hdr;
122
123 if (!firmware) {
124 printf("Fman%u: Invalid address for firmware\n", fm_idx + 1);
125 return -EINVAL;
126 }
127
128 hdr = &firmware->header;
129 length = be32_to_cpu(hdr->length);
130
131 /* Check the magic */
132 if ((hdr->magic[0] != 'Q') || (hdr->magic[1] != 'E') ||
133 (hdr->magic[2] != 'F')) {
134 printf("Fman%u: Data at %p is not a firmware\n", fm_idx + 1,
135 firmware);
136 return -EPERM;
137 }
138
139 /* Check the version */
140 if (hdr->version != 1) {
141 printf("Fman%u: Unsupported firmware version %u\n", fm_idx + 1,
142 hdr->version);
143 return -EPERM;
144 }
145
146 /* Validate some of the fields */
147 if ((firmware->count != 1)) {
148 printf("Fman%u: Invalid data in firmware header\n", fm_idx + 1);
149 return -EINVAL;
150 }
151
152 /* Validate the length and check if there's a CRC */
153 calc_size += (firmware->count - 1) * sizeof(struct qe_microcode);
154
155 for (i = 0; i < firmware->count; i++)
156 /*
157 * For situations where the second RISC uses the same microcode
158 * as the first, the 'code_offset' and 'count' fields will be
159 * zero, so it's okay to add those.
160 */
161 calc_size += sizeof(u32) *
162 be32_to_cpu(firmware->microcode[i].count);
163
164 /* Validate the length */
165 if (length != calc_size + sizeof(u32)) {
166 printf("Fman%u: Invalid length in firmware header\n",
167 fm_idx + 1);
168 return -EPERM;
169 }
170
171 /*
172 * Validate the CRC. We would normally call crc32_no_comp(), but that
173 * function isn't available unless you turn on JFFS support.
174 */
175 crc = be32_to_cpu(*(u32 *)((void *)firmware + calc_size));
176 if (crc != (crc32(-1, (const void *)firmware, calc_size) ^ -1)) {
177 printf("Fman%u: Firmware CRC is invalid\n", fm_idx + 1);
178 return -EIO;
179 }
180
181 /* Loop through each microcode. */
182 for (i = 0; i < firmware->count; i++) {
183 const struct qe_microcode *ucode = &firmware->microcode[i];
184
185 /* Upload a microcode if it's present */
Hou Zhiqiang3a25ece2015-10-26 19:47:43 +0800186 if (be32_to_cpu(ucode->code_offset)) {
Kumar Gala2683c532011-04-13 08:37:44 -0500187 u32 ucode_size;
188 u32 *code;
189 printf("Fman%u: Uploading microcode version %u.%u.%u\n",
190 fm_idx + 1, ucode->major, ucode->minor,
191 ucode->revision);
Hou Zhiqiang3a25ece2015-10-26 19:47:43 +0800192 code = (void *)firmware +
193 be32_to_cpu(ucode->code_offset);
194 ucode_size = sizeof(u32) * be32_to_cpu(ucode->count);
Kumar Gala2683c532011-04-13 08:37:44 -0500195 fm_upload_ucode(fm_idx, fm_imem, code, ucode_size);
196 }
197 }
198
199 return 0;
200}
201
202static u32 fm_assign_risc(int port_id)
203{
204 u32 risc_sel, val;
205 risc_sel = (port_id & 0x1) ? FMFPPRC_RISC2 : FMFPPRC_RISC1;
206 val = (port_id << FMFPPRC_PORTID_SHIFT) & FMFPPRC_PORTID_MASK;
207 val |= ((risc_sel << FMFPPRC_ORA_SHIFT) | risc_sel);
208
209 return val;
210}
211
212static void fm_init_fpm(struct fm_fpm *fpm)
213{
214 int i, port_id;
215 u32 val;
216
217 setbits_be32(&fpm->fmfpee, FMFPEE_EHM | FMFPEE_UEC |
218 FMFPEE_CER | FMFPEE_DER);
219
220 /* IM mode, each even port ID to RISC#1, each odd port ID to RISC#2 */
221
222 /* offline/parser port */
223 for (i = 0; i < MAX_NUM_OH_PORT; i++) {
224 port_id = OH_PORT_ID_BASE + i;
225 val = fm_assign_risc(port_id);
226 out_be32(&fpm->fpmprc, val);
227 }
228 /* Rx 1G port */
229 for (i = 0; i < MAX_NUM_RX_PORT_1G; i++) {
230 port_id = RX_PORT_1G_BASE + i;
231 val = fm_assign_risc(port_id);
232 out_be32(&fpm->fpmprc, val);
233 }
234 /* Tx 1G port */
235 for (i = 0; i < MAX_NUM_TX_PORT_1G; i++) {
236 port_id = TX_PORT_1G_BASE + i;
237 val = fm_assign_risc(port_id);
238 out_be32(&fpm->fpmprc, val);
239 }
240 /* Rx 10G port */
241 port_id = RX_PORT_10G_BASE;
242 val = fm_assign_risc(port_id);
243 out_be32(&fpm->fpmprc, val);
244 /* Tx 10G port */
245 port_id = TX_PORT_10G_BASE;
246 val = fm_assign_risc(port_id);
247 out_be32(&fpm->fpmprc, val);
248
249 /* disable the dispatch limit in IM case */
250 out_be32(&fpm->fpmflc, FMFP_FLC_DISP_LIM_NONE);
251 /* clear events */
252 out_be32(&fpm->fmfpee, FMFPEE_CLEAR_EVENT);
253
254 /* clear risc events */
255 for (i = 0; i < 4; i++)
256 out_be32(&fpm->fpmcev[i], 0xffffffff);
257
258 /* clear error */
259 out_be32(&fpm->fpmrcr, FMFP_RCR_MDEC | FMFP_RCR_IDEC);
260}
261
262static int fm_init_bmi(int fm_idx, struct fm_bmi_common *bmi)
263{
264 int blk, i, port_id;
Hou Zhiqiangea52d332015-10-26 19:47:44 +0800265 u32 val;
266 size_t offset;
267 void *base;
Kumar Gala2683c532011-04-13 08:37:44 -0500268
269 /* alloc free buffer pool in MURAM */
270 base = fm_muram_alloc(fm_idx, FM_FREE_POOL_SIZE, FM_FREE_POOL_ALIGN);
271 if (!base) {
272 printf("%s: no muram for free buffer pool\n", __func__);
273 return -ENOMEM;
274 }
275 offset = base - fm_muram_base(fm_idx);
276
277 /* Need 128KB total free buffer pool size */
278 val = offset / 256;
279 blk = FM_FREE_POOL_SIZE / 256;
280 /* in IM, we must not begin from offset 0 in MURAM */
281 val |= ((blk - 1) << FMBM_CFG1_FBPS_SHIFT);
282 out_be32(&bmi->fmbm_cfg1, val);
283
284 /* disable all BMI interrupt */
285 out_be32(&bmi->fmbm_ier, FMBM_IER_DISABLE_ALL);
286
287 /* clear all events */
288 out_be32(&bmi->fmbm_ievr, FMBM_IEVR_CLEAR_ALL);
289
290 /*
291 * set port parameters - FMBM_PP_x
292 * max tasks 10G Rx/Tx=12, 1G Rx/Tx 4, others is 1
293 * max dma 10G Rx/Tx=3, others is 1
294 * set port FIFO size - FMBM_PFS_x
295 * 4KB for all Rx and Tx ports
296 */
297 /* offline/parser port */
298 for (i = 0; i < MAX_NUM_OH_PORT; i++) {
299 port_id = OH_PORT_ID_BASE + i - 1;
300 /* max tasks=1, max dma=1, no extra */
301 out_be32(&bmi->fmbm_pp[port_id], 0);
302 /* port FIFO size - 256 bytes, no extra */
303 out_be32(&bmi->fmbm_pfs[port_id], 0);
304 }
305 /* Rx 1G port */
306 for (i = 0; i < MAX_NUM_RX_PORT_1G; i++) {
307 port_id = RX_PORT_1G_BASE + i - 1;
308 /* max tasks=4, max dma=1, no extra */
309 out_be32(&bmi->fmbm_pp[port_id], FMBM_PP_MXT(4));
310 /* FIFO size - 4KB, no extra */
311 out_be32(&bmi->fmbm_pfs[port_id], FMBM_PFS_IFSZ(0xf));
312 }
313 /* Tx 1G port FIFO size - 4KB, no extra */
314 for (i = 0; i < MAX_NUM_TX_PORT_1G; i++) {
315 port_id = TX_PORT_1G_BASE + i - 1;
316 /* max tasks=4, max dma=1, no extra */
317 out_be32(&bmi->fmbm_pp[port_id], FMBM_PP_MXT(4));
318 /* FIFO size - 4KB, no extra */
319 out_be32(&bmi->fmbm_pfs[port_id], FMBM_PFS_IFSZ(0xf));
320 }
321 /* Rx 10G port */
322 port_id = RX_PORT_10G_BASE - 1;
323 /* max tasks=12, max dma=3, no extra */
324 out_be32(&bmi->fmbm_pp[port_id], FMBM_PP_MXT(12) | FMBM_PP_MXD(3));
325 /* FIFO size - 4KB, no extra */
326 out_be32(&bmi->fmbm_pfs[port_id], FMBM_PFS_IFSZ(0xf));
327
328 /* Tx 10G port */
329 port_id = TX_PORT_10G_BASE - 1;
330 /* max tasks=12, max dma=3, no extra */
331 out_be32(&bmi->fmbm_pp[port_id], FMBM_PP_MXT(12) | FMBM_PP_MXD(3));
332 /* FIFO size - 4KB, no extra */
333 out_be32(&bmi->fmbm_pfs[port_id], FMBM_PFS_IFSZ(0xf));
334
335 /* initialize internal buffers data base (linked list) */
336 out_be32(&bmi->fmbm_init, FMBM_INIT_START);
337
338 return 0;
339}
340
341static void fm_init_qmi(struct fm_qmi_common *qmi)
342{
Kumar Gala2683c532011-04-13 08:37:44 -0500343 /* disable all error interrupts */
344 out_be32(&qmi->fmqm_eien, FMQM_EIEN_DISABLE_ALL);
345 /* clear all error events */
346 out_be32(&qmi->fmqm_eie, FMQM_EIE_CLEAR_ALL);
347
348 /* disable all interrupts */
349 out_be32(&qmi->fmqm_ien, FMQM_IEN_DISABLE_ALL);
350 /* clear all interrupts */
351 out_be32(&qmi->fmqm_ie, FMQM_IE_CLEAR_ALL);
352}
353
354/* Init common part of FM, index is fm num# like fm as above */
Rajesh Bhagat1dec9612018-11-05 18:02:23 +0000355#ifdef CONFIG_TFABOOT
Kumar Gala2683c532011-04-13 08:37:44 -0500356int fm_init_common(int index, struct ccsr_fman *reg)
357{
358 int rc;
Rajesh Bhagat1dec9612018-11-05 18:02:23 +0000359 void *addr = NULL;
360 enum boot_src src = get_boot_src();
361
362 if (src == BOOT_SOURCE_IFC_NOR) {
363 addr = (void *)(CONFIG_SYS_FMAN_FW_ADDR +
364 CONFIG_SYS_FSL_IFC_BASE);
Francois Gervais28ff2ef2020-04-08 09:48:12 -0400365#ifdef CONFIG_CMD_NAND
Rajesh Bhagat1dec9612018-11-05 18:02:23 +0000366 } else if (src == BOOT_SOURCE_IFC_NAND) {
367 size_t fw_length = CONFIG_SYS_QE_FMAN_FW_LENGTH;
368
369 addr = malloc(CONFIG_SYS_QE_FMAN_FW_LENGTH);
370
371 rc = nand_read(get_nand_dev_by_index(0),
372 (loff_t)CONFIG_SYS_FMAN_FW_ADDR,
373 &fw_length, (u_char *)addr);
374 if (rc == -EUCLEAN) {
375 printf("NAND read of FMAN firmware at offset 0x%x failed %d\n",
376 CONFIG_SYS_FMAN_FW_ADDR, rc);
377 }
Francois Gervais28ff2ef2020-04-08 09:48:12 -0400378#endif
Rajesh Bhagat1dec9612018-11-05 18:02:23 +0000379 } else if (src == BOOT_SOURCE_QSPI_NOR) {
380 struct spi_flash *ucode_flash;
381
382 addr = malloc(CONFIG_SYS_QE_FMAN_FW_LENGTH);
383 int ret = 0;
384
Lukasz Majewski76f442982020-06-04 23:11:53 +0800385#if CONFIG_IS_ENABLED(DM_SPI_FLASH)
Rajesh Bhagat1dec9612018-11-05 18:02:23 +0000386 struct udevice *new;
387
388 /* speed and mode will be read from DT */
Tom Rini119d2fb2021-12-11 14:55:48 -0500389 ret = spi_flash_probe_bus_cs(CONFIG_SF_DEFAULT_BUS,
Patrice Chotard05b1aa62022-03-30 09:33:14 +0200390 CONFIG_SF_DEFAULT_CS, &new);
Rajesh Bhagat1dec9612018-11-05 18:02:23 +0000391
392 ucode_flash = dev_get_uclass_priv(new);
393#else
394 ucode_flash = spi_flash_probe(CONFIG_ENV_SPI_BUS,
395 CONFIG_ENV_SPI_CS,
396 CONFIG_ENV_SPI_MAX_HZ,
397 CONFIG_ENV_SPI_MODE);
398#endif
399 if (!ucode_flash) {
400 printf("SF: probe for ucode failed\n");
401 } else {
402 ret = spi_flash_read(ucode_flash,
403 CONFIG_SYS_FMAN_FW_ADDR +
Tom Rini376b88a2022-10-28 20:27:13 -0400404 CFG_SYS_FSL_QSPI_BASE,
Rajesh Bhagat1dec9612018-11-05 18:02:23 +0000405 CONFIG_SYS_QE_FMAN_FW_LENGTH,
406 addr);
407 if (ret)
408 printf("SF: read for ucode failed\n");
409 spi_flash_free(ucode_flash);
410 }
411 } else if (src == BOOT_SOURCE_SD_MMC) {
412 int dev = CONFIG_SYS_MMC_ENV_DEV;
413
414 addr = malloc(CONFIG_SYS_QE_FMAN_FW_LENGTH);
415 u32 cnt = CONFIG_SYS_QE_FMAN_FW_LENGTH / 512;
416 u32 blk = CONFIG_SYS_FMAN_FW_ADDR / 512;
417 struct mmc *mmc = find_mmc_device(CONFIG_SYS_MMC_ENV_DEV);
418
419 if (!mmc) {
420 printf("\nMMC cannot find device for ucode\n");
421 } else {
422 printf("\nMMC read: dev # %u, block # %u, count %u ...\n",
423 dev, blk, cnt);
424 mmc_init(mmc);
425 (void)blk_dread(mmc_get_blk_desc(mmc), blk, cnt,
426 addr);
427 }
428 } else {
429 addr = NULL;
430 }
431
432 /* Upload the Fman microcode if it's present */
433 rc = fman_upload_firmware(index, &reg->fm_imem, addr);
434 if (rc)
435 return rc;
436 env_set_addr("fman_ucode", addr);
437
438 fm_init_muram(index, &reg->muram);
439 fm_init_qmi(&reg->fm_qmi_common);
440 fm_init_fpm(&reg->fm_fpm);
441
442 /* clear DMA status */
443 setbits_be32(&reg->fm_dma.fmdmsr, FMDMSR_CLEAR_ALL);
444
445 /* set DMA mode */
446 setbits_be32(&reg->fm_dma.fmdmmr, FMDMMR_SBER);
447
448 return fm_init_bmi(index, &reg->fm_bmi_common);
449}
450#else
451int fm_init_common(int index, struct ccsr_fman *reg)
452{
453 int rc;
Timur Tabi275f4bb2011-11-22 09:21:25 -0600454#if defined(CONFIG_SYS_QE_FMAN_FW_IN_NOR)
Zhao Qiang83a90842014-03-21 16:21:44 +0800455 void *addr = (void *)CONFIG_SYS_FMAN_FW_ADDR;
Timur Tabi275f4bb2011-11-22 09:21:25 -0600456#elif defined(CONFIG_SYS_QE_FMAN_FW_IN_NAND)
457 size_t fw_length = CONFIG_SYS_QE_FMAN_FW_LENGTH;
458 void *addr = malloc(CONFIG_SYS_QE_FMAN_FW_LENGTH);
Kumar Gala2683c532011-04-13 08:37:44 -0500459
Grygorii Strashkoaa942fe2017-06-26 19:13:00 -0500460 rc = nand_read(get_nand_dev_by_index(0),
461 (loff_t)CONFIG_SYS_FMAN_FW_ADDR,
Kumar Gala2683c532011-04-13 08:37:44 -0500462 &fw_length, (u_char *)addr);
463 if (rc == -EUCLEAN) {
464 printf("NAND read of FMAN firmware at offset 0x%x failed %d\n",
Zhao Qiang83a90842014-03-21 16:21:44 +0800465 CONFIG_SYS_FMAN_FW_ADDR, rc);
Kumar Gala2683c532011-04-13 08:37:44 -0500466 }
Tom Rinifa911f82019-05-12 07:59:12 -0400467#elif defined(CONFIG_SYS_QE_FMAN_FW_IN_SPIFLASH)
Kumar Gala2683c532011-04-13 08:37:44 -0500468 struct spi_flash *ucode_flash;
Timur Tabi275f4bb2011-11-22 09:21:25 -0600469 void *addr = malloc(CONFIG_SYS_QE_FMAN_FW_LENGTH);
Kumar Gala2683c532011-04-13 08:37:44 -0500470 int ret = 0;
471
Lukasz Majewski76f442982020-06-04 23:11:53 +0800472#if CONFIG_IS_ENABLED(DM_SPI_FLASH)
Qianyu Gongea4923e2016-08-03 11:04:25 +0800473 struct udevice *new;
474
475 /* speed and mode will be read from DT */
Tom Rini119d2fb2021-12-11 14:55:48 -0500476 ret = spi_flash_probe_bus_cs(CONFIG_SF_DEFAULT_BUS, CONFIG_SF_DEFAULT_CS,
Patrice Chotard05b1aa62022-03-30 09:33:14 +0200477 &new);
Qianyu Gongea4923e2016-08-03 11:04:25 +0800478
479 ucode_flash = dev_get_uclass_priv(new);
480#else
Kumar Gala2683c532011-04-13 08:37:44 -0500481 ucode_flash = spi_flash_probe(CONFIG_ENV_SPI_BUS, CONFIG_ENV_SPI_CS,
482 CONFIG_ENV_SPI_MAX_HZ, CONFIG_ENV_SPI_MODE);
Qianyu Gongea4923e2016-08-03 11:04:25 +0800483#endif
Kumar Gala2683c532011-04-13 08:37:44 -0500484 if (!ucode_flash)
485 printf("SF: probe for ucode failed\n");
486 else {
Zhao Qiang83a90842014-03-21 16:21:44 +0800487 ret = spi_flash_read(ucode_flash, CONFIG_SYS_FMAN_FW_ADDR,
Timur Tabi275f4bb2011-11-22 09:21:25 -0600488 CONFIG_SYS_QE_FMAN_FW_LENGTH, addr);
Kumar Gala2683c532011-04-13 08:37:44 -0500489 if (ret)
490 printf("SF: read for ucode failed\n");
491 spi_flash_free(ucode_flash);
492 }
Timur Tabi275f4bb2011-11-22 09:21:25 -0600493#elif defined(CONFIG_SYS_QE_FMAN_FW_IN_MMC)
Kumar Gala2683c532011-04-13 08:37:44 -0500494 int dev = CONFIG_SYS_MMC_ENV_DEV;
Timur Tabi275f4bb2011-11-22 09:21:25 -0600495 void *addr = malloc(CONFIG_SYS_QE_FMAN_FW_LENGTH);
496 u32 cnt = CONFIG_SYS_QE_FMAN_FW_LENGTH / 512;
Zhao Qiang83a90842014-03-21 16:21:44 +0800497 u32 blk = CONFIG_SYS_FMAN_FW_ADDR / 512;
Kumar Gala2683c532011-04-13 08:37:44 -0500498 struct mmc *mmc = find_mmc_device(CONFIG_SYS_MMC_ENV_DEV);
499
500 if (!mmc)
501 printf("\nMMC cannot find device for ucode\n");
502 else {
503 printf("\nMMC read: dev # %u, block # %u, count %u ...\n",
504 dev, blk, cnt);
505 mmc_init(mmc);
Yinbo Zhu45c20bd2018-09-25 14:47:06 +0800506 (void)blk_dread(mmc_get_blk_desc(mmc), blk, cnt,
Stephen Warrene73f2962015-12-07 11:38:48 -0700507 addr);
Kumar Gala2683c532011-04-13 08:37:44 -0500508 }
Liu Gang1e084582012-03-08 00:33:18 +0000509#elif defined(CONFIG_SYS_QE_FMAN_FW_IN_REMOTE)
Zhao Qiang83a90842014-03-21 16:21:44 +0800510 void *addr = (void *)CONFIG_SYS_FMAN_FW_ADDR;
York Sun5f321a32013-06-25 11:37:40 -0700511#else
512 void *addr = NULL;
Kumar Gala2683c532011-04-13 08:37:44 -0500513#endif
514
Sean Anderson9a2c7732022-09-07 13:44:55 +0800515 rc = fit_check_format(addr, CONFIG_SYS_QE_FMAN_FW_LENGTH);
516 if (!rc) {
517 size_t unused;
518 const void *new_addr;
519
520 rc = fit_get_data_conf_prop(addr, "fman", &new_addr, &unused);
521 if (rc)
522 return rc;
523 addr = (void *)new_addr;
524 } else if (CONFIG_IS_ENABLED(FIT_SIGNATURE)) {
525 /*
526 * Using a (signed) FIT wrapper is mandatory if we are
527 * doing verified boot.
528 */
529 return rc;
530 }
531
Kumar Gala2683c532011-04-13 08:37:44 -0500532 /* Upload the Fman microcode if it's present */
533 rc = fman_upload_firmware(index, &reg->fm_imem, addr);
534 if (rc)
535 return rc;
Simon Glass4d949a22017-08-03 12:22:10 -0600536 env_set_addr("fman_ucode", addr);
Kumar Gala2683c532011-04-13 08:37:44 -0500537
538 fm_init_muram(index, &reg->muram);
539 fm_init_qmi(&reg->fm_qmi_common);
540 fm_init_fpm(&reg->fm_fpm);
541
542 /* clear DMA status */
543 setbits_be32(&reg->fm_dma.fmdmsr, FMDMSR_CLEAR_ALL);
544
545 /* set DMA mode */
546 setbits_be32(&reg->fm_dma.fmdmmr, FMDMMR_SBER);
547
548 return fm_init_bmi(index, &reg->fm_bmi_common);
549}
Rajesh Bhagat1dec9612018-11-05 18:02:23 +0000550#endif
Madalin Bucurb76b0a62020-04-23 16:25:19 +0300551
Madalin Bucurb76b0a62020-04-23 16:25:19 +0300552struct fman_priv {
553 struct ccsr_fman *reg;
554 unsigned int fman_id;
555};
556
557static const struct udevice_id fman_ids[] = {
558 { .compatible = "fsl,fman" },
559 {}
560};
561
562static int fman_probe(struct udevice *dev)
563{
564 struct fman_priv *priv = dev_get_priv(dev);
565
566 priv->reg = (struct ccsr_fman *)(uintptr_t)dev_read_addr(dev);
567
568 if (dev_read_u32(dev, "cell-index", &priv->fman_id)) {
569 printf("FMan node property cell-index missing\n");
570 return -EINVAL;
571 }
572
573 return fm_init_common(priv->fman_id, priv->reg);
574}
575
576static int fman_remove(struct udevice *dev)
577{
578 return 0;
579}
580
581int fman_id(struct udevice *dev)
582{
583 struct fman_priv *priv = dev_get_priv(dev);
584
585 return priv->fman_id;
586}
587
588void *fman_port(struct udevice *dev, int num)
589{
590 struct fman_priv *priv = dev_get_priv(dev);
591
592 return &priv->reg->port[num - 1].fm_bmi;
593}
594
595void *fman_mdio(struct udevice *dev, enum fm_mac_type type, int num)
596{
597 struct fman_priv *priv = dev_get_priv(dev);
598 void *res = NULL;
599
600 switch (type) {
601#ifdef CONFIG_SYS_FMAN_V3
602 case FM_MEMAC:
603 res = &priv->reg->memac[num].fm_memac_mdio;
604 break;
605#else
606 case FM_DTSEC:
607 res = &priv->reg->mac_1g[num].fm_mdio.miimcfg;
608 break;
609 case FM_TGEC:
610 res = &priv->reg->mac_10g[num].fm_10gec_mdio;
611 break;
612#endif
613 }
614 return res;
615}
616
617U_BOOT_DRIVER(fman) = {
618 .name = "fman",
619 .id = UCLASS_SIMPLE_BUS,
620 .of_match = fman_ids,
621 .probe = fman_probe,
622 .remove = fman_remove,
Simon Glass8a2b47f2020-12-03 16:55:17 -0700623 .priv_auto = sizeof(struct fman_priv),
Madalin Bucurb76b0a62020-04-23 16:25:19 +0300624 .flags = DM_FLAG_ALLOC_PRIV_DMA,
625};