Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
0002 /* Copyright(c) 2007 - 2011 Realtek Corporation. */
0003 
0004 #include "../include/HalPwrSeqCmd.h"
0005 
0006 #define PWR_CMD_WRITE           0x01
0007      /*  offset: the read register offset */
0008      /*  msk: the mask of the write bits */
0009      /*  value: write value */
0010      /*  note: driver shall implement this cmd by read & msk after write */
0011 
0012 #define PWR_CMD_POLLING         0x02
0013      /*  offset: the read register offset */
0014      /*  msk: the mask of the polled value */
0015      /*  value: the value to be polled, masked by the msd field. */
0016      /*  note: driver shall implement this cmd by */
0017      /*  do{ */
0018      /*  if ( (Read(offset) & msk) == (value & msk) ) */
0019      /*  break; */
0020      /*  } while (not timeout); */
0021 
0022 #define PWR_CMD_DELAY           0x03
0023      /*  offset: the value to delay (in us) */
0024      /*  msk: N/A */
0025      /*  value: N/A */
0026 
0027 struct wl_pwr_cfg {
0028     u16 offset;
0029     u8 cmd:4;
0030     u8 msk;
0031     u8 value;
0032 };
0033 
0034 #define GET_PWR_CFG_OFFSET(__PWR_CMD)       __PWR_CMD.offset
0035 #define GET_PWR_CFG_CMD(__PWR_CMD)      __PWR_CMD.cmd
0036 #define GET_PWR_CFG_MASK(__PWR_CMD)     __PWR_CMD.msk
0037 #define GET_PWR_CFG_VALUE(__PWR_CMD)        __PWR_CMD.value
0038 
0039 static struct wl_pwr_cfg rtl8188E_power_on_flow[] = {
0040     { 0x0006, PWR_CMD_POLLING, BIT(1), BIT(1) },
0041     { 0x0002, PWR_CMD_WRITE, BIT(0) | BIT(1), 0 }, /* reset BB */
0042     { 0x0026, PWR_CMD_WRITE, BIT(7), BIT(7) }, /* schmitt trigger */
0043     { 0x0005, PWR_CMD_WRITE, BIT(7), 0 }, /* disable HWPDN (control by DRV)*/
0044     { 0x0005, PWR_CMD_WRITE, BIT(4) | BIT(3), 0 }, /* disable WL suspend*/
0045     { 0x0005, PWR_CMD_WRITE, BIT(0), BIT(0) },
0046     { 0x0005, PWR_CMD_POLLING, BIT(0), 0 },
0047     { 0x0023, PWR_CMD_WRITE, BIT(4), 0 },
0048 };
0049 
0050 static struct wl_pwr_cfg rtl8188E_card_disable_flow[] = {
0051     { 0x001F, PWR_CMD_WRITE, 0xFF, 0 }, /* turn off RF */
0052     { 0x0023, PWR_CMD_WRITE, BIT(4), BIT(4) }, /* LDO Sleep mode */
0053     { 0x0005, PWR_CMD_WRITE, BIT(1), BIT(1) }, /* turn off MAC by HW state machine */
0054     { 0x0005, PWR_CMD_POLLING, BIT(1), 0 },
0055     { 0x0026, PWR_CMD_WRITE, BIT(7), BIT(7) }, /* schmitt trigger */
0056     { 0x0005, PWR_CMD_WRITE, BIT(3) | BIT(4), BIT(3) }, /* enable WL suspend */
0057     { 0x0007, PWR_CMD_WRITE, 0xFF, 0 }, /* enable bandgap mbias in suspend */
0058     { 0x0041, PWR_CMD_WRITE, BIT(4), 0 }, /* Clear SIC_EN register */
0059     { 0xfe10, PWR_CMD_WRITE, BIT(4), BIT(4) }, /* Set USB suspend enable local register */
0060 };
0061 
0062 /* This is used by driver for LPSRadioOff Procedure, not for FW LPS Step */
0063 static struct wl_pwr_cfg rtl8188E_enter_lps_flow[] = {
0064     { 0x0522, PWR_CMD_WRITE, 0xFF, 0x7F },/* Tx Pause */
0065     { 0x05F8, PWR_CMD_POLLING, 0xFF, 0 }, /* Should be zero if no packet is transmitted */
0066     { 0x05F9, PWR_CMD_POLLING, 0xFF, 0 }, /* Should be zero if no packet is transmitted */
0067     { 0x05FA, PWR_CMD_POLLING, 0xFF, 0 }, /* Should be zero if no packet is transmitted */
0068     { 0x05FB, PWR_CMD_POLLING, 0xFF, 0 }, /* Should be zero if no packet is transmitted */
0069     { 0x0002, PWR_CMD_WRITE, BIT(0), 0 }, /* CCK and OFDM are disabled, clocks are gated */
0070     { 0x0002, PWR_CMD_DELAY, 0, 0 },
0071     { 0x0100, PWR_CMD_WRITE, 0xFF, 0x3F }, /* Reset MAC TRX */
0072     { 0x0101, PWR_CMD_WRITE, BIT(1), 0 }, /* check if removed later */
0073     { 0x0553, PWR_CMD_WRITE, BIT(5), BIT(5) }, /* Respond TxOK to scheduler */
0074 };
0075 
0076 u8 HalPwrSeqCmdParsing(struct adapter *padapter, enum r8188eu_pwr_seq seq)
0077 {
0078     struct wl_pwr_cfg pwrcfgcmd = {0};
0079     struct wl_pwr_cfg *pwrseqcmd;
0080     u8 poll_bit = false;
0081     u8 idx, num_steps;
0082     u8 value = 0;
0083     u32 offset = 0;
0084     u32 poll_count = 0; /*  polling autoload done. */
0085     u32 max_poll_count = 5000;
0086     int res;
0087 
0088     switch (seq) {
0089     case PWR_ON_FLOW:
0090         pwrseqcmd = rtl8188E_power_on_flow;
0091         num_steps = ARRAY_SIZE(rtl8188E_power_on_flow);
0092         break;
0093     case DISABLE_FLOW:
0094         pwrseqcmd = rtl8188E_card_disable_flow;
0095         num_steps = ARRAY_SIZE(rtl8188E_card_disable_flow);
0096         break;
0097     case LPS_ENTER_FLOW:
0098         pwrseqcmd = rtl8188E_enter_lps_flow;
0099         num_steps = ARRAY_SIZE(rtl8188E_enter_lps_flow);
0100         break;
0101     default:
0102         return false;
0103     }
0104 
0105     for (idx = 0; idx < num_steps; idx++) {
0106         pwrcfgcmd = pwrseqcmd[idx];
0107 
0108         switch (GET_PWR_CFG_CMD(pwrcfgcmd)) {
0109         case PWR_CMD_WRITE:
0110             offset = GET_PWR_CFG_OFFSET(pwrcfgcmd);
0111 
0112             /*  Read the value from system register */
0113             res = rtw_read8(padapter, offset, &value);
0114             if (res)
0115                 return false;
0116 
0117             value &= ~(GET_PWR_CFG_MASK(pwrcfgcmd));
0118             value |= (GET_PWR_CFG_VALUE(pwrcfgcmd) & GET_PWR_CFG_MASK(pwrcfgcmd));
0119 
0120             /*  Write the value back to system register */
0121             rtw_write8(padapter, offset, value);
0122             break;
0123         case PWR_CMD_POLLING:
0124             poll_bit = false;
0125             offset = GET_PWR_CFG_OFFSET(pwrcfgcmd);
0126             do {
0127                 res = rtw_read8(padapter, offset, &value);
0128                 if (res)
0129                     return false;
0130 
0131                 value &= GET_PWR_CFG_MASK(pwrcfgcmd);
0132                 if (value == (GET_PWR_CFG_VALUE(pwrcfgcmd) & GET_PWR_CFG_MASK(pwrcfgcmd)))
0133                     poll_bit = true;
0134                 else
0135                     udelay(10);
0136 
0137                 if (poll_count++ > max_poll_count)
0138                     return false;
0139             } while (!poll_bit);
0140             break;
0141         case PWR_CMD_DELAY:
0142             udelay(GET_PWR_CFG_OFFSET(pwrcfgcmd));
0143             break;
0144         default:
0145             break;
0146         }
0147     }
0148     return true;
0149 }