18c2ecf20Sopenharmony_ci/* 28c2ecf20Sopenharmony_ci * Copyright 2008-2015 Freescale Semiconductor Inc. 38c2ecf20Sopenharmony_ci * Copyright 2020 NXP 48c2ecf20Sopenharmony_ci * 58c2ecf20Sopenharmony_ci * Redistribution and use in source and binary forms, with or without 68c2ecf20Sopenharmony_ci * modification, are permitted provided that the following conditions are met: 78c2ecf20Sopenharmony_ci * * Redistributions of source code must retain the above copyright 88c2ecf20Sopenharmony_ci * notice, this list of conditions and the following disclaimer. 98c2ecf20Sopenharmony_ci * * Redistributions in binary form must reproduce the above copyright 108c2ecf20Sopenharmony_ci * notice, this list of conditions and the following disclaimer in the 118c2ecf20Sopenharmony_ci * documentation and/or other materials provided with the distribution. 128c2ecf20Sopenharmony_ci * * Neither the name of Freescale Semiconductor nor the 138c2ecf20Sopenharmony_ci * names of its contributors may be used to endorse or promote products 148c2ecf20Sopenharmony_ci * derived from this software without specific prior written permission. 158c2ecf20Sopenharmony_ci * 168c2ecf20Sopenharmony_ci * 178c2ecf20Sopenharmony_ci * ALTERNATIVELY, this software may be distributed under the terms of the 188c2ecf20Sopenharmony_ci * GNU General Public License ("GPL") as published by the Free Software 198c2ecf20Sopenharmony_ci * Foundation, either version 2 of that License or (at your option) any 208c2ecf20Sopenharmony_ci * later version. 218c2ecf20Sopenharmony_ci * 228c2ecf20Sopenharmony_ci * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY 238c2ecf20Sopenharmony_ci * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 248c2ecf20Sopenharmony_ci * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 258c2ecf20Sopenharmony_ci * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY 268c2ecf20Sopenharmony_ci * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 278c2ecf20Sopenharmony_ci * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 288c2ecf20Sopenharmony_ci * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 298c2ecf20Sopenharmony_ci * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 308c2ecf20Sopenharmony_ci * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 318c2ecf20Sopenharmony_ci * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 328c2ecf20Sopenharmony_ci */ 338c2ecf20Sopenharmony_ci 348c2ecf20Sopenharmony_ci#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt 358c2ecf20Sopenharmony_ci 368c2ecf20Sopenharmony_ci#include <linux/fsl/guts.h> 378c2ecf20Sopenharmony_ci#include <linux/slab.h> 388c2ecf20Sopenharmony_ci#include <linux/delay.h> 398c2ecf20Sopenharmony_ci#include <linux/module.h> 408c2ecf20Sopenharmony_ci#include <linux/of_platform.h> 418c2ecf20Sopenharmony_ci#include <linux/clk.h> 428c2ecf20Sopenharmony_ci#include <linux/of_address.h> 438c2ecf20Sopenharmony_ci#include <linux/of_irq.h> 448c2ecf20Sopenharmony_ci#include <linux/interrupt.h> 458c2ecf20Sopenharmony_ci#include <linux/libfdt_env.h> 468c2ecf20Sopenharmony_ci 478c2ecf20Sopenharmony_ci#include "fman.h" 488c2ecf20Sopenharmony_ci#include "fman_muram.h" 498c2ecf20Sopenharmony_ci#include "fman_keygen.h" 508c2ecf20Sopenharmony_ci 518c2ecf20Sopenharmony_ci/* General defines */ 528c2ecf20Sopenharmony_ci#define FMAN_LIODN_TBL 64 /* size of LIODN table */ 538c2ecf20Sopenharmony_ci#define MAX_NUM_OF_MACS 10 548c2ecf20Sopenharmony_ci#define FM_NUM_OF_FMAN_CTRL_EVENT_REGS 4 558c2ecf20Sopenharmony_ci#define BASE_RX_PORTID 0x08 568c2ecf20Sopenharmony_ci#define BASE_TX_PORTID 0x28 578c2ecf20Sopenharmony_ci 588c2ecf20Sopenharmony_ci/* Modules registers offsets */ 598c2ecf20Sopenharmony_ci#define BMI_OFFSET 0x00080000 608c2ecf20Sopenharmony_ci#define QMI_OFFSET 0x00080400 618c2ecf20Sopenharmony_ci#define KG_OFFSET 0x000C1000 628c2ecf20Sopenharmony_ci#define DMA_OFFSET 0x000C2000 638c2ecf20Sopenharmony_ci#define FPM_OFFSET 0x000C3000 648c2ecf20Sopenharmony_ci#define IMEM_OFFSET 0x000C4000 658c2ecf20Sopenharmony_ci#define HWP_OFFSET 0x000C7000 668c2ecf20Sopenharmony_ci#define CGP_OFFSET 0x000DB000 678c2ecf20Sopenharmony_ci 688c2ecf20Sopenharmony_ci/* Exceptions bit map */ 698c2ecf20Sopenharmony_ci#define EX_DMA_BUS_ERROR 0x80000000 708c2ecf20Sopenharmony_ci#define EX_DMA_READ_ECC 0x40000000 718c2ecf20Sopenharmony_ci#define EX_DMA_SYSTEM_WRITE_ECC 0x20000000 728c2ecf20Sopenharmony_ci#define EX_DMA_FM_WRITE_ECC 0x10000000 738c2ecf20Sopenharmony_ci#define EX_FPM_STALL_ON_TASKS 0x08000000 748c2ecf20Sopenharmony_ci#define EX_FPM_SINGLE_ECC 0x04000000 758c2ecf20Sopenharmony_ci#define EX_FPM_DOUBLE_ECC 0x02000000 768c2ecf20Sopenharmony_ci#define EX_QMI_SINGLE_ECC 0x01000000 778c2ecf20Sopenharmony_ci#define EX_QMI_DEQ_FROM_UNKNOWN_PORTID 0x00800000 788c2ecf20Sopenharmony_ci#define EX_QMI_DOUBLE_ECC 0x00400000 798c2ecf20Sopenharmony_ci#define EX_BMI_LIST_RAM_ECC 0x00200000 808c2ecf20Sopenharmony_ci#define EX_BMI_STORAGE_PROFILE_ECC 0x00100000 818c2ecf20Sopenharmony_ci#define EX_BMI_STATISTICS_RAM_ECC 0x00080000 828c2ecf20Sopenharmony_ci#define EX_IRAM_ECC 0x00040000 838c2ecf20Sopenharmony_ci#define EX_MURAM_ECC 0x00020000 848c2ecf20Sopenharmony_ci#define EX_BMI_DISPATCH_RAM_ECC 0x00010000 858c2ecf20Sopenharmony_ci#define EX_DMA_SINGLE_PORT_ECC 0x00008000 868c2ecf20Sopenharmony_ci 878c2ecf20Sopenharmony_ci/* DMA defines */ 888c2ecf20Sopenharmony_ci/* masks */ 898c2ecf20Sopenharmony_ci#define DMA_MODE_BER 0x00200000 908c2ecf20Sopenharmony_ci#define DMA_MODE_ECC 0x00000020 918c2ecf20Sopenharmony_ci#define DMA_MODE_SECURE_PROT 0x00000800 928c2ecf20Sopenharmony_ci#define DMA_MODE_AXI_DBG_MASK 0x0F000000 938c2ecf20Sopenharmony_ci 948c2ecf20Sopenharmony_ci#define DMA_TRANSFER_PORTID_MASK 0xFF000000 958c2ecf20Sopenharmony_ci#define DMA_TRANSFER_TNUM_MASK 0x00FF0000 968c2ecf20Sopenharmony_ci#define DMA_TRANSFER_LIODN_MASK 0x00000FFF 978c2ecf20Sopenharmony_ci 988c2ecf20Sopenharmony_ci#define DMA_STATUS_BUS_ERR 0x08000000 998c2ecf20Sopenharmony_ci#define DMA_STATUS_READ_ECC 0x04000000 1008c2ecf20Sopenharmony_ci#define DMA_STATUS_SYSTEM_WRITE_ECC 0x02000000 1018c2ecf20Sopenharmony_ci#define DMA_STATUS_FM_WRITE_ECC 0x01000000 1028c2ecf20Sopenharmony_ci#define DMA_STATUS_FM_SPDAT_ECC 0x00080000 1038c2ecf20Sopenharmony_ci 1048c2ecf20Sopenharmony_ci#define DMA_MODE_CACHE_OR_SHIFT 30 1058c2ecf20Sopenharmony_ci#define DMA_MODE_AXI_DBG_SHIFT 24 1068c2ecf20Sopenharmony_ci#define DMA_MODE_CEN_SHIFT 13 1078c2ecf20Sopenharmony_ci#define DMA_MODE_CEN_MASK 0x00000007 1088c2ecf20Sopenharmony_ci#define DMA_MODE_DBG_SHIFT 7 1098c2ecf20Sopenharmony_ci#define DMA_MODE_AID_MODE_SHIFT 4 1108c2ecf20Sopenharmony_ci 1118c2ecf20Sopenharmony_ci#define DMA_THRESH_COMMQ_SHIFT 24 1128c2ecf20Sopenharmony_ci#define DMA_THRESH_READ_INT_BUF_SHIFT 16 1138c2ecf20Sopenharmony_ci#define DMA_THRESH_READ_INT_BUF_MASK 0x0000003f 1148c2ecf20Sopenharmony_ci#define DMA_THRESH_WRITE_INT_BUF_MASK 0x0000003f 1158c2ecf20Sopenharmony_ci 1168c2ecf20Sopenharmony_ci#define DMA_TRANSFER_PORTID_SHIFT 24 1178c2ecf20Sopenharmony_ci#define DMA_TRANSFER_TNUM_SHIFT 16 1188c2ecf20Sopenharmony_ci 1198c2ecf20Sopenharmony_ci#define DMA_CAM_SIZEOF_ENTRY 0x40 1208c2ecf20Sopenharmony_ci#define DMA_CAM_UNITS 8 1218c2ecf20Sopenharmony_ci 1228c2ecf20Sopenharmony_ci#define DMA_LIODN_SHIFT 16 1238c2ecf20Sopenharmony_ci#define DMA_LIODN_BASE_MASK 0x00000FFF 1248c2ecf20Sopenharmony_ci 1258c2ecf20Sopenharmony_ci/* FPM defines */ 1268c2ecf20Sopenharmony_ci#define FPM_EV_MASK_DOUBLE_ECC 0x80000000 1278c2ecf20Sopenharmony_ci#define FPM_EV_MASK_STALL 0x40000000 1288c2ecf20Sopenharmony_ci#define FPM_EV_MASK_SINGLE_ECC 0x20000000 1298c2ecf20Sopenharmony_ci#define FPM_EV_MASK_RELEASE_FM 0x00010000 1308c2ecf20Sopenharmony_ci#define FPM_EV_MASK_DOUBLE_ECC_EN 0x00008000 1318c2ecf20Sopenharmony_ci#define FPM_EV_MASK_STALL_EN 0x00004000 1328c2ecf20Sopenharmony_ci#define FPM_EV_MASK_SINGLE_ECC_EN 0x00002000 1338c2ecf20Sopenharmony_ci#define FPM_EV_MASK_EXTERNAL_HALT 0x00000008 1348c2ecf20Sopenharmony_ci#define FPM_EV_MASK_ECC_ERR_HALT 0x00000004 1358c2ecf20Sopenharmony_ci 1368c2ecf20Sopenharmony_ci#define FPM_RAM_MURAM_ECC 0x00008000 1378c2ecf20Sopenharmony_ci#define FPM_RAM_IRAM_ECC 0x00004000 1388c2ecf20Sopenharmony_ci#define FPM_IRAM_ECC_ERR_EX_EN 0x00020000 1398c2ecf20Sopenharmony_ci#define FPM_MURAM_ECC_ERR_EX_EN 0x00040000 1408c2ecf20Sopenharmony_ci#define FPM_RAM_IRAM_ECC_EN 0x40000000 1418c2ecf20Sopenharmony_ci#define FPM_RAM_RAMS_ECC_EN 0x80000000 1428c2ecf20Sopenharmony_ci#define FPM_RAM_RAMS_ECC_EN_SRC_SEL 0x08000000 1438c2ecf20Sopenharmony_ci 1448c2ecf20Sopenharmony_ci#define FPM_REV1_MAJOR_MASK 0x0000FF00 1458c2ecf20Sopenharmony_ci#define FPM_REV1_MINOR_MASK 0x000000FF 1468c2ecf20Sopenharmony_ci 1478c2ecf20Sopenharmony_ci#define FPM_DISP_LIMIT_SHIFT 24 1488c2ecf20Sopenharmony_ci 1498c2ecf20Sopenharmony_ci#define FPM_PRT_FM_CTL1 0x00000001 1508c2ecf20Sopenharmony_ci#define FPM_PRT_FM_CTL2 0x00000002 1518c2ecf20Sopenharmony_ci#define FPM_PORT_FM_CTL_PORTID_SHIFT 24 1528c2ecf20Sopenharmony_ci#define FPM_PRC_ORA_FM_CTL_SEL_SHIFT 16 1538c2ecf20Sopenharmony_ci 1548c2ecf20Sopenharmony_ci#define FPM_THR1_PRS_SHIFT 24 1558c2ecf20Sopenharmony_ci#define FPM_THR1_KG_SHIFT 16 1568c2ecf20Sopenharmony_ci#define FPM_THR1_PLCR_SHIFT 8 1578c2ecf20Sopenharmony_ci#define FPM_THR1_BMI_SHIFT 0 1588c2ecf20Sopenharmony_ci 1598c2ecf20Sopenharmony_ci#define FPM_THR2_QMI_ENQ_SHIFT 24 1608c2ecf20Sopenharmony_ci#define FPM_THR2_QMI_DEQ_SHIFT 0 1618c2ecf20Sopenharmony_ci#define FPM_THR2_FM_CTL1_SHIFT 16 1628c2ecf20Sopenharmony_ci#define FPM_THR2_FM_CTL2_SHIFT 8 1638c2ecf20Sopenharmony_ci 1648c2ecf20Sopenharmony_ci#define FPM_EV_MASK_CAT_ERR_SHIFT 1 1658c2ecf20Sopenharmony_ci#define FPM_EV_MASK_DMA_ERR_SHIFT 0 1668c2ecf20Sopenharmony_ci 1678c2ecf20Sopenharmony_ci#define FPM_REV1_MAJOR_SHIFT 8 1688c2ecf20Sopenharmony_ci 1698c2ecf20Sopenharmony_ci#define FPM_RSTC_FM_RESET 0x80000000 1708c2ecf20Sopenharmony_ci#define FPM_RSTC_MAC0_RESET 0x40000000 1718c2ecf20Sopenharmony_ci#define FPM_RSTC_MAC1_RESET 0x20000000 1728c2ecf20Sopenharmony_ci#define FPM_RSTC_MAC2_RESET 0x10000000 1738c2ecf20Sopenharmony_ci#define FPM_RSTC_MAC3_RESET 0x08000000 1748c2ecf20Sopenharmony_ci#define FPM_RSTC_MAC8_RESET 0x04000000 1758c2ecf20Sopenharmony_ci#define FPM_RSTC_MAC4_RESET 0x02000000 1768c2ecf20Sopenharmony_ci#define FPM_RSTC_MAC5_RESET 0x01000000 1778c2ecf20Sopenharmony_ci#define FPM_RSTC_MAC6_RESET 0x00800000 1788c2ecf20Sopenharmony_ci#define FPM_RSTC_MAC7_RESET 0x00400000 1798c2ecf20Sopenharmony_ci#define FPM_RSTC_MAC9_RESET 0x00200000 1808c2ecf20Sopenharmony_ci 1818c2ecf20Sopenharmony_ci#define FPM_TS_INT_SHIFT 16 1828c2ecf20Sopenharmony_ci#define FPM_TS_CTL_EN 0x80000000 1838c2ecf20Sopenharmony_ci 1848c2ecf20Sopenharmony_ci/* BMI defines */ 1858c2ecf20Sopenharmony_ci#define BMI_INIT_START 0x80000000 1868c2ecf20Sopenharmony_ci#define BMI_ERR_INTR_EN_STORAGE_PROFILE_ECC 0x80000000 1878c2ecf20Sopenharmony_ci#define BMI_ERR_INTR_EN_LIST_RAM_ECC 0x40000000 1888c2ecf20Sopenharmony_ci#define BMI_ERR_INTR_EN_STATISTICS_RAM_ECC 0x20000000 1898c2ecf20Sopenharmony_ci#define BMI_ERR_INTR_EN_DISPATCH_RAM_ECC 0x10000000 1908c2ecf20Sopenharmony_ci#define BMI_NUM_OF_TASKS_MASK 0x3F000000 1918c2ecf20Sopenharmony_ci#define BMI_NUM_OF_EXTRA_TASKS_MASK 0x000F0000 1928c2ecf20Sopenharmony_ci#define BMI_NUM_OF_DMAS_MASK 0x00000F00 1938c2ecf20Sopenharmony_ci#define BMI_NUM_OF_EXTRA_DMAS_MASK 0x0000000F 1948c2ecf20Sopenharmony_ci#define BMI_FIFO_SIZE_MASK 0x000003FF 1958c2ecf20Sopenharmony_ci#define BMI_EXTRA_FIFO_SIZE_MASK 0x03FF0000 1968c2ecf20Sopenharmony_ci#define BMI_CFG2_DMAS_MASK 0x0000003F 1978c2ecf20Sopenharmony_ci#define BMI_CFG2_TASKS_MASK 0x0000003F 1988c2ecf20Sopenharmony_ci 1998c2ecf20Sopenharmony_ci#define BMI_CFG2_TASKS_SHIFT 16 2008c2ecf20Sopenharmony_ci#define BMI_CFG2_DMAS_SHIFT 0 2018c2ecf20Sopenharmony_ci#define BMI_CFG1_FIFO_SIZE_SHIFT 16 2028c2ecf20Sopenharmony_ci#define BMI_NUM_OF_TASKS_SHIFT 24 2038c2ecf20Sopenharmony_ci#define BMI_EXTRA_NUM_OF_TASKS_SHIFT 16 2048c2ecf20Sopenharmony_ci#define BMI_NUM_OF_DMAS_SHIFT 8 2058c2ecf20Sopenharmony_ci#define BMI_EXTRA_NUM_OF_DMAS_SHIFT 0 2068c2ecf20Sopenharmony_ci 2078c2ecf20Sopenharmony_ci#define BMI_FIFO_ALIGN 0x100 2088c2ecf20Sopenharmony_ci 2098c2ecf20Sopenharmony_ci#define BMI_EXTRA_FIFO_SIZE_SHIFT 16 2108c2ecf20Sopenharmony_ci 2118c2ecf20Sopenharmony_ci/* QMI defines */ 2128c2ecf20Sopenharmony_ci#define QMI_CFG_ENQ_EN 0x80000000 2138c2ecf20Sopenharmony_ci#define QMI_CFG_DEQ_EN 0x40000000 2148c2ecf20Sopenharmony_ci#define QMI_CFG_EN_COUNTERS 0x10000000 2158c2ecf20Sopenharmony_ci#define QMI_CFG_DEQ_MASK 0x0000003F 2168c2ecf20Sopenharmony_ci#define QMI_CFG_ENQ_MASK 0x00003F00 2178c2ecf20Sopenharmony_ci#define QMI_CFG_ENQ_SHIFT 8 2188c2ecf20Sopenharmony_ci 2198c2ecf20Sopenharmony_ci#define QMI_ERR_INTR_EN_DOUBLE_ECC 0x80000000 2208c2ecf20Sopenharmony_ci#define QMI_ERR_INTR_EN_DEQ_FROM_DEF 0x40000000 2218c2ecf20Sopenharmony_ci#define QMI_INTR_EN_SINGLE_ECC 0x80000000 2228c2ecf20Sopenharmony_ci 2238c2ecf20Sopenharmony_ci#define QMI_GS_HALT_NOT_BUSY 0x00000002 2248c2ecf20Sopenharmony_ci 2258c2ecf20Sopenharmony_ci/* HWP defines */ 2268c2ecf20Sopenharmony_ci#define HWP_RPIMAC_PEN 0x00000001 2278c2ecf20Sopenharmony_ci 2288c2ecf20Sopenharmony_ci/* IRAM defines */ 2298c2ecf20Sopenharmony_ci#define IRAM_IADD_AIE 0x80000000 2308c2ecf20Sopenharmony_ci#define IRAM_READY 0x80000000 2318c2ecf20Sopenharmony_ci 2328c2ecf20Sopenharmony_ci/* Default values */ 2338c2ecf20Sopenharmony_ci#define DEFAULT_CATASTROPHIC_ERR 0 2348c2ecf20Sopenharmony_ci#define DEFAULT_DMA_ERR 0 2358c2ecf20Sopenharmony_ci#define DEFAULT_AID_MODE FMAN_DMA_AID_OUT_TNUM 2368c2ecf20Sopenharmony_ci#define DEFAULT_DMA_COMM_Q_LOW 0x2A 2378c2ecf20Sopenharmony_ci#define DEFAULT_DMA_COMM_Q_HIGH 0x3F 2388c2ecf20Sopenharmony_ci#define DEFAULT_CACHE_OVERRIDE 0 2398c2ecf20Sopenharmony_ci#define DEFAULT_DMA_CAM_NUM_OF_ENTRIES 64 2408c2ecf20Sopenharmony_ci#define DEFAULT_DMA_DBG_CNT_MODE 0 2418c2ecf20Sopenharmony_ci#define DEFAULT_DMA_SOS_EMERGENCY 0 2428c2ecf20Sopenharmony_ci#define DEFAULT_DMA_WATCHDOG 0 2438c2ecf20Sopenharmony_ci#define DEFAULT_DISP_LIMIT 0 2448c2ecf20Sopenharmony_ci#define DEFAULT_PRS_DISP_TH 16 2458c2ecf20Sopenharmony_ci#define DEFAULT_PLCR_DISP_TH 16 2468c2ecf20Sopenharmony_ci#define DEFAULT_KG_DISP_TH 16 2478c2ecf20Sopenharmony_ci#define DEFAULT_BMI_DISP_TH 16 2488c2ecf20Sopenharmony_ci#define DEFAULT_QMI_ENQ_DISP_TH 16 2498c2ecf20Sopenharmony_ci#define DEFAULT_QMI_DEQ_DISP_TH 16 2508c2ecf20Sopenharmony_ci#define DEFAULT_FM_CTL1_DISP_TH 16 2518c2ecf20Sopenharmony_ci#define DEFAULT_FM_CTL2_DISP_TH 16 2528c2ecf20Sopenharmony_ci 2538c2ecf20Sopenharmony_ci#define DFLT_AXI_DBG_NUM_OF_BEATS 1 2548c2ecf20Sopenharmony_ci 2558c2ecf20Sopenharmony_ci#define DFLT_DMA_READ_INT_BUF_LOW(dma_thresh_max_buf) \ 2568c2ecf20Sopenharmony_ci ((dma_thresh_max_buf + 1) / 2) 2578c2ecf20Sopenharmony_ci#define DFLT_DMA_READ_INT_BUF_HIGH(dma_thresh_max_buf) \ 2588c2ecf20Sopenharmony_ci ((dma_thresh_max_buf + 1) * 3 / 4) 2598c2ecf20Sopenharmony_ci#define DFLT_DMA_WRITE_INT_BUF_LOW(dma_thresh_max_buf) \ 2608c2ecf20Sopenharmony_ci ((dma_thresh_max_buf + 1) / 2) 2618c2ecf20Sopenharmony_ci#define DFLT_DMA_WRITE_INT_BUF_HIGH(dma_thresh_max_buf)\ 2628c2ecf20Sopenharmony_ci ((dma_thresh_max_buf + 1) * 3 / 4) 2638c2ecf20Sopenharmony_ci 2648c2ecf20Sopenharmony_ci#define DMA_COMM_Q_LOW_FMAN_V3 0x2A 2658c2ecf20Sopenharmony_ci#define DMA_COMM_Q_LOW_FMAN_V2(dma_thresh_max_commq) \ 2668c2ecf20Sopenharmony_ci ((dma_thresh_max_commq + 1) / 2) 2678c2ecf20Sopenharmony_ci#define DFLT_DMA_COMM_Q_LOW(major, dma_thresh_max_commq) \ 2688c2ecf20Sopenharmony_ci ((major == 6) ? DMA_COMM_Q_LOW_FMAN_V3 : \ 2698c2ecf20Sopenharmony_ci DMA_COMM_Q_LOW_FMAN_V2(dma_thresh_max_commq)) 2708c2ecf20Sopenharmony_ci 2718c2ecf20Sopenharmony_ci#define DMA_COMM_Q_HIGH_FMAN_V3 0x3f 2728c2ecf20Sopenharmony_ci#define DMA_COMM_Q_HIGH_FMAN_V2(dma_thresh_max_commq) \ 2738c2ecf20Sopenharmony_ci ((dma_thresh_max_commq + 1) * 3 / 4) 2748c2ecf20Sopenharmony_ci#define DFLT_DMA_COMM_Q_HIGH(major, dma_thresh_max_commq) \ 2758c2ecf20Sopenharmony_ci ((major == 6) ? DMA_COMM_Q_HIGH_FMAN_V3 : \ 2768c2ecf20Sopenharmony_ci DMA_COMM_Q_HIGH_FMAN_V2(dma_thresh_max_commq)) 2778c2ecf20Sopenharmony_ci 2788c2ecf20Sopenharmony_ci#define TOTAL_NUM_OF_TASKS_FMAN_V3L 59 2798c2ecf20Sopenharmony_ci#define TOTAL_NUM_OF_TASKS_FMAN_V3H 124 2808c2ecf20Sopenharmony_ci#define DFLT_TOTAL_NUM_OF_TASKS(major, minor, bmi_max_num_of_tasks) \ 2818c2ecf20Sopenharmony_ci ((major == 6) ? ((minor == 1 || minor == 4) ? \ 2828c2ecf20Sopenharmony_ci TOTAL_NUM_OF_TASKS_FMAN_V3L : TOTAL_NUM_OF_TASKS_FMAN_V3H) : \ 2838c2ecf20Sopenharmony_ci bmi_max_num_of_tasks) 2848c2ecf20Sopenharmony_ci 2858c2ecf20Sopenharmony_ci#define DMA_CAM_NUM_OF_ENTRIES_FMAN_V3 64 2868c2ecf20Sopenharmony_ci#define DMA_CAM_NUM_OF_ENTRIES_FMAN_V2 32 2878c2ecf20Sopenharmony_ci#define DFLT_DMA_CAM_NUM_OF_ENTRIES(major) \ 2888c2ecf20Sopenharmony_ci (major == 6 ? DMA_CAM_NUM_OF_ENTRIES_FMAN_V3 : \ 2898c2ecf20Sopenharmony_ci DMA_CAM_NUM_OF_ENTRIES_FMAN_V2) 2908c2ecf20Sopenharmony_ci 2918c2ecf20Sopenharmony_ci#define FM_TIMESTAMP_1_USEC_BIT 8 2928c2ecf20Sopenharmony_ci 2938c2ecf20Sopenharmony_ci/* Defines used for enabling/disabling FMan interrupts */ 2948c2ecf20Sopenharmony_ci#define ERR_INTR_EN_DMA 0x00010000 2958c2ecf20Sopenharmony_ci#define ERR_INTR_EN_FPM 0x80000000 2968c2ecf20Sopenharmony_ci#define ERR_INTR_EN_BMI 0x00800000 2978c2ecf20Sopenharmony_ci#define ERR_INTR_EN_QMI 0x00400000 2988c2ecf20Sopenharmony_ci#define ERR_INTR_EN_MURAM 0x00040000 2998c2ecf20Sopenharmony_ci#define ERR_INTR_EN_MAC0 0x00004000 3008c2ecf20Sopenharmony_ci#define ERR_INTR_EN_MAC1 0x00002000 3018c2ecf20Sopenharmony_ci#define ERR_INTR_EN_MAC2 0x00001000 3028c2ecf20Sopenharmony_ci#define ERR_INTR_EN_MAC3 0x00000800 3038c2ecf20Sopenharmony_ci#define ERR_INTR_EN_MAC4 0x00000400 3048c2ecf20Sopenharmony_ci#define ERR_INTR_EN_MAC5 0x00000200 3058c2ecf20Sopenharmony_ci#define ERR_INTR_EN_MAC6 0x00000100 3068c2ecf20Sopenharmony_ci#define ERR_INTR_EN_MAC7 0x00000080 3078c2ecf20Sopenharmony_ci#define ERR_INTR_EN_MAC8 0x00008000 3088c2ecf20Sopenharmony_ci#define ERR_INTR_EN_MAC9 0x00000040 3098c2ecf20Sopenharmony_ci 3108c2ecf20Sopenharmony_ci#define INTR_EN_QMI 0x40000000 3118c2ecf20Sopenharmony_ci#define INTR_EN_MAC0 0x00080000 3128c2ecf20Sopenharmony_ci#define INTR_EN_MAC1 0x00040000 3138c2ecf20Sopenharmony_ci#define INTR_EN_MAC2 0x00020000 3148c2ecf20Sopenharmony_ci#define INTR_EN_MAC3 0x00010000 3158c2ecf20Sopenharmony_ci#define INTR_EN_MAC4 0x00000040 3168c2ecf20Sopenharmony_ci#define INTR_EN_MAC5 0x00000020 3178c2ecf20Sopenharmony_ci#define INTR_EN_MAC6 0x00000008 3188c2ecf20Sopenharmony_ci#define INTR_EN_MAC7 0x00000002 3198c2ecf20Sopenharmony_ci#define INTR_EN_MAC8 0x00200000 3208c2ecf20Sopenharmony_ci#define INTR_EN_MAC9 0x00100000 3218c2ecf20Sopenharmony_ci#define INTR_EN_REV0 0x00008000 3228c2ecf20Sopenharmony_ci#define INTR_EN_REV1 0x00004000 3238c2ecf20Sopenharmony_ci#define INTR_EN_REV2 0x00002000 3248c2ecf20Sopenharmony_ci#define INTR_EN_REV3 0x00001000 3258c2ecf20Sopenharmony_ci#define INTR_EN_TMR 0x01000000 3268c2ecf20Sopenharmony_ci 3278c2ecf20Sopenharmony_cienum fman_dma_aid_mode { 3288c2ecf20Sopenharmony_ci FMAN_DMA_AID_OUT_PORT_ID = 0, /* 4 LSB of PORT_ID */ 3298c2ecf20Sopenharmony_ci FMAN_DMA_AID_OUT_TNUM /* 4 LSB of TNUM */ 3308c2ecf20Sopenharmony_ci}; 3318c2ecf20Sopenharmony_ci 3328c2ecf20Sopenharmony_cistruct fman_iram_regs { 3338c2ecf20Sopenharmony_ci u32 iadd; /* FM IRAM instruction address register */ 3348c2ecf20Sopenharmony_ci u32 idata; /* FM IRAM instruction data register */ 3358c2ecf20Sopenharmony_ci u32 itcfg; /* FM IRAM timing config register */ 3368c2ecf20Sopenharmony_ci u32 iready; /* FM IRAM ready register */ 3378c2ecf20Sopenharmony_ci}; 3388c2ecf20Sopenharmony_ci 3398c2ecf20Sopenharmony_cistruct fman_fpm_regs { 3408c2ecf20Sopenharmony_ci u32 fmfp_tnc; /* FPM TNUM Control 0x00 */ 3418c2ecf20Sopenharmony_ci u32 fmfp_prc; /* FPM Port_ID FmCtl Association 0x04 */ 3428c2ecf20Sopenharmony_ci u32 fmfp_brkc; /* FPM Breakpoint Control 0x08 */ 3438c2ecf20Sopenharmony_ci u32 fmfp_mxd; /* FPM Flush Control 0x0c */ 3448c2ecf20Sopenharmony_ci u32 fmfp_dist1; /* FPM Dispatch Thresholds1 0x10 */ 3458c2ecf20Sopenharmony_ci u32 fmfp_dist2; /* FPM Dispatch Thresholds2 0x14 */ 3468c2ecf20Sopenharmony_ci u32 fm_epi; /* FM Error Pending Interrupts 0x18 */ 3478c2ecf20Sopenharmony_ci u32 fm_rie; /* FM Error Interrupt Enable 0x1c */ 3488c2ecf20Sopenharmony_ci u32 fmfp_fcev[4]; /* FPM FMan-Controller Event 1-4 0x20-0x2f */ 3498c2ecf20Sopenharmony_ci u32 res0030[4]; /* res 0x30 - 0x3f */ 3508c2ecf20Sopenharmony_ci u32 fmfp_cee[4]; /* PM FMan-Controller Event 1-4 0x40-0x4f */ 3518c2ecf20Sopenharmony_ci u32 res0050[4]; /* res 0x50-0x5f */ 3528c2ecf20Sopenharmony_ci u32 fmfp_tsc1; /* FPM TimeStamp Control1 0x60 */ 3538c2ecf20Sopenharmony_ci u32 fmfp_tsc2; /* FPM TimeStamp Control2 0x64 */ 3548c2ecf20Sopenharmony_ci u32 fmfp_tsp; /* FPM Time Stamp 0x68 */ 3558c2ecf20Sopenharmony_ci u32 fmfp_tsf; /* FPM Time Stamp Fraction 0x6c */ 3568c2ecf20Sopenharmony_ci u32 fm_rcr; /* FM Rams Control 0x70 */ 3578c2ecf20Sopenharmony_ci u32 fmfp_extc; /* FPM External Requests Control 0x74 */ 3588c2ecf20Sopenharmony_ci u32 fmfp_ext1; /* FPM External Requests Config1 0x78 */ 3598c2ecf20Sopenharmony_ci u32 fmfp_ext2; /* FPM External Requests Config2 0x7c */ 3608c2ecf20Sopenharmony_ci u32 fmfp_drd[16]; /* FPM Data_Ram Data 0-15 0x80 - 0xbf */ 3618c2ecf20Sopenharmony_ci u32 fmfp_dra; /* FPM Data Ram Access 0xc0 */ 3628c2ecf20Sopenharmony_ci u32 fm_ip_rev_1; /* FM IP Block Revision 1 0xc4 */ 3638c2ecf20Sopenharmony_ci u32 fm_ip_rev_2; /* FM IP Block Revision 2 0xc8 */ 3648c2ecf20Sopenharmony_ci u32 fm_rstc; /* FM Reset Command 0xcc */ 3658c2ecf20Sopenharmony_ci u32 fm_cld; /* FM Classifier Debug 0xd0 */ 3668c2ecf20Sopenharmony_ci u32 fm_npi; /* FM Normal Pending Interrupts 0xd4 */ 3678c2ecf20Sopenharmony_ci u32 fmfp_exte; /* FPM External Requests Enable 0xd8 */ 3688c2ecf20Sopenharmony_ci u32 fmfp_ee; /* FPM Event&Mask 0xdc */ 3698c2ecf20Sopenharmony_ci u32 fmfp_cev[4]; /* FPM CPU Event 1-4 0xe0-0xef */ 3708c2ecf20Sopenharmony_ci u32 res00f0[4]; /* res 0xf0-0xff */ 3718c2ecf20Sopenharmony_ci u32 fmfp_ps[50]; /* FPM Port Status 0x100-0x1c7 */ 3728c2ecf20Sopenharmony_ci u32 res01c8[14]; /* res 0x1c8-0x1ff */ 3738c2ecf20Sopenharmony_ci u32 fmfp_clfabc; /* FPM CLFABC 0x200 */ 3748c2ecf20Sopenharmony_ci u32 fmfp_clfcc; /* FPM CLFCC 0x204 */ 3758c2ecf20Sopenharmony_ci u32 fmfp_clfaval; /* FPM CLFAVAL 0x208 */ 3768c2ecf20Sopenharmony_ci u32 fmfp_clfbval; /* FPM CLFBVAL 0x20c */ 3778c2ecf20Sopenharmony_ci u32 fmfp_clfcval; /* FPM CLFCVAL 0x210 */ 3788c2ecf20Sopenharmony_ci u32 fmfp_clfamsk; /* FPM CLFAMSK 0x214 */ 3798c2ecf20Sopenharmony_ci u32 fmfp_clfbmsk; /* FPM CLFBMSK 0x218 */ 3808c2ecf20Sopenharmony_ci u32 fmfp_clfcmsk; /* FPM CLFCMSK 0x21c */ 3818c2ecf20Sopenharmony_ci u32 fmfp_clfamc; /* FPM CLFAMC 0x220 */ 3828c2ecf20Sopenharmony_ci u32 fmfp_clfbmc; /* FPM CLFBMC 0x224 */ 3838c2ecf20Sopenharmony_ci u32 fmfp_clfcmc; /* FPM CLFCMC 0x228 */ 3848c2ecf20Sopenharmony_ci u32 fmfp_decceh; /* FPM DECCEH 0x22c */ 3858c2ecf20Sopenharmony_ci u32 res0230[116]; /* res 0x230 - 0x3ff */ 3868c2ecf20Sopenharmony_ci u32 fmfp_ts[128]; /* 0x400: FPM Task Status 0x400 - 0x5ff */ 3878c2ecf20Sopenharmony_ci u32 res0600[0x400 - 384]; 3888c2ecf20Sopenharmony_ci}; 3898c2ecf20Sopenharmony_ci 3908c2ecf20Sopenharmony_cistruct fman_bmi_regs { 3918c2ecf20Sopenharmony_ci u32 fmbm_init; /* BMI Initialization 0x00 */ 3928c2ecf20Sopenharmony_ci u32 fmbm_cfg1; /* BMI Configuration 1 0x04 */ 3938c2ecf20Sopenharmony_ci u32 fmbm_cfg2; /* BMI Configuration 2 0x08 */ 3948c2ecf20Sopenharmony_ci u32 res000c[5]; /* 0x0c - 0x1f */ 3958c2ecf20Sopenharmony_ci u32 fmbm_ievr; /* Interrupt Event Register 0x20 */ 3968c2ecf20Sopenharmony_ci u32 fmbm_ier; /* Interrupt Enable Register 0x24 */ 3978c2ecf20Sopenharmony_ci u32 fmbm_ifr; /* Interrupt Force Register 0x28 */ 3988c2ecf20Sopenharmony_ci u32 res002c[5]; /* 0x2c - 0x3f */ 3998c2ecf20Sopenharmony_ci u32 fmbm_arb[8]; /* BMI Arbitration 0x40 - 0x5f */ 4008c2ecf20Sopenharmony_ci u32 res0060[12]; /* 0x60 - 0x8f */ 4018c2ecf20Sopenharmony_ci u32 fmbm_dtc[3]; /* Debug Trap Counter 0x90 - 0x9b */ 4028c2ecf20Sopenharmony_ci u32 res009c; /* 0x9c */ 4038c2ecf20Sopenharmony_ci u32 fmbm_dcv[3][4]; /* Debug Compare val 0xa0-0xcf */ 4048c2ecf20Sopenharmony_ci u32 fmbm_dcm[3][4]; /* Debug Compare Mask 0xd0-0xff */ 4058c2ecf20Sopenharmony_ci u32 fmbm_gde; /* BMI Global Debug Enable 0x100 */ 4068c2ecf20Sopenharmony_ci u32 fmbm_pp[63]; /* BMI Port Parameters 0x104 - 0x1ff */ 4078c2ecf20Sopenharmony_ci u32 res0200; /* 0x200 */ 4088c2ecf20Sopenharmony_ci u32 fmbm_pfs[63]; /* BMI Port FIFO Size 0x204 - 0x2ff */ 4098c2ecf20Sopenharmony_ci u32 res0300; /* 0x300 */ 4108c2ecf20Sopenharmony_ci u32 fmbm_spliodn[63]; /* Port Partition ID 0x304 - 0x3ff */ 4118c2ecf20Sopenharmony_ci}; 4128c2ecf20Sopenharmony_ci 4138c2ecf20Sopenharmony_cistruct fman_qmi_regs { 4148c2ecf20Sopenharmony_ci u32 fmqm_gc; /* General Configuration Register 0x00 */ 4158c2ecf20Sopenharmony_ci u32 res0004; /* 0x04 */ 4168c2ecf20Sopenharmony_ci u32 fmqm_eie; /* Error Interrupt Event Register 0x08 */ 4178c2ecf20Sopenharmony_ci u32 fmqm_eien; /* Error Interrupt Enable Register 0x0c */ 4188c2ecf20Sopenharmony_ci u32 fmqm_eif; /* Error Interrupt Force Register 0x10 */ 4198c2ecf20Sopenharmony_ci u32 fmqm_ie; /* Interrupt Event Register 0x14 */ 4208c2ecf20Sopenharmony_ci u32 fmqm_ien; /* Interrupt Enable Register 0x18 */ 4218c2ecf20Sopenharmony_ci u32 fmqm_if; /* Interrupt Force Register 0x1c */ 4228c2ecf20Sopenharmony_ci u32 fmqm_gs; /* Global Status Register 0x20 */ 4238c2ecf20Sopenharmony_ci u32 fmqm_ts; /* Task Status Register 0x24 */ 4248c2ecf20Sopenharmony_ci u32 fmqm_etfc; /* Enqueue Total Frame Counter 0x28 */ 4258c2ecf20Sopenharmony_ci u32 fmqm_dtfc; /* Dequeue Total Frame Counter 0x2c */ 4268c2ecf20Sopenharmony_ci u32 fmqm_dc0; /* Dequeue Counter 0 0x30 */ 4278c2ecf20Sopenharmony_ci u32 fmqm_dc1; /* Dequeue Counter 1 0x34 */ 4288c2ecf20Sopenharmony_ci u32 fmqm_dc2; /* Dequeue Counter 2 0x38 */ 4298c2ecf20Sopenharmony_ci u32 fmqm_dc3; /* Dequeue Counter 3 0x3c */ 4308c2ecf20Sopenharmony_ci u32 fmqm_dfdc; /* Dequeue FQID from Default Counter 0x40 */ 4318c2ecf20Sopenharmony_ci u32 fmqm_dfcc; /* Dequeue FQID from Context Counter 0x44 */ 4328c2ecf20Sopenharmony_ci u32 fmqm_dffc; /* Dequeue FQID from FD Counter 0x48 */ 4338c2ecf20Sopenharmony_ci u32 fmqm_dcc; /* Dequeue Confirm Counter 0x4c */ 4348c2ecf20Sopenharmony_ci u32 res0050[7]; /* 0x50 - 0x6b */ 4358c2ecf20Sopenharmony_ci u32 fmqm_tapc; /* Tnum Aging Period Control 0x6c */ 4368c2ecf20Sopenharmony_ci u32 fmqm_dmcvc; /* Dequeue MAC Command Valid Counter 0x70 */ 4378c2ecf20Sopenharmony_ci u32 fmqm_difdcc; /* Dequeue Invalid FD Command Counter 0x74 */ 4388c2ecf20Sopenharmony_ci u32 fmqm_da1v; /* Dequeue A1 Valid Counter 0x78 */ 4398c2ecf20Sopenharmony_ci u32 res007c; /* 0x7c */ 4408c2ecf20Sopenharmony_ci u32 fmqm_dtc; /* 0x80 Debug Trap Counter 0x80 */ 4418c2ecf20Sopenharmony_ci u32 fmqm_efddd; /* 0x84 Enqueue Frame desc Dynamic dbg 0x84 */ 4428c2ecf20Sopenharmony_ci u32 res0088[2]; /* 0x88 - 0x8f */ 4438c2ecf20Sopenharmony_ci struct { 4448c2ecf20Sopenharmony_ci u32 fmqm_dtcfg1; /* 0x90 dbg trap cfg 1 Register 0x00 */ 4458c2ecf20Sopenharmony_ci u32 fmqm_dtval1; /* Debug Trap Value 1 Register 0x04 */ 4468c2ecf20Sopenharmony_ci u32 fmqm_dtm1; /* Debug Trap Mask 1 Register 0x08 */ 4478c2ecf20Sopenharmony_ci u32 fmqm_dtc1; /* Debug Trap Counter 1 Register 0x0c */ 4488c2ecf20Sopenharmony_ci u32 fmqm_dtcfg2; /* dbg Trap cfg 2 Register 0x10 */ 4498c2ecf20Sopenharmony_ci u32 fmqm_dtval2; /* Debug Trap Value 2 Register 0x14 */ 4508c2ecf20Sopenharmony_ci u32 fmqm_dtm2; /* Debug Trap Mask 2 Register 0x18 */ 4518c2ecf20Sopenharmony_ci u32 res001c; /* 0x1c */ 4528c2ecf20Sopenharmony_ci } dbg_traps[3]; /* 0x90 - 0xef */ 4538c2ecf20Sopenharmony_ci u8 res00f0[0x400 - 0xf0]; /* 0xf0 - 0x3ff */ 4548c2ecf20Sopenharmony_ci}; 4558c2ecf20Sopenharmony_ci 4568c2ecf20Sopenharmony_cistruct fman_dma_regs { 4578c2ecf20Sopenharmony_ci u32 fmdmsr; /* FM DMA status register 0x00 */ 4588c2ecf20Sopenharmony_ci u32 fmdmmr; /* FM DMA mode register 0x04 */ 4598c2ecf20Sopenharmony_ci u32 fmdmtr; /* FM DMA bus threshold register 0x08 */ 4608c2ecf20Sopenharmony_ci u32 fmdmhy; /* FM DMA bus hysteresis register 0x0c */ 4618c2ecf20Sopenharmony_ci u32 fmdmsetr; /* FM DMA SOS emergency Threshold Register 0x10 */ 4628c2ecf20Sopenharmony_ci u32 fmdmtah; /* FM DMA transfer bus address high reg 0x14 */ 4638c2ecf20Sopenharmony_ci u32 fmdmtal; /* FM DMA transfer bus address low reg 0x18 */ 4648c2ecf20Sopenharmony_ci u32 fmdmtcid; /* FM DMA transfer bus communication ID reg 0x1c */ 4658c2ecf20Sopenharmony_ci u32 fmdmra; /* FM DMA bus internal ram address register 0x20 */ 4668c2ecf20Sopenharmony_ci u32 fmdmrd; /* FM DMA bus internal ram data register 0x24 */ 4678c2ecf20Sopenharmony_ci u32 fmdmwcr; /* FM DMA CAM watchdog counter value 0x28 */ 4688c2ecf20Sopenharmony_ci u32 fmdmebcr; /* FM DMA CAM base in MURAM register 0x2c */ 4698c2ecf20Sopenharmony_ci u32 fmdmccqdr; /* FM DMA CAM and CMD Queue Debug reg 0x30 */ 4708c2ecf20Sopenharmony_ci u32 fmdmccqvr1; /* FM DMA CAM and CMD Queue Value reg #1 0x34 */ 4718c2ecf20Sopenharmony_ci u32 fmdmccqvr2; /* FM DMA CAM and CMD Queue Value reg #2 0x38 */ 4728c2ecf20Sopenharmony_ci u32 fmdmcqvr3; /* FM DMA CMD Queue Value register #3 0x3c */ 4738c2ecf20Sopenharmony_ci u32 fmdmcqvr4; /* FM DMA CMD Queue Value register #4 0x40 */ 4748c2ecf20Sopenharmony_ci u32 fmdmcqvr5; /* FM DMA CMD Queue Value register #5 0x44 */ 4758c2ecf20Sopenharmony_ci u32 fmdmsefrc; /* FM DMA Semaphore Entry Full Reject Cntr 0x48 */ 4768c2ecf20Sopenharmony_ci u32 fmdmsqfrc; /* FM DMA Semaphore Queue Full Reject Cntr 0x4c */ 4778c2ecf20Sopenharmony_ci u32 fmdmssrc; /* FM DMA Semaphore SYNC Reject Counter 0x50 */ 4788c2ecf20Sopenharmony_ci u32 fmdmdcr; /* FM DMA Debug Counter 0x54 */ 4798c2ecf20Sopenharmony_ci u32 fmdmemsr; /* FM DMA Emergency Smoother Register 0x58 */ 4808c2ecf20Sopenharmony_ci u32 res005c; /* 0x5c */ 4818c2ecf20Sopenharmony_ci u32 fmdmplr[FMAN_LIODN_TBL / 2]; /* DMA LIODN regs 0x60-0xdf */ 4828c2ecf20Sopenharmony_ci u32 res00e0[0x400 - 56]; 4838c2ecf20Sopenharmony_ci}; 4848c2ecf20Sopenharmony_ci 4858c2ecf20Sopenharmony_cistruct fman_hwp_regs { 4868c2ecf20Sopenharmony_ci u32 res0000[0x844 / 4]; /* 0x000..0x843 */ 4878c2ecf20Sopenharmony_ci u32 fmprrpimac; /* FM Parser Internal memory access control */ 4888c2ecf20Sopenharmony_ci u32 res[(0x1000 - 0x848) / 4]; /* 0x848..0xFFF */ 4898c2ecf20Sopenharmony_ci}; 4908c2ecf20Sopenharmony_ci 4918c2ecf20Sopenharmony_ci/* Structure that holds current FMan state. 4928c2ecf20Sopenharmony_ci * Used for saving run time information. 4938c2ecf20Sopenharmony_ci */ 4948c2ecf20Sopenharmony_cistruct fman_state_struct { 4958c2ecf20Sopenharmony_ci u8 fm_id; 4968c2ecf20Sopenharmony_ci u16 fm_clk_freq; 4978c2ecf20Sopenharmony_ci struct fman_rev_info rev_info; 4988c2ecf20Sopenharmony_ci bool enabled_time_stamp; 4998c2ecf20Sopenharmony_ci u8 count1_micro_bit; 5008c2ecf20Sopenharmony_ci u8 total_num_of_tasks; 5018c2ecf20Sopenharmony_ci u8 accumulated_num_of_tasks; 5028c2ecf20Sopenharmony_ci u32 accumulated_fifo_size; 5038c2ecf20Sopenharmony_ci u8 accumulated_num_of_open_dmas; 5048c2ecf20Sopenharmony_ci u8 accumulated_num_of_deq_tnums; 5058c2ecf20Sopenharmony_ci u32 exceptions; 5068c2ecf20Sopenharmony_ci u32 extra_fifo_pool_size; 5078c2ecf20Sopenharmony_ci u8 extra_tasks_pool_size; 5088c2ecf20Sopenharmony_ci u8 extra_open_dmas_pool_size; 5098c2ecf20Sopenharmony_ci u16 port_mfl[MAX_NUM_OF_MACS]; 5108c2ecf20Sopenharmony_ci u16 mac_mfl[MAX_NUM_OF_MACS]; 5118c2ecf20Sopenharmony_ci 5128c2ecf20Sopenharmony_ci /* SOC specific */ 5138c2ecf20Sopenharmony_ci u32 fm_iram_size; 5148c2ecf20Sopenharmony_ci /* DMA */ 5158c2ecf20Sopenharmony_ci u32 dma_thresh_max_commq; 5168c2ecf20Sopenharmony_ci u32 dma_thresh_max_buf; 5178c2ecf20Sopenharmony_ci u32 max_num_of_open_dmas; 5188c2ecf20Sopenharmony_ci /* QMI */ 5198c2ecf20Sopenharmony_ci u32 qmi_max_num_of_tnums; 5208c2ecf20Sopenharmony_ci u32 qmi_def_tnums_thresh; 5218c2ecf20Sopenharmony_ci /* BMI */ 5228c2ecf20Sopenharmony_ci u32 bmi_max_num_of_tasks; 5238c2ecf20Sopenharmony_ci u32 bmi_max_fifo_size; 5248c2ecf20Sopenharmony_ci /* General */ 5258c2ecf20Sopenharmony_ci u32 fm_port_num_of_cg; 5268c2ecf20Sopenharmony_ci u32 num_of_rx_ports; 5278c2ecf20Sopenharmony_ci u32 total_fifo_size; 5288c2ecf20Sopenharmony_ci 5298c2ecf20Sopenharmony_ci u32 qman_channel_base; 5308c2ecf20Sopenharmony_ci u32 num_of_qman_channels; 5318c2ecf20Sopenharmony_ci 5328c2ecf20Sopenharmony_ci struct resource *res; 5338c2ecf20Sopenharmony_ci}; 5348c2ecf20Sopenharmony_ci 5358c2ecf20Sopenharmony_ci/* Structure that holds FMan initial configuration */ 5368c2ecf20Sopenharmony_cistruct fman_cfg { 5378c2ecf20Sopenharmony_ci u8 disp_limit_tsh; 5388c2ecf20Sopenharmony_ci u8 prs_disp_tsh; 5398c2ecf20Sopenharmony_ci u8 plcr_disp_tsh; 5408c2ecf20Sopenharmony_ci u8 kg_disp_tsh; 5418c2ecf20Sopenharmony_ci u8 bmi_disp_tsh; 5428c2ecf20Sopenharmony_ci u8 qmi_enq_disp_tsh; 5438c2ecf20Sopenharmony_ci u8 qmi_deq_disp_tsh; 5448c2ecf20Sopenharmony_ci u8 fm_ctl1_disp_tsh; 5458c2ecf20Sopenharmony_ci u8 fm_ctl2_disp_tsh; 5468c2ecf20Sopenharmony_ci int dma_cache_override; 5478c2ecf20Sopenharmony_ci enum fman_dma_aid_mode dma_aid_mode; 5488c2ecf20Sopenharmony_ci u32 dma_axi_dbg_num_of_beats; 5498c2ecf20Sopenharmony_ci u32 dma_cam_num_of_entries; 5508c2ecf20Sopenharmony_ci u32 dma_watchdog; 5518c2ecf20Sopenharmony_ci u8 dma_comm_qtsh_asrt_emer; 5528c2ecf20Sopenharmony_ci u32 dma_write_buf_tsh_asrt_emer; 5538c2ecf20Sopenharmony_ci u32 dma_read_buf_tsh_asrt_emer; 5548c2ecf20Sopenharmony_ci u8 dma_comm_qtsh_clr_emer; 5558c2ecf20Sopenharmony_ci u32 dma_write_buf_tsh_clr_emer; 5568c2ecf20Sopenharmony_ci u32 dma_read_buf_tsh_clr_emer; 5578c2ecf20Sopenharmony_ci u32 dma_sos_emergency; 5588c2ecf20Sopenharmony_ci int dma_dbg_cnt_mode; 5598c2ecf20Sopenharmony_ci int catastrophic_err; 5608c2ecf20Sopenharmony_ci int dma_err; 5618c2ecf20Sopenharmony_ci u32 exceptions; 5628c2ecf20Sopenharmony_ci u16 clk_freq; 5638c2ecf20Sopenharmony_ci u32 cam_base_addr; 5648c2ecf20Sopenharmony_ci u32 fifo_base_addr; 5658c2ecf20Sopenharmony_ci u32 total_fifo_size; 5668c2ecf20Sopenharmony_ci u32 total_num_of_tasks; 5678c2ecf20Sopenharmony_ci u32 qmi_def_tnums_thresh; 5688c2ecf20Sopenharmony_ci}; 5698c2ecf20Sopenharmony_ci 5708c2ecf20Sopenharmony_ci#ifdef CONFIG_DPAA_ERRATUM_A050385 5718c2ecf20Sopenharmony_cistatic bool fman_has_err_a050385; 5728c2ecf20Sopenharmony_ci#endif 5738c2ecf20Sopenharmony_ci 5748c2ecf20Sopenharmony_cistatic irqreturn_t fman_exceptions(struct fman *fman, 5758c2ecf20Sopenharmony_ci enum fman_exceptions exception) 5768c2ecf20Sopenharmony_ci{ 5778c2ecf20Sopenharmony_ci dev_dbg(fman->dev, "%s: FMan[%d] exception %d\n", 5788c2ecf20Sopenharmony_ci __func__, fman->state->fm_id, exception); 5798c2ecf20Sopenharmony_ci 5808c2ecf20Sopenharmony_ci return IRQ_HANDLED; 5818c2ecf20Sopenharmony_ci} 5828c2ecf20Sopenharmony_ci 5838c2ecf20Sopenharmony_cistatic irqreturn_t fman_bus_error(struct fman *fman, u8 __maybe_unused port_id, 5848c2ecf20Sopenharmony_ci u64 __maybe_unused addr, 5858c2ecf20Sopenharmony_ci u8 __maybe_unused tnum, 5868c2ecf20Sopenharmony_ci u16 __maybe_unused liodn) 5878c2ecf20Sopenharmony_ci{ 5888c2ecf20Sopenharmony_ci dev_dbg(fman->dev, "%s: FMan[%d] bus error: port_id[%d]\n", 5898c2ecf20Sopenharmony_ci __func__, fman->state->fm_id, port_id); 5908c2ecf20Sopenharmony_ci 5918c2ecf20Sopenharmony_ci return IRQ_HANDLED; 5928c2ecf20Sopenharmony_ci} 5938c2ecf20Sopenharmony_ci 5948c2ecf20Sopenharmony_cistatic inline irqreturn_t call_mac_isr(struct fman *fman, u8 id) 5958c2ecf20Sopenharmony_ci{ 5968c2ecf20Sopenharmony_ci if (fman->intr_mng[id].isr_cb) { 5978c2ecf20Sopenharmony_ci fman->intr_mng[id].isr_cb(fman->intr_mng[id].src_handle); 5988c2ecf20Sopenharmony_ci 5998c2ecf20Sopenharmony_ci return IRQ_HANDLED; 6008c2ecf20Sopenharmony_ci } 6018c2ecf20Sopenharmony_ci 6028c2ecf20Sopenharmony_ci return IRQ_NONE; 6038c2ecf20Sopenharmony_ci} 6048c2ecf20Sopenharmony_ci 6058c2ecf20Sopenharmony_cistatic inline u8 hw_port_id_to_sw_port_id(u8 major, u8 hw_port_id) 6068c2ecf20Sopenharmony_ci{ 6078c2ecf20Sopenharmony_ci u8 sw_port_id = 0; 6088c2ecf20Sopenharmony_ci 6098c2ecf20Sopenharmony_ci if (hw_port_id >= BASE_TX_PORTID) 6108c2ecf20Sopenharmony_ci sw_port_id = hw_port_id - BASE_TX_PORTID; 6118c2ecf20Sopenharmony_ci else if (hw_port_id >= BASE_RX_PORTID) 6128c2ecf20Sopenharmony_ci sw_port_id = hw_port_id - BASE_RX_PORTID; 6138c2ecf20Sopenharmony_ci else 6148c2ecf20Sopenharmony_ci sw_port_id = 0; 6158c2ecf20Sopenharmony_ci 6168c2ecf20Sopenharmony_ci return sw_port_id; 6178c2ecf20Sopenharmony_ci} 6188c2ecf20Sopenharmony_ci 6198c2ecf20Sopenharmony_cistatic void set_port_order_restoration(struct fman_fpm_regs __iomem *fpm_rg, 6208c2ecf20Sopenharmony_ci u8 port_id) 6218c2ecf20Sopenharmony_ci{ 6228c2ecf20Sopenharmony_ci u32 tmp = 0; 6238c2ecf20Sopenharmony_ci 6248c2ecf20Sopenharmony_ci tmp = port_id << FPM_PORT_FM_CTL_PORTID_SHIFT; 6258c2ecf20Sopenharmony_ci 6268c2ecf20Sopenharmony_ci tmp |= FPM_PRT_FM_CTL2 | FPM_PRT_FM_CTL1; 6278c2ecf20Sopenharmony_ci 6288c2ecf20Sopenharmony_ci /* order restoration */ 6298c2ecf20Sopenharmony_ci if (port_id % 2) 6308c2ecf20Sopenharmony_ci tmp |= FPM_PRT_FM_CTL1 << FPM_PRC_ORA_FM_CTL_SEL_SHIFT; 6318c2ecf20Sopenharmony_ci else 6328c2ecf20Sopenharmony_ci tmp |= FPM_PRT_FM_CTL2 << FPM_PRC_ORA_FM_CTL_SEL_SHIFT; 6338c2ecf20Sopenharmony_ci 6348c2ecf20Sopenharmony_ci iowrite32be(tmp, &fpm_rg->fmfp_prc); 6358c2ecf20Sopenharmony_ci} 6368c2ecf20Sopenharmony_ci 6378c2ecf20Sopenharmony_cistatic void set_port_liodn(struct fman *fman, u8 port_id, 6388c2ecf20Sopenharmony_ci u32 liodn_base, u32 liodn_ofst) 6398c2ecf20Sopenharmony_ci{ 6408c2ecf20Sopenharmony_ci u32 tmp; 6418c2ecf20Sopenharmony_ci 6428c2ecf20Sopenharmony_ci iowrite32be(liodn_ofst, &fman->bmi_regs->fmbm_spliodn[port_id - 1]); 6438c2ecf20Sopenharmony_ci if (!IS_ENABLED(CONFIG_FSL_PAMU)) 6448c2ecf20Sopenharmony_ci return; 6458c2ecf20Sopenharmony_ci /* set LIODN base for this port */ 6468c2ecf20Sopenharmony_ci tmp = ioread32be(&fman->dma_regs->fmdmplr[port_id / 2]); 6478c2ecf20Sopenharmony_ci if (port_id % 2) { 6488c2ecf20Sopenharmony_ci tmp &= ~DMA_LIODN_BASE_MASK; 6498c2ecf20Sopenharmony_ci tmp |= liodn_base; 6508c2ecf20Sopenharmony_ci } else { 6518c2ecf20Sopenharmony_ci tmp &= ~(DMA_LIODN_BASE_MASK << DMA_LIODN_SHIFT); 6528c2ecf20Sopenharmony_ci tmp |= liodn_base << DMA_LIODN_SHIFT; 6538c2ecf20Sopenharmony_ci } 6548c2ecf20Sopenharmony_ci iowrite32be(tmp, &fman->dma_regs->fmdmplr[port_id / 2]); 6558c2ecf20Sopenharmony_ci} 6568c2ecf20Sopenharmony_ci 6578c2ecf20Sopenharmony_cistatic void enable_rams_ecc(struct fman_fpm_regs __iomem *fpm_rg) 6588c2ecf20Sopenharmony_ci{ 6598c2ecf20Sopenharmony_ci u32 tmp; 6608c2ecf20Sopenharmony_ci 6618c2ecf20Sopenharmony_ci tmp = ioread32be(&fpm_rg->fm_rcr); 6628c2ecf20Sopenharmony_ci if (tmp & FPM_RAM_RAMS_ECC_EN_SRC_SEL) 6638c2ecf20Sopenharmony_ci iowrite32be(tmp | FPM_RAM_IRAM_ECC_EN, &fpm_rg->fm_rcr); 6648c2ecf20Sopenharmony_ci else 6658c2ecf20Sopenharmony_ci iowrite32be(tmp | FPM_RAM_RAMS_ECC_EN | 6668c2ecf20Sopenharmony_ci FPM_RAM_IRAM_ECC_EN, &fpm_rg->fm_rcr); 6678c2ecf20Sopenharmony_ci} 6688c2ecf20Sopenharmony_ci 6698c2ecf20Sopenharmony_cistatic void disable_rams_ecc(struct fman_fpm_regs __iomem *fpm_rg) 6708c2ecf20Sopenharmony_ci{ 6718c2ecf20Sopenharmony_ci u32 tmp; 6728c2ecf20Sopenharmony_ci 6738c2ecf20Sopenharmony_ci tmp = ioread32be(&fpm_rg->fm_rcr); 6748c2ecf20Sopenharmony_ci if (tmp & FPM_RAM_RAMS_ECC_EN_SRC_SEL) 6758c2ecf20Sopenharmony_ci iowrite32be(tmp & ~FPM_RAM_IRAM_ECC_EN, &fpm_rg->fm_rcr); 6768c2ecf20Sopenharmony_ci else 6778c2ecf20Sopenharmony_ci iowrite32be(tmp & ~(FPM_RAM_RAMS_ECC_EN | FPM_RAM_IRAM_ECC_EN), 6788c2ecf20Sopenharmony_ci &fpm_rg->fm_rcr); 6798c2ecf20Sopenharmony_ci} 6808c2ecf20Sopenharmony_ci 6818c2ecf20Sopenharmony_cistatic void fman_defconfig(struct fman_cfg *cfg) 6828c2ecf20Sopenharmony_ci{ 6838c2ecf20Sopenharmony_ci memset(cfg, 0, sizeof(struct fman_cfg)); 6848c2ecf20Sopenharmony_ci 6858c2ecf20Sopenharmony_ci cfg->catastrophic_err = DEFAULT_CATASTROPHIC_ERR; 6868c2ecf20Sopenharmony_ci cfg->dma_err = DEFAULT_DMA_ERR; 6878c2ecf20Sopenharmony_ci cfg->dma_aid_mode = DEFAULT_AID_MODE; 6888c2ecf20Sopenharmony_ci cfg->dma_comm_qtsh_clr_emer = DEFAULT_DMA_COMM_Q_LOW; 6898c2ecf20Sopenharmony_ci cfg->dma_comm_qtsh_asrt_emer = DEFAULT_DMA_COMM_Q_HIGH; 6908c2ecf20Sopenharmony_ci cfg->dma_cache_override = DEFAULT_CACHE_OVERRIDE; 6918c2ecf20Sopenharmony_ci cfg->dma_cam_num_of_entries = DEFAULT_DMA_CAM_NUM_OF_ENTRIES; 6928c2ecf20Sopenharmony_ci cfg->dma_dbg_cnt_mode = DEFAULT_DMA_DBG_CNT_MODE; 6938c2ecf20Sopenharmony_ci cfg->dma_sos_emergency = DEFAULT_DMA_SOS_EMERGENCY; 6948c2ecf20Sopenharmony_ci cfg->dma_watchdog = DEFAULT_DMA_WATCHDOG; 6958c2ecf20Sopenharmony_ci cfg->disp_limit_tsh = DEFAULT_DISP_LIMIT; 6968c2ecf20Sopenharmony_ci cfg->prs_disp_tsh = DEFAULT_PRS_DISP_TH; 6978c2ecf20Sopenharmony_ci cfg->plcr_disp_tsh = DEFAULT_PLCR_DISP_TH; 6988c2ecf20Sopenharmony_ci cfg->kg_disp_tsh = DEFAULT_KG_DISP_TH; 6998c2ecf20Sopenharmony_ci cfg->bmi_disp_tsh = DEFAULT_BMI_DISP_TH; 7008c2ecf20Sopenharmony_ci cfg->qmi_enq_disp_tsh = DEFAULT_QMI_ENQ_DISP_TH; 7018c2ecf20Sopenharmony_ci cfg->qmi_deq_disp_tsh = DEFAULT_QMI_DEQ_DISP_TH; 7028c2ecf20Sopenharmony_ci cfg->fm_ctl1_disp_tsh = DEFAULT_FM_CTL1_DISP_TH; 7038c2ecf20Sopenharmony_ci cfg->fm_ctl2_disp_tsh = DEFAULT_FM_CTL2_DISP_TH; 7048c2ecf20Sopenharmony_ci} 7058c2ecf20Sopenharmony_ci 7068c2ecf20Sopenharmony_cistatic int dma_init(struct fman *fman) 7078c2ecf20Sopenharmony_ci{ 7088c2ecf20Sopenharmony_ci struct fman_dma_regs __iomem *dma_rg = fman->dma_regs; 7098c2ecf20Sopenharmony_ci struct fman_cfg *cfg = fman->cfg; 7108c2ecf20Sopenharmony_ci u32 tmp_reg; 7118c2ecf20Sopenharmony_ci 7128c2ecf20Sopenharmony_ci /* Init DMA Registers */ 7138c2ecf20Sopenharmony_ci 7148c2ecf20Sopenharmony_ci /* clear status reg events */ 7158c2ecf20Sopenharmony_ci tmp_reg = (DMA_STATUS_BUS_ERR | DMA_STATUS_READ_ECC | 7168c2ecf20Sopenharmony_ci DMA_STATUS_SYSTEM_WRITE_ECC | DMA_STATUS_FM_WRITE_ECC); 7178c2ecf20Sopenharmony_ci iowrite32be(ioread32be(&dma_rg->fmdmsr) | tmp_reg, &dma_rg->fmdmsr); 7188c2ecf20Sopenharmony_ci 7198c2ecf20Sopenharmony_ci /* configure mode register */ 7208c2ecf20Sopenharmony_ci tmp_reg = 0; 7218c2ecf20Sopenharmony_ci tmp_reg |= cfg->dma_cache_override << DMA_MODE_CACHE_OR_SHIFT; 7228c2ecf20Sopenharmony_ci if (cfg->exceptions & EX_DMA_BUS_ERROR) 7238c2ecf20Sopenharmony_ci tmp_reg |= DMA_MODE_BER; 7248c2ecf20Sopenharmony_ci if ((cfg->exceptions & EX_DMA_SYSTEM_WRITE_ECC) | 7258c2ecf20Sopenharmony_ci (cfg->exceptions & EX_DMA_READ_ECC) | 7268c2ecf20Sopenharmony_ci (cfg->exceptions & EX_DMA_FM_WRITE_ECC)) 7278c2ecf20Sopenharmony_ci tmp_reg |= DMA_MODE_ECC; 7288c2ecf20Sopenharmony_ci if (cfg->dma_axi_dbg_num_of_beats) 7298c2ecf20Sopenharmony_ci tmp_reg |= (DMA_MODE_AXI_DBG_MASK & 7308c2ecf20Sopenharmony_ci ((cfg->dma_axi_dbg_num_of_beats - 1) 7318c2ecf20Sopenharmony_ci << DMA_MODE_AXI_DBG_SHIFT)); 7328c2ecf20Sopenharmony_ci 7338c2ecf20Sopenharmony_ci tmp_reg |= (((cfg->dma_cam_num_of_entries / DMA_CAM_UNITS) - 1) & 7348c2ecf20Sopenharmony_ci DMA_MODE_CEN_MASK) << DMA_MODE_CEN_SHIFT; 7358c2ecf20Sopenharmony_ci tmp_reg |= DMA_MODE_SECURE_PROT; 7368c2ecf20Sopenharmony_ci tmp_reg |= cfg->dma_dbg_cnt_mode << DMA_MODE_DBG_SHIFT; 7378c2ecf20Sopenharmony_ci tmp_reg |= cfg->dma_aid_mode << DMA_MODE_AID_MODE_SHIFT; 7388c2ecf20Sopenharmony_ci 7398c2ecf20Sopenharmony_ci iowrite32be(tmp_reg, &dma_rg->fmdmmr); 7408c2ecf20Sopenharmony_ci 7418c2ecf20Sopenharmony_ci /* configure thresholds register */ 7428c2ecf20Sopenharmony_ci tmp_reg = ((u32)cfg->dma_comm_qtsh_asrt_emer << 7438c2ecf20Sopenharmony_ci DMA_THRESH_COMMQ_SHIFT); 7448c2ecf20Sopenharmony_ci tmp_reg |= (cfg->dma_read_buf_tsh_asrt_emer & 7458c2ecf20Sopenharmony_ci DMA_THRESH_READ_INT_BUF_MASK) << DMA_THRESH_READ_INT_BUF_SHIFT; 7468c2ecf20Sopenharmony_ci tmp_reg |= cfg->dma_write_buf_tsh_asrt_emer & 7478c2ecf20Sopenharmony_ci DMA_THRESH_WRITE_INT_BUF_MASK; 7488c2ecf20Sopenharmony_ci 7498c2ecf20Sopenharmony_ci iowrite32be(tmp_reg, &dma_rg->fmdmtr); 7508c2ecf20Sopenharmony_ci 7518c2ecf20Sopenharmony_ci /* configure hysteresis register */ 7528c2ecf20Sopenharmony_ci tmp_reg = ((u32)cfg->dma_comm_qtsh_clr_emer << 7538c2ecf20Sopenharmony_ci DMA_THRESH_COMMQ_SHIFT); 7548c2ecf20Sopenharmony_ci tmp_reg |= (cfg->dma_read_buf_tsh_clr_emer & 7558c2ecf20Sopenharmony_ci DMA_THRESH_READ_INT_BUF_MASK) << DMA_THRESH_READ_INT_BUF_SHIFT; 7568c2ecf20Sopenharmony_ci tmp_reg |= cfg->dma_write_buf_tsh_clr_emer & 7578c2ecf20Sopenharmony_ci DMA_THRESH_WRITE_INT_BUF_MASK; 7588c2ecf20Sopenharmony_ci 7598c2ecf20Sopenharmony_ci iowrite32be(tmp_reg, &dma_rg->fmdmhy); 7608c2ecf20Sopenharmony_ci 7618c2ecf20Sopenharmony_ci /* configure emergency threshold */ 7628c2ecf20Sopenharmony_ci iowrite32be(cfg->dma_sos_emergency, &dma_rg->fmdmsetr); 7638c2ecf20Sopenharmony_ci 7648c2ecf20Sopenharmony_ci /* configure Watchdog */ 7658c2ecf20Sopenharmony_ci iowrite32be((cfg->dma_watchdog * cfg->clk_freq), &dma_rg->fmdmwcr); 7668c2ecf20Sopenharmony_ci 7678c2ecf20Sopenharmony_ci iowrite32be(cfg->cam_base_addr, &dma_rg->fmdmebcr); 7688c2ecf20Sopenharmony_ci 7698c2ecf20Sopenharmony_ci /* Allocate MURAM for CAM */ 7708c2ecf20Sopenharmony_ci fman->cam_size = 7718c2ecf20Sopenharmony_ci (u32)(fman->cfg->dma_cam_num_of_entries * DMA_CAM_SIZEOF_ENTRY); 7728c2ecf20Sopenharmony_ci fman->cam_offset = fman_muram_alloc(fman->muram, fman->cam_size); 7738c2ecf20Sopenharmony_ci if (IS_ERR_VALUE(fman->cam_offset)) { 7748c2ecf20Sopenharmony_ci dev_err(fman->dev, "%s: MURAM alloc for DMA CAM failed\n", 7758c2ecf20Sopenharmony_ci __func__); 7768c2ecf20Sopenharmony_ci return -ENOMEM; 7778c2ecf20Sopenharmony_ci } 7788c2ecf20Sopenharmony_ci 7798c2ecf20Sopenharmony_ci if (fman->state->rev_info.major == 2) { 7808c2ecf20Sopenharmony_ci u32 __iomem *cam_base_addr; 7818c2ecf20Sopenharmony_ci 7828c2ecf20Sopenharmony_ci fman_muram_free_mem(fman->muram, fman->cam_offset, 7838c2ecf20Sopenharmony_ci fman->cam_size); 7848c2ecf20Sopenharmony_ci 7858c2ecf20Sopenharmony_ci fman->cam_size = fman->cfg->dma_cam_num_of_entries * 72 + 128; 7868c2ecf20Sopenharmony_ci fman->cam_offset = fman_muram_alloc(fman->muram, 7878c2ecf20Sopenharmony_ci fman->cam_size); 7888c2ecf20Sopenharmony_ci if (IS_ERR_VALUE(fman->cam_offset)) { 7898c2ecf20Sopenharmony_ci dev_err(fman->dev, "%s: MURAM alloc for DMA CAM failed\n", 7908c2ecf20Sopenharmony_ci __func__); 7918c2ecf20Sopenharmony_ci return -ENOMEM; 7928c2ecf20Sopenharmony_ci } 7938c2ecf20Sopenharmony_ci 7948c2ecf20Sopenharmony_ci if (fman->cfg->dma_cam_num_of_entries % 8 || 7958c2ecf20Sopenharmony_ci fman->cfg->dma_cam_num_of_entries > 32) { 7968c2ecf20Sopenharmony_ci dev_err(fman->dev, "%s: wrong dma_cam_num_of_entries\n", 7978c2ecf20Sopenharmony_ci __func__); 7988c2ecf20Sopenharmony_ci return -EINVAL; 7998c2ecf20Sopenharmony_ci } 8008c2ecf20Sopenharmony_ci 8018c2ecf20Sopenharmony_ci cam_base_addr = (u32 __iomem *) 8028c2ecf20Sopenharmony_ci fman_muram_offset_to_vbase(fman->muram, 8038c2ecf20Sopenharmony_ci fman->cam_offset); 8048c2ecf20Sopenharmony_ci iowrite32be(~((1 << 8058c2ecf20Sopenharmony_ci (32 - fman->cfg->dma_cam_num_of_entries)) - 1), 8068c2ecf20Sopenharmony_ci cam_base_addr); 8078c2ecf20Sopenharmony_ci } 8088c2ecf20Sopenharmony_ci 8098c2ecf20Sopenharmony_ci fman->cfg->cam_base_addr = fman->cam_offset; 8108c2ecf20Sopenharmony_ci 8118c2ecf20Sopenharmony_ci return 0; 8128c2ecf20Sopenharmony_ci} 8138c2ecf20Sopenharmony_ci 8148c2ecf20Sopenharmony_cistatic void fpm_init(struct fman_fpm_regs __iomem *fpm_rg, struct fman_cfg *cfg) 8158c2ecf20Sopenharmony_ci{ 8168c2ecf20Sopenharmony_ci u32 tmp_reg; 8178c2ecf20Sopenharmony_ci int i; 8188c2ecf20Sopenharmony_ci 8198c2ecf20Sopenharmony_ci /* Init FPM Registers */ 8208c2ecf20Sopenharmony_ci 8218c2ecf20Sopenharmony_ci tmp_reg = (u32)(cfg->disp_limit_tsh << FPM_DISP_LIMIT_SHIFT); 8228c2ecf20Sopenharmony_ci iowrite32be(tmp_reg, &fpm_rg->fmfp_mxd); 8238c2ecf20Sopenharmony_ci 8248c2ecf20Sopenharmony_ci tmp_reg = (((u32)cfg->prs_disp_tsh << FPM_THR1_PRS_SHIFT) | 8258c2ecf20Sopenharmony_ci ((u32)cfg->kg_disp_tsh << FPM_THR1_KG_SHIFT) | 8268c2ecf20Sopenharmony_ci ((u32)cfg->plcr_disp_tsh << FPM_THR1_PLCR_SHIFT) | 8278c2ecf20Sopenharmony_ci ((u32)cfg->bmi_disp_tsh << FPM_THR1_BMI_SHIFT)); 8288c2ecf20Sopenharmony_ci iowrite32be(tmp_reg, &fpm_rg->fmfp_dist1); 8298c2ecf20Sopenharmony_ci 8308c2ecf20Sopenharmony_ci tmp_reg = 8318c2ecf20Sopenharmony_ci (((u32)cfg->qmi_enq_disp_tsh << FPM_THR2_QMI_ENQ_SHIFT) | 8328c2ecf20Sopenharmony_ci ((u32)cfg->qmi_deq_disp_tsh << FPM_THR2_QMI_DEQ_SHIFT) | 8338c2ecf20Sopenharmony_ci ((u32)cfg->fm_ctl1_disp_tsh << FPM_THR2_FM_CTL1_SHIFT) | 8348c2ecf20Sopenharmony_ci ((u32)cfg->fm_ctl2_disp_tsh << FPM_THR2_FM_CTL2_SHIFT)); 8358c2ecf20Sopenharmony_ci iowrite32be(tmp_reg, &fpm_rg->fmfp_dist2); 8368c2ecf20Sopenharmony_ci 8378c2ecf20Sopenharmony_ci /* define exceptions and error behavior */ 8388c2ecf20Sopenharmony_ci tmp_reg = 0; 8398c2ecf20Sopenharmony_ci /* Clear events */ 8408c2ecf20Sopenharmony_ci tmp_reg |= (FPM_EV_MASK_STALL | FPM_EV_MASK_DOUBLE_ECC | 8418c2ecf20Sopenharmony_ci FPM_EV_MASK_SINGLE_ECC); 8428c2ecf20Sopenharmony_ci /* enable interrupts */ 8438c2ecf20Sopenharmony_ci if (cfg->exceptions & EX_FPM_STALL_ON_TASKS) 8448c2ecf20Sopenharmony_ci tmp_reg |= FPM_EV_MASK_STALL_EN; 8458c2ecf20Sopenharmony_ci if (cfg->exceptions & EX_FPM_SINGLE_ECC) 8468c2ecf20Sopenharmony_ci tmp_reg |= FPM_EV_MASK_SINGLE_ECC_EN; 8478c2ecf20Sopenharmony_ci if (cfg->exceptions & EX_FPM_DOUBLE_ECC) 8488c2ecf20Sopenharmony_ci tmp_reg |= FPM_EV_MASK_DOUBLE_ECC_EN; 8498c2ecf20Sopenharmony_ci tmp_reg |= (cfg->catastrophic_err << FPM_EV_MASK_CAT_ERR_SHIFT); 8508c2ecf20Sopenharmony_ci tmp_reg |= (cfg->dma_err << FPM_EV_MASK_DMA_ERR_SHIFT); 8518c2ecf20Sopenharmony_ci /* FMan is not halted upon external halt activation */ 8528c2ecf20Sopenharmony_ci tmp_reg |= FPM_EV_MASK_EXTERNAL_HALT; 8538c2ecf20Sopenharmony_ci /* Man is not halted upon Unrecoverable ECC error behavior */ 8548c2ecf20Sopenharmony_ci tmp_reg |= FPM_EV_MASK_ECC_ERR_HALT; 8558c2ecf20Sopenharmony_ci iowrite32be(tmp_reg, &fpm_rg->fmfp_ee); 8568c2ecf20Sopenharmony_ci 8578c2ecf20Sopenharmony_ci /* clear all fmCtls event registers */ 8588c2ecf20Sopenharmony_ci for (i = 0; i < FM_NUM_OF_FMAN_CTRL_EVENT_REGS; i++) 8598c2ecf20Sopenharmony_ci iowrite32be(0xFFFFFFFF, &fpm_rg->fmfp_cev[i]); 8608c2ecf20Sopenharmony_ci 8618c2ecf20Sopenharmony_ci /* RAM ECC - enable and clear events */ 8628c2ecf20Sopenharmony_ci /* first we need to clear all parser memory, 8638c2ecf20Sopenharmony_ci * as it is uninitialized and may cause ECC errors 8648c2ecf20Sopenharmony_ci */ 8658c2ecf20Sopenharmony_ci /* event bits */ 8668c2ecf20Sopenharmony_ci tmp_reg = (FPM_RAM_MURAM_ECC | FPM_RAM_IRAM_ECC); 8678c2ecf20Sopenharmony_ci 8688c2ecf20Sopenharmony_ci iowrite32be(tmp_reg, &fpm_rg->fm_rcr); 8698c2ecf20Sopenharmony_ci 8708c2ecf20Sopenharmony_ci tmp_reg = 0; 8718c2ecf20Sopenharmony_ci if (cfg->exceptions & EX_IRAM_ECC) { 8728c2ecf20Sopenharmony_ci tmp_reg |= FPM_IRAM_ECC_ERR_EX_EN; 8738c2ecf20Sopenharmony_ci enable_rams_ecc(fpm_rg); 8748c2ecf20Sopenharmony_ci } 8758c2ecf20Sopenharmony_ci if (cfg->exceptions & EX_MURAM_ECC) { 8768c2ecf20Sopenharmony_ci tmp_reg |= FPM_MURAM_ECC_ERR_EX_EN; 8778c2ecf20Sopenharmony_ci enable_rams_ecc(fpm_rg); 8788c2ecf20Sopenharmony_ci } 8798c2ecf20Sopenharmony_ci iowrite32be(tmp_reg, &fpm_rg->fm_rie); 8808c2ecf20Sopenharmony_ci} 8818c2ecf20Sopenharmony_ci 8828c2ecf20Sopenharmony_cistatic void bmi_init(struct fman_bmi_regs __iomem *bmi_rg, 8838c2ecf20Sopenharmony_ci struct fman_cfg *cfg) 8848c2ecf20Sopenharmony_ci{ 8858c2ecf20Sopenharmony_ci u32 tmp_reg; 8868c2ecf20Sopenharmony_ci 8878c2ecf20Sopenharmony_ci /* Init BMI Registers */ 8888c2ecf20Sopenharmony_ci 8898c2ecf20Sopenharmony_ci /* define common resources */ 8908c2ecf20Sopenharmony_ci tmp_reg = cfg->fifo_base_addr; 8918c2ecf20Sopenharmony_ci tmp_reg = tmp_reg / BMI_FIFO_ALIGN; 8928c2ecf20Sopenharmony_ci 8938c2ecf20Sopenharmony_ci tmp_reg |= ((cfg->total_fifo_size / FMAN_BMI_FIFO_UNITS - 1) << 8948c2ecf20Sopenharmony_ci BMI_CFG1_FIFO_SIZE_SHIFT); 8958c2ecf20Sopenharmony_ci iowrite32be(tmp_reg, &bmi_rg->fmbm_cfg1); 8968c2ecf20Sopenharmony_ci 8978c2ecf20Sopenharmony_ci tmp_reg = ((cfg->total_num_of_tasks - 1) & BMI_CFG2_TASKS_MASK) << 8988c2ecf20Sopenharmony_ci BMI_CFG2_TASKS_SHIFT; 8998c2ecf20Sopenharmony_ci /* num of DMA's will be dynamically updated when each port is set */ 9008c2ecf20Sopenharmony_ci iowrite32be(tmp_reg, &bmi_rg->fmbm_cfg2); 9018c2ecf20Sopenharmony_ci 9028c2ecf20Sopenharmony_ci /* define unmaskable exceptions, enable and clear events */ 9038c2ecf20Sopenharmony_ci tmp_reg = 0; 9048c2ecf20Sopenharmony_ci iowrite32be(BMI_ERR_INTR_EN_LIST_RAM_ECC | 9058c2ecf20Sopenharmony_ci BMI_ERR_INTR_EN_STORAGE_PROFILE_ECC | 9068c2ecf20Sopenharmony_ci BMI_ERR_INTR_EN_STATISTICS_RAM_ECC | 9078c2ecf20Sopenharmony_ci BMI_ERR_INTR_EN_DISPATCH_RAM_ECC, &bmi_rg->fmbm_ievr); 9088c2ecf20Sopenharmony_ci 9098c2ecf20Sopenharmony_ci if (cfg->exceptions & EX_BMI_LIST_RAM_ECC) 9108c2ecf20Sopenharmony_ci tmp_reg |= BMI_ERR_INTR_EN_LIST_RAM_ECC; 9118c2ecf20Sopenharmony_ci if (cfg->exceptions & EX_BMI_STORAGE_PROFILE_ECC) 9128c2ecf20Sopenharmony_ci tmp_reg |= BMI_ERR_INTR_EN_STORAGE_PROFILE_ECC; 9138c2ecf20Sopenharmony_ci if (cfg->exceptions & EX_BMI_STATISTICS_RAM_ECC) 9148c2ecf20Sopenharmony_ci tmp_reg |= BMI_ERR_INTR_EN_STATISTICS_RAM_ECC; 9158c2ecf20Sopenharmony_ci if (cfg->exceptions & EX_BMI_DISPATCH_RAM_ECC) 9168c2ecf20Sopenharmony_ci tmp_reg |= BMI_ERR_INTR_EN_DISPATCH_RAM_ECC; 9178c2ecf20Sopenharmony_ci iowrite32be(tmp_reg, &bmi_rg->fmbm_ier); 9188c2ecf20Sopenharmony_ci} 9198c2ecf20Sopenharmony_ci 9208c2ecf20Sopenharmony_cistatic void qmi_init(struct fman_qmi_regs __iomem *qmi_rg, 9218c2ecf20Sopenharmony_ci struct fman_cfg *cfg) 9228c2ecf20Sopenharmony_ci{ 9238c2ecf20Sopenharmony_ci u32 tmp_reg; 9248c2ecf20Sopenharmony_ci 9258c2ecf20Sopenharmony_ci /* Init QMI Registers */ 9268c2ecf20Sopenharmony_ci 9278c2ecf20Sopenharmony_ci /* Clear error interrupt events */ 9288c2ecf20Sopenharmony_ci 9298c2ecf20Sopenharmony_ci iowrite32be(QMI_ERR_INTR_EN_DOUBLE_ECC | QMI_ERR_INTR_EN_DEQ_FROM_DEF, 9308c2ecf20Sopenharmony_ci &qmi_rg->fmqm_eie); 9318c2ecf20Sopenharmony_ci tmp_reg = 0; 9328c2ecf20Sopenharmony_ci if (cfg->exceptions & EX_QMI_DEQ_FROM_UNKNOWN_PORTID) 9338c2ecf20Sopenharmony_ci tmp_reg |= QMI_ERR_INTR_EN_DEQ_FROM_DEF; 9348c2ecf20Sopenharmony_ci if (cfg->exceptions & EX_QMI_DOUBLE_ECC) 9358c2ecf20Sopenharmony_ci tmp_reg |= QMI_ERR_INTR_EN_DOUBLE_ECC; 9368c2ecf20Sopenharmony_ci /* enable events */ 9378c2ecf20Sopenharmony_ci iowrite32be(tmp_reg, &qmi_rg->fmqm_eien); 9388c2ecf20Sopenharmony_ci 9398c2ecf20Sopenharmony_ci tmp_reg = 0; 9408c2ecf20Sopenharmony_ci /* Clear interrupt events */ 9418c2ecf20Sopenharmony_ci iowrite32be(QMI_INTR_EN_SINGLE_ECC, &qmi_rg->fmqm_ie); 9428c2ecf20Sopenharmony_ci if (cfg->exceptions & EX_QMI_SINGLE_ECC) 9438c2ecf20Sopenharmony_ci tmp_reg |= QMI_INTR_EN_SINGLE_ECC; 9448c2ecf20Sopenharmony_ci /* enable events */ 9458c2ecf20Sopenharmony_ci iowrite32be(tmp_reg, &qmi_rg->fmqm_ien); 9468c2ecf20Sopenharmony_ci} 9478c2ecf20Sopenharmony_ci 9488c2ecf20Sopenharmony_cistatic void hwp_init(struct fman_hwp_regs __iomem *hwp_rg) 9498c2ecf20Sopenharmony_ci{ 9508c2ecf20Sopenharmony_ci /* enable HW Parser */ 9518c2ecf20Sopenharmony_ci iowrite32be(HWP_RPIMAC_PEN, &hwp_rg->fmprrpimac); 9528c2ecf20Sopenharmony_ci} 9538c2ecf20Sopenharmony_ci 9548c2ecf20Sopenharmony_cistatic int enable(struct fman *fman, struct fman_cfg *cfg) 9558c2ecf20Sopenharmony_ci{ 9568c2ecf20Sopenharmony_ci u32 cfg_reg = 0; 9578c2ecf20Sopenharmony_ci 9588c2ecf20Sopenharmony_ci /* Enable all modules */ 9598c2ecf20Sopenharmony_ci 9608c2ecf20Sopenharmony_ci /* clear&enable global counters - calculate reg and save for later, 9618c2ecf20Sopenharmony_ci * because it's the same reg for QMI enable 9628c2ecf20Sopenharmony_ci */ 9638c2ecf20Sopenharmony_ci cfg_reg = QMI_CFG_EN_COUNTERS; 9648c2ecf20Sopenharmony_ci 9658c2ecf20Sopenharmony_ci /* Set enqueue and dequeue thresholds */ 9668c2ecf20Sopenharmony_ci cfg_reg |= (cfg->qmi_def_tnums_thresh << 8) | cfg->qmi_def_tnums_thresh; 9678c2ecf20Sopenharmony_ci 9688c2ecf20Sopenharmony_ci iowrite32be(BMI_INIT_START, &fman->bmi_regs->fmbm_init); 9698c2ecf20Sopenharmony_ci iowrite32be(cfg_reg | QMI_CFG_ENQ_EN | QMI_CFG_DEQ_EN, 9708c2ecf20Sopenharmony_ci &fman->qmi_regs->fmqm_gc); 9718c2ecf20Sopenharmony_ci 9728c2ecf20Sopenharmony_ci return 0; 9738c2ecf20Sopenharmony_ci} 9748c2ecf20Sopenharmony_ci 9758c2ecf20Sopenharmony_cistatic int set_exception(struct fman *fman, 9768c2ecf20Sopenharmony_ci enum fman_exceptions exception, bool enable) 9778c2ecf20Sopenharmony_ci{ 9788c2ecf20Sopenharmony_ci u32 tmp; 9798c2ecf20Sopenharmony_ci 9808c2ecf20Sopenharmony_ci switch (exception) { 9818c2ecf20Sopenharmony_ci case FMAN_EX_DMA_BUS_ERROR: 9828c2ecf20Sopenharmony_ci tmp = ioread32be(&fman->dma_regs->fmdmmr); 9838c2ecf20Sopenharmony_ci if (enable) 9848c2ecf20Sopenharmony_ci tmp |= DMA_MODE_BER; 9858c2ecf20Sopenharmony_ci else 9868c2ecf20Sopenharmony_ci tmp &= ~DMA_MODE_BER; 9878c2ecf20Sopenharmony_ci /* disable bus error */ 9888c2ecf20Sopenharmony_ci iowrite32be(tmp, &fman->dma_regs->fmdmmr); 9898c2ecf20Sopenharmony_ci break; 9908c2ecf20Sopenharmony_ci case FMAN_EX_DMA_READ_ECC: 9918c2ecf20Sopenharmony_ci case FMAN_EX_DMA_SYSTEM_WRITE_ECC: 9928c2ecf20Sopenharmony_ci case FMAN_EX_DMA_FM_WRITE_ECC: 9938c2ecf20Sopenharmony_ci tmp = ioread32be(&fman->dma_regs->fmdmmr); 9948c2ecf20Sopenharmony_ci if (enable) 9958c2ecf20Sopenharmony_ci tmp |= DMA_MODE_ECC; 9968c2ecf20Sopenharmony_ci else 9978c2ecf20Sopenharmony_ci tmp &= ~DMA_MODE_ECC; 9988c2ecf20Sopenharmony_ci iowrite32be(tmp, &fman->dma_regs->fmdmmr); 9998c2ecf20Sopenharmony_ci break; 10008c2ecf20Sopenharmony_ci case FMAN_EX_FPM_STALL_ON_TASKS: 10018c2ecf20Sopenharmony_ci tmp = ioread32be(&fman->fpm_regs->fmfp_ee); 10028c2ecf20Sopenharmony_ci if (enable) 10038c2ecf20Sopenharmony_ci tmp |= FPM_EV_MASK_STALL_EN; 10048c2ecf20Sopenharmony_ci else 10058c2ecf20Sopenharmony_ci tmp &= ~FPM_EV_MASK_STALL_EN; 10068c2ecf20Sopenharmony_ci iowrite32be(tmp, &fman->fpm_regs->fmfp_ee); 10078c2ecf20Sopenharmony_ci break; 10088c2ecf20Sopenharmony_ci case FMAN_EX_FPM_SINGLE_ECC: 10098c2ecf20Sopenharmony_ci tmp = ioread32be(&fman->fpm_regs->fmfp_ee); 10108c2ecf20Sopenharmony_ci if (enable) 10118c2ecf20Sopenharmony_ci tmp |= FPM_EV_MASK_SINGLE_ECC_EN; 10128c2ecf20Sopenharmony_ci else 10138c2ecf20Sopenharmony_ci tmp &= ~FPM_EV_MASK_SINGLE_ECC_EN; 10148c2ecf20Sopenharmony_ci iowrite32be(tmp, &fman->fpm_regs->fmfp_ee); 10158c2ecf20Sopenharmony_ci break; 10168c2ecf20Sopenharmony_ci case FMAN_EX_FPM_DOUBLE_ECC: 10178c2ecf20Sopenharmony_ci tmp = ioread32be(&fman->fpm_regs->fmfp_ee); 10188c2ecf20Sopenharmony_ci if (enable) 10198c2ecf20Sopenharmony_ci tmp |= FPM_EV_MASK_DOUBLE_ECC_EN; 10208c2ecf20Sopenharmony_ci else 10218c2ecf20Sopenharmony_ci tmp &= ~FPM_EV_MASK_DOUBLE_ECC_EN; 10228c2ecf20Sopenharmony_ci iowrite32be(tmp, &fman->fpm_regs->fmfp_ee); 10238c2ecf20Sopenharmony_ci break; 10248c2ecf20Sopenharmony_ci case FMAN_EX_QMI_SINGLE_ECC: 10258c2ecf20Sopenharmony_ci tmp = ioread32be(&fman->qmi_regs->fmqm_ien); 10268c2ecf20Sopenharmony_ci if (enable) 10278c2ecf20Sopenharmony_ci tmp |= QMI_INTR_EN_SINGLE_ECC; 10288c2ecf20Sopenharmony_ci else 10298c2ecf20Sopenharmony_ci tmp &= ~QMI_INTR_EN_SINGLE_ECC; 10308c2ecf20Sopenharmony_ci iowrite32be(tmp, &fman->qmi_regs->fmqm_ien); 10318c2ecf20Sopenharmony_ci break; 10328c2ecf20Sopenharmony_ci case FMAN_EX_QMI_DOUBLE_ECC: 10338c2ecf20Sopenharmony_ci tmp = ioread32be(&fman->qmi_regs->fmqm_eien); 10348c2ecf20Sopenharmony_ci if (enable) 10358c2ecf20Sopenharmony_ci tmp |= QMI_ERR_INTR_EN_DOUBLE_ECC; 10368c2ecf20Sopenharmony_ci else 10378c2ecf20Sopenharmony_ci tmp &= ~QMI_ERR_INTR_EN_DOUBLE_ECC; 10388c2ecf20Sopenharmony_ci iowrite32be(tmp, &fman->qmi_regs->fmqm_eien); 10398c2ecf20Sopenharmony_ci break; 10408c2ecf20Sopenharmony_ci case FMAN_EX_QMI_DEQ_FROM_UNKNOWN_PORTID: 10418c2ecf20Sopenharmony_ci tmp = ioread32be(&fman->qmi_regs->fmqm_eien); 10428c2ecf20Sopenharmony_ci if (enable) 10438c2ecf20Sopenharmony_ci tmp |= QMI_ERR_INTR_EN_DEQ_FROM_DEF; 10448c2ecf20Sopenharmony_ci else 10458c2ecf20Sopenharmony_ci tmp &= ~QMI_ERR_INTR_EN_DEQ_FROM_DEF; 10468c2ecf20Sopenharmony_ci iowrite32be(tmp, &fman->qmi_regs->fmqm_eien); 10478c2ecf20Sopenharmony_ci break; 10488c2ecf20Sopenharmony_ci case FMAN_EX_BMI_LIST_RAM_ECC: 10498c2ecf20Sopenharmony_ci tmp = ioread32be(&fman->bmi_regs->fmbm_ier); 10508c2ecf20Sopenharmony_ci if (enable) 10518c2ecf20Sopenharmony_ci tmp |= BMI_ERR_INTR_EN_LIST_RAM_ECC; 10528c2ecf20Sopenharmony_ci else 10538c2ecf20Sopenharmony_ci tmp &= ~BMI_ERR_INTR_EN_LIST_RAM_ECC; 10548c2ecf20Sopenharmony_ci iowrite32be(tmp, &fman->bmi_regs->fmbm_ier); 10558c2ecf20Sopenharmony_ci break; 10568c2ecf20Sopenharmony_ci case FMAN_EX_BMI_STORAGE_PROFILE_ECC: 10578c2ecf20Sopenharmony_ci tmp = ioread32be(&fman->bmi_regs->fmbm_ier); 10588c2ecf20Sopenharmony_ci if (enable) 10598c2ecf20Sopenharmony_ci tmp |= BMI_ERR_INTR_EN_STORAGE_PROFILE_ECC; 10608c2ecf20Sopenharmony_ci else 10618c2ecf20Sopenharmony_ci tmp &= ~BMI_ERR_INTR_EN_STORAGE_PROFILE_ECC; 10628c2ecf20Sopenharmony_ci iowrite32be(tmp, &fman->bmi_regs->fmbm_ier); 10638c2ecf20Sopenharmony_ci break; 10648c2ecf20Sopenharmony_ci case FMAN_EX_BMI_STATISTICS_RAM_ECC: 10658c2ecf20Sopenharmony_ci tmp = ioread32be(&fman->bmi_regs->fmbm_ier); 10668c2ecf20Sopenharmony_ci if (enable) 10678c2ecf20Sopenharmony_ci tmp |= BMI_ERR_INTR_EN_STATISTICS_RAM_ECC; 10688c2ecf20Sopenharmony_ci else 10698c2ecf20Sopenharmony_ci tmp &= ~BMI_ERR_INTR_EN_STATISTICS_RAM_ECC; 10708c2ecf20Sopenharmony_ci iowrite32be(tmp, &fman->bmi_regs->fmbm_ier); 10718c2ecf20Sopenharmony_ci break; 10728c2ecf20Sopenharmony_ci case FMAN_EX_BMI_DISPATCH_RAM_ECC: 10738c2ecf20Sopenharmony_ci tmp = ioread32be(&fman->bmi_regs->fmbm_ier); 10748c2ecf20Sopenharmony_ci if (enable) 10758c2ecf20Sopenharmony_ci tmp |= BMI_ERR_INTR_EN_DISPATCH_RAM_ECC; 10768c2ecf20Sopenharmony_ci else 10778c2ecf20Sopenharmony_ci tmp &= ~BMI_ERR_INTR_EN_DISPATCH_RAM_ECC; 10788c2ecf20Sopenharmony_ci iowrite32be(tmp, &fman->bmi_regs->fmbm_ier); 10798c2ecf20Sopenharmony_ci break; 10808c2ecf20Sopenharmony_ci case FMAN_EX_IRAM_ECC: 10818c2ecf20Sopenharmony_ci tmp = ioread32be(&fman->fpm_regs->fm_rie); 10828c2ecf20Sopenharmony_ci if (enable) { 10838c2ecf20Sopenharmony_ci /* enable ECC if not enabled */ 10848c2ecf20Sopenharmony_ci enable_rams_ecc(fman->fpm_regs); 10858c2ecf20Sopenharmony_ci /* enable ECC interrupts */ 10868c2ecf20Sopenharmony_ci tmp |= FPM_IRAM_ECC_ERR_EX_EN; 10878c2ecf20Sopenharmony_ci } else { 10888c2ecf20Sopenharmony_ci /* ECC mechanism may be disabled, 10898c2ecf20Sopenharmony_ci * depending on driver status 10908c2ecf20Sopenharmony_ci */ 10918c2ecf20Sopenharmony_ci disable_rams_ecc(fman->fpm_regs); 10928c2ecf20Sopenharmony_ci tmp &= ~FPM_IRAM_ECC_ERR_EX_EN; 10938c2ecf20Sopenharmony_ci } 10948c2ecf20Sopenharmony_ci iowrite32be(tmp, &fman->fpm_regs->fm_rie); 10958c2ecf20Sopenharmony_ci break; 10968c2ecf20Sopenharmony_ci case FMAN_EX_MURAM_ECC: 10978c2ecf20Sopenharmony_ci tmp = ioread32be(&fman->fpm_regs->fm_rie); 10988c2ecf20Sopenharmony_ci if (enable) { 10998c2ecf20Sopenharmony_ci /* enable ECC if not enabled */ 11008c2ecf20Sopenharmony_ci enable_rams_ecc(fman->fpm_regs); 11018c2ecf20Sopenharmony_ci /* enable ECC interrupts */ 11028c2ecf20Sopenharmony_ci tmp |= FPM_MURAM_ECC_ERR_EX_EN; 11038c2ecf20Sopenharmony_ci } else { 11048c2ecf20Sopenharmony_ci /* ECC mechanism may be disabled, 11058c2ecf20Sopenharmony_ci * depending on driver status 11068c2ecf20Sopenharmony_ci */ 11078c2ecf20Sopenharmony_ci disable_rams_ecc(fman->fpm_regs); 11088c2ecf20Sopenharmony_ci tmp &= ~FPM_MURAM_ECC_ERR_EX_EN; 11098c2ecf20Sopenharmony_ci } 11108c2ecf20Sopenharmony_ci iowrite32be(tmp, &fman->fpm_regs->fm_rie); 11118c2ecf20Sopenharmony_ci break; 11128c2ecf20Sopenharmony_ci default: 11138c2ecf20Sopenharmony_ci return -EINVAL; 11148c2ecf20Sopenharmony_ci } 11158c2ecf20Sopenharmony_ci return 0; 11168c2ecf20Sopenharmony_ci} 11178c2ecf20Sopenharmony_ci 11188c2ecf20Sopenharmony_cistatic void resume(struct fman_fpm_regs __iomem *fpm_rg) 11198c2ecf20Sopenharmony_ci{ 11208c2ecf20Sopenharmony_ci u32 tmp; 11218c2ecf20Sopenharmony_ci 11228c2ecf20Sopenharmony_ci tmp = ioread32be(&fpm_rg->fmfp_ee); 11238c2ecf20Sopenharmony_ci /* clear tmp_reg event bits in order not to clear standing events */ 11248c2ecf20Sopenharmony_ci tmp &= ~(FPM_EV_MASK_DOUBLE_ECC | 11258c2ecf20Sopenharmony_ci FPM_EV_MASK_STALL | FPM_EV_MASK_SINGLE_ECC); 11268c2ecf20Sopenharmony_ci tmp |= FPM_EV_MASK_RELEASE_FM; 11278c2ecf20Sopenharmony_ci 11288c2ecf20Sopenharmony_ci iowrite32be(tmp, &fpm_rg->fmfp_ee); 11298c2ecf20Sopenharmony_ci} 11308c2ecf20Sopenharmony_ci 11318c2ecf20Sopenharmony_cistatic int fill_soc_specific_params(struct fman_state_struct *state) 11328c2ecf20Sopenharmony_ci{ 11338c2ecf20Sopenharmony_ci u8 minor = state->rev_info.minor; 11348c2ecf20Sopenharmony_ci /* P4080 - Major 2 11358c2ecf20Sopenharmony_ci * P2041/P3041/P5020/P5040 - Major 3 11368c2ecf20Sopenharmony_ci * Tx/Bx - Major 6 11378c2ecf20Sopenharmony_ci */ 11388c2ecf20Sopenharmony_ci switch (state->rev_info.major) { 11398c2ecf20Sopenharmony_ci case 3: 11408c2ecf20Sopenharmony_ci state->bmi_max_fifo_size = 160 * 1024; 11418c2ecf20Sopenharmony_ci state->fm_iram_size = 64 * 1024; 11428c2ecf20Sopenharmony_ci state->dma_thresh_max_commq = 31; 11438c2ecf20Sopenharmony_ci state->dma_thresh_max_buf = 127; 11448c2ecf20Sopenharmony_ci state->qmi_max_num_of_tnums = 64; 11458c2ecf20Sopenharmony_ci state->qmi_def_tnums_thresh = 48; 11468c2ecf20Sopenharmony_ci state->bmi_max_num_of_tasks = 128; 11478c2ecf20Sopenharmony_ci state->max_num_of_open_dmas = 32; 11488c2ecf20Sopenharmony_ci state->fm_port_num_of_cg = 256; 11498c2ecf20Sopenharmony_ci state->num_of_rx_ports = 6; 11508c2ecf20Sopenharmony_ci state->total_fifo_size = 136 * 1024; 11518c2ecf20Sopenharmony_ci break; 11528c2ecf20Sopenharmony_ci 11538c2ecf20Sopenharmony_ci case 2: 11548c2ecf20Sopenharmony_ci state->bmi_max_fifo_size = 160 * 1024; 11558c2ecf20Sopenharmony_ci state->fm_iram_size = 64 * 1024; 11568c2ecf20Sopenharmony_ci state->dma_thresh_max_commq = 31; 11578c2ecf20Sopenharmony_ci state->dma_thresh_max_buf = 127; 11588c2ecf20Sopenharmony_ci state->qmi_max_num_of_tnums = 64; 11598c2ecf20Sopenharmony_ci state->qmi_def_tnums_thresh = 48; 11608c2ecf20Sopenharmony_ci state->bmi_max_num_of_tasks = 128; 11618c2ecf20Sopenharmony_ci state->max_num_of_open_dmas = 32; 11628c2ecf20Sopenharmony_ci state->fm_port_num_of_cg = 256; 11638c2ecf20Sopenharmony_ci state->num_of_rx_ports = 5; 11648c2ecf20Sopenharmony_ci state->total_fifo_size = 100 * 1024; 11658c2ecf20Sopenharmony_ci break; 11668c2ecf20Sopenharmony_ci 11678c2ecf20Sopenharmony_ci case 6: 11688c2ecf20Sopenharmony_ci state->dma_thresh_max_commq = 83; 11698c2ecf20Sopenharmony_ci state->dma_thresh_max_buf = 127; 11708c2ecf20Sopenharmony_ci state->qmi_max_num_of_tnums = 64; 11718c2ecf20Sopenharmony_ci state->qmi_def_tnums_thresh = 32; 11728c2ecf20Sopenharmony_ci state->fm_port_num_of_cg = 256; 11738c2ecf20Sopenharmony_ci 11748c2ecf20Sopenharmony_ci /* FManV3L */ 11758c2ecf20Sopenharmony_ci if (minor == 1 || minor == 4) { 11768c2ecf20Sopenharmony_ci state->bmi_max_fifo_size = 192 * 1024; 11778c2ecf20Sopenharmony_ci state->bmi_max_num_of_tasks = 64; 11788c2ecf20Sopenharmony_ci state->max_num_of_open_dmas = 32; 11798c2ecf20Sopenharmony_ci state->num_of_rx_ports = 5; 11808c2ecf20Sopenharmony_ci if (minor == 1) 11818c2ecf20Sopenharmony_ci state->fm_iram_size = 32 * 1024; 11828c2ecf20Sopenharmony_ci else 11838c2ecf20Sopenharmony_ci state->fm_iram_size = 64 * 1024; 11848c2ecf20Sopenharmony_ci state->total_fifo_size = 156 * 1024; 11858c2ecf20Sopenharmony_ci } 11868c2ecf20Sopenharmony_ci /* FManV3H */ 11878c2ecf20Sopenharmony_ci else if (minor == 0 || minor == 2 || minor == 3) { 11888c2ecf20Sopenharmony_ci state->bmi_max_fifo_size = 384 * 1024; 11898c2ecf20Sopenharmony_ci state->fm_iram_size = 64 * 1024; 11908c2ecf20Sopenharmony_ci state->bmi_max_num_of_tasks = 128; 11918c2ecf20Sopenharmony_ci state->max_num_of_open_dmas = 84; 11928c2ecf20Sopenharmony_ci state->num_of_rx_ports = 8; 11938c2ecf20Sopenharmony_ci state->total_fifo_size = 295 * 1024; 11948c2ecf20Sopenharmony_ci } else { 11958c2ecf20Sopenharmony_ci pr_err("Unsupported FManv3 version\n"); 11968c2ecf20Sopenharmony_ci return -EINVAL; 11978c2ecf20Sopenharmony_ci } 11988c2ecf20Sopenharmony_ci 11998c2ecf20Sopenharmony_ci break; 12008c2ecf20Sopenharmony_ci default: 12018c2ecf20Sopenharmony_ci pr_err("Unsupported FMan version\n"); 12028c2ecf20Sopenharmony_ci return -EINVAL; 12038c2ecf20Sopenharmony_ci } 12048c2ecf20Sopenharmony_ci 12058c2ecf20Sopenharmony_ci return 0; 12068c2ecf20Sopenharmony_ci} 12078c2ecf20Sopenharmony_ci 12088c2ecf20Sopenharmony_cistatic bool is_init_done(struct fman_cfg *cfg) 12098c2ecf20Sopenharmony_ci{ 12108c2ecf20Sopenharmony_ci /* Checks if FMan driver parameters were initialized */ 12118c2ecf20Sopenharmony_ci if (!cfg) 12128c2ecf20Sopenharmony_ci return true; 12138c2ecf20Sopenharmony_ci 12148c2ecf20Sopenharmony_ci return false; 12158c2ecf20Sopenharmony_ci} 12168c2ecf20Sopenharmony_ci 12178c2ecf20Sopenharmony_cistatic void free_init_resources(struct fman *fman) 12188c2ecf20Sopenharmony_ci{ 12198c2ecf20Sopenharmony_ci if (fman->cam_offset) 12208c2ecf20Sopenharmony_ci fman_muram_free_mem(fman->muram, fman->cam_offset, 12218c2ecf20Sopenharmony_ci fman->cam_size); 12228c2ecf20Sopenharmony_ci if (fman->fifo_offset) 12238c2ecf20Sopenharmony_ci fman_muram_free_mem(fman->muram, fman->fifo_offset, 12248c2ecf20Sopenharmony_ci fman->fifo_size); 12258c2ecf20Sopenharmony_ci} 12268c2ecf20Sopenharmony_ci 12278c2ecf20Sopenharmony_cistatic irqreturn_t bmi_err_event(struct fman *fman) 12288c2ecf20Sopenharmony_ci{ 12298c2ecf20Sopenharmony_ci u32 event, mask, force; 12308c2ecf20Sopenharmony_ci struct fman_bmi_regs __iomem *bmi_rg = fman->bmi_regs; 12318c2ecf20Sopenharmony_ci irqreturn_t ret = IRQ_NONE; 12328c2ecf20Sopenharmony_ci 12338c2ecf20Sopenharmony_ci event = ioread32be(&bmi_rg->fmbm_ievr); 12348c2ecf20Sopenharmony_ci mask = ioread32be(&bmi_rg->fmbm_ier); 12358c2ecf20Sopenharmony_ci event &= mask; 12368c2ecf20Sopenharmony_ci /* clear the forced events */ 12378c2ecf20Sopenharmony_ci force = ioread32be(&bmi_rg->fmbm_ifr); 12388c2ecf20Sopenharmony_ci if (force & event) 12398c2ecf20Sopenharmony_ci iowrite32be(force & ~event, &bmi_rg->fmbm_ifr); 12408c2ecf20Sopenharmony_ci /* clear the acknowledged events */ 12418c2ecf20Sopenharmony_ci iowrite32be(event, &bmi_rg->fmbm_ievr); 12428c2ecf20Sopenharmony_ci 12438c2ecf20Sopenharmony_ci if (event & BMI_ERR_INTR_EN_STORAGE_PROFILE_ECC) 12448c2ecf20Sopenharmony_ci ret = fman->exception_cb(fman, FMAN_EX_BMI_STORAGE_PROFILE_ECC); 12458c2ecf20Sopenharmony_ci if (event & BMI_ERR_INTR_EN_LIST_RAM_ECC) 12468c2ecf20Sopenharmony_ci ret = fman->exception_cb(fman, FMAN_EX_BMI_LIST_RAM_ECC); 12478c2ecf20Sopenharmony_ci if (event & BMI_ERR_INTR_EN_STATISTICS_RAM_ECC) 12488c2ecf20Sopenharmony_ci ret = fman->exception_cb(fman, FMAN_EX_BMI_STATISTICS_RAM_ECC); 12498c2ecf20Sopenharmony_ci if (event & BMI_ERR_INTR_EN_DISPATCH_RAM_ECC) 12508c2ecf20Sopenharmony_ci ret = fman->exception_cb(fman, FMAN_EX_BMI_DISPATCH_RAM_ECC); 12518c2ecf20Sopenharmony_ci 12528c2ecf20Sopenharmony_ci return ret; 12538c2ecf20Sopenharmony_ci} 12548c2ecf20Sopenharmony_ci 12558c2ecf20Sopenharmony_cistatic irqreturn_t qmi_err_event(struct fman *fman) 12568c2ecf20Sopenharmony_ci{ 12578c2ecf20Sopenharmony_ci u32 event, mask, force; 12588c2ecf20Sopenharmony_ci struct fman_qmi_regs __iomem *qmi_rg = fman->qmi_regs; 12598c2ecf20Sopenharmony_ci irqreturn_t ret = IRQ_NONE; 12608c2ecf20Sopenharmony_ci 12618c2ecf20Sopenharmony_ci event = ioread32be(&qmi_rg->fmqm_eie); 12628c2ecf20Sopenharmony_ci mask = ioread32be(&qmi_rg->fmqm_eien); 12638c2ecf20Sopenharmony_ci event &= mask; 12648c2ecf20Sopenharmony_ci 12658c2ecf20Sopenharmony_ci /* clear the forced events */ 12668c2ecf20Sopenharmony_ci force = ioread32be(&qmi_rg->fmqm_eif); 12678c2ecf20Sopenharmony_ci if (force & event) 12688c2ecf20Sopenharmony_ci iowrite32be(force & ~event, &qmi_rg->fmqm_eif); 12698c2ecf20Sopenharmony_ci /* clear the acknowledged events */ 12708c2ecf20Sopenharmony_ci iowrite32be(event, &qmi_rg->fmqm_eie); 12718c2ecf20Sopenharmony_ci 12728c2ecf20Sopenharmony_ci if (event & QMI_ERR_INTR_EN_DOUBLE_ECC) 12738c2ecf20Sopenharmony_ci ret = fman->exception_cb(fman, FMAN_EX_QMI_DOUBLE_ECC); 12748c2ecf20Sopenharmony_ci if (event & QMI_ERR_INTR_EN_DEQ_FROM_DEF) 12758c2ecf20Sopenharmony_ci ret = fman->exception_cb(fman, 12768c2ecf20Sopenharmony_ci FMAN_EX_QMI_DEQ_FROM_UNKNOWN_PORTID); 12778c2ecf20Sopenharmony_ci 12788c2ecf20Sopenharmony_ci return ret; 12798c2ecf20Sopenharmony_ci} 12808c2ecf20Sopenharmony_ci 12818c2ecf20Sopenharmony_cistatic irqreturn_t dma_err_event(struct fman *fman) 12828c2ecf20Sopenharmony_ci{ 12838c2ecf20Sopenharmony_ci u32 status, mask, com_id; 12848c2ecf20Sopenharmony_ci u8 tnum, port_id, relative_port_id; 12858c2ecf20Sopenharmony_ci u16 liodn; 12868c2ecf20Sopenharmony_ci struct fman_dma_regs __iomem *dma_rg = fman->dma_regs; 12878c2ecf20Sopenharmony_ci irqreturn_t ret = IRQ_NONE; 12888c2ecf20Sopenharmony_ci 12898c2ecf20Sopenharmony_ci status = ioread32be(&dma_rg->fmdmsr); 12908c2ecf20Sopenharmony_ci mask = ioread32be(&dma_rg->fmdmmr); 12918c2ecf20Sopenharmony_ci 12928c2ecf20Sopenharmony_ci /* clear DMA_STATUS_BUS_ERR if mask has no DMA_MODE_BER */ 12938c2ecf20Sopenharmony_ci if ((mask & DMA_MODE_BER) != DMA_MODE_BER) 12948c2ecf20Sopenharmony_ci status &= ~DMA_STATUS_BUS_ERR; 12958c2ecf20Sopenharmony_ci 12968c2ecf20Sopenharmony_ci /* clear relevant bits if mask has no DMA_MODE_ECC */ 12978c2ecf20Sopenharmony_ci if ((mask & DMA_MODE_ECC) != DMA_MODE_ECC) 12988c2ecf20Sopenharmony_ci status &= ~(DMA_STATUS_FM_SPDAT_ECC | 12998c2ecf20Sopenharmony_ci DMA_STATUS_READ_ECC | 13008c2ecf20Sopenharmony_ci DMA_STATUS_SYSTEM_WRITE_ECC | 13018c2ecf20Sopenharmony_ci DMA_STATUS_FM_WRITE_ECC); 13028c2ecf20Sopenharmony_ci 13038c2ecf20Sopenharmony_ci /* clear set events */ 13048c2ecf20Sopenharmony_ci iowrite32be(status, &dma_rg->fmdmsr); 13058c2ecf20Sopenharmony_ci 13068c2ecf20Sopenharmony_ci if (status & DMA_STATUS_BUS_ERR) { 13078c2ecf20Sopenharmony_ci u64 addr; 13088c2ecf20Sopenharmony_ci 13098c2ecf20Sopenharmony_ci addr = (u64)ioread32be(&dma_rg->fmdmtal); 13108c2ecf20Sopenharmony_ci addr |= ((u64)(ioread32be(&dma_rg->fmdmtah)) << 32); 13118c2ecf20Sopenharmony_ci 13128c2ecf20Sopenharmony_ci com_id = ioread32be(&dma_rg->fmdmtcid); 13138c2ecf20Sopenharmony_ci port_id = (u8)(((com_id & DMA_TRANSFER_PORTID_MASK) >> 13148c2ecf20Sopenharmony_ci DMA_TRANSFER_PORTID_SHIFT)); 13158c2ecf20Sopenharmony_ci relative_port_id = 13168c2ecf20Sopenharmony_ci hw_port_id_to_sw_port_id(fman->state->rev_info.major, port_id); 13178c2ecf20Sopenharmony_ci tnum = (u8)((com_id & DMA_TRANSFER_TNUM_MASK) >> 13188c2ecf20Sopenharmony_ci DMA_TRANSFER_TNUM_SHIFT); 13198c2ecf20Sopenharmony_ci liodn = (u16)(com_id & DMA_TRANSFER_LIODN_MASK); 13208c2ecf20Sopenharmony_ci ret = fman->bus_error_cb(fman, relative_port_id, addr, tnum, 13218c2ecf20Sopenharmony_ci liodn); 13228c2ecf20Sopenharmony_ci } 13238c2ecf20Sopenharmony_ci if (status & DMA_STATUS_FM_SPDAT_ECC) 13248c2ecf20Sopenharmony_ci ret = fman->exception_cb(fman, FMAN_EX_DMA_SINGLE_PORT_ECC); 13258c2ecf20Sopenharmony_ci if (status & DMA_STATUS_READ_ECC) 13268c2ecf20Sopenharmony_ci ret = fman->exception_cb(fman, FMAN_EX_DMA_READ_ECC); 13278c2ecf20Sopenharmony_ci if (status & DMA_STATUS_SYSTEM_WRITE_ECC) 13288c2ecf20Sopenharmony_ci ret = fman->exception_cb(fman, FMAN_EX_DMA_SYSTEM_WRITE_ECC); 13298c2ecf20Sopenharmony_ci if (status & DMA_STATUS_FM_WRITE_ECC) 13308c2ecf20Sopenharmony_ci ret = fman->exception_cb(fman, FMAN_EX_DMA_FM_WRITE_ECC); 13318c2ecf20Sopenharmony_ci 13328c2ecf20Sopenharmony_ci return ret; 13338c2ecf20Sopenharmony_ci} 13348c2ecf20Sopenharmony_ci 13358c2ecf20Sopenharmony_cistatic irqreturn_t fpm_err_event(struct fman *fman) 13368c2ecf20Sopenharmony_ci{ 13378c2ecf20Sopenharmony_ci u32 event; 13388c2ecf20Sopenharmony_ci struct fman_fpm_regs __iomem *fpm_rg = fman->fpm_regs; 13398c2ecf20Sopenharmony_ci irqreturn_t ret = IRQ_NONE; 13408c2ecf20Sopenharmony_ci 13418c2ecf20Sopenharmony_ci event = ioread32be(&fpm_rg->fmfp_ee); 13428c2ecf20Sopenharmony_ci /* clear the all occurred events */ 13438c2ecf20Sopenharmony_ci iowrite32be(event, &fpm_rg->fmfp_ee); 13448c2ecf20Sopenharmony_ci 13458c2ecf20Sopenharmony_ci if ((event & FPM_EV_MASK_DOUBLE_ECC) && 13468c2ecf20Sopenharmony_ci (event & FPM_EV_MASK_DOUBLE_ECC_EN)) 13478c2ecf20Sopenharmony_ci ret = fman->exception_cb(fman, FMAN_EX_FPM_DOUBLE_ECC); 13488c2ecf20Sopenharmony_ci if ((event & FPM_EV_MASK_STALL) && (event & FPM_EV_MASK_STALL_EN)) 13498c2ecf20Sopenharmony_ci ret = fman->exception_cb(fman, FMAN_EX_FPM_STALL_ON_TASKS); 13508c2ecf20Sopenharmony_ci if ((event & FPM_EV_MASK_SINGLE_ECC) && 13518c2ecf20Sopenharmony_ci (event & FPM_EV_MASK_SINGLE_ECC_EN)) 13528c2ecf20Sopenharmony_ci ret = fman->exception_cb(fman, FMAN_EX_FPM_SINGLE_ECC); 13538c2ecf20Sopenharmony_ci 13548c2ecf20Sopenharmony_ci return ret; 13558c2ecf20Sopenharmony_ci} 13568c2ecf20Sopenharmony_ci 13578c2ecf20Sopenharmony_cistatic irqreturn_t muram_err_intr(struct fman *fman) 13588c2ecf20Sopenharmony_ci{ 13598c2ecf20Sopenharmony_ci u32 event, mask; 13608c2ecf20Sopenharmony_ci struct fman_fpm_regs __iomem *fpm_rg = fman->fpm_regs; 13618c2ecf20Sopenharmony_ci irqreturn_t ret = IRQ_NONE; 13628c2ecf20Sopenharmony_ci 13638c2ecf20Sopenharmony_ci event = ioread32be(&fpm_rg->fm_rcr); 13648c2ecf20Sopenharmony_ci mask = ioread32be(&fpm_rg->fm_rie); 13658c2ecf20Sopenharmony_ci 13668c2ecf20Sopenharmony_ci /* clear MURAM event bit (do not clear IRAM event) */ 13678c2ecf20Sopenharmony_ci iowrite32be(event & ~FPM_RAM_IRAM_ECC, &fpm_rg->fm_rcr); 13688c2ecf20Sopenharmony_ci 13698c2ecf20Sopenharmony_ci if ((mask & FPM_MURAM_ECC_ERR_EX_EN) && (event & FPM_RAM_MURAM_ECC)) 13708c2ecf20Sopenharmony_ci ret = fman->exception_cb(fman, FMAN_EX_MURAM_ECC); 13718c2ecf20Sopenharmony_ci 13728c2ecf20Sopenharmony_ci return ret; 13738c2ecf20Sopenharmony_ci} 13748c2ecf20Sopenharmony_ci 13758c2ecf20Sopenharmony_cistatic irqreturn_t qmi_event(struct fman *fman) 13768c2ecf20Sopenharmony_ci{ 13778c2ecf20Sopenharmony_ci u32 event, mask, force; 13788c2ecf20Sopenharmony_ci struct fman_qmi_regs __iomem *qmi_rg = fman->qmi_regs; 13798c2ecf20Sopenharmony_ci irqreturn_t ret = IRQ_NONE; 13808c2ecf20Sopenharmony_ci 13818c2ecf20Sopenharmony_ci event = ioread32be(&qmi_rg->fmqm_ie); 13828c2ecf20Sopenharmony_ci mask = ioread32be(&qmi_rg->fmqm_ien); 13838c2ecf20Sopenharmony_ci event &= mask; 13848c2ecf20Sopenharmony_ci /* clear the forced events */ 13858c2ecf20Sopenharmony_ci force = ioread32be(&qmi_rg->fmqm_if); 13868c2ecf20Sopenharmony_ci if (force & event) 13878c2ecf20Sopenharmony_ci iowrite32be(force & ~event, &qmi_rg->fmqm_if); 13888c2ecf20Sopenharmony_ci /* clear the acknowledged events */ 13898c2ecf20Sopenharmony_ci iowrite32be(event, &qmi_rg->fmqm_ie); 13908c2ecf20Sopenharmony_ci 13918c2ecf20Sopenharmony_ci if (event & QMI_INTR_EN_SINGLE_ECC) 13928c2ecf20Sopenharmony_ci ret = fman->exception_cb(fman, FMAN_EX_QMI_SINGLE_ECC); 13938c2ecf20Sopenharmony_ci 13948c2ecf20Sopenharmony_ci return ret; 13958c2ecf20Sopenharmony_ci} 13968c2ecf20Sopenharmony_ci 13978c2ecf20Sopenharmony_cistatic void enable_time_stamp(struct fman *fman) 13988c2ecf20Sopenharmony_ci{ 13998c2ecf20Sopenharmony_ci struct fman_fpm_regs __iomem *fpm_rg = fman->fpm_regs; 14008c2ecf20Sopenharmony_ci u16 fm_clk_freq = fman->state->fm_clk_freq; 14018c2ecf20Sopenharmony_ci u32 tmp, intgr, ts_freq, frac; 14028c2ecf20Sopenharmony_ci 14038c2ecf20Sopenharmony_ci ts_freq = (u32)(1 << fman->state->count1_micro_bit); 14048c2ecf20Sopenharmony_ci /* configure timestamp so that bit 8 will count 1 microsecond 14058c2ecf20Sopenharmony_ci * Find effective count rate at TIMESTAMP least significant bits: 14068c2ecf20Sopenharmony_ci * Effective_Count_Rate = 1MHz x 2^8 = 256MHz 14078c2ecf20Sopenharmony_ci * Find frequency ratio between effective count rate and the clock: 14088c2ecf20Sopenharmony_ci * Effective_Count_Rate / CLK e.g. for 600 MHz clock: 14098c2ecf20Sopenharmony_ci * 256/600 = 0.4266666... 14108c2ecf20Sopenharmony_ci */ 14118c2ecf20Sopenharmony_ci 14128c2ecf20Sopenharmony_ci intgr = ts_freq / fm_clk_freq; 14138c2ecf20Sopenharmony_ci /* we multiply by 2^16 to keep the fraction of the division 14148c2ecf20Sopenharmony_ci * we do not div back, since we write this value as a fraction 14158c2ecf20Sopenharmony_ci * see spec 14168c2ecf20Sopenharmony_ci */ 14178c2ecf20Sopenharmony_ci 14188c2ecf20Sopenharmony_ci frac = ((ts_freq << 16) - (intgr << 16) * fm_clk_freq) / fm_clk_freq; 14198c2ecf20Sopenharmony_ci /* we check remainder of the division in order to round up if not int */ 14208c2ecf20Sopenharmony_ci if (((ts_freq << 16) - (intgr << 16) * fm_clk_freq) % fm_clk_freq) 14218c2ecf20Sopenharmony_ci frac++; 14228c2ecf20Sopenharmony_ci 14238c2ecf20Sopenharmony_ci tmp = (intgr << FPM_TS_INT_SHIFT) | (u16)frac; 14248c2ecf20Sopenharmony_ci iowrite32be(tmp, &fpm_rg->fmfp_tsc2); 14258c2ecf20Sopenharmony_ci 14268c2ecf20Sopenharmony_ci /* enable timestamp with original clock */ 14278c2ecf20Sopenharmony_ci iowrite32be(FPM_TS_CTL_EN, &fpm_rg->fmfp_tsc1); 14288c2ecf20Sopenharmony_ci fman->state->enabled_time_stamp = true; 14298c2ecf20Sopenharmony_ci} 14308c2ecf20Sopenharmony_ci 14318c2ecf20Sopenharmony_cistatic int clear_iram(struct fman *fman) 14328c2ecf20Sopenharmony_ci{ 14338c2ecf20Sopenharmony_ci struct fman_iram_regs __iomem *iram; 14348c2ecf20Sopenharmony_ci int i, count; 14358c2ecf20Sopenharmony_ci 14368c2ecf20Sopenharmony_ci iram = fman->base_addr + IMEM_OFFSET; 14378c2ecf20Sopenharmony_ci 14388c2ecf20Sopenharmony_ci /* Enable the auto-increment */ 14398c2ecf20Sopenharmony_ci iowrite32be(IRAM_IADD_AIE, &iram->iadd); 14408c2ecf20Sopenharmony_ci count = 100; 14418c2ecf20Sopenharmony_ci do { 14428c2ecf20Sopenharmony_ci udelay(1); 14438c2ecf20Sopenharmony_ci } while ((ioread32be(&iram->iadd) != IRAM_IADD_AIE) && --count); 14448c2ecf20Sopenharmony_ci if (count == 0) 14458c2ecf20Sopenharmony_ci return -EBUSY; 14468c2ecf20Sopenharmony_ci 14478c2ecf20Sopenharmony_ci for (i = 0; i < (fman->state->fm_iram_size / 4); i++) 14488c2ecf20Sopenharmony_ci iowrite32be(0xffffffff, &iram->idata); 14498c2ecf20Sopenharmony_ci 14508c2ecf20Sopenharmony_ci iowrite32be(fman->state->fm_iram_size - 4, &iram->iadd); 14518c2ecf20Sopenharmony_ci count = 100; 14528c2ecf20Sopenharmony_ci do { 14538c2ecf20Sopenharmony_ci udelay(1); 14548c2ecf20Sopenharmony_ci } while ((ioread32be(&iram->idata) != 0xffffffff) && --count); 14558c2ecf20Sopenharmony_ci if (count == 0) 14568c2ecf20Sopenharmony_ci return -EBUSY; 14578c2ecf20Sopenharmony_ci 14588c2ecf20Sopenharmony_ci return 0; 14598c2ecf20Sopenharmony_ci} 14608c2ecf20Sopenharmony_ci 14618c2ecf20Sopenharmony_cistatic u32 get_exception_flag(enum fman_exceptions exception) 14628c2ecf20Sopenharmony_ci{ 14638c2ecf20Sopenharmony_ci u32 bit_mask; 14648c2ecf20Sopenharmony_ci 14658c2ecf20Sopenharmony_ci switch (exception) { 14668c2ecf20Sopenharmony_ci case FMAN_EX_DMA_BUS_ERROR: 14678c2ecf20Sopenharmony_ci bit_mask = EX_DMA_BUS_ERROR; 14688c2ecf20Sopenharmony_ci break; 14698c2ecf20Sopenharmony_ci case FMAN_EX_DMA_SINGLE_PORT_ECC: 14708c2ecf20Sopenharmony_ci bit_mask = EX_DMA_SINGLE_PORT_ECC; 14718c2ecf20Sopenharmony_ci break; 14728c2ecf20Sopenharmony_ci case FMAN_EX_DMA_READ_ECC: 14738c2ecf20Sopenharmony_ci bit_mask = EX_DMA_READ_ECC; 14748c2ecf20Sopenharmony_ci break; 14758c2ecf20Sopenharmony_ci case FMAN_EX_DMA_SYSTEM_WRITE_ECC: 14768c2ecf20Sopenharmony_ci bit_mask = EX_DMA_SYSTEM_WRITE_ECC; 14778c2ecf20Sopenharmony_ci break; 14788c2ecf20Sopenharmony_ci case FMAN_EX_DMA_FM_WRITE_ECC: 14798c2ecf20Sopenharmony_ci bit_mask = EX_DMA_FM_WRITE_ECC; 14808c2ecf20Sopenharmony_ci break; 14818c2ecf20Sopenharmony_ci case FMAN_EX_FPM_STALL_ON_TASKS: 14828c2ecf20Sopenharmony_ci bit_mask = EX_FPM_STALL_ON_TASKS; 14838c2ecf20Sopenharmony_ci break; 14848c2ecf20Sopenharmony_ci case FMAN_EX_FPM_SINGLE_ECC: 14858c2ecf20Sopenharmony_ci bit_mask = EX_FPM_SINGLE_ECC; 14868c2ecf20Sopenharmony_ci break; 14878c2ecf20Sopenharmony_ci case FMAN_EX_FPM_DOUBLE_ECC: 14888c2ecf20Sopenharmony_ci bit_mask = EX_FPM_DOUBLE_ECC; 14898c2ecf20Sopenharmony_ci break; 14908c2ecf20Sopenharmony_ci case FMAN_EX_QMI_SINGLE_ECC: 14918c2ecf20Sopenharmony_ci bit_mask = EX_QMI_SINGLE_ECC; 14928c2ecf20Sopenharmony_ci break; 14938c2ecf20Sopenharmony_ci case FMAN_EX_QMI_DOUBLE_ECC: 14948c2ecf20Sopenharmony_ci bit_mask = EX_QMI_DOUBLE_ECC; 14958c2ecf20Sopenharmony_ci break; 14968c2ecf20Sopenharmony_ci case FMAN_EX_QMI_DEQ_FROM_UNKNOWN_PORTID: 14978c2ecf20Sopenharmony_ci bit_mask = EX_QMI_DEQ_FROM_UNKNOWN_PORTID; 14988c2ecf20Sopenharmony_ci break; 14998c2ecf20Sopenharmony_ci case FMAN_EX_BMI_LIST_RAM_ECC: 15008c2ecf20Sopenharmony_ci bit_mask = EX_BMI_LIST_RAM_ECC; 15018c2ecf20Sopenharmony_ci break; 15028c2ecf20Sopenharmony_ci case FMAN_EX_BMI_STORAGE_PROFILE_ECC: 15038c2ecf20Sopenharmony_ci bit_mask = EX_BMI_STORAGE_PROFILE_ECC; 15048c2ecf20Sopenharmony_ci break; 15058c2ecf20Sopenharmony_ci case FMAN_EX_BMI_STATISTICS_RAM_ECC: 15068c2ecf20Sopenharmony_ci bit_mask = EX_BMI_STATISTICS_RAM_ECC; 15078c2ecf20Sopenharmony_ci break; 15088c2ecf20Sopenharmony_ci case FMAN_EX_BMI_DISPATCH_RAM_ECC: 15098c2ecf20Sopenharmony_ci bit_mask = EX_BMI_DISPATCH_RAM_ECC; 15108c2ecf20Sopenharmony_ci break; 15118c2ecf20Sopenharmony_ci case FMAN_EX_MURAM_ECC: 15128c2ecf20Sopenharmony_ci bit_mask = EX_MURAM_ECC; 15138c2ecf20Sopenharmony_ci break; 15148c2ecf20Sopenharmony_ci default: 15158c2ecf20Sopenharmony_ci bit_mask = 0; 15168c2ecf20Sopenharmony_ci break; 15178c2ecf20Sopenharmony_ci } 15188c2ecf20Sopenharmony_ci 15198c2ecf20Sopenharmony_ci return bit_mask; 15208c2ecf20Sopenharmony_ci} 15218c2ecf20Sopenharmony_ci 15228c2ecf20Sopenharmony_cistatic int get_module_event(enum fman_event_modules module, u8 mod_id, 15238c2ecf20Sopenharmony_ci enum fman_intr_type intr_type) 15248c2ecf20Sopenharmony_ci{ 15258c2ecf20Sopenharmony_ci int event; 15268c2ecf20Sopenharmony_ci 15278c2ecf20Sopenharmony_ci switch (module) { 15288c2ecf20Sopenharmony_ci case FMAN_MOD_MAC: 15298c2ecf20Sopenharmony_ci if (intr_type == FMAN_INTR_TYPE_ERR) 15308c2ecf20Sopenharmony_ci event = FMAN_EV_ERR_MAC0 + mod_id; 15318c2ecf20Sopenharmony_ci else 15328c2ecf20Sopenharmony_ci event = FMAN_EV_MAC0 + mod_id; 15338c2ecf20Sopenharmony_ci break; 15348c2ecf20Sopenharmony_ci case FMAN_MOD_FMAN_CTRL: 15358c2ecf20Sopenharmony_ci if (intr_type == FMAN_INTR_TYPE_ERR) 15368c2ecf20Sopenharmony_ci event = FMAN_EV_CNT; 15378c2ecf20Sopenharmony_ci else 15388c2ecf20Sopenharmony_ci event = (FMAN_EV_FMAN_CTRL_0 + mod_id); 15398c2ecf20Sopenharmony_ci break; 15408c2ecf20Sopenharmony_ci case FMAN_MOD_DUMMY_LAST: 15418c2ecf20Sopenharmony_ci event = FMAN_EV_CNT; 15428c2ecf20Sopenharmony_ci break; 15438c2ecf20Sopenharmony_ci default: 15448c2ecf20Sopenharmony_ci event = FMAN_EV_CNT; 15458c2ecf20Sopenharmony_ci break; 15468c2ecf20Sopenharmony_ci } 15478c2ecf20Sopenharmony_ci 15488c2ecf20Sopenharmony_ci return event; 15498c2ecf20Sopenharmony_ci} 15508c2ecf20Sopenharmony_ci 15518c2ecf20Sopenharmony_cistatic int set_size_of_fifo(struct fman *fman, u8 port_id, u32 *size_of_fifo, 15528c2ecf20Sopenharmony_ci u32 *extra_size_of_fifo) 15538c2ecf20Sopenharmony_ci{ 15548c2ecf20Sopenharmony_ci struct fman_bmi_regs __iomem *bmi_rg = fman->bmi_regs; 15558c2ecf20Sopenharmony_ci u32 fifo = *size_of_fifo; 15568c2ecf20Sopenharmony_ci u32 extra_fifo = *extra_size_of_fifo; 15578c2ecf20Sopenharmony_ci u32 tmp; 15588c2ecf20Sopenharmony_ci 15598c2ecf20Sopenharmony_ci /* if this is the first time a port requires extra_fifo_pool_size, 15608c2ecf20Sopenharmony_ci * the total extra_fifo_pool_size must be initialized to 1 buffer per 15618c2ecf20Sopenharmony_ci * port 15628c2ecf20Sopenharmony_ci */ 15638c2ecf20Sopenharmony_ci if (extra_fifo && !fman->state->extra_fifo_pool_size) 15648c2ecf20Sopenharmony_ci fman->state->extra_fifo_pool_size = 15658c2ecf20Sopenharmony_ci fman->state->num_of_rx_ports * FMAN_BMI_FIFO_UNITS; 15668c2ecf20Sopenharmony_ci 15678c2ecf20Sopenharmony_ci fman->state->extra_fifo_pool_size = 15688c2ecf20Sopenharmony_ci max(fman->state->extra_fifo_pool_size, extra_fifo); 15698c2ecf20Sopenharmony_ci 15708c2ecf20Sopenharmony_ci /* check that there are enough uncommitted fifo size */ 15718c2ecf20Sopenharmony_ci if ((fman->state->accumulated_fifo_size + fifo) > 15728c2ecf20Sopenharmony_ci (fman->state->total_fifo_size - 15738c2ecf20Sopenharmony_ci fman->state->extra_fifo_pool_size)) { 15748c2ecf20Sopenharmony_ci dev_err(fman->dev, "%s: Requested fifo size and extra size exceed total FIFO size.\n", 15758c2ecf20Sopenharmony_ci __func__); 15768c2ecf20Sopenharmony_ci return -EAGAIN; 15778c2ecf20Sopenharmony_ci } 15788c2ecf20Sopenharmony_ci 15798c2ecf20Sopenharmony_ci /* Read, modify and write to HW */ 15808c2ecf20Sopenharmony_ci tmp = (fifo / FMAN_BMI_FIFO_UNITS - 1) | 15818c2ecf20Sopenharmony_ci ((extra_fifo / FMAN_BMI_FIFO_UNITS) << 15828c2ecf20Sopenharmony_ci BMI_EXTRA_FIFO_SIZE_SHIFT); 15838c2ecf20Sopenharmony_ci iowrite32be(tmp, &bmi_rg->fmbm_pfs[port_id - 1]); 15848c2ecf20Sopenharmony_ci 15858c2ecf20Sopenharmony_ci /* update accumulated */ 15868c2ecf20Sopenharmony_ci fman->state->accumulated_fifo_size += fifo; 15878c2ecf20Sopenharmony_ci 15888c2ecf20Sopenharmony_ci return 0; 15898c2ecf20Sopenharmony_ci} 15908c2ecf20Sopenharmony_ci 15918c2ecf20Sopenharmony_cistatic int set_num_of_tasks(struct fman *fman, u8 port_id, u8 *num_of_tasks, 15928c2ecf20Sopenharmony_ci u8 *num_of_extra_tasks) 15938c2ecf20Sopenharmony_ci{ 15948c2ecf20Sopenharmony_ci struct fman_bmi_regs __iomem *bmi_rg = fman->bmi_regs; 15958c2ecf20Sopenharmony_ci u8 tasks = *num_of_tasks; 15968c2ecf20Sopenharmony_ci u8 extra_tasks = *num_of_extra_tasks; 15978c2ecf20Sopenharmony_ci u32 tmp; 15988c2ecf20Sopenharmony_ci 15998c2ecf20Sopenharmony_ci if (extra_tasks) 16008c2ecf20Sopenharmony_ci fman->state->extra_tasks_pool_size = 16018c2ecf20Sopenharmony_ci max(fman->state->extra_tasks_pool_size, extra_tasks); 16028c2ecf20Sopenharmony_ci 16038c2ecf20Sopenharmony_ci /* check that there are enough uncommitted tasks */ 16048c2ecf20Sopenharmony_ci if ((fman->state->accumulated_num_of_tasks + tasks) > 16058c2ecf20Sopenharmony_ci (fman->state->total_num_of_tasks - 16068c2ecf20Sopenharmony_ci fman->state->extra_tasks_pool_size)) { 16078c2ecf20Sopenharmony_ci dev_err(fman->dev, "%s: Requested num_of_tasks and extra tasks pool for fm%d exceed total num_of_tasks.\n", 16088c2ecf20Sopenharmony_ci __func__, fman->state->fm_id); 16098c2ecf20Sopenharmony_ci return -EAGAIN; 16108c2ecf20Sopenharmony_ci } 16118c2ecf20Sopenharmony_ci /* update accumulated */ 16128c2ecf20Sopenharmony_ci fman->state->accumulated_num_of_tasks += tasks; 16138c2ecf20Sopenharmony_ci 16148c2ecf20Sopenharmony_ci /* Write to HW */ 16158c2ecf20Sopenharmony_ci tmp = ioread32be(&bmi_rg->fmbm_pp[port_id - 1]) & 16168c2ecf20Sopenharmony_ci ~(BMI_NUM_OF_TASKS_MASK | BMI_NUM_OF_EXTRA_TASKS_MASK); 16178c2ecf20Sopenharmony_ci tmp |= ((u32)((tasks - 1) << BMI_NUM_OF_TASKS_SHIFT) | 16188c2ecf20Sopenharmony_ci (u32)(extra_tasks << BMI_EXTRA_NUM_OF_TASKS_SHIFT)); 16198c2ecf20Sopenharmony_ci iowrite32be(tmp, &bmi_rg->fmbm_pp[port_id - 1]); 16208c2ecf20Sopenharmony_ci 16218c2ecf20Sopenharmony_ci return 0; 16228c2ecf20Sopenharmony_ci} 16238c2ecf20Sopenharmony_ci 16248c2ecf20Sopenharmony_cistatic int set_num_of_open_dmas(struct fman *fman, u8 port_id, 16258c2ecf20Sopenharmony_ci u8 *num_of_open_dmas, 16268c2ecf20Sopenharmony_ci u8 *num_of_extra_open_dmas) 16278c2ecf20Sopenharmony_ci{ 16288c2ecf20Sopenharmony_ci struct fman_bmi_regs __iomem *bmi_rg = fman->bmi_regs; 16298c2ecf20Sopenharmony_ci u8 open_dmas = *num_of_open_dmas; 16308c2ecf20Sopenharmony_ci u8 extra_open_dmas = *num_of_extra_open_dmas; 16318c2ecf20Sopenharmony_ci u8 total_num_dmas = 0, current_val = 0, current_extra_val = 0; 16328c2ecf20Sopenharmony_ci u32 tmp; 16338c2ecf20Sopenharmony_ci 16348c2ecf20Sopenharmony_ci if (!open_dmas) { 16358c2ecf20Sopenharmony_ci /* Configuration according to values in the HW. 16368c2ecf20Sopenharmony_ci * read the current number of open Dma's 16378c2ecf20Sopenharmony_ci */ 16388c2ecf20Sopenharmony_ci tmp = ioread32be(&bmi_rg->fmbm_pp[port_id - 1]); 16398c2ecf20Sopenharmony_ci current_extra_val = (u8)((tmp & BMI_NUM_OF_EXTRA_DMAS_MASK) >> 16408c2ecf20Sopenharmony_ci BMI_EXTRA_NUM_OF_DMAS_SHIFT); 16418c2ecf20Sopenharmony_ci 16428c2ecf20Sopenharmony_ci tmp = ioread32be(&bmi_rg->fmbm_pp[port_id - 1]); 16438c2ecf20Sopenharmony_ci current_val = (u8)(((tmp & BMI_NUM_OF_DMAS_MASK) >> 16448c2ecf20Sopenharmony_ci BMI_NUM_OF_DMAS_SHIFT) + 1); 16458c2ecf20Sopenharmony_ci 16468c2ecf20Sopenharmony_ci /* This is the first configuration and user did not 16478c2ecf20Sopenharmony_ci * specify value (!open_dmas), reset values will be used 16488c2ecf20Sopenharmony_ci * and we just save these values for resource management 16498c2ecf20Sopenharmony_ci */ 16508c2ecf20Sopenharmony_ci fman->state->extra_open_dmas_pool_size = 16518c2ecf20Sopenharmony_ci (u8)max(fman->state->extra_open_dmas_pool_size, 16528c2ecf20Sopenharmony_ci current_extra_val); 16538c2ecf20Sopenharmony_ci fman->state->accumulated_num_of_open_dmas += current_val; 16548c2ecf20Sopenharmony_ci *num_of_open_dmas = current_val; 16558c2ecf20Sopenharmony_ci *num_of_extra_open_dmas = current_extra_val; 16568c2ecf20Sopenharmony_ci return 0; 16578c2ecf20Sopenharmony_ci } 16588c2ecf20Sopenharmony_ci 16598c2ecf20Sopenharmony_ci if (extra_open_dmas > current_extra_val) 16608c2ecf20Sopenharmony_ci fman->state->extra_open_dmas_pool_size = 16618c2ecf20Sopenharmony_ci (u8)max(fman->state->extra_open_dmas_pool_size, 16628c2ecf20Sopenharmony_ci extra_open_dmas); 16638c2ecf20Sopenharmony_ci 16648c2ecf20Sopenharmony_ci if ((fman->state->rev_info.major < 6) && 16658c2ecf20Sopenharmony_ci (fman->state->accumulated_num_of_open_dmas - current_val + 16668c2ecf20Sopenharmony_ci open_dmas > fman->state->max_num_of_open_dmas)) { 16678c2ecf20Sopenharmony_ci dev_err(fman->dev, "%s: Requested num_of_open_dmas for fm%d exceeds total num_of_open_dmas.\n", 16688c2ecf20Sopenharmony_ci __func__, fman->state->fm_id); 16698c2ecf20Sopenharmony_ci return -EAGAIN; 16708c2ecf20Sopenharmony_ci } else if ((fman->state->rev_info.major >= 6) && 16718c2ecf20Sopenharmony_ci !((fman->state->rev_info.major == 6) && 16728c2ecf20Sopenharmony_ci (fman->state->rev_info.minor == 0)) && 16738c2ecf20Sopenharmony_ci (fman->state->accumulated_num_of_open_dmas - 16748c2ecf20Sopenharmony_ci current_val + open_dmas > 16758c2ecf20Sopenharmony_ci fman->state->dma_thresh_max_commq + 1)) { 16768c2ecf20Sopenharmony_ci dev_err(fman->dev, "%s: Requested num_of_open_dmas for fm%d exceeds DMA Command queue (%d)\n", 16778c2ecf20Sopenharmony_ci __func__, fman->state->fm_id, 16788c2ecf20Sopenharmony_ci fman->state->dma_thresh_max_commq + 1); 16798c2ecf20Sopenharmony_ci return -EAGAIN; 16808c2ecf20Sopenharmony_ci } 16818c2ecf20Sopenharmony_ci 16828c2ecf20Sopenharmony_ci WARN_ON(fman->state->accumulated_num_of_open_dmas < current_val); 16838c2ecf20Sopenharmony_ci /* update acummulated */ 16848c2ecf20Sopenharmony_ci fman->state->accumulated_num_of_open_dmas -= current_val; 16858c2ecf20Sopenharmony_ci fman->state->accumulated_num_of_open_dmas += open_dmas; 16868c2ecf20Sopenharmony_ci 16878c2ecf20Sopenharmony_ci if (fman->state->rev_info.major < 6) 16888c2ecf20Sopenharmony_ci total_num_dmas = 16898c2ecf20Sopenharmony_ci (u8)(fman->state->accumulated_num_of_open_dmas + 16908c2ecf20Sopenharmony_ci fman->state->extra_open_dmas_pool_size); 16918c2ecf20Sopenharmony_ci 16928c2ecf20Sopenharmony_ci /* calculate reg */ 16938c2ecf20Sopenharmony_ci tmp = ioread32be(&bmi_rg->fmbm_pp[port_id - 1]) & 16948c2ecf20Sopenharmony_ci ~(BMI_NUM_OF_DMAS_MASK | BMI_NUM_OF_EXTRA_DMAS_MASK); 16958c2ecf20Sopenharmony_ci tmp |= (u32)(((open_dmas - 1) << BMI_NUM_OF_DMAS_SHIFT) | 16968c2ecf20Sopenharmony_ci (extra_open_dmas << BMI_EXTRA_NUM_OF_DMAS_SHIFT)); 16978c2ecf20Sopenharmony_ci iowrite32be(tmp, &bmi_rg->fmbm_pp[port_id - 1]); 16988c2ecf20Sopenharmony_ci 16998c2ecf20Sopenharmony_ci /* update total num of DMA's with committed number of open DMAS, 17008c2ecf20Sopenharmony_ci * and max uncommitted pool. 17018c2ecf20Sopenharmony_ci */ 17028c2ecf20Sopenharmony_ci if (total_num_dmas) { 17038c2ecf20Sopenharmony_ci tmp = ioread32be(&bmi_rg->fmbm_cfg2) & ~BMI_CFG2_DMAS_MASK; 17048c2ecf20Sopenharmony_ci tmp |= (u32)(total_num_dmas - 1) << BMI_CFG2_DMAS_SHIFT; 17058c2ecf20Sopenharmony_ci iowrite32be(tmp, &bmi_rg->fmbm_cfg2); 17068c2ecf20Sopenharmony_ci } 17078c2ecf20Sopenharmony_ci 17088c2ecf20Sopenharmony_ci return 0; 17098c2ecf20Sopenharmony_ci} 17108c2ecf20Sopenharmony_ci 17118c2ecf20Sopenharmony_cistatic int fman_config(struct fman *fman) 17128c2ecf20Sopenharmony_ci{ 17138c2ecf20Sopenharmony_ci void __iomem *base_addr; 17148c2ecf20Sopenharmony_ci int err; 17158c2ecf20Sopenharmony_ci 17168c2ecf20Sopenharmony_ci base_addr = fman->dts_params.base_addr; 17178c2ecf20Sopenharmony_ci 17188c2ecf20Sopenharmony_ci fman->state = kzalloc(sizeof(*fman->state), GFP_KERNEL); 17198c2ecf20Sopenharmony_ci if (!fman->state) 17208c2ecf20Sopenharmony_ci goto err_fm_state; 17218c2ecf20Sopenharmony_ci 17228c2ecf20Sopenharmony_ci /* Allocate the FM driver's parameters structure */ 17238c2ecf20Sopenharmony_ci fman->cfg = kzalloc(sizeof(*fman->cfg), GFP_KERNEL); 17248c2ecf20Sopenharmony_ci if (!fman->cfg) 17258c2ecf20Sopenharmony_ci goto err_fm_drv; 17268c2ecf20Sopenharmony_ci 17278c2ecf20Sopenharmony_ci /* Initialize MURAM block */ 17288c2ecf20Sopenharmony_ci fman->muram = 17298c2ecf20Sopenharmony_ci fman_muram_init(fman->dts_params.muram_res.start, 17308c2ecf20Sopenharmony_ci resource_size(&fman->dts_params.muram_res)); 17318c2ecf20Sopenharmony_ci if (!fman->muram) 17328c2ecf20Sopenharmony_ci goto err_fm_soc_specific; 17338c2ecf20Sopenharmony_ci 17348c2ecf20Sopenharmony_ci /* Initialize FM parameters which will be kept by the driver */ 17358c2ecf20Sopenharmony_ci fman->state->fm_id = fman->dts_params.id; 17368c2ecf20Sopenharmony_ci fman->state->fm_clk_freq = fman->dts_params.clk_freq; 17378c2ecf20Sopenharmony_ci fman->state->qman_channel_base = fman->dts_params.qman_channel_base; 17388c2ecf20Sopenharmony_ci fman->state->num_of_qman_channels = 17398c2ecf20Sopenharmony_ci fman->dts_params.num_of_qman_channels; 17408c2ecf20Sopenharmony_ci fman->state->res = fman->dts_params.res; 17418c2ecf20Sopenharmony_ci fman->exception_cb = fman_exceptions; 17428c2ecf20Sopenharmony_ci fman->bus_error_cb = fman_bus_error; 17438c2ecf20Sopenharmony_ci fman->fpm_regs = base_addr + FPM_OFFSET; 17448c2ecf20Sopenharmony_ci fman->bmi_regs = base_addr + BMI_OFFSET; 17458c2ecf20Sopenharmony_ci fman->qmi_regs = base_addr + QMI_OFFSET; 17468c2ecf20Sopenharmony_ci fman->dma_regs = base_addr + DMA_OFFSET; 17478c2ecf20Sopenharmony_ci fman->hwp_regs = base_addr + HWP_OFFSET; 17488c2ecf20Sopenharmony_ci fman->kg_regs = base_addr + KG_OFFSET; 17498c2ecf20Sopenharmony_ci fman->base_addr = base_addr; 17508c2ecf20Sopenharmony_ci 17518c2ecf20Sopenharmony_ci spin_lock_init(&fman->spinlock); 17528c2ecf20Sopenharmony_ci fman_defconfig(fman->cfg); 17538c2ecf20Sopenharmony_ci 17548c2ecf20Sopenharmony_ci fman->state->extra_fifo_pool_size = 0; 17558c2ecf20Sopenharmony_ci fman->state->exceptions = (EX_DMA_BUS_ERROR | 17568c2ecf20Sopenharmony_ci EX_DMA_READ_ECC | 17578c2ecf20Sopenharmony_ci EX_DMA_SYSTEM_WRITE_ECC | 17588c2ecf20Sopenharmony_ci EX_DMA_FM_WRITE_ECC | 17598c2ecf20Sopenharmony_ci EX_FPM_STALL_ON_TASKS | 17608c2ecf20Sopenharmony_ci EX_FPM_SINGLE_ECC | 17618c2ecf20Sopenharmony_ci EX_FPM_DOUBLE_ECC | 17628c2ecf20Sopenharmony_ci EX_QMI_DEQ_FROM_UNKNOWN_PORTID | 17638c2ecf20Sopenharmony_ci EX_BMI_LIST_RAM_ECC | 17648c2ecf20Sopenharmony_ci EX_BMI_STORAGE_PROFILE_ECC | 17658c2ecf20Sopenharmony_ci EX_BMI_STATISTICS_RAM_ECC | 17668c2ecf20Sopenharmony_ci EX_MURAM_ECC | 17678c2ecf20Sopenharmony_ci EX_BMI_DISPATCH_RAM_ECC | 17688c2ecf20Sopenharmony_ci EX_QMI_DOUBLE_ECC | 17698c2ecf20Sopenharmony_ci EX_QMI_SINGLE_ECC); 17708c2ecf20Sopenharmony_ci 17718c2ecf20Sopenharmony_ci /* Read FMan revision for future use*/ 17728c2ecf20Sopenharmony_ci fman_get_revision(fman, &fman->state->rev_info); 17738c2ecf20Sopenharmony_ci 17748c2ecf20Sopenharmony_ci err = fill_soc_specific_params(fman->state); 17758c2ecf20Sopenharmony_ci if (err) 17768c2ecf20Sopenharmony_ci goto err_fm_soc_specific; 17778c2ecf20Sopenharmony_ci 17788c2ecf20Sopenharmony_ci /* FM_AID_MODE_NO_TNUM_SW005 Errata workaround */ 17798c2ecf20Sopenharmony_ci if (fman->state->rev_info.major >= 6) 17808c2ecf20Sopenharmony_ci fman->cfg->dma_aid_mode = FMAN_DMA_AID_OUT_PORT_ID; 17818c2ecf20Sopenharmony_ci 17828c2ecf20Sopenharmony_ci fman->cfg->qmi_def_tnums_thresh = fman->state->qmi_def_tnums_thresh; 17838c2ecf20Sopenharmony_ci 17848c2ecf20Sopenharmony_ci fman->state->total_num_of_tasks = 17858c2ecf20Sopenharmony_ci (u8)DFLT_TOTAL_NUM_OF_TASKS(fman->state->rev_info.major, 17868c2ecf20Sopenharmony_ci fman->state->rev_info.minor, 17878c2ecf20Sopenharmony_ci fman->state->bmi_max_num_of_tasks); 17888c2ecf20Sopenharmony_ci 17898c2ecf20Sopenharmony_ci if (fman->state->rev_info.major < 6) { 17908c2ecf20Sopenharmony_ci fman->cfg->dma_comm_qtsh_clr_emer = 17918c2ecf20Sopenharmony_ci (u8)DFLT_DMA_COMM_Q_LOW(fman->state->rev_info.major, 17928c2ecf20Sopenharmony_ci fman->state->dma_thresh_max_commq); 17938c2ecf20Sopenharmony_ci 17948c2ecf20Sopenharmony_ci fman->cfg->dma_comm_qtsh_asrt_emer = 17958c2ecf20Sopenharmony_ci (u8)DFLT_DMA_COMM_Q_HIGH(fman->state->rev_info.major, 17968c2ecf20Sopenharmony_ci fman->state->dma_thresh_max_commq); 17978c2ecf20Sopenharmony_ci 17988c2ecf20Sopenharmony_ci fman->cfg->dma_cam_num_of_entries = 17998c2ecf20Sopenharmony_ci DFLT_DMA_CAM_NUM_OF_ENTRIES(fman->state->rev_info.major); 18008c2ecf20Sopenharmony_ci 18018c2ecf20Sopenharmony_ci fman->cfg->dma_read_buf_tsh_clr_emer = 18028c2ecf20Sopenharmony_ci DFLT_DMA_READ_INT_BUF_LOW(fman->state->dma_thresh_max_buf); 18038c2ecf20Sopenharmony_ci 18048c2ecf20Sopenharmony_ci fman->cfg->dma_read_buf_tsh_asrt_emer = 18058c2ecf20Sopenharmony_ci DFLT_DMA_READ_INT_BUF_HIGH(fman->state->dma_thresh_max_buf); 18068c2ecf20Sopenharmony_ci 18078c2ecf20Sopenharmony_ci fman->cfg->dma_write_buf_tsh_clr_emer = 18088c2ecf20Sopenharmony_ci DFLT_DMA_WRITE_INT_BUF_LOW(fman->state->dma_thresh_max_buf); 18098c2ecf20Sopenharmony_ci 18108c2ecf20Sopenharmony_ci fman->cfg->dma_write_buf_tsh_asrt_emer = 18118c2ecf20Sopenharmony_ci DFLT_DMA_WRITE_INT_BUF_HIGH(fman->state->dma_thresh_max_buf); 18128c2ecf20Sopenharmony_ci 18138c2ecf20Sopenharmony_ci fman->cfg->dma_axi_dbg_num_of_beats = 18148c2ecf20Sopenharmony_ci DFLT_AXI_DBG_NUM_OF_BEATS; 18158c2ecf20Sopenharmony_ci } 18168c2ecf20Sopenharmony_ci 18178c2ecf20Sopenharmony_ci return 0; 18188c2ecf20Sopenharmony_ci 18198c2ecf20Sopenharmony_cierr_fm_soc_specific: 18208c2ecf20Sopenharmony_ci kfree(fman->cfg); 18218c2ecf20Sopenharmony_cierr_fm_drv: 18228c2ecf20Sopenharmony_ci kfree(fman->state); 18238c2ecf20Sopenharmony_cierr_fm_state: 18248c2ecf20Sopenharmony_ci kfree(fman); 18258c2ecf20Sopenharmony_ci return -EINVAL; 18268c2ecf20Sopenharmony_ci} 18278c2ecf20Sopenharmony_ci 18288c2ecf20Sopenharmony_cistatic int fman_reset(struct fman *fman) 18298c2ecf20Sopenharmony_ci{ 18308c2ecf20Sopenharmony_ci u32 count; 18318c2ecf20Sopenharmony_ci int err = 0; 18328c2ecf20Sopenharmony_ci 18338c2ecf20Sopenharmony_ci if (fman->state->rev_info.major < 6) { 18348c2ecf20Sopenharmony_ci iowrite32be(FPM_RSTC_FM_RESET, &fman->fpm_regs->fm_rstc); 18358c2ecf20Sopenharmony_ci /* Wait for reset completion */ 18368c2ecf20Sopenharmony_ci count = 100; 18378c2ecf20Sopenharmony_ci do { 18388c2ecf20Sopenharmony_ci udelay(1); 18398c2ecf20Sopenharmony_ci } while (((ioread32be(&fman->fpm_regs->fm_rstc)) & 18408c2ecf20Sopenharmony_ci FPM_RSTC_FM_RESET) && --count); 18418c2ecf20Sopenharmony_ci if (count == 0) 18428c2ecf20Sopenharmony_ci err = -EBUSY; 18438c2ecf20Sopenharmony_ci 18448c2ecf20Sopenharmony_ci goto _return; 18458c2ecf20Sopenharmony_ci } else { 18468c2ecf20Sopenharmony_ci#ifdef CONFIG_PPC 18478c2ecf20Sopenharmony_ci struct device_node *guts_node; 18488c2ecf20Sopenharmony_ci struct ccsr_guts __iomem *guts_regs; 18498c2ecf20Sopenharmony_ci u32 devdisr2, reg; 18508c2ecf20Sopenharmony_ci 18518c2ecf20Sopenharmony_ci /* Errata A007273 */ 18528c2ecf20Sopenharmony_ci guts_node = 18538c2ecf20Sopenharmony_ci of_find_compatible_node(NULL, NULL, 18548c2ecf20Sopenharmony_ci "fsl,qoriq-device-config-2.0"); 18558c2ecf20Sopenharmony_ci if (!guts_node) { 18568c2ecf20Sopenharmony_ci dev_err(fman->dev, "%s: Couldn't find guts node\n", 18578c2ecf20Sopenharmony_ci __func__); 18588c2ecf20Sopenharmony_ci goto guts_node; 18598c2ecf20Sopenharmony_ci } 18608c2ecf20Sopenharmony_ci 18618c2ecf20Sopenharmony_ci guts_regs = of_iomap(guts_node, 0); 18628c2ecf20Sopenharmony_ci if (!guts_regs) { 18638c2ecf20Sopenharmony_ci dev_err(fman->dev, "%s: Couldn't map %pOF regs\n", 18648c2ecf20Sopenharmony_ci __func__, guts_node); 18658c2ecf20Sopenharmony_ci goto guts_regs; 18668c2ecf20Sopenharmony_ci } 18678c2ecf20Sopenharmony_ci#define FMAN1_ALL_MACS_MASK 0xFCC00000 18688c2ecf20Sopenharmony_ci#define FMAN2_ALL_MACS_MASK 0x000FCC00 18698c2ecf20Sopenharmony_ci /* Read current state */ 18708c2ecf20Sopenharmony_ci devdisr2 = ioread32be(&guts_regs->devdisr2); 18718c2ecf20Sopenharmony_ci if (fman->dts_params.id == 0) 18728c2ecf20Sopenharmony_ci reg = devdisr2 & ~FMAN1_ALL_MACS_MASK; 18738c2ecf20Sopenharmony_ci else 18748c2ecf20Sopenharmony_ci reg = devdisr2 & ~FMAN2_ALL_MACS_MASK; 18758c2ecf20Sopenharmony_ci 18768c2ecf20Sopenharmony_ci /* Enable all MACs */ 18778c2ecf20Sopenharmony_ci iowrite32be(reg, &guts_regs->devdisr2); 18788c2ecf20Sopenharmony_ci#endif 18798c2ecf20Sopenharmony_ci 18808c2ecf20Sopenharmony_ci /* Perform FMan reset */ 18818c2ecf20Sopenharmony_ci iowrite32be(FPM_RSTC_FM_RESET, &fman->fpm_regs->fm_rstc); 18828c2ecf20Sopenharmony_ci 18838c2ecf20Sopenharmony_ci /* Wait for reset completion */ 18848c2ecf20Sopenharmony_ci count = 100; 18858c2ecf20Sopenharmony_ci do { 18868c2ecf20Sopenharmony_ci udelay(1); 18878c2ecf20Sopenharmony_ci } while (((ioread32be(&fman->fpm_regs->fm_rstc)) & 18888c2ecf20Sopenharmony_ci FPM_RSTC_FM_RESET) && --count); 18898c2ecf20Sopenharmony_ci if (count == 0) { 18908c2ecf20Sopenharmony_ci#ifdef CONFIG_PPC 18918c2ecf20Sopenharmony_ci iounmap(guts_regs); 18928c2ecf20Sopenharmony_ci of_node_put(guts_node); 18938c2ecf20Sopenharmony_ci#endif 18948c2ecf20Sopenharmony_ci err = -EBUSY; 18958c2ecf20Sopenharmony_ci goto _return; 18968c2ecf20Sopenharmony_ci } 18978c2ecf20Sopenharmony_ci#ifdef CONFIG_PPC 18988c2ecf20Sopenharmony_ci 18998c2ecf20Sopenharmony_ci /* Restore devdisr2 value */ 19008c2ecf20Sopenharmony_ci iowrite32be(devdisr2, &guts_regs->devdisr2); 19018c2ecf20Sopenharmony_ci 19028c2ecf20Sopenharmony_ci iounmap(guts_regs); 19038c2ecf20Sopenharmony_ci of_node_put(guts_node); 19048c2ecf20Sopenharmony_ci#endif 19058c2ecf20Sopenharmony_ci 19068c2ecf20Sopenharmony_ci goto _return; 19078c2ecf20Sopenharmony_ci 19088c2ecf20Sopenharmony_ci#ifdef CONFIG_PPC 19098c2ecf20Sopenharmony_ciguts_regs: 19108c2ecf20Sopenharmony_ci of_node_put(guts_node); 19118c2ecf20Sopenharmony_ciguts_node: 19128c2ecf20Sopenharmony_ci dev_dbg(fman->dev, "%s: Didn't perform FManV3 reset due to Errata A007273!\n", 19138c2ecf20Sopenharmony_ci __func__); 19148c2ecf20Sopenharmony_ci#endif 19158c2ecf20Sopenharmony_ci } 19168c2ecf20Sopenharmony_ci_return: 19178c2ecf20Sopenharmony_ci return err; 19188c2ecf20Sopenharmony_ci} 19198c2ecf20Sopenharmony_ci 19208c2ecf20Sopenharmony_cistatic int fman_init(struct fman *fman) 19218c2ecf20Sopenharmony_ci{ 19228c2ecf20Sopenharmony_ci struct fman_cfg *cfg = NULL; 19238c2ecf20Sopenharmony_ci int err = 0, i, count; 19248c2ecf20Sopenharmony_ci 19258c2ecf20Sopenharmony_ci if (is_init_done(fman->cfg)) 19268c2ecf20Sopenharmony_ci return -EINVAL; 19278c2ecf20Sopenharmony_ci 19288c2ecf20Sopenharmony_ci fman->state->count1_micro_bit = FM_TIMESTAMP_1_USEC_BIT; 19298c2ecf20Sopenharmony_ci 19308c2ecf20Sopenharmony_ci cfg = fman->cfg; 19318c2ecf20Sopenharmony_ci 19328c2ecf20Sopenharmony_ci /* clear revision-dependent non existing exception */ 19338c2ecf20Sopenharmony_ci if (fman->state->rev_info.major < 6) 19348c2ecf20Sopenharmony_ci fman->state->exceptions &= ~FMAN_EX_BMI_DISPATCH_RAM_ECC; 19358c2ecf20Sopenharmony_ci 19368c2ecf20Sopenharmony_ci if (fman->state->rev_info.major >= 6) 19378c2ecf20Sopenharmony_ci fman->state->exceptions &= ~FMAN_EX_QMI_SINGLE_ECC; 19388c2ecf20Sopenharmony_ci 19398c2ecf20Sopenharmony_ci /* clear CPG */ 19408c2ecf20Sopenharmony_ci memset_io((void __iomem *)(fman->base_addr + CGP_OFFSET), 0, 19418c2ecf20Sopenharmony_ci fman->state->fm_port_num_of_cg); 19428c2ecf20Sopenharmony_ci 19438c2ecf20Sopenharmony_ci /* Save LIODN info before FMan reset 19448c2ecf20Sopenharmony_ci * Skipping non-existent port 0 (i = 1) 19458c2ecf20Sopenharmony_ci */ 19468c2ecf20Sopenharmony_ci for (i = 1; i < FMAN_LIODN_TBL; i++) { 19478c2ecf20Sopenharmony_ci u32 liodn_base; 19488c2ecf20Sopenharmony_ci 19498c2ecf20Sopenharmony_ci fman->liodn_offset[i] = 19508c2ecf20Sopenharmony_ci ioread32be(&fman->bmi_regs->fmbm_spliodn[i - 1]); 19518c2ecf20Sopenharmony_ci if (!IS_ENABLED(CONFIG_FSL_PAMU)) 19528c2ecf20Sopenharmony_ci continue; 19538c2ecf20Sopenharmony_ci liodn_base = ioread32be(&fman->dma_regs->fmdmplr[i / 2]); 19548c2ecf20Sopenharmony_ci if (i % 2) { 19558c2ecf20Sopenharmony_ci /* FMDM_PLR LSB holds LIODN base for odd ports */ 19568c2ecf20Sopenharmony_ci liodn_base &= DMA_LIODN_BASE_MASK; 19578c2ecf20Sopenharmony_ci } else { 19588c2ecf20Sopenharmony_ci /* FMDM_PLR MSB holds LIODN base for even ports */ 19598c2ecf20Sopenharmony_ci liodn_base >>= DMA_LIODN_SHIFT; 19608c2ecf20Sopenharmony_ci liodn_base &= DMA_LIODN_BASE_MASK; 19618c2ecf20Sopenharmony_ci } 19628c2ecf20Sopenharmony_ci fman->liodn_base[i] = liodn_base; 19638c2ecf20Sopenharmony_ci } 19648c2ecf20Sopenharmony_ci 19658c2ecf20Sopenharmony_ci err = fman_reset(fman); 19668c2ecf20Sopenharmony_ci if (err) 19678c2ecf20Sopenharmony_ci return err; 19688c2ecf20Sopenharmony_ci 19698c2ecf20Sopenharmony_ci if (ioread32be(&fman->qmi_regs->fmqm_gs) & QMI_GS_HALT_NOT_BUSY) { 19708c2ecf20Sopenharmony_ci resume(fman->fpm_regs); 19718c2ecf20Sopenharmony_ci /* Wait until QMI is not in halt not busy state */ 19728c2ecf20Sopenharmony_ci count = 100; 19738c2ecf20Sopenharmony_ci do { 19748c2ecf20Sopenharmony_ci udelay(1); 19758c2ecf20Sopenharmony_ci } while (((ioread32be(&fman->qmi_regs->fmqm_gs)) & 19768c2ecf20Sopenharmony_ci QMI_GS_HALT_NOT_BUSY) && --count); 19778c2ecf20Sopenharmony_ci if (count == 0) 19788c2ecf20Sopenharmony_ci dev_warn(fman->dev, "%s: QMI is in halt not busy state\n", 19798c2ecf20Sopenharmony_ci __func__); 19808c2ecf20Sopenharmony_ci } 19818c2ecf20Sopenharmony_ci 19828c2ecf20Sopenharmony_ci if (clear_iram(fman) != 0) 19838c2ecf20Sopenharmony_ci return -EINVAL; 19848c2ecf20Sopenharmony_ci 19858c2ecf20Sopenharmony_ci cfg->exceptions = fman->state->exceptions; 19868c2ecf20Sopenharmony_ci 19878c2ecf20Sopenharmony_ci /* Init DMA Registers */ 19888c2ecf20Sopenharmony_ci 19898c2ecf20Sopenharmony_ci err = dma_init(fman); 19908c2ecf20Sopenharmony_ci if (err != 0) { 19918c2ecf20Sopenharmony_ci free_init_resources(fman); 19928c2ecf20Sopenharmony_ci return err; 19938c2ecf20Sopenharmony_ci } 19948c2ecf20Sopenharmony_ci 19958c2ecf20Sopenharmony_ci /* Init FPM Registers */ 19968c2ecf20Sopenharmony_ci fpm_init(fman->fpm_regs, fman->cfg); 19978c2ecf20Sopenharmony_ci 19988c2ecf20Sopenharmony_ci /* define common resources */ 19998c2ecf20Sopenharmony_ci /* allocate MURAM for FIFO according to total size */ 20008c2ecf20Sopenharmony_ci fman->fifo_offset = fman_muram_alloc(fman->muram, 20018c2ecf20Sopenharmony_ci fman->state->total_fifo_size); 20028c2ecf20Sopenharmony_ci if (IS_ERR_VALUE(fman->fifo_offset)) { 20038c2ecf20Sopenharmony_ci free_init_resources(fman); 20048c2ecf20Sopenharmony_ci dev_err(fman->dev, "%s: MURAM alloc for BMI FIFO failed\n", 20058c2ecf20Sopenharmony_ci __func__); 20068c2ecf20Sopenharmony_ci return -ENOMEM; 20078c2ecf20Sopenharmony_ci } 20088c2ecf20Sopenharmony_ci 20098c2ecf20Sopenharmony_ci cfg->fifo_base_addr = fman->fifo_offset; 20108c2ecf20Sopenharmony_ci cfg->total_fifo_size = fman->state->total_fifo_size; 20118c2ecf20Sopenharmony_ci cfg->total_num_of_tasks = fman->state->total_num_of_tasks; 20128c2ecf20Sopenharmony_ci cfg->clk_freq = fman->state->fm_clk_freq; 20138c2ecf20Sopenharmony_ci 20148c2ecf20Sopenharmony_ci /* Init BMI Registers */ 20158c2ecf20Sopenharmony_ci bmi_init(fman->bmi_regs, fman->cfg); 20168c2ecf20Sopenharmony_ci 20178c2ecf20Sopenharmony_ci /* Init QMI Registers */ 20188c2ecf20Sopenharmony_ci qmi_init(fman->qmi_regs, fman->cfg); 20198c2ecf20Sopenharmony_ci 20208c2ecf20Sopenharmony_ci /* Init HW Parser */ 20218c2ecf20Sopenharmony_ci hwp_init(fman->hwp_regs); 20228c2ecf20Sopenharmony_ci 20238c2ecf20Sopenharmony_ci /* Init KeyGen */ 20248c2ecf20Sopenharmony_ci fman->keygen = keygen_init(fman->kg_regs); 20258c2ecf20Sopenharmony_ci if (!fman->keygen) 20268c2ecf20Sopenharmony_ci return -EINVAL; 20278c2ecf20Sopenharmony_ci 20288c2ecf20Sopenharmony_ci err = enable(fman, cfg); 20298c2ecf20Sopenharmony_ci if (err != 0) 20308c2ecf20Sopenharmony_ci return err; 20318c2ecf20Sopenharmony_ci 20328c2ecf20Sopenharmony_ci enable_time_stamp(fman); 20338c2ecf20Sopenharmony_ci 20348c2ecf20Sopenharmony_ci kfree(fman->cfg); 20358c2ecf20Sopenharmony_ci fman->cfg = NULL; 20368c2ecf20Sopenharmony_ci 20378c2ecf20Sopenharmony_ci return 0; 20388c2ecf20Sopenharmony_ci} 20398c2ecf20Sopenharmony_ci 20408c2ecf20Sopenharmony_cistatic int fman_set_exception(struct fman *fman, 20418c2ecf20Sopenharmony_ci enum fman_exceptions exception, bool enable) 20428c2ecf20Sopenharmony_ci{ 20438c2ecf20Sopenharmony_ci u32 bit_mask = 0; 20448c2ecf20Sopenharmony_ci 20458c2ecf20Sopenharmony_ci if (!is_init_done(fman->cfg)) 20468c2ecf20Sopenharmony_ci return -EINVAL; 20478c2ecf20Sopenharmony_ci 20488c2ecf20Sopenharmony_ci bit_mask = get_exception_flag(exception); 20498c2ecf20Sopenharmony_ci if (bit_mask) { 20508c2ecf20Sopenharmony_ci if (enable) 20518c2ecf20Sopenharmony_ci fman->state->exceptions |= bit_mask; 20528c2ecf20Sopenharmony_ci else 20538c2ecf20Sopenharmony_ci fman->state->exceptions &= ~bit_mask; 20548c2ecf20Sopenharmony_ci } else { 20558c2ecf20Sopenharmony_ci dev_err(fman->dev, "%s: Undefined exception (%d)\n", 20568c2ecf20Sopenharmony_ci __func__, exception); 20578c2ecf20Sopenharmony_ci return -EINVAL; 20588c2ecf20Sopenharmony_ci } 20598c2ecf20Sopenharmony_ci 20608c2ecf20Sopenharmony_ci return set_exception(fman, exception, enable); 20618c2ecf20Sopenharmony_ci} 20628c2ecf20Sopenharmony_ci 20638c2ecf20Sopenharmony_ci/** 20648c2ecf20Sopenharmony_ci * fman_register_intr 20658c2ecf20Sopenharmony_ci * @fman: A Pointer to FMan device 20668c2ecf20Sopenharmony_ci * @module: Calling module 20678c2ecf20Sopenharmony_ci * @mod_id: Module id (if more than 1 exists, '0' if not) 20688c2ecf20Sopenharmony_ci * @intr_type: Interrupt type (error/normal) selection. 20698c2ecf20Sopenharmony_ci * @isr_cb: The interrupt service routine. 20708c2ecf20Sopenharmony_ci * @src_arg: Argument to be passed to isr_cb. 20718c2ecf20Sopenharmony_ci * 20728c2ecf20Sopenharmony_ci * Used to register an event handler to be processed by FMan 20738c2ecf20Sopenharmony_ci * 20748c2ecf20Sopenharmony_ci * Return: 0 on success; Error code otherwise. 20758c2ecf20Sopenharmony_ci */ 20768c2ecf20Sopenharmony_civoid fman_register_intr(struct fman *fman, enum fman_event_modules module, 20778c2ecf20Sopenharmony_ci u8 mod_id, enum fman_intr_type intr_type, 20788c2ecf20Sopenharmony_ci void (*isr_cb)(void *src_arg), void *src_arg) 20798c2ecf20Sopenharmony_ci{ 20808c2ecf20Sopenharmony_ci int event = 0; 20818c2ecf20Sopenharmony_ci 20828c2ecf20Sopenharmony_ci event = get_module_event(module, mod_id, intr_type); 20838c2ecf20Sopenharmony_ci WARN_ON(event >= FMAN_EV_CNT); 20848c2ecf20Sopenharmony_ci 20858c2ecf20Sopenharmony_ci /* register in local FM structure */ 20868c2ecf20Sopenharmony_ci fman->intr_mng[event].isr_cb = isr_cb; 20878c2ecf20Sopenharmony_ci fman->intr_mng[event].src_handle = src_arg; 20888c2ecf20Sopenharmony_ci} 20898c2ecf20Sopenharmony_ciEXPORT_SYMBOL(fman_register_intr); 20908c2ecf20Sopenharmony_ci 20918c2ecf20Sopenharmony_ci/** 20928c2ecf20Sopenharmony_ci * fman_unregister_intr 20938c2ecf20Sopenharmony_ci * @fman: A Pointer to FMan device 20948c2ecf20Sopenharmony_ci * @module: Calling module 20958c2ecf20Sopenharmony_ci * @mod_id: Module id (if more than 1 exists, '0' if not) 20968c2ecf20Sopenharmony_ci * @intr_type: Interrupt type (error/normal) selection. 20978c2ecf20Sopenharmony_ci * 20988c2ecf20Sopenharmony_ci * Used to unregister an event handler to be processed by FMan 20998c2ecf20Sopenharmony_ci * 21008c2ecf20Sopenharmony_ci * Return: 0 on success; Error code otherwise. 21018c2ecf20Sopenharmony_ci */ 21028c2ecf20Sopenharmony_civoid fman_unregister_intr(struct fman *fman, enum fman_event_modules module, 21038c2ecf20Sopenharmony_ci u8 mod_id, enum fman_intr_type intr_type) 21048c2ecf20Sopenharmony_ci{ 21058c2ecf20Sopenharmony_ci int event = 0; 21068c2ecf20Sopenharmony_ci 21078c2ecf20Sopenharmony_ci event = get_module_event(module, mod_id, intr_type); 21088c2ecf20Sopenharmony_ci WARN_ON(event >= FMAN_EV_CNT); 21098c2ecf20Sopenharmony_ci 21108c2ecf20Sopenharmony_ci fman->intr_mng[event].isr_cb = NULL; 21118c2ecf20Sopenharmony_ci fman->intr_mng[event].src_handle = NULL; 21128c2ecf20Sopenharmony_ci} 21138c2ecf20Sopenharmony_ciEXPORT_SYMBOL(fman_unregister_intr); 21148c2ecf20Sopenharmony_ci 21158c2ecf20Sopenharmony_ci/** 21168c2ecf20Sopenharmony_ci * fman_set_port_params 21178c2ecf20Sopenharmony_ci * @fman: A Pointer to FMan device 21188c2ecf20Sopenharmony_ci * @port_params: Port parameters 21198c2ecf20Sopenharmony_ci * 21208c2ecf20Sopenharmony_ci * Used by FMan Port to pass parameters to the FMan 21218c2ecf20Sopenharmony_ci * 21228c2ecf20Sopenharmony_ci * Return: 0 on success; Error code otherwise. 21238c2ecf20Sopenharmony_ci */ 21248c2ecf20Sopenharmony_ciint fman_set_port_params(struct fman *fman, 21258c2ecf20Sopenharmony_ci struct fman_port_init_params *port_params) 21268c2ecf20Sopenharmony_ci{ 21278c2ecf20Sopenharmony_ci int err; 21288c2ecf20Sopenharmony_ci unsigned long flags; 21298c2ecf20Sopenharmony_ci u8 port_id = port_params->port_id, mac_id; 21308c2ecf20Sopenharmony_ci 21318c2ecf20Sopenharmony_ci spin_lock_irqsave(&fman->spinlock, flags); 21328c2ecf20Sopenharmony_ci 21338c2ecf20Sopenharmony_ci err = set_num_of_tasks(fman, port_params->port_id, 21348c2ecf20Sopenharmony_ci &port_params->num_of_tasks, 21358c2ecf20Sopenharmony_ci &port_params->num_of_extra_tasks); 21368c2ecf20Sopenharmony_ci if (err) 21378c2ecf20Sopenharmony_ci goto return_err; 21388c2ecf20Sopenharmony_ci 21398c2ecf20Sopenharmony_ci /* TX Ports */ 21408c2ecf20Sopenharmony_ci if (port_params->port_type != FMAN_PORT_TYPE_RX) { 21418c2ecf20Sopenharmony_ci u32 enq_th, deq_th, reg; 21428c2ecf20Sopenharmony_ci 21438c2ecf20Sopenharmony_ci /* update qmi ENQ/DEQ threshold */ 21448c2ecf20Sopenharmony_ci fman->state->accumulated_num_of_deq_tnums += 21458c2ecf20Sopenharmony_ci port_params->deq_pipeline_depth; 21468c2ecf20Sopenharmony_ci enq_th = (ioread32be(&fman->qmi_regs->fmqm_gc) & 21478c2ecf20Sopenharmony_ci QMI_CFG_ENQ_MASK) >> QMI_CFG_ENQ_SHIFT; 21488c2ecf20Sopenharmony_ci /* if enq_th is too big, we reduce it to the max value 21498c2ecf20Sopenharmony_ci * that is still 0 21508c2ecf20Sopenharmony_ci */ 21518c2ecf20Sopenharmony_ci if (enq_th >= (fman->state->qmi_max_num_of_tnums - 21528c2ecf20Sopenharmony_ci fman->state->accumulated_num_of_deq_tnums)) { 21538c2ecf20Sopenharmony_ci enq_th = 21548c2ecf20Sopenharmony_ci fman->state->qmi_max_num_of_tnums - 21558c2ecf20Sopenharmony_ci fman->state->accumulated_num_of_deq_tnums - 1; 21568c2ecf20Sopenharmony_ci 21578c2ecf20Sopenharmony_ci reg = ioread32be(&fman->qmi_regs->fmqm_gc); 21588c2ecf20Sopenharmony_ci reg &= ~QMI_CFG_ENQ_MASK; 21598c2ecf20Sopenharmony_ci reg |= (enq_th << QMI_CFG_ENQ_SHIFT); 21608c2ecf20Sopenharmony_ci iowrite32be(reg, &fman->qmi_regs->fmqm_gc); 21618c2ecf20Sopenharmony_ci } 21628c2ecf20Sopenharmony_ci 21638c2ecf20Sopenharmony_ci deq_th = ioread32be(&fman->qmi_regs->fmqm_gc) & 21648c2ecf20Sopenharmony_ci QMI_CFG_DEQ_MASK; 21658c2ecf20Sopenharmony_ci /* if deq_th is too small, we enlarge it to the min 21668c2ecf20Sopenharmony_ci * value that is still 0. 21678c2ecf20Sopenharmony_ci * depTh may not be larger than 63 21688c2ecf20Sopenharmony_ci * (fman->state->qmi_max_num_of_tnums-1). 21698c2ecf20Sopenharmony_ci */ 21708c2ecf20Sopenharmony_ci if ((deq_th <= fman->state->accumulated_num_of_deq_tnums) && 21718c2ecf20Sopenharmony_ci (deq_th < fman->state->qmi_max_num_of_tnums - 1)) { 21728c2ecf20Sopenharmony_ci deq_th = fman->state->accumulated_num_of_deq_tnums + 1; 21738c2ecf20Sopenharmony_ci reg = ioread32be(&fman->qmi_regs->fmqm_gc); 21748c2ecf20Sopenharmony_ci reg &= ~QMI_CFG_DEQ_MASK; 21758c2ecf20Sopenharmony_ci reg |= deq_th; 21768c2ecf20Sopenharmony_ci iowrite32be(reg, &fman->qmi_regs->fmqm_gc); 21778c2ecf20Sopenharmony_ci } 21788c2ecf20Sopenharmony_ci } 21798c2ecf20Sopenharmony_ci 21808c2ecf20Sopenharmony_ci err = set_size_of_fifo(fman, port_params->port_id, 21818c2ecf20Sopenharmony_ci &port_params->size_of_fifo, 21828c2ecf20Sopenharmony_ci &port_params->extra_size_of_fifo); 21838c2ecf20Sopenharmony_ci if (err) 21848c2ecf20Sopenharmony_ci goto return_err; 21858c2ecf20Sopenharmony_ci 21868c2ecf20Sopenharmony_ci err = set_num_of_open_dmas(fman, port_params->port_id, 21878c2ecf20Sopenharmony_ci &port_params->num_of_open_dmas, 21888c2ecf20Sopenharmony_ci &port_params->num_of_extra_open_dmas); 21898c2ecf20Sopenharmony_ci if (err) 21908c2ecf20Sopenharmony_ci goto return_err; 21918c2ecf20Sopenharmony_ci 21928c2ecf20Sopenharmony_ci set_port_liodn(fman, port_id, fman->liodn_base[port_id], 21938c2ecf20Sopenharmony_ci fman->liodn_offset[port_id]); 21948c2ecf20Sopenharmony_ci 21958c2ecf20Sopenharmony_ci if (fman->state->rev_info.major < 6) 21968c2ecf20Sopenharmony_ci set_port_order_restoration(fman->fpm_regs, port_id); 21978c2ecf20Sopenharmony_ci 21988c2ecf20Sopenharmony_ci mac_id = hw_port_id_to_sw_port_id(fman->state->rev_info.major, port_id); 21998c2ecf20Sopenharmony_ci 22008c2ecf20Sopenharmony_ci if (port_params->max_frame_length >= fman->state->mac_mfl[mac_id]) { 22018c2ecf20Sopenharmony_ci fman->state->port_mfl[mac_id] = port_params->max_frame_length; 22028c2ecf20Sopenharmony_ci } else { 22038c2ecf20Sopenharmony_ci dev_warn(fman->dev, "%s: Port (%d) max_frame_length is smaller than MAC (%d) current MTU\n", 22048c2ecf20Sopenharmony_ci __func__, port_id, mac_id); 22058c2ecf20Sopenharmony_ci err = -EINVAL; 22068c2ecf20Sopenharmony_ci goto return_err; 22078c2ecf20Sopenharmony_ci } 22088c2ecf20Sopenharmony_ci 22098c2ecf20Sopenharmony_ci spin_unlock_irqrestore(&fman->spinlock, flags); 22108c2ecf20Sopenharmony_ci 22118c2ecf20Sopenharmony_ci return 0; 22128c2ecf20Sopenharmony_ci 22138c2ecf20Sopenharmony_cireturn_err: 22148c2ecf20Sopenharmony_ci spin_unlock_irqrestore(&fman->spinlock, flags); 22158c2ecf20Sopenharmony_ci return err; 22168c2ecf20Sopenharmony_ci} 22178c2ecf20Sopenharmony_ciEXPORT_SYMBOL(fman_set_port_params); 22188c2ecf20Sopenharmony_ci 22198c2ecf20Sopenharmony_ci/** 22208c2ecf20Sopenharmony_ci * fman_reset_mac 22218c2ecf20Sopenharmony_ci * @fman: A Pointer to FMan device 22228c2ecf20Sopenharmony_ci * @mac_id: MAC id to be reset 22238c2ecf20Sopenharmony_ci * 22248c2ecf20Sopenharmony_ci * Reset a specific MAC 22258c2ecf20Sopenharmony_ci * 22268c2ecf20Sopenharmony_ci * Return: 0 on success; Error code otherwise. 22278c2ecf20Sopenharmony_ci */ 22288c2ecf20Sopenharmony_ciint fman_reset_mac(struct fman *fman, u8 mac_id) 22298c2ecf20Sopenharmony_ci{ 22308c2ecf20Sopenharmony_ci struct fman_fpm_regs __iomem *fpm_rg = fman->fpm_regs; 22318c2ecf20Sopenharmony_ci u32 msk, timeout = 100; 22328c2ecf20Sopenharmony_ci 22338c2ecf20Sopenharmony_ci if (fman->state->rev_info.major >= 6) { 22348c2ecf20Sopenharmony_ci dev_err(fman->dev, "%s: FMan MAC reset no available for FMan V3!\n", 22358c2ecf20Sopenharmony_ci __func__); 22368c2ecf20Sopenharmony_ci return -EINVAL; 22378c2ecf20Sopenharmony_ci } 22388c2ecf20Sopenharmony_ci 22398c2ecf20Sopenharmony_ci /* Get the relevant bit mask */ 22408c2ecf20Sopenharmony_ci switch (mac_id) { 22418c2ecf20Sopenharmony_ci case 0: 22428c2ecf20Sopenharmony_ci msk = FPM_RSTC_MAC0_RESET; 22438c2ecf20Sopenharmony_ci break; 22448c2ecf20Sopenharmony_ci case 1: 22458c2ecf20Sopenharmony_ci msk = FPM_RSTC_MAC1_RESET; 22468c2ecf20Sopenharmony_ci break; 22478c2ecf20Sopenharmony_ci case 2: 22488c2ecf20Sopenharmony_ci msk = FPM_RSTC_MAC2_RESET; 22498c2ecf20Sopenharmony_ci break; 22508c2ecf20Sopenharmony_ci case 3: 22518c2ecf20Sopenharmony_ci msk = FPM_RSTC_MAC3_RESET; 22528c2ecf20Sopenharmony_ci break; 22538c2ecf20Sopenharmony_ci case 4: 22548c2ecf20Sopenharmony_ci msk = FPM_RSTC_MAC4_RESET; 22558c2ecf20Sopenharmony_ci break; 22568c2ecf20Sopenharmony_ci case 5: 22578c2ecf20Sopenharmony_ci msk = FPM_RSTC_MAC5_RESET; 22588c2ecf20Sopenharmony_ci break; 22598c2ecf20Sopenharmony_ci case 6: 22608c2ecf20Sopenharmony_ci msk = FPM_RSTC_MAC6_RESET; 22618c2ecf20Sopenharmony_ci break; 22628c2ecf20Sopenharmony_ci case 7: 22638c2ecf20Sopenharmony_ci msk = FPM_RSTC_MAC7_RESET; 22648c2ecf20Sopenharmony_ci break; 22658c2ecf20Sopenharmony_ci case 8: 22668c2ecf20Sopenharmony_ci msk = FPM_RSTC_MAC8_RESET; 22678c2ecf20Sopenharmony_ci break; 22688c2ecf20Sopenharmony_ci case 9: 22698c2ecf20Sopenharmony_ci msk = FPM_RSTC_MAC9_RESET; 22708c2ecf20Sopenharmony_ci break; 22718c2ecf20Sopenharmony_ci default: 22728c2ecf20Sopenharmony_ci dev_warn(fman->dev, "%s: Illegal MAC Id [%d]\n", 22738c2ecf20Sopenharmony_ci __func__, mac_id); 22748c2ecf20Sopenharmony_ci return -EINVAL; 22758c2ecf20Sopenharmony_ci } 22768c2ecf20Sopenharmony_ci 22778c2ecf20Sopenharmony_ci /* reset */ 22788c2ecf20Sopenharmony_ci iowrite32be(msk, &fpm_rg->fm_rstc); 22798c2ecf20Sopenharmony_ci while ((ioread32be(&fpm_rg->fm_rstc) & msk) && --timeout) 22808c2ecf20Sopenharmony_ci udelay(10); 22818c2ecf20Sopenharmony_ci 22828c2ecf20Sopenharmony_ci if (!timeout) 22838c2ecf20Sopenharmony_ci return -EIO; 22848c2ecf20Sopenharmony_ci 22858c2ecf20Sopenharmony_ci return 0; 22868c2ecf20Sopenharmony_ci} 22878c2ecf20Sopenharmony_ciEXPORT_SYMBOL(fman_reset_mac); 22888c2ecf20Sopenharmony_ci 22898c2ecf20Sopenharmony_ci/** 22908c2ecf20Sopenharmony_ci * fman_set_mac_max_frame 22918c2ecf20Sopenharmony_ci * @fman: A Pointer to FMan device 22928c2ecf20Sopenharmony_ci * @mac_id: MAC id 22938c2ecf20Sopenharmony_ci * @mfl: Maximum frame length 22948c2ecf20Sopenharmony_ci * 22958c2ecf20Sopenharmony_ci * Set maximum frame length of specific MAC in FMan driver 22968c2ecf20Sopenharmony_ci * 22978c2ecf20Sopenharmony_ci * Return: 0 on success; Error code otherwise. 22988c2ecf20Sopenharmony_ci */ 22998c2ecf20Sopenharmony_ciint fman_set_mac_max_frame(struct fman *fman, u8 mac_id, u16 mfl) 23008c2ecf20Sopenharmony_ci{ 23018c2ecf20Sopenharmony_ci /* if port is already initialized, check that MaxFrameLength is smaller 23028c2ecf20Sopenharmony_ci * or equal to the port's max 23038c2ecf20Sopenharmony_ci */ 23048c2ecf20Sopenharmony_ci if ((!fman->state->port_mfl[mac_id]) || 23058c2ecf20Sopenharmony_ci (mfl <= fman->state->port_mfl[mac_id])) { 23068c2ecf20Sopenharmony_ci fman->state->mac_mfl[mac_id] = mfl; 23078c2ecf20Sopenharmony_ci } else { 23088c2ecf20Sopenharmony_ci dev_warn(fman->dev, "%s: MAC max_frame_length is larger than Port max_frame_length\n", 23098c2ecf20Sopenharmony_ci __func__); 23108c2ecf20Sopenharmony_ci return -EINVAL; 23118c2ecf20Sopenharmony_ci } 23128c2ecf20Sopenharmony_ci return 0; 23138c2ecf20Sopenharmony_ci} 23148c2ecf20Sopenharmony_ciEXPORT_SYMBOL(fman_set_mac_max_frame); 23158c2ecf20Sopenharmony_ci 23168c2ecf20Sopenharmony_ci/** 23178c2ecf20Sopenharmony_ci * fman_get_clock_freq 23188c2ecf20Sopenharmony_ci * @fman: A Pointer to FMan device 23198c2ecf20Sopenharmony_ci * 23208c2ecf20Sopenharmony_ci * Get FMan clock frequency 23218c2ecf20Sopenharmony_ci * 23228c2ecf20Sopenharmony_ci * Return: FMan clock frequency 23238c2ecf20Sopenharmony_ci */ 23248c2ecf20Sopenharmony_ciu16 fman_get_clock_freq(struct fman *fman) 23258c2ecf20Sopenharmony_ci{ 23268c2ecf20Sopenharmony_ci return fman->state->fm_clk_freq; 23278c2ecf20Sopenharmony_ci} 23288c2ecf20Sopenharmony_ci 23298c2ecf20Sopenharmony_ci/** 23308c2ecf20Sopenharmony_ci * fman_get_bmi_max_fifo_size 23318c2ecf20Sopenharmony_ci * @fman: A Pointer to FMan device 23328c2ecf20Sopenharmony_ci * 23338c2ecf20Sopenharmony_ci * Get FMan maximum FIFO size 23348c2ecf20Sopenharmony_ci * 23358c2ecf20Sopenharmony_ci * Return: FMan Maximum FIFO size 23368c2ecf20Sopenharmony_ci */ 23378c2ecf20Sopenharmony_ciu32 fman_get_bmi_max_fifo_size(struct fman *fman) 23388c2ecf20Sopenharmony_ci{ 23398c2ecf20Sopenharmony_ci return fman->state->bmi_max_fifo_size; 23408c2ecf20Sopenharmony_ci} 23418c2ecf20Sopenharmony_ciEXPORT_SYMBOL(fman_get_bmi_max_fifo_size); 23428c2ecf20Sopenharmony_ci 23438c2ecf20Sopenharmony_ci/** 23448c2ecf20Sopenharmony_ci * fman_get_revision 23458c2ecf20Sopenharmony_ci * @fman: - Pointer to the FMan module 23468c2ecf20Sopenharmony_ci * @rev_info: - A structure of revision information parameters. 23478c2ecf20Sopenharmony_ci * 23488c2ecf20Sopenharmony_ci * Returns the FM revision 23498c2ecf20Sopenharmony_ci * 23508c2ecf20Sopenharmony_ci * Allowed only following fman_init(). 23518c2ecf20Sopenharmony_ci * 23528c2ecf20Sopenharmony_ci * Return: 0 on success; Error code otherwise. 23538c2ecf20Sopenharmony_ci */ 23548c2ecf20Sopenharmony_civoid fman_get_revision(struct fman *fman, struct fman_rev_info *rev_info) 23558c2ecf20Sopenharmony_ci{ 23568c2ecf20Sopenharmony_ci u32 tmp; 23578c2ecf20Sopenharmony_ci 23588c2ecf20Sopenharmony_ci tmp = ioread32be(&fman->fpm_regs->fm_ip_rev_1); 23598c2ecf20Sopenharmony_ci rev_info->major = (u8)((tmp & FPM_REV1_MAJOR_MASK) >> 23608c2ecf20Sopenharmony_ci FPM_REV1_MAJOR_SHIFT); 23618c2ecf20Sopenharmony_ci rev_info->minor = tmp & FPM_REV1_MINOR_MASK; 23628c2ecf20Sopenharmony_ci} 23638c2ecf20Sopenharmony_ciEXPORT_SYMBOL(fman_get_revision); 23648c2ecf20Sopenharmony_ci 23658c2ecf20Sopenharmony_ci/** 23668c2ecf20Sopenharmony_ci * fman_get_qman_channel_id 23678c2ecf20Sopenharmony_ci * @fman: A Pointer to FMan device 23688c2ecf20Sopenharmony_ci * @port_id: Port id 23698c2ecf20Sopenharmony_ci * 23708c2ecf20Sopenharmony_ci * Get QMan channel ID associated to the Port id 23718c2ecf20Sopenharmony_ci * 23728c2ecf20Sopenharmony_ci * Return: QMan channel ID 23738c2ecf20Sopenharmony_ci */ 23748c2ecf20Sopenharmony_ciu32 fman_get_qman_channel_id(struct fman *fman, u32 port_id) 23758c2ecf20Sopenharmony_ci{ 23768c2ecf20Sopenharmony_ci int i; 23778c2ecf20Sopenharmony_ci 23788c2ecf20Sopenharmony_ci if (fman->state->rev_info.major >= 6) { 23798c2ecf20Sopenharmony_ci static const u32 port_ids[] = { 23808c2ecf20Sopenharmony_ci 0x30, 0x31, 0x28, 0x29, 0x2a, 0x2b, 23818c2ecf20Sopenharmony_ci 0x2c, 0x2d, 0x2, 0x3, 0x4, 0x5, 0x7, 0x7 23828c2ecf20Sopenharmony_ci }; 23838c2ecf20Sopenharmony_ci 23848c2ecf20Sopenharmony_ci for (i = 0; i < fman->state->num_of_qman_channels; i++) { 23858c2ecf20Sopenharmony_ci if (port_ids[i] == port_id) 23868c2ecf20Sopenharmony_ci break; 23878c2ecf20Sopenharmony_ci } 23888c2ecf20Sopenharmony_ci } else { 23898c2ecf20Sopenharmony_ci static const u32 port_ids[] = { 23908c2ecf20Sopenharmony_ci 0x30, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x1, 23918c2ecf20Sopenharmony_ci 0x2, 0x3, 0x4, 0x5, 0x7, 0x7 23928c2ecf20Sopenharmony_ci }; 23938c2ecf20Sopenharmony_ci 23948c2ecf20Sopenharmony_ci for (i = 0; i < fman->state->num_of_qman_channels; i++) { 23958c2ecf20Sopenharmony_ci if (port_ids[i] == port_id) 23968c2ecf20Sopenharmony_ci break; 23978c2ecf20Sopenharmony_ci } 23988c2ecf20Sopenharmony_ci } 23998c2ecf20Sopenharmony_ci 24008c2ecf20Sopenharmony_ci if (i == fman->state->num_of_qman_channels) 24018c2ecf20Sopenharmony_ci return 0; 24028c2ecf20Sopenharmony_ci 24038c2ecf20Sopenharmony_ci return fman->state->qman_channel_base + i; 24048c2ecf20Sopenharmony_ci} 24058c2ecf20Sopenharmony_ciEXPORT_SYMBOL(fman_get_qman_channel_id); 24068c2ecf20Sopenharmony_ci 24078c2ecf20Sopenharmony_ci/** 24088c2ecf20Sopenharmony_ci * fman_get_mem_region 24098c2ecf20Sopenharmony_ci * @fman: A Pointer to FMan device 24108c2ecf20Sopenharmony_ci * 24118c2ecf20Sopenharmony_ci * Get FMan memory region 24128c2ecf20Sopenharmony_ci * 24138c2ecf20Sopenharmony_ci * Return: A structure with FMan memory region information 24148c2ecf20Sopenharmony_ci */ 24158c2ecf20Sopenharmony_cistruct resource *fman_get_mem_region(struct fman *fman) 24168c2ecf20Sopenharmony_ci{ 24178c2ecf20Sopenharmony_ci return fman->state->res; 24188c2ecf20Sopenharmony_ci} 24198c2ecf20Sopenharmony_ciEXPORT_SYMBOL(fman_get_mem_region); 24208c2ecf20Sopenharmony_ci 24218c2ecf20Sopenharmony_ci/* Bootargs defines */ 24228c2ecf20Sopenharmony_ci/* Extra headroom for RX buffers - Default, min and max */ 24238c2ecf20Sopenharmony_ci#define FSL_FM_RX_EXTRA_HEADROOM 64 24248c2ecf20Sopenharmony_ci#define FSL_FM_RX_EXTRA_HEADROOM_MIN 16 24258c2ecf20Sopenharmony_ci#define FSL_FM_RX_EXTRA_HEADROOM_MAX 384 24268c2ecf20Sopenharmony_ci 24278c2ecf20Sopenharmony_ci/* Maximum frame length */ 24288c2ecf20Sopenharmony_ci#define FSL_FM_MAX_FRAME_SIZE 1522 24298c2ecf20Sopenharmony_ci#define FSL_FM_MAX_POSSIBLE_FRAME_SIZE 9600 24308c2ecf20Sopenharmony_ci#define FSL_FM_MIN_POSSIBLE_FRAME_SIZE 64 24318c2ecf20Sopenharmony_ci 24328c2ecf20Sopenharmony_ci/* Extra headroom for Rx buffers. 24338c2ecf20Sopenharmony_ci * FMan is instructed to allocate, on the Rx path, this amount of 24348c2ecf20Sopenharmony_ci * space at the beginning of a data buffer, beside the DPA private 24358c2ecf20Sopenharmony_ci * data area and the IC fields. 24368c2ecf20Sopenharmony_ci * Does not impact Tx buffer layout. 24378c2ecf20Sopenharmony_ci * Configurable from bootargs. 64 by default, it's needed on 24388c2ecf20Sopenharmony_ci * particular forwarding scenarios that add extra headers to the 24398c2ecf20Sopenharmony_ci * forwarded frame. 24408c2ecf20Sopenharmony_ci */ 24418c2ecf20Sopenharmony_cistatic int fsl_fm_rx_extra_headroom = FSL_FM_RX_EXTRA_HEADROOM; 24428c2ecf20Sopenharmony_cimodule_param(fsl_fm_rx_extra_headroom, int, 0); 24438c2ecf20Sopenharmony_ciMODULE_PARM_DESC(fsl_fm_rx_extra_headroom, "Extra headroom for Rx buffers"); 24448c2ecf20Sopenharmony_ci 24458c2ecf20Sopenharmony_ci/* Max frame size, across all interfaces. 24468c2ecf20Sopenharmony_ci * Configurable from bootargs, to avoid allocating oversized (socket) 24478c2ecf20Sopenharmony_ci * buffers when not using jumbo frames. 24488c2ecf20Sopenharmony_ci * Must be large enough to accommodate the network MTU, but small enough 24498c2ecf20Sopenharmony_ci * to avoid wasting skb memory. 24508c2ecf20Sopenharmony_ci */ 24518c2ecf20Sopenharmony_cistatic int fsl_fm_max_frm = FSL_FM_MAX_FRAME_SIZE; 24528c2ecf20Sopenharmony_cimodule_param(fsl_fm_max_frm, int, 0); 24538c2ecf20Sopenharmony_ciMODULE_PARM_DESC(fsl_fm_max_frm, "Maximum frame size, across all interfaces"); 24548c2ecf20Sopenharmony_ci 24558c2ecf20Sopenharmony_ci/** 24568c2ecf20Sopenharmony_ci * fman_get_max_frm 24578c2ecf20Sopenharmony_ci * 24588c2ecf20Sopenharmony_ci * Return: Max frame length configured in the FM driver 24598c2ecf20Sopenharmony_ci */ 24608c2ecf20Sopenharmony_ciu16 fman_get_max_frm(void) 24618c2ecf20Sopenharmony_ci{ 24628c2ecf20Sopenharmony_ci static bool fm_check_mfl; 24638c2ecf20Sopenharmony_ci 24648c2ecf20Sopenharmony_ci if (!fm_check_mfl) { 24658c2ecf20Sopenharmony_ci if (fsl_fm_max_frm > FSL_FM_MAX_POSSIBLE_FRAME_SIZE || 24668c2ecf20Sopenharmony_ci fsl_fm_max_frm < FSL_FM_MIN_POSSIBLE_FRAME_SIZE) { 24678c2ecf20Sopenharmony_ci pr_warn("Invalid fsl_fm_max_frm value (%d) in bootargs, valid range is %d-%d. Falling back to the default (%d)\n", 24688c2ecf20Sopenharmony_ci fsl_fm_max_frm, 24698c2ecf20Sopenharmony_ci FSL_FM_MIN_POSSIBLE_FRAME_SIZE, 24708c2ecf20Sopenharmony_ci FSL_FM_MAX_POSSIBLE_FRAME_SIZE, 24718c2ecf20Sopenharmony_ci FSL_FM_MAX_FRAME_SIZE); 24728c2ecf20Sopenharmony_ci fsl_fm_max_frm = FSL_FM_MAX_FRAME_SIZE; 24738c2ecf20Sopenharmony_ci } 24748c2ecf20Sopenharmony_ci fm_check_mfl = true; 24758c2ecf20Sopenharmony_ci } 24768c2ecf20Sopenharmony_ci 24778c2ecf20Sopenharmony_ci return fsl_fm_max_frm; 24788c2ecf20Sopenharmony_ci} 24798c2ecf20Sopenharmony_ciEXPORT_SYMBOL(fman_get_max_frm); 24808c2ecf20Sopenharmony_ci 24818c2ecf20Sopenharmony_ci/** 24828c2ecf20Sopenharmony_ci * fman_get_rx_extra_headroom 24838c2ecf20Sopenharmony_ci * 24848c2ecf20Sopenharmony_ci * Return: Extra headroom size configured in the FM driver 24858c2ecf20Sopenharmony_ci */ 24868c2ecf20Sopenharmony_ciint fman_get_rx_extra_headroom(void) 24878c2ecf20Sopenharmony_ci{ 24888c2ecf20Sopenharmony_ci static bool fm_check_rx_extra_headroom; 24898c2ecf20Sopenharmony_ci 24908c2ecf20Sopenharmony_ci if (!fm_check_rx_extra_headroom) { 24918c2ecf20Sopenharmony_ci if (fsl_fm_rx_extra_headroom > FSL_FM_RX_EXTRA_HEADROOM_MAX || 24928c2ecf20Sopenharmony_ci fsl_fm_rx_extra_headroom < FSL_FM_RX_EXTRA_HEADROOM_MIN) { 24938c2ecf20Sopenharmony_ci pr_warn("Invalid fsl_fm_rx_extra_headroom value (%d) in bootargs, valid range is %d-%d. Falling back to the default (%d)\n", 24948c2ecf20Sopenharmony_ci fsl_fm_rx_extra_headroom, 24958c2ecf20Sopenharmony_ci FSL_FM_RX_EXTRA_HEADROOM_MIN, 24968c2ecf20Sopenharmony_ci FSL_FM_RX_EXTRA_HEADROOM_MAX, 24978c2ecf20Sopenharmony_ci FSL_FM_RX_EXTRA_HEADROOM); 24988c2ecf20Sopenharmony_ci fsl_fm_rx_extra_headroom = FSL_FM_RX_EXTRA_HEADROOM; 24998c2ecf20Sopenharmony_ci } 25008c2ecf20Sopenharmony_ci 25018c2ecf20Sopenharmony_ci fm_check_rx_extra_headroom = true; 25028c2ecf20Sopenharmony_ci fsl_fm_rx_extra_headroom = ALIGN(fsl_fm_rx_extra_headroom, 16); 25038c2ecf20Sopenharmony_ci } 25048c2ecf20Sopenharmony_ci 25058c2ecf20Sopenharmony_ci return fsl_fm_rx_extra_headroom; 25068c2ecf20Sopenharmony_ci} 25078c2ecf20Sopenharmony_ciEXPORT_SYMBOL(fman_get_rx_extra_headroom); 25088c2ecf20Sopenharmony_ci 25098c2ecf20Sopenharmony_ci/** 25108c2ecf20Sopenharmony_ci * fman_bind 25118c2ecf20Sopenharmony_ci * @fm_dev: FMan OF device pointer 25128c2ecf20Sopenharmony_ci * 25138c2ecf20Sopenharmony_ci * Bind to a specific FMan device. 25148c2ecf20Sopenharmony_ci * 25158c2ecf20Sopenharmony_ci * Allowed only after the port was created. 25168c2ecf20Sopenharmony_ci * 25178c2ecf20Sopenharmony_ci * Return: A pointer to the FMan device 25188c2ecf20Sopenharmony_ci */ 25198c2ecf20Sopenharmony_cistruct fman *fman_bind(struct device *fm_dev) 25208c2ecf20Sopenharmony_ci{ 25218c2ecf20Sopenharmony_ci return (struct fman *)(dev_get_drvdata(get_device(fm_dev))); 25228c2ecf20Sopenharmony_ci} 25238c2ecf20Sopenharmony_ciEXPORT_SYMBOL(fman_bind); 25248c2ecf20Sopenharmony_ci 25258c2ecf20Sopenharmony_ci#ifdef CONFIG_DPAA_ERRATUM_A050385 25268c2ecf20Sopenharmony_cibool fman_has_errata_a050385(void) 25278c2ecf20Sopenharmony_ci{ 25288c2ecf20Sopenharmony_ci return fman_has_err_a050385; 25298c2ecf20Sopenharmony_ci} 25308c2ecf20Sopenharmony_ciEXPORT_SYMBOL(fman_has_errata_a050385); 25318c2ecf20Sopenharmony_ci#endif 25328c2ecf20Sopenharmony_ci 25338c2ecf20Sopenharmony_cistatic irqreturn_t fman_err_irq(int irq, void *handle) 25348c2ecf20Sopenharmony_ci{ 25358c2ecf20Sopenharmony_ci struct fman *fman = (struct fman *)handle; 25368c2ecf20Sopenharmony_ci u32 pending; 25378c2ecf20Sopenharmony_ci struct fman_fpm_regs __iomem *fpm_rg; 25388c2ecf20Sopenharmony_ci irqreturn_t single_ret, ret = IRQ_NONE; 25398c2ecf20Sopenharmony_ci 25408c2ecf20Sopenharmony_ci if (!is_init_done(fman->cfg)) 25418c2ecf20Sopenharmony_ci return IRQ_NONE; 25428c2ecf20Sopenharmony_ci 25438c2ecf20Sopenharmony_ci fpm_rg = fman->fpm_regs; 25448c2ecf20Sopenharmony_ci 25458c2ecf20Sopenharmony_ci /* error interrupts */ 25468c2ecf20Sopenharmony_ci pending = ioread32be(&fpm_rg->fm_epi); 25478c2ecf20Sopenharmony_ci if (!pending) 25488c2ecf20Sopenharmony_ci return IRQ_NONE; 25498c2ecf20Sopenharmony_ci 25508c2ecf20Sopenharmony_ci if (pending & ERR_INTR_EN_BMI) { 25518c2ecf20Sopenharmony_ci single_ret = bmi_err_event(fman); 25528c2ecf20Sopenharmony_ci if (single_ret == IRQ_HANDLED) 25538c2ecf20Sopenharmony_ci ret = IRQ_HANDLED; 25548c2ecf20Sopenharmony_ci } 25558c2ecf20Sopenharmony_ci if (pending & ERR_INTR_EN_QMI) { 25568c2ecf20Sopenharmony_ci single_ret = qmi_err_event(fman); 25578c2ecf20Sopenharmony_ci if (single_ret == IRQ_HANDLED) 25588c2ecf20Sopenharmony_ci ret = IRQ_HANDLED; 25598c2ecf20Sopenharmony_ci } 25608c2ecf20Sopenharmony_ci if (pending & ERR_INTR_EN_FPM) { 25618c2ecf20Sopenharmony_ci single_ret = fpm_err_event(fman); 25628c2ecf20Sopenharmony_ci if (single_ret == IRQ_HANDLED) 25638c2ecf20Sopenharmony_ci ret = IRQ_HANDLED; 25648c2ecf20Sopenharmony_ci } 25658c2ecf20Sopenharmony_ci if (pending & ERR_INTR_EN_DMA) { 25668c2ecf20Sopenharmony_ci single_ret = dma_err_event(fman); 25678c2ecf20Sopenharmony_ci if (single_ret == IRQ_HANDLED) 25688c2ecf20Sopenharmony_ci ret = IRQ_HANDLED; 25698c2ecf20Sopenharmony_ci } 25708c2ecf20Sopenharmony_ci if (pending & ERR_INTR_EN_MURAM) { 25718c2ecf20Sopenharmony_ci single_ret = muram_err_intr(fman); 25728c2ecf20Sopenharmony_ci if (single_ret == IRQ_HANDLED) 25738c2ecf20Sopenharmony_ci ret = IRQ_HANDLED; 25748c2ecf20Sopenharmony_ci } 25758c2ecf20Sopenharmony_ci 25768c2ecf20Sopenharmony_ci /* MAC error interrupts */ 25778c2ecf20Sopenharmony_ci if (pending & ERR_INTR_EN_MAC0) { 25788c2ecf20Sopenharmony_ci single_ret = call_mac_isr(fman, FMAN_EV_ERR_MAC0 + 0); 25798c2ecf20Sopenharmony_ci if (single_ret == IRQ_HANDLED) 25808c2ecf20Sopenharmony_ci ret = IRQ_HANDLED; 25818c2ecf20Sopenharmony_ci } 25828c2ecf20Sopenharmony_ci if (pending & ERR_INTR_EN_MAC1) { 25838c2ecf20Sopenharmony_ci single_ret = call_mac_isr(fman, FMAN_EV_ERR_MAC0 + 1); 25848c2ecf20Sopenharmony_ci if (single_ret == IRQ_HANDLED) 25858c2ecf20Sopenharmony_ci ret = IRQ_HANDLED; 25868c2ecf20Sopenharmony_ci } 25878c2ecf20Sopenharmony_ci if (pending & ERR_INTR_EN_MAC2) { 25888c2ecf20Sopenharmony_ci single_ret = call_mac_isr(fman, FMAN_EV_ERR_MAC0 + 2); 25898c2ecf20Sopenharmony_ci if (single_ret == IRQ_HANDLED) 25908c2ecf20Sopenharmony_ci ret = IRQ_HANDLED; 25918c2ecf20Sopenharmony_ci } 25928c2ecf20Sopenharmony_ci if (pending & ERR_INTR_EN_MAC3) { 25938c2ecf20Sopenharmony_ci single_ret = call_mac_isr(fman, FMAN_EV_ERR_MAC0 + 3); 25948c2ecf20Sopenharmony_ci if (single_ret == IRQ_HANDLED) 25958c2ecf20Sopenharmony_ci ret = IRQ_HANDLED; 25968c2ecf20Sopenharmony_ci } 25978c2ecf20Sopenharmony_ci if (pending & ERR_INTR_EN_MAC4) { 25988c2ecf20Sopenharmony_ci single_ret = call_mac_isr(fman, FMAN_EV_ERR_MAC0 + 4); 25998c2ecf20Sopenharmony_ci if (single_ret == IRQ_HANDLED) 26008c2ecf20Sopenharmony_ci ret = IRQ_HANDLED; 26018c2ecf20Sopenharmony_ci } 26028c2ecf20Sopenharmony_ci if (pending & ERR_INTR_EN_MAC5) { 26038c2ecf20Sopenharmony_ci single_ret = call_mac_isr(fman, FMAN_EV_ERR_MAC0 + 5); 26048c2ecf20Sopenharmony_ci if (single_ret == IRQ_HANDLED) 26058c2ecf20Sopenharmony_ci ret = IRQ_HANDLED; 26068c2ecf20Sopenharmony_ci } 26078c2ecf20Sopenharmony_ci if (pending & ERR_INTR_EN_MAC6) { 26088c2ecf20Sopenharmony_ci single_ret = call_mac_isr(fman, FMAN_EV_ERR_MAC0 + 6); 26098c2ecf20Sopenharmony_ci if (single_ret == IRQ_HANDLED) 26108c2ecf20Sopenharmony_ci ret = IRQ_HANDLED; 26118c2ecf20Sopenharmony_ci } 26128c2ecf20Sopenharmony_ci if (pending & ERR_INTR_EN_MAC7) { 26138c2ecf20Sopenharmony_ci single_ret = call_mac_isr(fman, FMAN_EV_ERR_MAC0 + 7); 26148c2ecf20Sopenharmony_ci if (single_ret == IRQ_HANDLED) 26158c2ecf20Sopenharmony_ci ret = IRQ_HANDLED; 26168c2ecf20Sopenharmony_ci } 26178c2ecf20Sopenharmony_ci if (pending & ERR_INTR_EN_MAC8) { 26188c2ecf20Sopenharmony_ci single_ret = call_mac_isr(fman, FMAN_EV_ERR_MAC0 + 8); 26198c2ecf20Sopenharmony_ci if (single_ret == IRQ_HANDLED) 26208c2ecf20Sopenharmony_ci ret = IRQ_HANDLED; 26218c2ecf20Sopenharmony_ci } 26228c2ecf20Sopenharmony_ci if (pending & ERR_INTR_EN_MAC9) { 26238c2ecf20Sopenharmony_ci single_ret = call_mac_isr(fman, FMAN_EV_ERR_MAC0 + 9); 26248c2ecf20Sopenharmony_ci if (single_ret == IRQ_HANDLED) 26258c2ecf20Sopenharmony_ci ret = IRQ_HANDLED; 26268c2ecf20Sopenharmony_ci } 26278c2ecf20Sopenharmony_ci 26288c2ecf20Sopenharmony_ci return ret; 26298c2ecf20Sopenharmony_ci} 26308c2ecf20Sopenharmony_ci 26318c2ecf20Sopenharmony_cistatic irqreturn_t fman_irq(int irq, void *handle) 26328c2ecf20Sopenharmony_ci{ 26338c2ecf20Sopenharmony_ci struct fman *fman = (struct fman *)handle; 26348c2ecf20Sopenharmony_ci u32 pending; 26358c2ecf20Sopenharmony_ci struct fman_fpm_regs __iomem *fpm_rg; 26368c2ecf20Sopenharmony_ci irqreturn_t single_ret, ret = IRQ_NONE; 26378c2ecf20Sopenharmony_ci 26388c2ecf20Sopenharmony_ci if (!is_init_done(fman->cfg)) 26398c2ecf20Sopenharmony_ci return IRQ_NONE; 26408c2ecf20Sopenharmony_ci 26418c2ecf20Sopenharmony_ci fpm_rg = fman->fpm_regs; 26428c2ecf20Sopenharmony_ci 26438c2ecf20Sopenharmony_ci /* normal interrupts */ 26448c2ecf20Sopenharmony_ci pending = ioread32be(&fpm_rg->fm_npi); 26458c2ecf20Sopenharmony_ci if (!pending) 26468c2ecf20Sopenharmony_ci return IRQ_NONE; 26478c2ecf20Sopenharmony_ci 26488c2ecf20Sopenharmony_ci if (pending & INTR_EN_QMI) { 26498c2ecf20Sopenharmony_ci single_ret = qmi_event(fman); 26508c2ecf20Sopenharmony_ci if (single_ret == IRQ_HANDLED) 26518c2ecf20Sopenharmony_ci ret = IRQ_HANDLED; 26528c2ecf20Sopenharmony_ci } 26538c2ecf20Sopenharmony_ci 26548c2ecf20Sopenharmony_ci /* MAC interrupts */ 26558c2ecf20Sopenharmony_ci if (pending & INTR_EN_MAC0) { 26568c2ecf20Sopenharmony_ci single_ret = call_mac_isr(fman, FMAN_EV_MAC0 + 0); 26578c2ecf20Sopenharmony_ci if (single_ret == IRQ_HANDLED) 26588c2ecf20Sopenharmony_ci ret = IRQ_HANDLED; 26598c2ecf20Sopenharmony_ci } 26608c2ecf20Sopenharmony_ci if (pending & INTR_EN_MAC1) { 26618c2ecf20Sopenharmony_ci single_ret = call_mac_isr(fman, FMAN_EV_MAC0 + 1); 26628c2ecf20Sopenharmony_ci if (single_ret == IRQ_HANDLED) 26638c2ecf20Sopenharmony_ci ret = IRQ_HANDLED; 26648c2ecf20Sopenharmony_ci } 26658c2ecf20Sopenharmony_ci if (pending & INTR_EN_MAC2) { 26668c2ecf20Sopenharmony_ci single_ret = call_mac_isr(fman, FMAN_EV_MAC0 + 2); 26678c2ecf20Sopenharmony_ci if (single_ret == IRQ_HANDLED) 26688c2ecf20Sopenharmony_ci ret = IRQ_HANDLED; 26698c2ecf20Sopenharmony_ci } 26708c2ecf20Sopenharmony_ci if (pending & INTR_EN_MAC3) { 26718c2ecf20Sopenharmony_ci single_ret = call_mac_isr(fman, FMAN_EV_MAC0 + 3); 26728c2ecf20Sopenharmony_ci if (single_ret == IRQ_HANDLED) 26738c2ecf20Sopenharmony_ci ret = IRQ_HANDLED; 26748c2ecf20Sopenharmony_ci } 26758c2ecf20Sopenharmony_ci if (pending & INTR_EN_MAC4) { 26768c2ecf20Sopenharmony_ci single_ret = call_mac_isr(fman, FMAN_EV_MAC0 + 4); 26778c2ecf20Sopenharmony_ci if (single_ret == IRQ_HANDLED) 26788c2ecf20Sopenharmony_ci ret = IRQ_HANDLED; 26798c2ecf20Sopenharmony_ci } 26808c2ecf20Sopenharmony_ci if (pending & INTR_EN_MAC5) { 26818c2ecf20Sopenharmony_ci single_ret = call_mac_isr(fman, FMAN_EV_MAC0 + 5); 26828c2ecf20Sopenharmony_ci if (single_ret == IRQ_HANDLED) 26838c2ecf20Sopenharmony_ci ret = IRQ_HANDLED; 26848c2ecf20Sopenharmony_ci } 26858c2ecf20Sopenharmony_ci if (pending & INTR_EN_MAC6) { 26868c2ecf20Sopenharmony_ci single_ret = call_mac_isr(fman, FMAN_EV_MAC0 + 6); 26878c2ecf20Sopenharmony_ci if (single_ret == IRQ_HANDLED) 26888c2ecf20Sopenharmony_ci ret = IRQ_HANDLED; 26898c2ecf20Sopenharmony_ci } 26908c2ecf20Sopenharmony_ci if (pending & INTR_EN_MAC7) { 26918c2ecf20Sopenharmony_ci single_ret = call_mac_isr(fman, FMAN_EV_MAC0 + 7); 26928c2ecf20Sopenharmony_ci if (single_ret == IRQ_HANDLED) 26938c2ecf20Sopenharmony_ci ret = IRQ_HANDLED; 26948c2ecf20Sopenharmony_ci } 26958c2ecf20Sopenharmony_ci if (pending & INTR_EN_MAC8) { 26968c2ecf20Sopenharmony_ci single_ret = call_mac_isr(fman, FMAN_EV_MAC0 + 8); 26978c2ecf20Sopenharmony_ci if (single_ret == IRQ_HANDLED) 26988c2ecf20Sopenharmony_ci ret = IRQ_HANDLED; 26998c2ecf20Sopenharmony_ci } 27008c2ecf20Sopenharmony_ci if (pending & INTR_EN_MAC9) { 27018c2ecf20Sopenharmony_ci single_ret = call_mac_isr(fman, FMAN_EV_MAC0 + 9); 27028c2ecf20Sopenharmony_ci if (single_ret == IRQ_HANDLED) 27038c2ecf20Sopenharmony_ci ret = IRQ_HANDLED; 27048c2ecf20Sopenharmony_ci } 27058c2ecf20Sopenharmony_ci 27068c2ecf20Sopenharmony_ci return ret; 27078c2ecf20Sopenharmony_ci} 27088c2ecf20Sopenharmony_ci 27098c2ecf20Sopenharmony_cistatic const struct of_device_id fman_muram_match[] = { 27108c2ecf20Sopenharmony_ci { 27118c2ecf20Sopenharmony_ci .compatible = "fsl,fman-muram"}, 27128c2ecf20Sopenharmony_ci {} 27138c2ecf20Sopenharmony_ci}; 27148c2ecf20Sopenharmony_ciMODULE_DEVICE_TABLE(of, fman_muram_match); 27158c2ecf20Sopenharmony_ci 27168c2ecf20Sopenharmony_cistatic struct fman *read_dts_node(struct platform_device *of_dev) 27178c2ecf20Sopenharmony_ci{ 27188c2ecf20Sopenharmony_ci struct fman *fman; 27198c2ecf20Sopenharmony_ci struct device_node *fm_node, *muram_node; 27208c2ecf20Sopenharmony_ci struct resource *res; 27218c2ecf20Sopenharmony_ci u32 val, range[2]; 27228c2ecf20Sopenharmony_ci int err, irq; 27238c2ecf20Sopenharmony_ci struct clk *clk; 27248c2ecf20Sopenharmony_ci u32 clk_rate; 27258c2ecf20Sopenharmony_ci phys_addr_t phys_base_addr; 27268c2ecf20Sopenharmony_ci resource_size_t mem_size; 27278c2ecf20Sopenharmony_ci 27288c2ecf20Sopenharmony_ci fman = kzalloc(sizeof(*fman), GFP_KERNEL); 27298c2ecf20Sopenharmony_ci if (!fman) 27308c2ecf20Sopenharmony_ci return NULL; 27318c2ecf20Sopenharmony_ci 27328c2ecf20Sopenharmony_ci fm_node = of_node_get(of_dev->dev.of_node); 27338c2ecf20Sopenharmony_ci 27348c2ecf20Sopenharmony_ci err = of_property_read_u32(fm_node, "cell-index", &val); 27358c2ecf20Sopenharmony_ci if (err) { 27368c2ecf20Sopenharmony_ci dev_err(&of_dev->dev, "%s: failed to read cell-index for %pOF\n", 27378c2ecf20Sopenharmony_ci __func__, fm_node); 27388c2ecf20Sopenharmony_ci goto fman_node_put; 27398c2ecf20Sopenharmony_ci } 27408c2ecf20Sopenharmony_ci fman->dts_params.id = (u8)val; 27418c2ecf20Sopenharmony_ci 27428c2ecf20Sopenharmony_ci /* Get the FM interrupt */ 27438c2ecf20Sopenharmony_ci res = platform_get_resource(of_dev, IORESOURCE_IRQ, 0); 27448c2ecf20Sopenharmony_ci if (!res) { 27458c2ecf20Sopenharmony_ci dev_err(&of_dev->dev, "%s: Can't get FMan IRQ resource\n", 27468c2ecf20Sopenharmony_ci __func__); 27478c2ecf20Sopenharmony_ci goto fman_node_put; 27488c2ecf20Sopenharmony_ci } 27498c2ecf20Sopenharmony_ci irq = res->start; 27508c2ecf20Sopenharmony_ci 27518c2ecf20Sopenharmony_ci /* Get the FM error interrupt */ 27528c2ecf20Sopenharmony_ci res = platform_get_resource(of_dev, IORESOURCE_IRQ, 1); 27538c2ecf20Sopenharmony_ci if (!res) { 27548c2ecf20Sopenharmony_ci dev_err(&of_dev->dev, "%s: Can't get FMan Error IRQ resource\n", 27558c2ecf20Sopenharmony_ci __func__); 27568c2ecf20Sopenharmony_ci goto fman_node_put; 27578c2ecf20Sopenharmony_ci } 27588c2ecf20Sopenharmony_ci fman->dts_params.err_irq = res->start; 27598c2ecf20Sopenharmony_ci 27608c2ecf20Sopenharmony_ci /* Get the FM address */ 27618c2ecf20Sopenharmony_ci res = platform_get_resource(of_dev, IORESOURCE_MEM, 0); 27628c2ecf20Sopenharmony_ci if (!res) { 27638c2ecf20Sopenharmony_ci dev_err(&of_dev->dev, "%s: Can't get FMan memory resource\n", 27648c2ecf20Sopenharmony_ci __func__); 27658c2ecf20Sopenharmony_ci goto fman_node_put; 27668c2ecf20Sopenharmony_ci } 27678c2ecf20Sopenharmony_ci 27688c2ecf20Sopenharmony_ci phys_base_addr = res->start; 27698c2ecf20Sopenharmony_ci mem_size = resource_size(res); 27708c2ecf20Sopenharmony_ci 27718c2ecf20Sopenharmony_ci clk = of_clk_get(fm_node, 0); 27728c2ecf20Sopenharmony_ci if (IS_ERR(clk)) { 27738c2ecf20Sopenharmony_ci dev_err(&of_dev->dev, "%s: Failed to get FM%d clock structure\n", 27748c2ecf20Sopenharmony_ci __func__, fman->dts_params.id); 27758c2ecf20Sopenharmony_ci goto fman_node_put; 27768c2ecf20Sopenharmony_ci } 27778c2ecf20Sopenharmony_ci 27788c2ecf20Sopenharmony_ci clk_rate = clk_get_rate(clk); 27798c2ecf20Sopenharmony_ci if (!clk_rate) { 27808c2ecf20Sopenharmony_ci dev_err(&of_dev->dev, "%s: Failed to determine FM%d clock rate\n", 27818c2ecf20Sopenharmony_ci __func__, fman->dts_params.id); 27828c2ecf20Sopenharmony_ci goto fman_node_put; 27838c2ecf20Sopenharmony_ci } 27848c2ecf20Sopenharmony_ci /* Rounding to MHz */ 27858c2ecf20Sopenharmony_ci fman->dts_params.clk_freq = DIV_ROUND_UP(clk_rate, 1000000); 27868c2ecf20Sopenharmony_ci 27878c2ecf20Sopenharmony_ci err = of_property_read_u32_array(fm_node, "fsl,qman-channel-range", 27888c2ecf20Sopenharmony_ci &range[0], 2); 27898c2ecf20Sopenharmony_ci if (err) { 27908c2ecf20Sopenharmony_ci dev_err(&of_dev->dev, "%s: failed to read fsl,qman-channel-range for %pOF\n", 27918c2ecf20Sopenharmony_ci __func__, fm_node); 27928c2ecf20Sopenharmony_ci goto fman_node_put; 27938c2ecf20Sopenharmony_ci } 27948c2ecf20Sopenharmony_ci fman->dts_params.qman_channel_base = range[0]; 27958c2ecf20Sopenharmony_ci fman->dts_params.num_of_qman_channels = range[1]; 27968c2ecf20Sopenharmony_ci 27978c2ecf20Sopenharmony_ci /* Get the MURAM base address and size */ 27988c2ecf20Sopenharmony_ci muram_node = of_find_matching_node(fm_node, fman_muram_match); 27998c2ecf20Sopenharmony_ci if (!muram_node) { 28008c2ecf20Sopenharmony_ci dev_err(&of_dev->dev, "%s: could not find MURAM node\n", 28018c2ecf20Sopenharmony_ci __func__); 28028c2ecf20Sopenharmony_ci goto fman_free; 28038c2ecf20Sopenharmony_ci } 28048c2ecf20Sopenharmony_ci 28058c2ecf20Sopenharmony_ci err = of_address_to_resource(muram_node, 0, 28068c2ecf20Sopenharmony_ci &fman->dts_params.muram_res); 28078c2ecf20Sopenharmony_ci if (err) { 28088c2ecf20Sopenharmony_ci of_node_put(muram_node); 28098c2ecf20Sopenharmony_ci dev_err(&of_dev->dev, "%s: of_address_to_resource() = %d\n", 28108c2ecf20Sopenharmony_ci __func__, err); 28118c2ecf20Sopenharmony_ci goto fman_free; 28128c2ecf20Sopenharmony_ci } 28138c2ecf20Sopenharmony_ci 28148c2ecf20Sopenharmony_ci of_node_put(muram_node); 28158c2ecf20Sopenharmony_ci 28168c2ecf20Sopenharmony_ci err = devm_request_irq(&of_dev->dev, irq, fman_irq, IRQF_SHARED, 28178c2ecf20Sopenharmony_ci "fman", fman); 28188c2ecf20Sopenharmony_ci if (err < 0) { 28198c2ecf20Sopenharmony_ci dev_err(&of_dev->dev, "%s: irq %d allocation failed (error = %d)\n", 28208c2ecf20Sopenharmony_ci __func__, irq, err); 28218c2ecf20Sopenharmony_ci goto fman_free; 28228c2ecf20Sopenharmony_ci } 28238c2ecf20Sopenharmony_ci 28248c2ecf20Sopenharmony_ci if (fman->dts_params.err_irq != 0) { 28258c2ecf20Sopenharmony_ci err = devm_request_irq(&of_dev->dev, fman->dts_params.err_irq, 28268c2ecf20Sopenharmony_ci fman_err_irq, IRQF_SHARED, 28278c2ecf20Sopenharmony_ci "fman-err", fman); 28288c2ecf20Sopenharmony_ci if (err < 0) { 28298c2ecf20Sopenharmony_ci dev_err(&of_dev->dev, "%s: irq %d allocation failed (error = %d)\n", 28308c2ecf20Sopenharmony_ci __func__, fman->dts_params.err_irq, err); 28318c2ecf20Sopenharmony_ci goto fman_free; 28328c2ecf20Sopenharmony_ci } 28338c2ecf20Sopenharmony_ci } 28348c2ecf20Sopenharmony_ci 28358c2ecf20Sopenharmony_ci fman->dts_params.res = 28368c2ecf20Sopenharmony_ci devm_request_mem_region(&of_dev->dev, phys_base_addr, 28378c2ecf20Sopenharmony_ci mem_size, "fman"); 28388c2ecf20Sopenharmony_ci if (!fman->dts_params.res) { 28398c2ecf20Sopenharmony_ci dev_err(&of_dev->dev, "%s: request_mem_region() failed\n", 28408c2ecf20Sopenharmony_ci __func__); 28418c2ecf20Sopenharmony_ci goto fman_free; 28428c2ecf20Sopenharmony_ci } 28438c2ecf20Sopenharmony_ci 28448c2ecf20Sopenharmony_ci fman->dts_params.base_addr = 28458c2ecf20Sopenharmony_ci devm_ioremap(&of_dev->dev, phys_base_addr, mem_size); 28468c2ecf20Sopenharmony_ci if (!fman->dts_params.base_addr) { 28478c2ecf20Sopenharmony_ci dev_err(&of_dev->dev, "%s: devm_ioremap() failed\n", __func__); 28488c2ecf20Sopenharmony_ci goto fman_free; 28498c2ecf20Sopenharmony_ci } 28508c2ecf20Sopenharmony_ci 28518c2ecf20Sopenharmony_ci fman->dev = &of_dev->dev; 28528c2ecf20Sopenharmony_ci 28538c2ecf20Sopenharmony_ci err = of_platform_populate(fm_node, NULL, NULL, &of_dev->dev); 28548c2ecf20Sopenharmony_ci if (err) { 28558c2ecf20Sopenharmony_ci dev_err(&of_dev->dev, "%s: of_platform_populate() failed\n", 28568c2ecf20Sopenharmony_ci __func__); 28578c2ecf20Sopenharmony_ci goto fman_free; 28588c2ecf20Sopenharmony_ci } 28598c2ecf20Sopenharmony_ci 28608c2ecf20Sopenharmony_ci#ifdef CONFIG_DPAA_ERRATUM_A050385 28618c2ecf20Sopenharmony_ci fman_has_err_a050385 = 28628c2ecf20Sopenharmony_ci of_property_read_bool(fm_node, "fsl,erratum-a050385"); 28638c2ecf20Sopenharmony_ci#endif 28648c2ecf20Sopenharmony_ci 28658c2ecf20Sopenharmony_ci return fman; 28668c2ecf20Sopenharmony_ci 28678c2ecf20Sopenharmony_cifman_node_put: 28688c2ecf20Sopenharmony_ci of_node_put(fm_node); 28698c2ecf20Sopenharmony_cifman_free: 28708c2ecf20Sopenharmony_ci kfree(fman); 28718c2ecf20Sopenharmony_ci return NULL; 28728c2ecf20Sopenharmony_ci} 28738c2ecf20Sopenharmony_ci 28748c2ecf20Sopenharmony_cistatic int fman_probe(struct platform_device *of_dev) 28758c2ecf20Sopenharmony_ci{ 28768c2ecf20Sopenharmony_ci struct fman *fman; 28778c2ecf20Sopenharmony_ci struct device *dev; 28788c2ecf20Sopenharmony_ci int err; 28798c2ecf20Sopenharmony_ci 28808c2ecf20Sopenharmony_ci dev = &of_dev->dev; 28818c2ecf20Sopenharmony_ci 28828c2ecf20Sopenharmony_ci fman = read_dts_node(of_dev); 28838c2ecf20Sopenharmony_ci if (!fman) 28848c2ecf20Sopenharmony_ci return -EIO; 28858c2ecf20Sopenharmony_ci 28868c2ecf20Sopenharmony_ci err = fman_config(fman); 28878c2ecf20Sopenharmony_ci if (err) { 28888c2ecf20Sopenharmony_ci dev_err(dev, "%s: FMan config failed\n", __func__); 28898c2ecf20Sopenharmony_ci return -EINVAL; 28908c2ecf20Sopenharmony_ci } 28918c2ecf20Sopenharmony_ci 28928c2ecf20Sopenharmony_ci if (fman_init(fman) != 0) { 28938c2ecf20Sopenharmony_ci dev_err(dev, "%s: FMan init failed\n", __func__); 28948c2ecf20Sopenharmony_ci return -EINVAL; 28958c2ecf20Sopenharmony_ci } 28968c2ecf20Sopenharmony_ci 28978c2ecf20Sopenharmony_ci if (fman->dts_params.err_irq == 0) { 28988c2ecf20Sopenharmony_ci fman_set_exception(fman, FMAN_EX_DMA_BUS_ERROR, false); 28998c2ecf20Sopenharmony_ci fman_set_exception(fman, FMAN_EX_DMA_READ_ECC, false); 29008c2ecf20Sopenharmony_ci fman_set_exception(fman, FMAN_EX_DMA_SYSTEM_WRITE_ECC, false); 29018c2ecf20Sopenharmony_ci fman_set_exception(fman, FMAN_EX_DMA_FM_WRITE_ECC, false); 29028c2ecf20Sopenharmony_ci fman_set_exception(fman, FMAN_EX_DMA_SINGLE_PORT_ECC, false); 29038c2ecf20Sopenharmony_ci fman_set_exception(fman, FMAN_EX_FPM_STALL_ON_TASKS, false); 29048c2ecf20Sopenharmony_ci fman_set_exception(fman, FMAN_EX_FPM_SINGLE_ECC, false); 29058c2ecf20Sopenharmony_ci fman_set_exception(fman, FMAN_EX_FPM_DOUBLE_ECC, false); 29068c2ecf20Sopenharmony_ci fman_set_exception(fman, FMAN_EX_QMI_SINGLE_ECC, false); 29078c2ecf20Sopenharmony_ci fman_set_exception(fman, FMAN_EX_QMI_DOUBLE_ECC, false); 29088c2ecf20Sopenharmony_ci fman_set_exception(fman, 29098c2ecf20Sopenharmony_ci FMAN_EX_QMI_DEQ_FROM_UNKNOWN_PORTID, false); 29108c2ecf20Sopenharmony_ci fman_set_exception(fman, FMAN_EX_BMI_LIST_RAM_ECC, false); 29118c2ecf20Sopenharmony_ci fman_set_exception(fman, FMAN_EX_BMI_STORAGE_PROFILE_ECC, 29128c2ecf20Sopenharmony_ci false); 29138c2ecf20Sopenharmony_ci fman_set_exception(fman, FMAN_EX_BMI_STATISTICS_RAM_ECC, false); 29148c2ecf20Sopenharmony_ci fman_set_exception(fman, FMAN_EX_BMI_DISPATCH_RAM_ECC, false); 29158c2ecf20Sopenharmony_ci } 29168c2ecf20Sopenharmony_ci 29178c2ecf20Sopenharmony_ci dev_set_drvdata(dev, fman); 29188c2ecf20Sopenharmony_ci 29198c2ecf20Sopenharmony_ci dev_dbg(dev, "FMan%d probed\n", fman->dts_params.id); 29208c2ecf20Sopenharmony_ci 29218c2ecf20Sopenharmony_ci return 0; 29228c2ecf20Sopenharmony_ci} 29238c2ecf20Sopenharmony_ci 29248c2ecf20Sopenharmony_cistatic const struct of_device_id fman_match[] = { 29258c2ecf20Sopenharmony_ci { 29268c2ecf20Sopenharmony_ci .compatible = "fsl,fman"}, 29278c2ecf20Sopenharmony_ci {} 29288c2ecf20Sopenharmony_ci}; 29298c2ecf20Sopenharmony_ci 29308c2ecf20Sopenharmony_ciMODULE_DEVICE_TABLE(of, fman_match); 29318c2ecf20Sopenharmony_ci 29328c2ecf20Sopenharmony_cistatic struct platform_driver fman_driver = { 29338c2ecf20Sopenharmony_ci .driver = { 29348c2ecf20Sopenharmony_ci .name = "fsl-fman", 29358c2ecf20Sopenharmony_ci .of_match_table = fman_match, 29368c2ecf20Sopenharmony_ci }, 29378c2ecf20Sopenharmony_ci .probe = fman_probe, 29388c2ecf20Sopenharmony_ci}; 29398c2ecf20Sopenharmony_ci 29408c2ecf20Sopenharmony_cistatic int __init fman_load(void) 29418c2ecf20Sopenharmony_ci{ 29428c2ecf20Sopenharmony_ci int err; 29438c2ecf20Sopenharmony_ci 29448c2ecf20Sopenharmony_ci pr_debug("FSL DPAA FMan driver\n"); 29458c2ecf20Sopenharmony_ci 29468c2ecf20Sopenharmony_ci err = platform_driver_register(&fman_driver); 29478c2ecf20Sopenharmony_ci if (err < 0) 29488c2ecf20Sopenharmony_ci pr_err("Error, platform_driver_register() = %d\n", err); 29498c2ecf20Sopenharmony_ci 29508c2ecf20Sopenharmony_ci return err; 29518c2ecf20Sopenharmony_ci} 29528c2ecf20Sopenharmony_cimodule_init(fman_load); 29538c2ecf20Sopenharmony_ci 29548c2ecf20Sopenharmony_cistatic void __exit fman_unload(void) 29558c2ecf20Sopenharmony_ci{ 29568c2ecf20Sopenharmony_ci platform_driver_unregister(&fman_driver); 29578c2ecf20Sopenharmony_ci} 29588c2ecf20Sopenharmony_cimodule_exit(fman_unload); 29598c2ecf20Sopenharmony_ci 29608c2ecf20Sopenharmony_ciMODULE_LICENSE("Dual BSD/GPL"); 29618c2ecf20Sopenharmony_ciMODULE_DESCRIPTION("Freescale DPAA Frame Manager driver"); 2962