Commit 5da4e04a authored by Rui Feng's avatar Rui Feng Committed by Lee Jones

misc: rtsx: Add support for RTS5260

Add support for new chip rts5260.
In order to support rts5260, the definitions of
some internal registers and workflow have to be
modified and are different from its predecessors
and OCP function is added for RTS5260. So we need
this patch to ensure RTS5260 can work.
Signed-off-by: default avatarRui Feng <rui_feng@realsil.com.cn>
Reviewed-by: default avatarDaniel Bristot de Oliveira <bristot@redhat.com>
Tested-by: default avatarPerry Yuan <perry_yuan@dell.com>
Signed-off-by: default avatarLee Jones <lee.jones@linaro.org>
parent e455b69d
......@@ -4,7 +4,7 @@ config MISC_RTSX_PCI
select MFD_CORE
help
This supports for Realtek PCI-Express card reader including rts5209,
rts5227, rts522A, rts5229, rts5249, rts524A, rts525A, rtl8411.
rts5227, rts522A, rts5229, rts5249, rts524A, rts525A, rtl8411, rts5260.
Realtek card readers support access to many types of memory cards,
such as Memory Stick, Memory Stick Pro, Secure Digital and
MultiMediaCard.
......
rtsx_pci-objs := rtsx_pcr.o rts5209.o rts5229.o rtl8411.o rts5227.o rts5249.o
rtsx_pci-objs := rtsx_pcr.o rts5209.o rts5229.o rtl8411.o rts5227.o rts5249.o rts5260.o
obj-$(CONFIG_MISC_RTSX_PCI) += rtsx_pci.o
obj-$(CONFIG_MISC_RTSX_USB) += rtsx_usb.o
This diff is collapsed.
#ifndef __RTS5260_H__
#define __RTS5260_H__
#define RTS5260_DVCC_CTRL 0xFF73
#define RTS5260_DVCC_OCP_EN (0x01 << 7)
#define RTS5260_DVCC_OCP_THD_MASK (0x07 << 4)
#define RTS5260_DVCC_POWERON (0x01 << 3)
#define RTS5260_DVCC_OCP_CL_EN (0x01 << 2)
#define RTS5260_DVIO_CTRL 0xFF75
#define RTS5260_DVIO_OCP_EN (0x01 << 7)
#define RTS5260_DVIO_OCP_THD_MASK (0x07 << 4)
#define RTS5260_DVIO_POWERON (0x01 << 3)
#define RTS5260_DVIO_OCP_CL_EN (0x01 << 2)
#define RTS5260_DV331812_CFG 0xFF71
#define RTS5260_DV331812_OCP_EN (0x01 << 7)
#define RTS5260_DV331812_OCP_THD_MASK (0x07 << 4)
#define RTS5260_DV331812_POWERON (0x01 << 3)
#define RTS5260_DV331812_SEL (0x01 << 2)
#define RTS5260_DV331812_VDD1 (0x01 << 2)
#define RTS5260_DV331812_VDD2 (0x00 << 2)
#define RTS5260_DV331812_OCP_THD_120 (0x00 << 4)
#define RTS5260_DV331812_OCP_THD_140 (0x01 << 4)
#define RTS5260_DV331812_OCP_THD_160 (0x02 << 4)
#define RTS5260_DV331812_OCP_THD_180 (0x03 << 4)
#define RTS5260_DV331812_OCP_THD_210 (0x04 << 4)
#define RTS5260_DV331812_OCP_THD_240 (0x05 << 4)
#define RTS5260_DV331812_OCP_THD_270 (0x06 << 4)
#define RTS5260_DV331812_OCP_THD_300 (0x07 << 4)
#define RTS5260_DVIO_OCP_THD_250 (0x00 << 4)
#define RTS5260_DVIO_OCP_THD_300 (0x01 << 4)
#define RTS5260_DVIO_OCP_THD_350 (0x02 << 4)
#define RTS5260_DVIO_OCP_THD_400 (0x03 << 4)
#define RTS5260_DVIO_OCP_THD_450 (0x04 << 4)
#define RTS5260_DVIO_OCP_THD_500 (0x05 << 4)
#define RTS5260_DVIO_OCP_THD_550 (0x06 << 4)
#define RTS5260_DVIO_OCP_THD_600 (0x07 << 4)
#define RTS5260_DVCC_OCP_THD_550 (0x00 << 4)
#define RTS5260_DVCC_OCP_THD_970 (0x05 << 4)
#endif
......@@ -62,6 +62,7 @@ static const struct pci_device_id rtsx_pci_ids[] = {
{ PCI_DEVICE(0x10EC, 0x5286), PCI_CLASS_OTHERS << 16, 0xFF0000 },
{ PCI_DEVICE(0x10EC, 0x524A), PCI_CLASS_OTHERS << 16, 0xFF0000 },
{ PCI_DEVICE(0x10EC, 0x525A), PCI_CLASS_OTHERS << 16, 0xFF0000 },
{ PCI_DEVICE(0x10EC, 0x5260), PCI_CLASS_OTHERS << 16, 0xFF0000 },
{ 0, }
};
......@@ -334,6 +335,9 @@ EXPORT_SYMBOL_GPL(rtsx_pci_read_phy_register);
void rtsx_pci_stop_cmd(struct rtsx_pcr *pcr)
{
if (pcr->ops->stop_cmd)
return pcr->ops->stop_cmd(pcr);
rtsx_pci_writel(pcr, RTSX_HCBCTLR, STOP_CMD);
rtsx_pci_writel(pcr, RTSX_HDBCTLR, STOP_DMA);
......@@ -826,7 +830,7 @@ int rtsx_pci_switch_clock(struct rtsx_pcr *pcr, unsigned int card_clock,
return err;
/* Wait SSC clock stable */
udelay(10);
udelay(SSC_CLOCK_STABLE_WAIT);
err = rtsx_pci_write_register(pcr, CLK_CTL, CLK_LOW_FREQ, 0);
if (err < 0)
return err;
......@@ -963,6 +967,20 @@ static void rtsx_pci_card_detect(struct work_struct *work)
pcr->slots[RTSX_MS_CARD].p_dev);
}
void rtsx_pci_process_ocp(struct rtsx_pcr *pcr)
{
if (pcr->ops->process_ocp)
pcr->ops->process_ocp(pcr);
}
int rtsx_pci_process_ocp_interrupt(struct rtsx_pcr *pcr)
{
if (pcr->option.ocp_en)
rtsx_pci_process_ocp(pcr);
return 0;
}
static irqreturn_t rtsx_pci_isr(int irq, void *dev_id)
{
struct rtsx_pcr *pcr = dev_id;
......@@ -987,6 +1005,9 @@ static irqreturn_t rtsx_pci_isr(int irq, void *dev_id)
int_reg &= (pcr->bier | 0x7FFFFF);
if (int_reg & SD_OC_INT)
rtsx_pci_process_ocp_interrupt(pcr);
if (int_reg & SD_INT) {
if (int_reg & SD_EXIST) {
pcr->card_inserted |= SD_EXIST;
......@@ -1119,6 +1140,102 @@ static void rtsx_pci_power_off(struct rtsx_pcr *pcr, u8 pm_state)
}
#endif
void rtsx_pci_enable_ocp(struct rtsx_pcr *pcr)
{
u8 val = SD_OCP_INT_EN | SD_DETECT_EN;
if (pcr->ops->enable_ocp)
pcr->ops->enable_ocp(pcr);
else
rtsx_pci_write_register(pcr, REG_OCPCTL, 0xFF, val);
}
void rtsx_pci_disable_ocp(struct rtsx_pcr *pcr)
{
u8 mask = SD_OCP_INT_EN | SD_DETECT_EN;
if (pcr->ops->disable_ocp)
pcr->ops->disable_ocp(pcr);
else
rtsx_pci_write_register(pcr, REG_OCPCTL, mask, 0);
}
void rtsx_pci_init_ocp(struct rtsx_pcr *pcr)
{
if (pcr->ops->init_ocp) {
pcr->ops->init_ocp(pcr);
} else {
struct rtsx_cr_option *option = &(pcr->option);
if (option->ocp_en) {
u8 val = option->sd_400mA_ocp_thd;
rtsx_pci_write_register(pcr, FPDCTL, OC_POWER_DOWN, 0);
rtsx_pci_write_register(pcr, REG_OCPPARA1,
SD_OCP_TIME_MASK, SD_OCP_TIME_800);
rtsx_pci_write_register(pcr, REG_OCPPARA2,
SD_OCP_THD_MASK, val);
rtsx_pci_write_register(pcr, REG_OCPGLITCH,
SD_OCP_GLITCH_MASK, pcr->hw_param.ocp_glitch);
rtsx_pci_enable_ocp(pcr);
} else {
/* OC power down */
rtsx_pci_write_register(pcr, FPDCTL, OC_POWER_DOWN,
OC_POWER_DOWN);
}
}
}
int rtsx_pci_get_ocpstat(struct rtsx_pcr *pcr, u8 *val)
{
if (pcr->ops->get_ocpstat)
return pcr->ops->get_ocpstat(pcr, val);
else
return rtsx_pci_read_register(pcr, REG_OCPSTAT, val);
}
void rtsx_pci_clear_ocpstat(struct rtsx_pcr *pcr)
{
if (pcr->ops->clear_ocpstat) {
pcr->ops->clear_ocpstat(pcr);
} else {
u8 mask = SD_OCP_INT_CLR | SD_OC_CLR;
u8 val = SD_OCP_INT_CLR | SD_OC_CLR;
rtsx_pci_write_register(pcr, REG_OCPCTL, mask, val);
rtsx_pci_write_register(pcr, REG_OCPCTL, mask, 0);
}
}
int sd_power_off_card3v3(struct rtsx_pcr *pcr)
{
rtsx_pci_write_register(pcr, CARD_CLK_EN, SD_CLK_EN |
MS_CLK_EN | SD40_CLK_EN, 0);
rtsx_pci_write_register(pcr, CARD_OE, SD_OUTPUT_EN, 0);
rtsx_pci_card_power_off(pcr, RTSX_SD_CARD);
msleep(50);
rtsx_pci_card_pull_ctl_disable(pcr, RTSX_SD_CARD);
return 0;
}
int ms_power_off_card3v3(struct rtsx_pcr *pcr)
{
rtsx_pci_write_register(pcr, CARD_CLK_EN, SD_CLK_EN |
MS_CLK_EN | SD40_CLK_EN, 0);
rtsx_pci_card_pull_ctl_disable(pcr, RTSX_MS_CARD);
rtsx_pci_write_register(pcr, CARD_OE, MS_OUTPUT_EN, 0);
rtsx_pci_card_power_off(pcr, RTSX_MS_CARD);
return 0;
}
static int rtsx_pci_init_hw(struct rtsx_pcr *pcr)
{
int err;
......@@ -1189,6 +1306,7 @@ static int rtsx_pci_init_hw(struct rtsx_pcr *pcr)
case PID_5250:
case PID_524A:
case PID_525A:
case PID_5260:
rtsx_pci_write_register(pcr, PM_CLK_FORCE_CTL, 1, 1);
break;
default:
......@@ -1265,6 +1383,9 @@ static int rtsx_pci_init_chip(struct rtsx_pcr *pcr)
case 0x5286:
rtl8402_init_params(pcr);
break;
case 0x5260:
rts5260_init_params(pcr);
break;
}
pcr_dbg(pcr, "PID: 0x%04x, IC version: 0x%02x\n",
......
......@@ -44,6 +44,8 @@
#define ASPM_MASK_NEG 0xFC
#define MASK_8_BIT_DEF 0xFF
#define SSC_CLOCK_STABLE_WAIT 130
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);
......@@ -57,6 +59,7 @@ void rts5249_init_params(struct rtsx_pcr *pcr);
void rts524a_init_params(struct rtsx_pcr *pcr);
void rts525a_init_params(struct rtsx_pcr *pcr);
void rtl8411b_init_params(struct rtsx_pcr *pcr);
void rts5260_init_params(struct rtsx_pcr *pcr);
static inline u8 map_sd_drive(int idx)
{
......@@ -99,5 +102,12 @@ do { \
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);
void rtsx_pci_init_ocp(struct rtsx_pcr *pcr);
void rtsx_pci_disable_ocp(struct rtsx_pcr *pcr);
void rtsx_pci_enable_ocp(struct rtsx_pcr *pcr);
int rtsx_pci_get_ocpstat(struct rtsx_pcr *pcr, u8 *val);
void rtsx_pci_clear_ocpstat(struct rtsx_pcr *pcr);
int sd_power_off_card3v3(struct rtsx_pcr *pcr);
int ms_power_off_card3v3(struct rtsx_pcr *pcr);
#endif
This diff is collapsed.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment