From 49a1bd52cb9a328460ee793967249223e379b809 Mon Sep 17 00:00:00 2001 From: Eyal Harari Date: Fri, 23 May 2014 10:57:56 +0300 Subject: FMD: DSAR: workaround patch which enables AR in DS Signed-off-by: Eyal Harari Change-Id: I90e7e97c9ff8a149893c8244cb0e8376c66eb2ad Reviewed-on: http://git.am.freescale.net:8181/12925 Reviewed-by: Cristian-Constantin Sovaiala Tested-by: Richard Schmitt Reviewed-by: Jose Rivera Tested-by: Jose Rivera diff --git a/drivers/net/ethernet/freescale/fman/Peripherals/FM/Port/fm_port.c b/drivers/net/ethernet/freescale/fman/Peripherals/FM/Port/fm_port.c index 00a3489..df05848 100644 --- a/drivers/net/ethernet/freescale/fman/Peripherals/FM/Port/fm_port.c +++ b/drivers/net/ethernet/freescale/fman/Peripherals/FM/Port/fm_port.c @@ -3166,10 +3166,13 @@ t_Error FM_PORT_Disable(t_Handle h_FmPort) return E_OK; } +t_FmPort* opXX; t_Error FM_PORT_Enable(t_Handle h_FmPort) { t_FmPort *p_FmPort = (t_FmPort*)h_FmPort; int err; + if (p_FmPort->portId == 0) // save HC port for DSAR disable + opXX = p_FmPort; SANITY_CHECK_RETURN_ERROR(p_FmPort, E_INVALID_HANDLE); SANITY_CHECK_RETURN_ERROR(!p_FmPort->p_FmPortDriverParam, E_INVALID_STATE); @@ -5465,6 +5468,20 @@ static int GetBERLen(uint8_t* buf) } #define TOTAL_BER_LEN(len) (len < 128) ? len + 2 : len + 3 +#define SCFG_FMCLKDPSLPCR_ADDR 0xFFE0FC00C +#define SCFG_FMCLKDPSLPCR_DS_VAL 0x08402000 +#define SCFG_FMCLKDPSLPCR_NORMAL_VAL 0x00402000 +static int fm_soc_suspend(void) +{ + uint32_t *fmclk, tmp32; + fmclk = ioremap(SCFG_FMCLKDPSLPCR_ADDR, 4); + tmp32 = GET_UINT32(*fmclk); + WRITE_UINT32(*fmclk, SCFG_FMCLKDPSLPCR_DS_VAL); + tmp32 = GET_UINT32(*fmclk); + return 0; +} + +t_FmPort *g_DsarFmPortRx, *g_DsarFmPortTx; t_Error FM_PORT_EnterDsar(t_Handle h_FmPortRx, t_FmPortDsarParams *params) { int i,j; @@ -5481,12 +5498,14 @@ t_Error FM_PORT_EnterDsar(t_Handle h_FmPortRx, t_FmPortDsarParams *params) t_ArCommonDesc *ArCommonDescPtr = (t_ArCommonDesc*)(XX_PhysToVirt(p_FmPort->fmMuramPhysBaseAddr + GET_UINT32(*param_page))); struct arOffsets* of; uint8_t tmp = 0; - t_Handle *h_FmPcd; t_FmGetSetParams fmGetSetParams; memset(&fmGetSetParams, 0, sizeof (t_FmGetSetParams)); fmGetSetParams.setParams.type = UPDATE_FPM_BRKC_SLP; fmGetSetParams.setParams.sleep = 1; + g_DsarFmPortRx = p_FmPort; + g_DsarFmPortTx = p_FmPortTx; + err = DsarCheckParams(params, p_FmPort->deepSleepVars.autoResMaxSizes); if (err != E_OK) return err; @@ -5760,7 +5779,27 @@ t_Error FM_PORT_EnterDsar(t_Handle h_FmPortRx, t_FmPortDsarParams *params) WRITE_UINT32(ArCommonDescPtr->p_ArStats, PTR_TO_UINT(ArCommonDescPtr) + of->stats - fmMuramVirtBaseAddr); // get into Deep Sleep sequence: - // Stage 6: configure tx port to im + + // Ensures that FMan do not enter the idle state. This is done by programing + // FMDPSLPCR[FM_STOP] to one. + fm_soc_suspend(); + + ARDesc = UINT_TO_PTR(XX_VirtToPhys(ArCommonDescPtr)); + return E_OK; + +} + +void FM_PORT_Dsar_enter_final(void) +{ + t_Handle *h_FmPcd; + t_FmGetSetParams fmGetSetParams; + + t_FmPort *p_FmPort = g_DsarFmPortRx; + t_FmPort *p_FmPortTx = g_DsarFmPortTx; + // Issue graceful stop to HC port + FM_PORT_Disable(opXX); + + // config auto response p_FmPort->deepSleepVars.fmbm_tcfg = GET_UINT32(p_FmPortTx->p_FmPortBmiRegs->txPortBmiRegs.fmbm_tcfg); WRITE_UINT32(p_FmPortTx->p_FmPortBmiRegs->txPortBmiRegs.fmbm_tcfg, GET_UINT32(p_FmPortTx->p_FmPortBmiRegs->txPortBmiRegs.fmbm_tcfg) | BMI_PORT_CFG_IM); // ???? @@ -5780,20 +5819,55 @@ t_Error FM_PORT_EnterDsar(t_Handle h_FmPortRx, t_FmPortDsarParams *params) p_FmPort->deepSleepVars.dsarEnabledParser = FALSE; WRITE_UINT32(p_FmPort->p_FmPortBmiRegs->rxPortBmiRegs.fmbm_rfpne, 0x2E); - // Stage 8: We don't support magic packet for now. - // Stage 9: Accumulate mode + + // save rcfg for restoring: accumulate mode is changed by ucode p_FmPort->deepSleepVars.fmbm_rcfg = GET_UINT32(p_FmPort->port.bmi_regs->rx.fmbm_rcfg); WRITE_UINT32(p_FmPort->port.bmi_regs->rx.fmbm_rcfg, p_FmPort->deepSleepVars.fmbm_rcfg | BMI_PORT_CFG_AM); - FmGetSetParams(p_FmPort->h_Fm, &fmGetSetParams); +// ***** issue external request sync command + memset(&fmGetSetParams, 0, sizeof (t_FmGetSetParams)); + fmGetSetParams.setParams.type = UPDATE_FPM_EXTC; + FmGetSetParams(p_FmPort->h_Fm, &fmGetSetParams); + // get + memset(&fmGetSetParams, 0, sizeof (t_FmGetSetParams)); + fmGetSetParams.getParams.type = GET_FMFP_EXTC; + FmGetSetParams(p_FmPort->h_Fm, &fmGetSetParams); + if (fmGetSetParams.getParams.fmfp_extc != 0) + { + // clear + XX_Print("FM: Sync did not finish 0\n"); + memset(&fmGetSetParams, 0, sizeof (t_FmGetSetParams)); + fmGetSetParams.setParams.type = UPDATE_FPM_EXTC_CLEAR; + FmGetSetParams(p_FmPort->h_Fm, &fmGetSetParams); + } - ARDesc = UINT_TO_PTR(XX_VirtToPhys(ArCommonDescPtr)); - return E_OK; + // get + memset(&fmGetSetParams, 0, sizeof (t_FmGetSetParams)); + fmGetSetParams.getParams.type = GET_FMFP_EXTC; + FmGetSetParams(p_FmPort->h_Fm, &fmGetSetParams); + while (fmGetSetParams.getParams.fmfp_extc != 0) + { + // get + memset(&fmGetSetParams, 0, sizeof (t_FmGetSetParams)); + fmGetSetParams.getParams.type = GET_FMFP_EXTC; + FmGetSetParams(p_FmPort->h_Fm, &fmGetSetParams); + } + + // check that all stoped + memset(&fmGetSetParams, 0, sizeof (t_FmGetSetParams)); + fmGetSetParams.getParams.type = GET_FMQM_GS | GET_FM_NPI; + FmGetSetParams(p_FmPort->h_Fm, &fmGetSetParams); + while (fmGetSetParams.getParams.fmqm_gs & 0xF0000000) + FmGetSetParams(p_FmPort->h_Fm, &fmGetSetParams); + if (fmGetSetParams.getParams.fmqm_gs == 0 && fmGetSetParams.getParams.fm_npi == 0) + XX_Print("FM: Sleeping\n"); } +EXPORT_SYMBOL(FM_PORT_Dsar_enter_final); + void FM_PORT_Dsar_DumpRegs() { uint32_t* hh = XX_PhysToVirt(PTR_TO_UINT(ARDesc)); - DUMP_MEMORY(hh, 0x180); + DUMP_MEMORY(hh, 0x220); } void FM_PORT_ExitDsar(t_Handle h_FmPortRx, t_Handle h_FmPortTx) @@ -5823,6 +5897,7 @@ void FM_PORT_ExitDsar(t_Handle h_FmPortRx, t_Handle h_FmPortTx) FmGetSetParams(p_FmPort->h_Fm, &fmGetSetParams); WRITE_UINT32(p_FmPortTx->p_FmPortBmiRegs->txPortBmiRegs.fmbm_tcmne, p_FmPort->deepSleepVars.fmbm_tcmne); WRITE_UINT32(p_FmPortTx->p_FmPortBmiRegs->txPortBmiRegs.fmbm_tcfg, p_FmPort->deepSleepVars.fmbm_tcfg); + FM_PORT_Enable(opXX); } bool FM_PORT_IsInDsar(t_Handle h_FmPort) diff --git a/drivers/net/ethernet/freescale/fman/Peripherals/FM/fm.c b/drivers/net/ethernet/freescale/fman/Peripherals/FM/fm.c index 811c4f2..3f569b8 100644 --- a/drivers/net/ethernet/freescale/fman/Peripherals/FM/fm.c +++ b/drivers/net/ethernet/freescale/fman/Peripherals/FM/fm.c @@ -4182,6 +4182,33 @@ UNUSED(p_Fm); return E_OK; } +t_Error FmGetSetParams(t_Handle h_Fm, t_FmGetSetParams *p_Params) +{ + t_Fm* p_Fm = (t_Fm*)h_Fm; + + if (p_Params->setParams.type & UPDATE_FPM_EXTC) + WRITE_UINT32(p_Fm->p_FmFpmRegs->fmfp_extc,0x80000000); + if (p_Params->setParams.type & UPDATE_FPM_EXTC_CLEAR) + WRITE_UINT32(p_Fm->p_FmFpmRegs->fmfp_extc,0x08000000); + if (p_Params->setParams.type & UPDATE_FPM_BRKC_SLP) + { + if (p_Params->setParams.sleep) + WRITE_UINT32(p_Fm->p_FmFpmRegs->fmfp_brkc, GET_UINT32( + p_Fm->p_FmFpmRegs->fmfp_brkc) | FPM_BRKC_SLP); + else + WRITE_UINT32(p_Fm->p_FmFpmRegs->fmfp_brkc, GET_UINT32( + p_Fm->p_FmFpmRegs->fmfp_brkc) & ~FPM_BRKC_SLP); + } + if (p_Params->getParams.type & GET_FMQM_GS) + p_Params->getParams.fmqm_gs = GET_UINT32(p_Fm->p_FmQmiRegs->fmqm_gs); + if (p_Params->getParams.type & GET_FM_NPI) + p_Params->getParams.fm_npi = GET_UINT32(p_Fm->p_FmFpmRegs->fm_npi); + if (p_Params->getParams.type & GET_FMFP_EXTC) + p_Params->getParams.fmfp_extc = GET_UINT32(p_Fm->p_FmFpmRegs->fmfp_extc); + return E_OK; +} + + /****************************************************/ /* API Run-time Control uint functions */ /****************************************************/ @@ -4215,7 +4242,14 @@ void FM_EventIsr(t_Handle h_Fm) pending = fman_get_normal_pending(fpm_rg); if (!pending) return; - + if (pending & 0x10000000) // this is a wake up from sleep interrupt + { + t_FmGetSetParams fmGetSetParams; + memset(&fmGetSetParams, 0, sizeof (t_FmGetSetParams)); + fmGetSetParams.setParams.type = UPDATE_FPM_BRKC_SLP; + fmGetSetParams.setParams.sleep = 0; + FmGetSetParams(h_Fm, &fmGetSetParams); + } if (pending & INTR_EN_QMI) QmiEvent(p_Fm); if (pending & INTR_EN_PRS) @@ -5212,17 +5246,3 @@ t_Handle FmGetPcd(t_Handle h_Fm) return ((t_Fm*)h_Fm)->h_Pcd; } -t_Error FmGetSetParams(t_Handle h_Fm, t_FmGetSetParams *p_Params) -{ - t_Fm* p_Fm = (t_Fm*)h_Fm; - if (p_Params->setParams.type == UPDATE_FPM_BRKC_SLP) - { - if (p_Params->setParams.sleep) - WRITE_UINT32(p_Fm->p_FmFpmRegs->fmfp_brkc, GET_UINT32( - p_Fm->p_FmFpmRegs->fmfp_brkc) | FPM_BRKC_SLP); - else - WRITE_UINT32(p_Fm->p_FmFpmRegs->fmfp_brkc, GET_UINT32( - p_Fm->p_FmFpmRegs->fmfp_brkc) & ~FPM_BRKC_SLP); - } - return E_OK; -} diff --git a/drivers/net/ethernet/freescale/fman/Peripherals/FM/inc/fm_common.h b/drivers/net/ethernet/freescale/fman/Peripherals/FM/inc/fm_common.h index c9c963a..f5f5428 100644 --- a/drivers/net/ethernet/freescale/fman/Peripherals/FM/inc/fm_common.h +++ b/drivers/net/ethernet/freescale/fman/Peripherals/FM/inc/fm_common.h @@ -264,7 +264,15 @@ typedef struct { } t_FmSetParams; typedef struct { + uint32_t type; + uint32_t fmqm_gs; + uint32_t fm_npi; + uint32_t fmfp_extc; +} t_FmGetParams; + +typedef struct { t_FmSetParams setParams; + t_FmGetParams getParams; } t_FmGetSetParams; t_Error FmGetSetParams(t_Handle h_Fm, t_FmGetSetParams *p_Params); @@ -335,6 +343,11 @@ static __inline__ bool TRY_LOCK(t_Handle h_Spinlock, volatile bool *p_Flag) /* @} */ #define UPDATE_FPM_BRKC_SLP 0x80000000 +#define UPDATE_FPM_EXTC 0x40000000 +#define UPDATE_FPM_EXTC_CLEAR 0x20000000 +#define GET_FMQM_GS 0x10000000 +#define GET_FM_NPI 0x08000000 +#define GET_FMFP_EXTC 0x04000000 #define FM_MAX_NUM_OF_PORTS (FM_MAX_NUM_OF_OH_PORTS + \ FM_MAX_NUM_OF_1G_RX_PORTS + \ FM_MAX_NUM_OF_10G_RX_PORTS + \ diff --git a/drivers/net/ethernet/freescale/fman/src/inc/wrapper/lnxwrp_fsl_fman.h b/drivers/net/ethernet/freescale/fman/src/inc/wrapper/lnxwrp_fsl_fman.h index 97a7c0c..4e66564 100644 --- a/drivers/net/ethernet/freescale/fman/src/inc/wrapper/lnxwrp_fsl_fman.h +++ b/drivers/net/ethernet/freescale/fman/src/inc/wrapper/lnxwrp_fsl_fman.h @@ -468,6 +468,7 @@ struct auto_res_snmp_info char *community_read_only_string; struct auto_res_snmp_entry *oid_table; uint32_t oid_table_size; + uint32_t *statistics; }; /* Filtering */ diff --git a/drivers/net/ethernet/freescale/fman/src/wrapper/lnxwrp_fm.c b/drivers/net/ethernet/freescale/fman/src/wrapper/lnxwrp_fm.c index cdffe7a..646a90c 100755 --- a/drivers/net/ethernet/freescale/fman/src/wrapper/lnxwrp_fm.c +++ b/drivers/net/ethernet/freescale/fman/src/wrapper/lnxwrp_fm.c @@ -60,6 +60,7 @@ #include #include /* For struct qe_firmware */ #include +#include #include /* For file access mask */ #include #include @@ -1102,20 +1103,30 @@ MODULE_DEVICE_TABLE(of, fm_match); #define SCFG_FMCLKDPSLPCR_ADDR 0xFFE0FC00C #define SCFG_FMCLKDPSLPCR_DS_VAL 0x48402000 #define SCFG_FMCLKDPSLPCR_NORMAL_VAL 0x00402000 - +void FM_PORT_Dsar_enter_final(void); +static bool started_ar_enter = false; static int fm_soc_suspend(struct device *dev) { - uint32_t *fmclk; - fmclk = ioremap(SCFG_FMCLKDPSLPCR_ADDR, 4); - WRITE_UINT32(*fmclk, SCFG_FMCLKDPSLPCR_DS_VAL); + if (started_ar_enter) + { + uint32_t *fmclk; + fsl_set_power_except(dev,1); + FM_PORT_Dsar_enter_final(); + fmclk = ioremap(SCFG_FMCLKDPSLPCR_ADDR, 4); + WRITE_UINT32(*fmclk, SCFG_FMCLKDPSLPCR_DS_VAL); + } return 0; } static int fm_soc_resume(struct device *dev) { - uint32_t *fmclk; - fmclk = ioremap(SCFG_FMCLKDPSLPCR_ADDR, 4); - WRITE_UINT32(*fmclk, SCFG_FMCLKDPSLPCR_NORMAL_VAL); + if (started_ar_enter) + { + uint32_t *fmclk; + fmclk = ioremap(SCFG_FMCLKDPSLPCR_ADDR, 4); + WRITE_UINT32(*fmclk, SCFG_FMCLKDPSLPCR_NORMAL_VAL); + started_ar_enter = false; + } return 0; } @@ -1360,6 +1371,7 @@ int fm_port_enter_autores_for_deepsleep(struct fm_port *port, return -EFAULT; FM_PORT_EnterDsar(p_LnxWrpFmPortDev->h_Dev, (t_FmPortDsarParams*)params); + started_ar_enter = true; return 0; } EXPORT_SYMBOL(fm_port_enter_autores_for_deepsleep); @@ -1367,7 +1379,9 @@ EXPORT_SYMBOL(fm_port_enter_autores_for_deepsleep); void fm_port_exit_auto_res_for_deep_sleep(struct fm_port *port_rx, struct fm_port *port_tx) { - FM_PORT_ExitDsar(port_rx, port_tx); + t_LnxWrpFmPortDev *p_LnxWrpFmPortDevRx = (t_LnxWrpFmPortDev *)port_rx; + t_LnxWrpFmPortDev *p_LnxWrpFmPortDevTx = (t_LnxWrpFmPortDev *)port_tx; + FM_PORT_ExitDsar(p_LnxWrpFmPortDevRx->h_Dev, p_LnxWrpFmPortDevTx->h_Dev); } EXPORT_SYMBOL(fm_port_exit_auto_res_for_deep_sleep); diff --git a/drivers/net/ethernet/freescale/fman/src/wrapper/lnxwrp_sysfs_fm_port.c b/drivers/net/ethernet/freescale/fman/src/wrapper/lnxwrp_sysfs_fm_port.c index ead8c7a..ebed557 100644 --- a/drivers/net/ethernet/freescale/fman/src/wrapper/lnxwrp_sysfs_fm_port.c +++ b/drivers/net/ethernet/freescale/fman/src/wrapper/lnxwrp_sysfs_fm_port.c @@ -302,10 +302,10 @@ static int fm_port_dsar_dump_mem(void *h_dev, char *buf, int nn) /* do I need request_mem_region here? */ param_page = ioremap(p_FmPort->fmMuramPhysBaseAddr + ioread32be(&p_FmPort->p_FmPortBmiRegs->rxPortBmiRegs.fmbm_rgpr), 4); - ArCommonDescPtr = (t_ArCommonDesc*)(ioremap(p_FmPort->fmMuramPhysBaseAddr + ioread32be(param_page), sizeof(t_ArCommonDesc))); /* this should be changed*/ + ArCommonDescPtr = (t_ArCommonDesc*)(ioremap(p_FmPort->fmMuramPhysBaseAddr + ioread32be(param_page), 300*4)); /* this should be changed*/ mem = (uint32_t*)ArCommonDescPtr; - for (i = 0; i < 100; i+=4) - FM_DMP_LN(buf, n, "%08x %08x %08x %08x\n", mem[i], mem[i + 1], mem[i + 2], mem[i + 3]); + for (i = 0; i < 300; i+=4) + FM_DMP_LN(buf, n, "%08x: %08x %08x %08x %08x\n", i*4, mem[i], mem[i + 1], mem[i + 2], mem[i + 3]); iounmap(ArCommonDescPtr); iounmap(param_page); return n; -- cgit v0.10.2