From 087f4784b96585b712b62a110b0fe83e45ae4351 Mon Sep 17 00:00:00 2001 From: Eyal Harari Date: Tue, 3 Jun 2014 08:34:13 +0300 Subject: FMD: DSAR - fix deep sleep entry sequence The current sequence fixes the order of operations executed when entering deep sleep state. It also implements a workaround for a hardware bug by writing to fm_cld register - disabling DMA after a short idle period. Signed-off-by: Eyal Harari Change-Id: I2c73406543495dad5a7fb240a2e8fab01b81e05e diff --git a/drivers/net/ethernet/freescale/fman/Peripherals/FM/HC/hc.c b/drivers/net/ethernet/freescale/fman/Peripherals/FM/HC/hc.c index 74047dd..9485caa 100644 --- a/drivers/net/ethernet/freescale/fman/Peripherals/FM/HC/hc.c +++ b/drivers/net/ethernet/freescale/fman/Peripherals/FM/HC/hc.c @@ -1223,3 +1223,8 @@ t_Error FmHcPcdSync(t_Handle h_FmHc) return E_OK; } +t_Handle FmHcGetPort(t_Handle h_FmHc) +{ + t_FmHc *p_FmHc = (t_FmHc*)h_FmHc; + return p_FmHc->h_HcPortDev; +} diff --git a/drivers/net/ethernet/freescale/fman/Peripherals/FM/MAC/memac.c b/drivers/net/ethernet/freescale/fman/Peripherals/FM/MAC/memac.c index 9169ff7..266716d 100644 --- a/drivers/net/ethernet/freescale/fman/Peripherals/FM/MAC/memac.c +++ b/drivers/net/ethernet/freescale/fman/Peripherals/FM/MAC/memac.c @@ -857,7 +857,7 @@ static t_Error MemacDumpRegs(t_Handle h_Memac) /*****************************************************************************/ /* ......................................................................... */ - +void *g_MemacRegs; static t_Error MemacInit(t_Handle h_Memac) { t_Memac *p_Memac = (t_Memac *)h_Memac; @@ -869,6 +869,9 @@ static t_Error MemacInit(t_Handle h_Memac) e_FmMacType portType; t_Error err; + if (p_Memac->macId == 3) /* This is a quick WA */ + g_MemacRegs = p_Memac->p_MemMap; + SANITY_CHECK_RETURN_ERROR(p_Memac, E_INVALID_HANDLE); SANITY_CHECK_RETURN_ERROR(p_Memac->p_MemacDriverParam, E_INVALID_STATE); SANITY_CHECK_RETURN_ERROR(p_Memac->fmMacControllerDriver.h_Fm, E_INVALID_HANDLE); diff --git a/drivers/net/ethernet/freescale/fman/Peripherals/FM/Pcd/fm_pcd.c b/drivers/net/ethernet/freescale/fman/Peripherals/FM/Pcd/fm_pcd.c index 37ff0fd..ae87a36 100644 --- a/drivers/net/ethernet/freescale/fman/Peripherals/FM/Pcd/fm_pcd.c +++ b/drivers/net/ethernet/freescale/fman/Peripherals/FM/Pcd/fm_pcd.c @@ -2114,4 +2114,9 @@ t_Error FM_PCD_ModifyCounter(t_Handle h_FmPcd, e_FmPcdCounters counter, uint32_t return E_OK; } +t_Handle FM_PCD_GetHcPort(t_Handle h_FmPcd) +{ + t_FmPcd *p_FmPcd = (t_FmPcd*)h_FmPcd; + return FmHcGetPort(p_FmPcd->h_Hc); +} 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 7359001..a3fec5a 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 @@ -3143,7 +3143,6 @@ t_Error FM_PORT_Disable(t_Handle h_FmPort) { t_FmPort *p_FmPort = (t_FmPort*)h_FmPort; int err; - SANITY_CHECK_RETURN_ERROR(p_FmPort, E_INVALID_HANDLE); SANITY_CHECK_RETURN_ERROR(!p_FmPort->p_FmPortDriverParam, E_INVALID_STATE); @@ -3166,13 +3165,10 @@ 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); @@ -5354,6 +5350,7 @@ uint32_t* ARDesc; void PrsEnable(t_Handle p_FmPcd); void PrsDisable(t_Handle p_FmPcd); int PrsIsEnabled(t_Handle p_FmPcd); +t_Handle FM_PCD_GetHcPort(t_Handle h_FmPcd); static t_Error DsarCheckParams(t_FmPortDsarParams *params, t_FmPortDsarTablesSizes *sizes) { @@ -5478,10 +5475,20 @@ static int fm_soc_suspend(void) tmp32 = GET_UINT32(*fmclk); WRITE_UINT32(*fmclk, SCFG_FMCLKDPSLPCR_DS_VAL); tmp32 = GET_UINT32(*fmclk); + iounmap(fmclk); return 0; } -t_FmPort *g_DsarFmPortRx, *g_DsarFmPortTx; +void fm_clk_down(void) +{ + uint32_t *fmclk, tmp32; + fmclk = ioremap(SCFG_FMCLKDPSLPCR_ADDR, 4); + tmp32 = GET_UINT32(*fmclk); + WRITE_UINT32(*fmclk, SCFG_FMCLKDPSLPCR_DS_VAL | 0x40000000); + tmp32 = GET_UINT32(*fmclk); + iounmap(fmclk); +} + t_Error FM_PORT_EnterDsar(t_Handle h_FmPortRx, t_FmPortDsarParams *params) { int i,j; @@ -5493,6 +5500,7 @@ t_Error FM_PORT_EnterDsar(t_Handle h_FmPortRx, t_FmPortDsarParams *params) t_DsarIcmpV4Descriptor* ICMPV4Descriptor; t_DsarIcmpV6Descriptor* ICMPV6Descriptor; t_DsarNdDescriptor* NDDescriptor; + uint64_t fmMuramVirtBaseAddr = (uint64_t)PTR_TO_UINT(XX_PhysToVirt(p_FmPort->fmMuramPhysBaseAddr)); uint32_t *param_page = XX_PhysToVirt(p_FmPort->fmMuramPhysBaseAddr + GET_UINT32(p_FmPort->p_FmPortBmiRegs->rxPortBmiRegs.fmbm_rgpr)); t_ArCommonDesc *ArCommonDescPtr = (t_ArCommonDesc*)(XX_PhysToVirt(p_FmPort->fmMuramPhysBaseAddr + GET_UINT32(*param_page))); @@ -5503,9 +5511,6 @@ t_Error FM_PORT_EnterDsar(t_Handle h_FmPortRx, t_FmPortDsarParams *params) 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; @@ -5789,28 +5794,31 @@ t_Error FM_PORT_EnterDsar(t_Handle h_FmPortRx, t_FmPortDsarParams *params) } -void FM_PORT_Dsar_enter_final(void) +void FM_ChangeClock(t_Handle h_Fm, int hardwarePortId); +t_Error FM_PORT_EnterDsarFinal(t_Handle h_DsarRxPort, t_Handle h_DsarTxPort) { - t_Handle *h_FmPcd; - t_FmGetSetParams fmGetSetParams; + t_FmGetSetParams fmGetSetParams; + t_FmPort *p_FmPort = (t_FmPort *)h_DsarRxPort; + t_FmPort *p_FmPortTx = (t_FmPort *)h_DsarTxPort; + t_Handle *h_FmPcd = FmGetPcd(p_FmPort->h_Fm); + t_FmPort *p_FmPortHc = FM_PCD_GetHcPort(h_FmPcd); + memset(&fmGetSetParams, 0, sizeof (t_FmGetSetParams)); + fmGetSetParams.setParams.type = UPDATE_FM_CLD; + FmGetSetParams(p_FmPort->h_Fm, &fmGetSetParams); - t_FmPort *p_FmPort = g_DsarFmPortRx; - t_FmPort *p_FmPortTx = g_DsarFmPortTx; - // Issue graceful stop to HC port - FM_PORT_Disable(opXX); + // Issue graceful stop to HC and DSAR Tx ports + FM_PORT_Disable(p_FmPortTx); + FM_PORT_Disable(p_FmPortHc); // config tx port p_FmPort->deepSleepVars.fmbm_tcfg = GET_UINT32(p_FmPortTx->p_FmPortBmiRegs->txPortBmiRegs.fmbm_tcfg); - WRITE_UINT32(p_FmPortTx->p_FmPortBmiRegs->txPortBmiRegs.fmbm_tfdne, 0x005000C0); WRITE_UINT32(p_FmPortTx->p_FmPortBmiRegs->txPortBmiRegs.fmbm_tcfg, GET_UINT32(p_FmPortTx->p_FmPortBmiRegs->txPortBmiRegs.fmbm_tcfg) | BMI_PORT_CFG_IM | BMI_PORT_CFG_EN); // ???? p_FmPort->deepSleepVars.fmbm_tcmne = GET_UINT32(p_FmPortTx->p_FmPortBmiRegs->txPortBmiRegs.fmbm_tcmne); WRITE_UINT32(p_FmPortTx->p_FmPortBmiRegs->txPortBmiRegs.fmbm_tcmne, 0xE); // Stage 7:echo - p_FmPort->deepSleepVars.fmbm_rfne = GET_UINT32(p_FmPort->p_FmPortBmiRegs->rxPortBmiRegs.fmbm_rfne); - WRITE_UINT32(p_FmPort->p_FmPortBmiRegs->rxPortBmiRegs.fmbm_rfne, 0x440000); p_FmPort->deepSleepVars.fmbm_rfpne = GET_UINT32(p_FmPort->p_FmPortBmiRegs->rxPortBmiRegs.fmbm_rfpne); - h_FmPcd = FmGetPcd(p_FmPort->h_Fm); + WRITE_UINT32(p_FmPort->p_FmPortBmiRegs->rxPortBmiRegs.fmbm_rfpne, 0x2E); if (!PrsIsEnabled(h_FmPcd)) { p_FmPort->deepSleepVars.dsarEnabledParser = TRUE; @@ -5818,12 +5826,18 @@ void FM_PORT_Dsar_enter_final(void) } else p_FmPort->deepSleepVars.dsarEnabledParser = FALSE; - - WRITE_UINT32(p_FmPort->p_FmPortBmiRegs->rxPortBmiRegs.fmbm_rfpne, 0x2E); + + p_FmPort->deepSleepVars.fmbm_rfne = GET_UINT32(p_FmPort->p_FmPortBmiRegs->rxPortBmiRegs.fmbm_rfne); + WRITE_UINT32(p_FmPort->p_FmPortBmiRegs->rxPortBmiRegs.fmbm_rfne, 0x440000); // 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); + memset(&fmGetSetParams, 0, sizeof (t_FmGetSetParams)); + fmGetSetParams.setParams.type = UPDATE_FPM_BRKC_SLP; + fmGetSetParams.setParams.sleep = 1; + FmGetSetParams(p_FmPort->h_Fm, &fmGetSetParams); + // ***** issue external request sync command memset(&fmGetSetParams, 0, sizeof (t_FmGetSetParams)); fmGetSetParams.setParams.type = UPDATE_FPM_EXTC; @@ -5857,9 +5871,12 @@ void FM_PORT_Dsar_enter_final(void) FmGetSetParams(p_FmPort->h_Fm, &fmGetSetParams); if (fmGetSetParams.getParams.fmqm_gs == 0 && fmGetSetParams.getParams.fm_npi == 0) XX_Print("FM: Sleeping\n"); +// FM_ChangeClock(p_FmPort->h_Fm, p_FmPort->hardwarePortId); + + return E_OK; } -EXPORT_SYMBOL(FM_PORT_Dsar_enter_final); +EXPORT_SYMBOL(FM_PORT_EnterDsarFinal); void FM_PORT_Dsar_DumpRegs() { @@ -5871,6 +5888,8 @@ void FM_PORT_ExitDsar(t_Handle h_FmPortRx, t_Handle h_FmPortTx) { t_FmPort *p_FmPort = (t_FmPort *)h_FmPortRx; t_FmPort *p_FmPortTx = (t_FmPort *)h_FmPortTx; + t_Handle *h_FmPcd = FmGetPcd(p_FmPort->h_Fm); + t_FmPort *p_FmPortHc = FM_PCD_GetHcPort(h_FmPcd); t_FmGetSetParams fmGetSetParams; memset(&fmGetSetParams, 0, sizeof (t_FmGetSetParams)); fmGetSetParams.setParams.type = UPDATE_FPM_BRKC_SLP; @@ -5880,11 +5899,6 @@ void FM_PORT_ExitDsar(t_Handle h_FmPortRx, t_Handle h_FmPortTx) XX_Free(p_FmPort->deepSleepVars.autoResOffsets); p_FmPort->deepSleepVars.autoResOffsets = 0; } - if (p_FmPort->deepSleepVars.autoResMaxSizes) - { - XX_Free(p_FmPort->deepSleepVars.autoResMaxSizes); - p_FmPort->deepSleepVars.autoResMaxSizes = 0; - } if (p_FmPort->deepSleepVars.dsarEnabledParser) PrsDisable(FmGetPcd(p_FmPort->h_Fm)); @@ -5894,7 +5908,8 @@ 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); + FM_PORT_Enable(p_FmPortTx); + FM_PORT_Enable(p_FmPortHc); } 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 ccb6042..38cc89c 100644 --- a/drivers/net/ethernet/freescale/fman/Peripherals/FM/fm.c +++ b/drivers/net/ethernet/freescale/fman/Peripherals/FM/fm.c @@ -4185,7 +4185,16 @@ UNUSED(p_Fm); 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_FM_CLD) + { + WRITE_UINT32(p_Fm->p_FmFpmRegs->fm_cld, GET_UINT32( + p_Fm->p_FmFpmRegs->fm_cld) | 0x00000800); + } + if (p_Params->setParams.type & CLEAR_IRAM_READY) + { + t_FMIramRegs *p_Iram = (t_FMIramRegs *)UINT_TO_PTR(p_Fm->baseAddr + FM_MM_IMEM); + WRITE_UINT32(p_Iram->iready,GET_UINT32(p_Iram->iready) & ~IRAM_READY); + } 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) @@ -4199,6 +4208,8 @@ t_Error FmGetSetParams(t_Handle h_Fm, t_FmGetSetParams *p_Params) 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_FM_CLD) + p_Params->getParams.fm_cld = GET_UINT32(p_Fm->p_FmFpmRegs->fm_cld); 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) @@ -4242,7 +4253,7 @@ 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 + if (pending & INTR_EN_WAKEUP) // this is a wake up from sleep interrupt { t_FmGetSetParams fmGetSetParams; memset(&fmGetSetParams, 0, sizeof (t_FmGetSetParams)); @@ -5049,9 +5060,7 @@ t_Error FM_DumpRegs(t_Handle h_Fm) { t_Fm *p_Fm = (t_Fm *)h_Fm; uint8_t i,j = 0; - DECLARE_DUMP; - SANITY_CHECK_RETURN_ERROR(p_Fm, E_INVALID_HANDLE); SANITY_CHECK_RETURN_ERROR(!p_Fm->p_FmDriverParam, E_INVALID_STATE); SANITY_CHECK_RETURN_ERROR(((p_Fm->guestId == NCSW_MASTER_ID) || @@ -5245,4 +5254,25 @@ t_Handle FmGetPcd(t_Handle h_Fm) { return ((t_Fm*)h_Fm)->h_Pcd; } - +extern void *g_MemacRegs; +void fm_clk_down(void); +uint32_t fman_memac_get_event(void *regs, uint32_t ev_mask); +void FM_ChangeClock(t_Handle h_Fm, int hardwarePortId) +{ + int macId; + uint32_t event, rcr; + t_Fm *p_Fm = (t_Fm*)h_Fm; + rcr = GET_UINT32(p_Fm->p_FmFpmRegs->fm_rcr); + rcr |= 0x04000000; + WRITE_UINT32(p_Fm->p_FmFpmRegs->fm_rcr, rcr); + + HW_PORT_ID_TO_SW_PORT_ID(macId, hardwarePortId); + do + { + event = fman_memac_get_event(g_MemacRegs, 0xFFFFFFFF); + } while ((event & 0x00000020) == 0); + fm_clk_down(); + rcr = GET_UINT32(p_Fm->p_FmFpmRegs->fm_rcr); + rcr &= ~0x04000000; + WRITE_UINT32(p_Fm->p_FmFpmRegs->fm_rcr, rcr); +} diff --git a/drivers/net/ethernet/freescale/fman/Peripherals/FM/fm.h b/drivers/net/ethernet/freescale/fman/Peripherals/FM/fm.h index 07431c3..ad391c8 100644 --- a/drivers/net/ethernet/freescale/fman/Peripherals/FM/fm.h +++ b/drivers/net/ethernet/freescale/fman/Peripherals/FM/fm.h @@ -425,6 +425,7 @@ switch (exception){ \ #define INTR_EN_QMI 0x40000000 #define INTR_EN_PRS 0x20000000 +#define INTR_EN_WAKEUP 0x10000000 #define INTR_EN_PLCR 0x08000000 #define INTR_EN_1G_MAC0 0x00080000 #define INTR_EN_1G_MAC1 0x00040000 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 00c5973..7343d6f 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 @@ -267,6 +267,7 @@ typedef struct { uint32_t type; uint32_t fmqm_gs; uint32_t fm_npi; + uint32_t fm_cld; uint32_t fmfp_extc; } t_FmGetParams; @@ -349,6 +350,9 @@ static __inline__ bool TRY_LOCK(t_Handle h_Spinlock, volatile bool *p_Flag) #define GET_FMQM_GS 0x10000000 #define GET_FM_NPI 0x08000000 #define GET_FMFP_EXTC 0x04000000 +#define CLEAR_IRAM_READY 0x02000000 +#define UPDATE_FM_CLD 0x01000000 +#define GET_FM_CLD 0x00800000 #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/Peripherals/FM/inc/fm_hc.h b/drivers/net/ethernet/freescale/fman/Peripherals/FM/inc/fm_hc.h index f6a1bb2..099a238 100644 --- a/drivers/net/ethernet/freescale/fman/Peripherals/FM/inc/fm_hc.h +++ b/drivers/net/ethernet/freescale/fman/Peripherals/FM/inc/fm_hc.h @@ -85,6 +85,8 @@ t_Error FmHcPcdKgCcGetSetParams(t_Handle h_FmHc, t_Handle h_Scheme, uint32_ t_Error FmHcPcdPlcrCcGetSetParams(t_Handle h_FmHc,uint16_t absoluteProfileId, uint32_t requiredAction); t_Error FmHcPcdSync(t_Handle h_FmHc); +t_Handle FmHcGetPort(t_Handle h_FmHc); + diff --git a/drivers/net/ethernet/freescale/fman/inc/Peripherals/fm_port_ext.h b/drivers/net/ethernet/freescale/fman/inc/Peripherals/fm_port_ext.h index 3a62b8d..3d5401c 100644 --- a/drivers/net/ethernet/freescale/fman/inc/Peripherals/fm_port_ext.h +++ b/drivers/net/ethernet/freescale/fman/inc/Peripherals/fm_port_ext.h @@ -1499,11 +1499,7 @@ typedef struct t_FmPortDsarParams @Description Enter Deep Sleep Auto Response mode. This function write the apropriate values to in the relevant - tables in the MURAM. It then set the Tx port in independent - mode as needed and redirect the receive flow to go through the - Dsar Fman-ctrl code - - Calling this routine invalidates the descriptor. + tables in the MURAM. @Param[in] h_FmPortRx - FM PORT module descriptor @Param[in] params - Auto Response parameters @@ -1515,6 +1511,23 @@ typedef struct t_FmPortDsarParams t_Error FM_PORT_EnterDsar(t_Handle h_FmPortRx, t_FmPortDsarParams *params); /**************************************************************************//** + @Function FM_PORT_EnterDsarFinal + + @Description Enter Deep Sleep Auto Response mode. + This function sets the Tx port in independent mode as needed + and redirect the receive flow to go through the + Dsar Fman-ctrl code + + @Param[in] h_DsarRxPort - FM Rx PORT module descriptor + @Param[in] h_DsarTxPort - FM Tx PORT module descriptor + + @Return E_OK on success; Error code otherwise. + + @Cautions Allowed only following FM_PORT_Init(). +*//***************************************************************************/ +t_Error FM_PORT_EnterDsarFinal(t_Handle h_DsarRxPort, t_Handle h_DsarTxPort); + +/**************************************************************************//** @Function FM_PORT_ExitDsar @Description Exit Deep Sleep Auto Response mode. 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 600cbc5..e70c929 100755 --- a/drivers/net/ethernet/freescale/fman/src/wrapper/lnxwrp_fm.c +++ b/drivers/net/ethernet/freescale/fman/src/wrapper/lnxwrp_fm.c @@ -79,7 +79,8 @@ #include "lnxwrp_sysfs_fm.h" #include "lnxwrp_sysfs_fm_port.h" #include "lnxwrp_exp_sym.h" - +#include "fm_common.h" +#include "../../fman/Peripherals/FM/fm.h" #define __ERR_MODULE__ MODULE_FM extern struct device_node *GetFmPortAdvArgsDevTreeNode (struct device_node *fm_node, @@ -236,12 +237,17 @@ early_param(FSL_FM_RX_EXTRA_HEADROOM_BOOTARG, fm_set_rx_extra_headroom); static irqreturn_t fm_irq(int irq, void *_dev) { t_LnxWrpFmDev *p_LnxWrpFmDev = (t_LnxWrpFmDev *)_dev; - + t_Fm *p_Fm = (t_Fm*)p_LnxWrpFmDev->h_Dev; if (!p_LnxWrpFmDev || !p_LnxWrpFmDev->h_Dev) return IRQ_NONE; +#ifdef CONFIG_PM_SLEEP + if (fman_get_normal_pending(p_Fm->p_FmFpmRegs) & INTR_EN_WAKEUP) + { + pm_wakeup_event(p_LnxWrpFmDev->dev, 200); + } +#endif FM_EventIsr(p_LnxWrpFmDev->h_Dev); - return IRQ_HANDLED; } @@ -1067,6 +1073,11 @@ static int /*__devinit*/ fm_probe(struct platform_device *of_dev) return -EIO; } +#ifdef CONFIG_PM + device_set_wakeup_capable(p_LnxWrpFmDev->dev, true); + device_set_wakeup_enable(p_LnxWrpFmDev->dev, 1); +#endif + DBG(TRACE, ("FM%d probed", p_LnxWrpFmDev->id)); return 0; @@ -1114,38 +1125,45 @@ 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; + +struct device *g_fm_dev; + static int fm_soc_suspend(struct device *dev) { - if (started_ar_enter) + int err = 0; + t_LnxWrpFmDev *p_LnxWrpFmDev = dev_get_drvdata(get_device(dev)); + g_fm_dev = dev; + if (p_LnxWrpFmDev->h_DsarRxPort) { uint32_t *fmclk; #ifdef CONFIG_FSL_QORIQ_PM fsl_set_power_except(dev,1); #endif - FM_PORT_Dsar_enter_final(); + err = FM_PORT_EnterDsarFinal(p_LnxWrpFmDev->h_DsarRxPort, + p_LnxWrpFmDev->h_DsarTxPort); fmclk = ioremap(SCFG_FMCLKDPSLPCR_ADDR, 4); WRITE_UINT32(*fmclk, SCFG_FMCLKDPSLPCR_DS_VAL); } - return 0; + return err; } static int fm_soc_resume(struct device *dev) { - if (started_ar_enter) + t_LnxWrpFmDev *p_LnxWrpFmDev = dev_get_drvdata(get_device(dev)); + if (p_LnxWrpFmDev->h_DsarRxPort) { uint32_t *fmclk; fmclk = ioremap(SCFG_FMCLKDPSLPCR_ADDR, 4); WRITE_UINT32(*fmclk, SCFG_FMCLKDPSLPCR_NORMAL_VAL); - started_ar_enter = false; + p_LnxWrpFmDev->h_DsarRxPort = 0; + p_LnxWrpFmDev->h_DsarTxPort = 0; } return 0; } static const struct dev_pm_ops fm_pm_ops = { - .suspend_noirq = fm_soc_suspend, - .resume_noirq = fm_soc_resume, + .suspend = fm_soc_suspend, + .resume = fm_soc_resume, }; #define FM_PM_OPS (&fm_pm_ops) @@ -1379,14 +1397,15 @@ int fm_port_enter_autores_for_deepsleep(struct fm_port *port, struct auto_res_port_params *params) { t_LnxWrpFmPortDev *p_LnxWrpFmPortDev = (t_LnxWrpFmPortDev *)port; + t_LnxWrpFmDev* p_LnxWrpFmDev = (t_LnxWrpFmDev*)p_LnxWrpFmPortDev->h_LnxWrpFmDev; + p_LnxWrpFmDev->h_DsarRxPort = p_LnxWrpFmPortDev->h_Dev; + p_LnxWrpFmDev->h_DsarTxPort = params->h_FmPortTx; + /*Register other under /proc/autoresponse */ if (WARN_ON(sizeof(t_FmPortDsarParams) != sizeof(struct auto_res_port_params))) return -EFAULT; FM_PORT_EnterDsar(p_LnxWrpFmPortDev->h_Dev, (t_FmPortDsarParams*)params); -#ifdef CONFIG_PM - started_ar_enter = true; -#endif return 0; } EXPORT_SYMBOL(fm_port_enter_autores_for_deepsleep); @@ -1413,6 +1432,8 @@ EXPORT_SYMBOL(fm_port_get_autores_stats); int fm_port_suspend(struct fm_port *port) { t_LnxWrpFmPortDev *p_LnxWrpFmPortDev = (t_LnxWrpFmPortDev *)port; + if (p_LnxWrpFmPortDev->id == 3) + return 0; if (!FM_PORT_IsInDsar(p_LnxWrpFmPortDev->h_Dev)) return FM_PORT_Disable(p_LnxWrpFmPortDev->h_Dev); else diff --git a/drivers/net/ethernet/freescale/fman/src/wrapper/lnxwrp_fm.h b/drivers/net/ethernet/freescale/fman/src/wrapper/lnxwrp_fm.h index 9c657ac..05202a2 100644 --- a/drivers/net/ethernet/freescale/fman/src/wrapper/lnxwrp_fm.h +++ b/drivers/net/ethernet/freescale/fman/src/wrapper/lnxwrp_fm.h @@ -217,6 +217,9 @@ typedef struct { t_Handle h_PcdDev; t_Handle h_RtcDev; + t_Handle h_DsarRxPort; + t_Handle h_DsarTxPort; + t_LnxWrpFmPortDev hcPort; t_LnxWrpFmPortDev opPorts[FM_MAX_NUM_OF_OH_PORTS-1]; t_LnxWrpFmPortDev rxPorts[FM_MAX_NUM_OF_RX_PORTS]; -- cgit v0.10.2