Messages in this thread | | | Date | Mon, 4 Sep 2017 14:19:42 +0100 | From | Lee Jones <> | Subject | Re: [PATCH v4] mfd: Add support for RTS5250S power saving |
| |
On Thu, 24 Aug 2017, rui_feng@realsil.com.cn wrote:
> From: rui_feng <rui_feng@realsil.com.cn> > > Signed-off-by: Rui Feng <rui_feng@realsil.com.cn> > --- > drivers/mfd/rts5249.c | 154 +++++++++++++++++++++++++++++++++++++ > drivers/mfd/rtsx_pcr.c | 177 +++++++++++++++++++++++++++++++++++++++++-- > drivers/mfd/rtsx_pcr.h | 12 +++ > include/linux/mfd/rtsx_pci.h | 85 +++++++++++++++++++++ > 4 files changed, 423 insertions(+), 5 deletions(-) > > diff --git a/drivers/mfd/rts5249.c b/drivers/mfd/rts5249.c > index 40f8bb1..25d25c7f 100644 > --- a/drivers/mfd/rts5249.c > +++ b/drivers/mfd/rts5249.c > @@ -103,8 +103,64 @@ static void rtsx_base_force_power_down(struct rtsx_pcr *pcr, u8 pm_state) > rtsx_pci_write_register(pcr, FPDCTL, 0x03, 0x03); > } > > +static void rts5249_init_from_cfg(struct rtsx_pcr *pcr) > +{ > + struct rtsx_cr_option *option = &(pcr->option); > + u32 lval; > + > + if (CHK_PCI_PID(pcr, PID_524A)) > + rtsx_pci_read_config_dword(pcr, > + PCR_ASPM_SETTING_REG1, &lval); > + else > + rtsx_pci_read_config_dword(pcr, > + PCR_ASPM_SETTING_REG2, &lval); > + > + if (lval & ASPM_L1_1_EN_MASK) > + rtsx_set_dev_flag(pcr, ASPM_L1_1_EN); > + > + if (lval & ASPM_L1_2_EN_MASK) > + rtsx_set_dev_flag(pcr, ASPM_L1_2_EN); > + > + if (lval & PM_L1_1_EN_MASK) > + rtsx_set_dev_flag(pcr, PM_L1_1_EN); > + > + if (lval & PM_L1_2_EN_MASK) > + rtsx_set_dev_flag(pcr, PM_L1_2_EN); > + > + if (option->ltr_en) { > + u16 val; > + > + pcie_capability_read_word(pcr->pci, PCI_EXP_DEVCTL2, &val); > + if (val & PCI_EXP_DEVCTL2_LTR_EN) { > + option->ltr_enabled = true; > + option->ltr_active = true; > + rtsx_set_ltr_latency(pcr, option->ltr_active_latency); > + } else { > + option->ltr_enabled = false; > + } > + } > +} > + > +static int rts5249_init_from_hw(struct rtsx_pcr *pcr) > +{ > + struct rtsx_cr_option *option = &(pcr->option); > + > + if (rtsx_check_dev_flag(pcr, ASPM_L1_1_EN | ASPM_L1_2_EN > + | PM_L1_1_EN | PM_L1_2_EN)) > + option->force_clkreq_0 = false; > + else > + option->force_clkreq_0 = true; > + > + return 0; > +} > + > static int rts5249_extra_init_hw(struct rtsx_pcr *pcr) > { > + struct rtsx_cr_option *option = &(pcr->option); > + > + rts5249_init_from_cfg(pcr); > + rts5249_init_from_hw(pcr); > + > rtsx_pci_init_cmd(pcr); > > /* Rest L1SUB Config */ > @@ -125,6 +181,17 @@ static int rts5249_extra_init_hw(struct rtsx_pcr *pcr) > else > rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, PETXCFG, 0xB0, 0x80); > > + /* > + *If u_force_clkreq_0 is enabled, CLKREQ# PIN will be forced > + *to drive low, and we forcibly request clock. > + */
You need spaces after the '*'s.
> + if (option->force_clkreq_0) > + rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, PETXCFG, > + FORCE_CLKREQ_DELINK_MASK, FORCE_CLKREQ_LOW); > + else > + rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, PETXCFG, > + FORCE_CLKREQ_DELINK_MASK, FORCE_CLKREQ_HIGH); > + > return rtsx_pci_send_cmd(pcr, 100);
What is 100?
> } > > @@ -285,6 +352,31 @@ static int rtsx_base_switch_output_voltage(struct rtsx_pcr *pcr, u8 voltage) > return rtsx_pci_send_cmd(pcr, 100); > } > > +static void rts5249_set_aspm(struct rtsx_pcr *pcr, bool enable) > +{ > + struct rtsx_cr_option *option = &pcr->option; > + u8 val = 0; > + > + if (pcr->aspm_enabled == enable) > + return; > + > + if (option->dev_aspm_mode == DEV_ASPM_DYNAMIC) { > + if (enable) > + val = pcr->aspm_en; > + rtsx_pci_update_cfg_byte(pcr, > + pcr->pcie_cap + PCI_EXP_LNKCTL, > + 0xFC, val);
0xFC needs defining.
> + } else if (option->dev_aspm_mode == DEV_ASPM_BACKDOOR) { > + u8 mask = FORCE_ASPM_VAL_MASK | FORCE_ASPM_CTL0; > + > + if (!enable) > + val = FORCE_ASPM_CTL0; > + rtsx_pci_write_register(pcr, ASPM_FORCE_CTL, mask, val); > + } > + > + pcr->aspm_enabled = enable; > +} > + > static const struct pcr_ops rts5249_pcr_ops = { > .fetch_vendor_settings = rtsx_base_fetch_vendor_settings, > .extra_init_hw = rts5249_extra_init_hw, > @@ -297,6 +389,7 @@ static int rtsx_base_switch_output_voltage(struct rtsx_pcr *pcr, u8 voltage) > .card_power_off = rtsx_base_card_power_off, > .switch_output_voltage = rtsx_base_switch_output_voltage, > .force_power_down = rtsx_base_force_power_down, > + .set_aspm = rts5249_set_aspm, > }; > > /* SD Pull Control Enable: > @@ -353,6 +446,8 @@ static int rtsx_base_switch_output_voltage(struct rtsx_pcr *pcr, u8 voltage) > > void rts5249_init_params(struct rtsx_pcr *pcr) > { > + struct rtsx_cr_option *option = &(pcr->option); > + > pcr->extra_caps = EXTRA_CAPS_SD_SDR50 | EXTRA_CAPS_SD_SDR104; > pcr->num_slots = 2; > pcr->ops = &rts5249_pcr_ops; > @@ -372,6 +467,21 @@ void rts5249_init_params(struct rtsx_pcr *pcr) > pcr->ms_pull_ctl_disable_tbl = rts5249_ms_pull_ctl_disable_tbl; > > pcr->reg_pm_ctrl3 = PM_CTRL3; > + > + option->dev_flags = 0;
Remove this line.
> + option->dev_flags |= (LTR_L1SS_PWR_GATE_CHECK_CARD_EN > + | LTR_L1SS_PWR_GATE_EN);
Don't 'OR', just '='.
> + option->ltr_en = true; > + > + /* init latency of active, idle, L1OFF to 60us, 300us, 3ms */
"Init"
> + option->ltr_active_latency = LTR_ACTIVE_LATENCY_DEFAULT; > + option->ltr_idle_latency = LTR_IDLE_LATENCY_DEFAULT; > + option->ltr_l1off_latency = LTR_L1OFF_LATENCY_DEFAULT; > + option->dev_aspm_mode = DEV_ASPM_DYNAMIC; > + option->l1_snooze_delay = L1_SNOOZE_DELAY_DEFAULT; > + option->ltr_l1off_sspwrgate = LTR_L1OFF_SSPWRGATE_5249_DEFAULT; > + option->ltr_l1off_snooze_sspwrgate = > + LTR_L1OFF_SNOOZE_SSPWRGATE_5249_DEFAULT; > } > > static int rts524a_write_phy(struct rtsx_pcr *pcr, u8 addr, u16 val) > @@ -459,6 +569,40 @@ static int rts524a_extra_init_hw(struct rtsx_pcr *pcr) > return 0; > } > > +static void rts5250_set_l1off_cfg_sub_d0(struct rtsx_pcr *pcr, int active) > +{ > + struct rtsx_cr_option *option = &(pcr->option); > + > + u32 interrupt = rtsx_pci_readl(pcr, RTSX_BIPR); > + int card_exist = (interrupt & SD_EXIST) | (interrupt & MS_EXIST); > + int aspm_L1_1, aspm_L1_2; > + u8 val = 0;
No need to pre-allocate.
> + aspm_L1_1 = rtsx_check_dev_flag(pcr, ASPM_L1_1_EN); > + aspm_L1_2 = rtsx_check_dev_flag(pcr, ASPM_L1_2_EN); > + > + if (active) { > + /* run, latency: 60us */ > + if (aspm_L1_1) > + val = option->ltr_l1off_snooze_sspwrgate; > + } else { > + /* l1off, latency: 300us */ > + if (aspm_L1_2) > + val = option->ltr_l1off_sspwrgate; > + } > + > + if (aspm_L1_1 || aspm_L1_2) { > + if (rtsx_check_dev_flag(pcr, > + LTR_L1SS_PWR_GATE_CHECK_CARD_EN)) { > + if (card_exist) > + val &= ~L1OFF_MBIAS2_EN_5250; > + else > + val |= L1OFF_MBIAS2_EN_5250; > + } > + } > + rtsx_set_l1off_sub(pcr, val); > +} > + > static const struct pcr_ops rts524a_pcr_ops = { > .write_phy = rts524a_write_phy, > .read_phy = rts524a_read_phy, > @@ -473,11 +617,16 @@ static int rts524a_extra_init_hw(struct rtsx_pcr *pcr) > .card_power_off = rtsx_base_card_power_off, > .switch_output_voltage = rtsx_base_switch_output_voltage, > .force_power_down = rtsx_base_force_power_down, > + .set_l1off_cfg_sub_d0 = rts5250_set_l1off_cfg_sub_d0, > + .set_aspm = rts5249_set_aspm, > }; > > void rts524a_init_params(struct rtsx_pcr *pcr) > { > rts5249_init_params(pcr); > + pcr->option.ltr_l1off_sspwrgate = LTR_L1OFF_SSPWRGATE_5250_DEFAULT; > + pcr->option.ltr_l1off_snooze_sspwrgate = > + LTR_L1OFF_SNOOZE_SSPWRGATE_5250_DEFAULT; > > pcr->reg_pm_ctrl3 = RTS524A_PM_CTRL3; > pcr->ops = &rts524a_pcr_ops; > @@ -576,11 +725,16 @@ static int rts525a_extra_init_hw(struct rtsx_pcr *pcr) > .card_power_off = rtsx_base_card_power_off, > .switch_output_voltage = rts525a_switch_output_voltage, > .force_power_down = rtsx_base_force_power_down, > + .set_l1off_cfg_sub_d0 = rts5250_set_l1off_cfg_sub_d0, > + .set_aspm = rts5249_set_aspm, > }; > > void rts525a_init_params(struct rtsx_pcr *pcr) > { > rts5249_init_params(pcr); > + pcr->option.ltr_l1off_sspwrgate = LTR_L1OFF_SSPWRGATE_5250_DEFAULT; > + pcr->option.ltr_l1off_snooze_sspwrgate = > + LTR_L1OFF_SNOOZE_SSPWRGATE_5250_DEFAULT; > > pcr->reg_pm_ctrl3 = RTS524A_PM_CTRL3; > pcr->ops = &rts525a_pcr_ops; > diff --git a/drivers/mfd/rtsx_pcr.c b/drivers/mfd/rtsx_pcr.c > index a0ac89d..50a6e67 100644 > --- a/drivers/mfd/rtsx_pcr.c > +++ b/drivers/mfd/rtsx_pcr.c > @@ -79,6 +79,131 @@ static inline void rtsx_pci_disable_aspm(struct rtsx_pcr *pcr) > 0xFC, 0); > } > > +int rtsx_comm_set_ltr_latency(struct rtsx_pcr *pcr, u32 latency) > +{ > + rtsx_pci_write_register(pcr, MSGTXDATA0, 0xFF, (u8) (latency & 0xFF));
What is (the first) 0xFF?
> + rtsx_pci_write_register(pcr, MSGTXDATA1, > + 0xFF, (u8)((latency >> 8) & 0xFF)); > + rtsx_pci_write_register(pcr, MSGTXDATA2, > + 0xFF, (u8)((latency >> 16) & 0xFF)); > + rtsx_pci_write_register(pcr, MSGTXDATA3, > + 0xFF, (u8)((latency >> 24) & 0xFF)); > + rtsx_pci_write_register(pcr, LTR_CTL, LTR_TX_EN_MASK | > + LTR_LATENCY_MODE_MASK, LTR_TX_EN_1 | LTR_LATENCY_MODE_SW); > + > + return 0; > +} > + > +int rtsx_set_ltr_latency(struct rtsx_pcr *pcr, u32 latency) > +{ > + if (pcr->ops->set_ltr_latency) > + return pcr->ops->set_ltr_latency(pcr, latency); > + else > + return rtsx_comm_set_ltr_latency(pcr, latency); > +} > + > +static void rtsx_comm_set_aspm(struct rtsx_pcr *pcr, bool enable) > +{ > + struct rtsx_cr_option *option = &pcr->option; > + > + if (pcr->aspm_enabled == enable) > + return; > + > + if (option->dev_aspm_mode == DEV_ASPM_DYNAMIC) { > + if (enable) > + rtsx_pci_enable_aspm(pcr); > + else > + rtsx_pci_disable_aspm(pcr); > + } else if (option->dev_aspm_mode == DEV_ASPM_BACKDOOR) { > + u8 mask = FORCE_ASPM_VAL_MASK; > + u8 val = 0; > + > + if (enable) > + val = pcr->aspm_en; > + rtsx_pci_write_register(pcr, ASPM_FORCE_CTL, mask, val); > + } > + > + pcr->aspm_enabled = enable; > +} > + > +static void rtsx_disable_aspm(struct rtsx_pcr *pcr) > +{ > + if (pcr->ops->set_aspm) > + pcr->ops->set_aspm(pcr, false); > + else > + rtsx_comm_set_aspm(pcr, false); > +} > + > +int rtsx_set_l1off_sub(struct rtsx_pcr *pcr, u8 val) > +{ > + rtsx_pci_write_register(pcr, L1SUB_CONFIG3, 0xFF, val); > + > + return 0; > +} > + > +static void rtsx_comm_set_l1off_cfg_sub_d0(struct rtsx_pcr *pcr, int active) > +{ > + struct rtsx_cr_option *option = &(pcr->option); > + > + u32 interrupt = rtsx_pci_readl(pcr, RTSX_BIPR); > + int card_exist = (interrupt & SD_EXIST) | (interrupt & MS_EXIST); > + int aspm_L1_1, aspm_L1_2; > + u8 val = 0;
No need to pre-initialise.
> + aspm_L1_1 = rtsx_check_dev_flag(pcr, ASPM_L1_1_EN); > + aspm_L1_2 = rtsx_check_dev_flag(pcr, ASPM_L1_2_EN); > + > + if (active) { > + /* run, latency: 60us */ > + if (aspm_L1_1) > + val = option->ltr_l1off_snooze_sspwrgate; > + } else { > + /* l1off, latency: 300us */ > + if (aspm_L1_2) > + val = option->ltr_l1off_sspwrgate; > + } > + > + if (aspm_L1_1 || aspm_L1_2) { > + if (rtsx_check_dev_flag(pcr, > + LTR_L1SS_PWR_GATE_CHECK_CARD_EN)) { > + if (card_exist) > + val &= ~L1OFF_MBIAS2_EN_COMM; > + else > + val |= L1OFF_MBIAS2_EN_COMM; > + } > + } > + rtsx_set_l1off_sub(pcr, val); > +}
This function looks very similar to the one above.
Any way you can integrate the two?
> +void rtsx_set_l1off_sub_cfg_d0(struct rtsx_pcr *pcr, int active) > +{ > + if (pcr->ops->set_l1off_cfg_sub_d0) > + pcr->ops->set_l1off_cfg_sub_d0(pcr, active); > + else > + rtsx_comm_set_l1off_cfg_sub_d0(pcr, active); > +} > + > +static void rtsx_comm_pm_full_on(struct rtsx_pcr *pcr) > +{ > + struct rtsx_cr_option *option = &pcr->option; > + > + rtsx_disable_aspm(pcr); > + > + if (option->ltr_enabled) > + rtsx_set_ltr_latency(pcr, option->ltr_active_latency); > + > + if (rtsx_check_dev_flag(pcr, LTR_L1SS_PWR_GATE_EN)) > + rtsx_set_l1off_sub_cfg_d0(pcr, 1); > +} > + > +void rtsx_pm_full_on(struct rtsx_pcr *pcr) > +{ > + if (pcr->ops->full_on) > + pcr->ops->full_on(pcr); > + else > + rtsx_comm_pm_full_on(pcr); > +} > + > void rtsx_pci_start_run(struct rtsx_pcr *pcr) > { > /* If pci device removed, don't queue idle work any more */ > @@ -89,9 +214,7 @@ void rtsx_pci_start_run(struct rtsx_pcr *pcr) > pcr->state = PDEV_STAT_RUN; > if (pcr->ops->enable_auto_blink) > pcr->ops->enable_auto_blink(pcr); > - > - if (pcr->aspm_en) > - rtsx_pci_disable_aspm(pcr); > + rtsx_pm_full_on(pcr); > } > > mod_delayed_work(system_wq, &pcr->idle_work, msecs_to_jiffies(200)); > @@ -958,6 +1081,41 @@ static int rtsx_pci_acquire_irq(struct rtsx_pcr *pcr) > return 0; > } > > +static void rtsx_enable_aspm(struct rtsx_pcr *pcr) > +{ > + if (pcr->ops->set_aspm) > + pcr->ops->set_aspm(pcr, true); > + else > + rtsx_comm_set_aspm(pcr, true); > +} > + > +static void rtsx_comm_pm_power_saving(struct rtsx_pcr *pcr) > +{ > + struct rtsx_cr_option *option = &pcr->option; > + > + if (option->ltr_enabled) { > + u32 latency = option->ltr_l1off_latency; > + > + if (rtsx_check_dev_flag(pcr, L1_SNOOZE_TEST_EN)) > + mdelay(option->l1_snooze_delay); > + > + rtsx_set_ltr_latency(pcr, latency); > + } > + > + if (rtsx_check_dev_flag(pcr, LTR_L1SS_PWR_GATE_EN)) > + rtsx_set_l1off_sub_cfg_d0(pcr, 0); > + > + rtsx_enable_aspm(pcr); > +} > + > +void rtsx_pm_power_saving(struct rtsx_pcr *pcr) > +{ > + if (pcr->ops->power_saving) > + pcr->ops->power_saving(pcr); > + else > + rtsx_comm_pm_power_saving(pcr); > +} > + > static void rtsx_pci_idle_work(struct work_struct *work) > { > struct delayed_work *dwork = to_delayed_work(work); > @@ -974,8 +1132,7 @@ static void rtsx_pci_idle_work(struct work_struct *work) > if (pcr->ops->turn_off_led) > pcr->ops->turn_off_led(pcr); > > - if (pcr->aspm_en) > - rtsx_pci_enable_aspm(pcr); > + rtsx_pm_power_saving(pcr); > > mutex_unlock(&pcr->pcr_mutex); > } > @@ -1063,6 +1220,16 @@ static int rtsx_pci_init_hw(struct rtsx_pcr *pcr) > if (err < 0) > return err; > > + switch (PCI_PID(pcr)) { > + case PID_5250: > + case PID_524A: > + case PID_525A: > + rtsx_pci_write_register(pcr, PM_CLK_FORCE_CTL, 1, 1); > + break; > + default: > + break; > + } > + > /* Enable clk_request_n to enable clock power management */ > rtsx_pci_write_config_byte(pcr, pcr->pcie_cap + PCI_EXP_LNKCTL + 1, 1); > /* Enter L1 when host tx idle */ > diff --git a/drivers/mfd/rtsx_pcr.h b/drivers/mfd/rtsx_pcr.h > index 931d1ae..39d4372 100644 > --- a/drivers/mfd/rtsx_pcr.h > +++ b/drivers/mfd/rtsx_pcr.h > @@ -32,6 +32,16 @@ > #define RTS524A_PME_FORCE_CTL 0xFF78 > #define RTS524A_PM_CTRL3 0xFF7E > > +#define LTR_ACTIVE_LATENCY_DEFAULT 0x883C > +#define LTR_IDLE_LATENCY_DEFAULT 0x892C > +#define LTR_L1OFF_LATENCY_DEFAULT 0x9003 > +#define L1_SNOOZE_DELAY_DEFAULT 1 > +#define LTR_L1OFF_SSPWRGATE_5249_DEFAULT 0xAF > +#define LTR_L1OFF_SSPWRGATE_5250_DEFAULT 0xFF > +#define LTR_L1OFF_SNOOZE_SSPWRGATE_5249_DEFAULT 0xAC > +#define LTR_L1OFF_SNOOZE_SSPWRGATE_5250_DEFAULT 0xF8
These should be prefixed/namespaced.
Shorten DEFAULT to DEF to save space.
> + > +
Why 2 '\n'?
> int __rtsx_pci_write_phy_register(struct rtsx_pcr *pcr, u8 addr, u16 val); > int __rtsx_pci_read_phy_register(struct rtsx_pcr *pcr, u8 addr, u16 *val); > > @@ -85,5 +95,7 @@ static inline u8 map_sd_drive(int idx) > > /* generic operations */ > int rtsx_gops_pm_reset(struct rtsx_pcr *pcr); > +int rtsx_set_ltr_latency(struct rtsx_pcr *pcr, u32 latency); > +int rtsx_set_l1off_sub(struct rtsx_pcr *pcr, u8 val); > > #endif > diff --git a/include/linux/mfd/rtsx_pci.h b/include/linux/mfd/rtsx_pci.h > index 116816f..4e2a9e7 100644 > --- a/include/linux/mfd/rtsx_pci.h > +++ b/include/linux/mfd/rtsx_pci.h > @@ -573,6 +573,12 @@ > #define MSGTXDATA3 0xFE47 > #define MSGTXCTL 0xFE48 > #define LTR_CTL 0xFE4A > +#define LTR_TX_EN_MASK BIT(7) > +#define LTR_TX_EN_1 BIT(7) > +#define LTR_TX_EN_0 0 > +#define LTR_LATENCY_MODE_MASK BIT(6) > +#define LTR_LATENCY_MODE_HW 0 > +#define LTR_LATENCY_MODE_SW BIT(6) > #define OBFF_CFG 0xFE4C > > #define CDRESUMECTL 0xFE52 > @@ -616,11 +622,16 @@ > #define L1SUB_CONFIG2 0xFE8E > #define L1SUB_AUTO_CFG 0x02 > #define L1SUB_CONFIG3 0xFE8F > +#define L1OFF_MBIAS2_EN_COMM BIT(4) > +#define L1OFF_MBIAS2_EN_5250 BIT(7) > > #define DUMMY_REG_RESET_0 0xFE90 > > #define AUTOLOAD_CFG_BASE 0xFF00 > #define PETXCFG 0xFF03 > +#define FORCE_CLKREQ_DELINK_MASK BIT(7) > +#define FORCE_CLKREQ_LOW 0x80 > +#define FORCE_CLKREQ_HIGH 0x00 > > #define PM_CTRL1 0xFF44 > #define CD_RESUME_EN_MASK 0xF0 > @@ -844,6 +855,9 @@ > #define PHY_DIG1E_RX_EN_KEEP 0x0001 > #define PHY_DUM_REG 0x1F > > +#define PCR_ASPM_SETTING_REG1 0x160 > +#define PCR_ASPM_SETTING_REG2 0x168 > + > #define PCR_SETTING_REG1 0x724 > #define PCR_SETTING_REG2 0x814 > #define PCR_SETTING_REG3 0x747 > @@ -876,14 +890,79 @@ struct pcr_ops { > int (*conv_clk_and_div_n)(int clk, int dir); > void (*fetch_vendor_settings)(struct rtsx_pcr *pcr); > void (*force_power_down)(struct rtsx_pcr *pcr, u8 pm_state); > + > + void (*set_aspm)(struct rtsx_pcr *pcr, bool enable); > + int (*set_ltr_latency)(struct rtsx_pcr *pcr, u32 latency); > + int (*set_l1off_sub)(struct rtsx_pcr *pcr, u8 val); > + void (*set_l1off_cfg_sub_d0)(struct rtsx_pcr *pcr, int active); > + void (*full_on)(struct rtsx_pcr *pcr); > + void (*power_saving)(struct rtsx_pcr *pcr); > }; > > enum PDEV_STAT {PDEV_STAT_IDLE, PDEV_STAT_RUN}; > > +#define ASPM_L1_1_EN_MASK BIT(3) > +#define ASPM_L1_2_EN_MASK BIT(2) > +#define PM_L1_1_EN_MASK BIT(1) > +#define PM_L1_2_EN_MASK BIT(0) > + > +#define ASPM_L1_1_EN BIT(0) > +#define ASPM_L1_2_EN BIT(1) > +#define PM_L1_1_EN BIT(2) > +#define PM_L1_2_EN BIT(3) > +#define LTR_L1SS_PWR_GATE_EN BIT(4) > +#define L1_SNOOZE_TEST_EN BIT(5) > +#define LTR_L1SS_PWR_GATE_CHECK_CARD_EN BIT(6) > + > +enum dev_aspm_mode { > + DEV_ASPM_DISABLE = 0, > + DEV_ASPM_DYNAMIC, > + DEV_ASPM_BACKDOOR, > + DEV_ASPM_STATIC, > +}; > + > +/* > + * struct rtsx_cr_option - card reader option > + * @dev_flags: device flags > + * @force_clkreq_0: force clock request > + * @ltr_en: enable ltr mode flag > + * @ltr_enabled: ltr mode in configure space flag > + * @ltr_active: ltr mode status > + * @ltr_active_latency: ltr mode active latency > + * @ltr_idle_latency: ltr mode idle latency > + * @ltr_l1off_latency: ltr mode l1off latency > + * @dev_aspm_mode: device aspm mode > + * @l1_snooze_delay: l1 snooze delay > + * @ltr_l1off_sspwrgate: ltr l1off sspwrgate > + * @ltr_l1off_snooze_sspwrgate: ltr l1off snooze sspwrgate > + */ > +struct rtsx_cr_option { > + u32 dev_flags; > + bool force_clkreq_0; > + bool ltr_en; > + bool ltr_enabled; > + bool ltr_active; > + u32 ltr_active_latency; > + u32 ltr_idle_latency; > + u32 ltr_l1off_latency; > + enum dev_aspm_mode dev_aspm_mode; > + u32 l1_snooze_delay; > + u8 ltr_l1off_sspwrgate; > + u8 ltr_l1off_snooze_sspwrgate; > +}; > + > +#define rtsx_set_dev_flag(cr, flag) \ > + ((cr)->option.dev_flags |= (flag)) > +#define rtsx_clear_dev_flag(cr, flag) \ > + ((cr)->option.dev_flags &= ~(flag)) > +#define rtsx_check_dev_flag(cr, flag) \ > + ((cr)->option.dev_flags & (flag)) > + > struct rtsx_pcr { > struct pci_dev *pci; > unsigned int id; > int pcie_cap; > + struct rtsx_cr_option option; > > /* pci resources */ > unsigned long addr; > @@ -940,6 +1019,7 @@ struct rtsx_pcr { > u8 card_drive_sel; > #define ASPM_L1_EN 0x02 > u8 aspm_en; > + bool aspm_enabled; > > #define PCR_MS_PMOS (1 << 0) > #define PCR_REVERSE_SOCKET (1 << 1) > @@ -964,6 +1044,11 @@ struct rtsx_pcr { > u8 dma_error_count; > }; > > +#define PID_524A 0x524A > +#define PID_5249 0x5249 > +#define PID_5250 0x5250 > +#define PID_525A 0x525A > + > #define CHK_PCI_PID(pcr, pid) ((pcr)->pci->device == (pid)) > #define PCI_VID(pcr) ((pcr)->pci->vendor) > #define PCI_PID(pcr) ((pcr)->pci->device)
-- Lee Jones Linaro STMicroelectronics Landing Team Lead Linaro.org │ Open source software for ARM SoCs Follow Linaro: Facebook | Twitter | Blog
| |