Commit 4c4b8c105a7bbd4a8d41ab4458f01174fdf3fcbb

Authored by Wei WANG
Committed by Samuel Ortiz
1 parent 95e50f6a2f

mfd: rtsx: Support RTS5249

RTS5249 supports SD UHS-II interface.

In order to support SD UHS-II,the definitions of some internal
registers of RTS5249 have to be modified and are different from its
predecessors. So we need this patch to ensure RTS5249 can work, even
SD/MMC stack doesn't support UHS-II interface.

Signed-off-by: Wei WANG <wei_wang@realsil.com.cn>
Signed-off-by: Samuel Ortiz <sameo@linux.intel.com>

Showing 5 changed files with 284 additions and 1 deletions Side-by-side Diff

drivers/mfd/Makefile
... ... @@ -12,7 +12,7 @@
12 12 obj-$(CONFIG_MFD_CROS_EC_I2C) += cros_ec_i2c.o
13 13 obj-$(CONFIG_MFD_CROS_EC_SPI) += cros_ec_spi.o
14 14  
15   -rtsx_pci-objs := rtsx_pcr.o rts5209.o rts5229.o rtl8411.o rts5227.o
  15 +rtsx_pci-objs := rtsx_pcr.o rts5209.o rts5229.o rtl8411.o rts5227.o rts5249.o
16 16 obj-$(CONFIG_MFD_RTSX_PCI) += rtsx_pci.o
17 17  
18 18 obj-$(CONFIG_HTC_EGPIO) += htc-egpio.o
drivers/mfd/rts5249.c
  1 +/* Driver for Realtek PCI-Express card reader
  2 + *
  3 + * Copyright(c) 2009-2013 Realtek Semiconductor Corp. All rights reserved.
  4 + *
  5 + * This program is free software; you can redistribute it and/or modify it
  6 + * under the terms of the GNU General Public License as published by the
  7 + * Free Software Foundation; either version 2, or (at your option) any
  8 + * later version.
  9 + *
  10 + * This program is distributed in the hope that it will be useful, but
  11 + * WITHOUT ANY WARRANTY; without even the implied warranty of
  12 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  13 + * General Public License for more details.
  14 + *
  15 + * You should have received a copy of the GNU General Public License along
  16 + * with this program; if not, see <http://www.gnu.org/licenses/>.
  17 + *
  18 + * Author:
  19 + * Wei WANG <wei_wang@realsil.com.cn>
  20 + * No. 128, West Shenhu Road, Suzhou Industry Park, Suzhou, China
  21 + */
  22 +
  23 +#include <linux/module.h>
  24 +#include <linux/delay.h>
  25 +#include <linux/mfd/rtsx_pci.h>
  26 +
  27 +#include "rtsx_pcr.h"
  28 +
  29 +static u8 rts5249_get_ic_version(struct rtsx_pcr *pcr)
  30 +{
  31 + u8 val;
  32 +
  33 + rtsx_pci_read_register(pcr, DUMMY_REG_RESET_0, &val);
  34 + return val & 0x0F;
  35 +}
  36 +
  37 +static int rts5249_extra_init_hw(struct rtsx_pcr *pcr)
  38 +{
  39 + rtsx_pci_init_cmd(pcr);
  40 +
  41 + /* Configure GPIO as output */
  42 + rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, GPIO_CTL, 0x02, 0x02);
  43 + /* Switch LDO3318 source from DV33 to card_3v3 */
  44 + rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, LDO_PWR_SEL, 0x03, 0x00);
  45 + rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, LDO_PWR_SEL, 0x03, 0x01);
  46 + /* LED shine disabled, set initial shine cycle period */
  47 + rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, OLT_LED_CTL, 0x0F, 0x02);
  48 + /* Correct driving */
  49 + rtsx_pci_add_cmd(pcr, WRITE_REG_CMD,
  50 + SD30_CLK_DRIVE_SEL, 0xFF, 0x99);
  51 + rtsx_pci_add_cmd(pcr, WRITE_REG_CMD,
  52 + SD30_CMD_DRIVE_SEL, 0xFF, 0x99);
  53 + rtsx_pci_add_cmd(pcr, WRITE_REG_CMD,
  54 + SD30_DAT_DRIVE_SEL, 0xFF, 0x92);
  55 +
  56 + return rtsx_pci_send_cmd(pcr, 100);
  57 +}
  58 +
  59 +static int rts5249_optimize_phy(struct rtsx_pcr *pcr)
  60 +{
  61 + int err;
  62 +
  63 + err = rtsx_pci_write_phy_register(pcr, PHY_REG_REV, 0xFE46);
  64 + if (err < 0)
  65 + return err;
  66 +
  67 + msleep(1);
  68 +
  69 + return rtsx_pci_write_phy_register(pcr, PHY_BPCR, 0x05C0);
  70 +}
  71 +
  72 +static int rts5249_turn_on_led(struct rtsx_pcr *pcr)
  73 +{
  74 + return rtsx_pci_write_register(pcr, GPIO_CTL, 0x02, 0x02);
  75 +}
  76 +
  77 +static int rts5249_turn_off_led(struct rtsx_pcr *pcr)
  78 +{
  79 + return rtsx_pci_write_register(pcr, GPIO_CTL, 0x02, 0x00);
  80 +}
  81 +
  82 +static int rts5249_enable_auto_blink(struct rtsx_pcr *pcr)
  83 +{
  84 + return rtsx_pci_write_register(pcr, OLT_LED_CTL, 0x08, 0x08);
  85 +}
  86 +
  87 +static int rts5249_disable_auto_blink(struct rtsx_pcr *pcr)
  88 +{
  89 + return rtsx_pci_write_register(pcr, OLT_LED_CTL, 0x08, 0x00);
  90 +}
  91 +
  92 +static int rts5249_card_power_on(struct rtsx_pcr *pcr, int card)
  93 +{
  94 + int err;
  95 +
  96 + rtsx_pci_init_cmd(pcr);
  97 + rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, CARD_PWR_CTL,
  98 + SD_POWER_MASK, SD_VCC_PARTIAL_POWER_ON);
  99 + rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, PWR_GATE_CTRL,
  100 + LDO3318_PWR_MASK, 0x02);
  101 + err = rtsx_pci_send_cmd(pcr, 100);
  102 + if (err < 0)
  103 + return err;
  104 +
  105 + msleep(5);
  106 +
  107 + rtsx_pci_init_cmd(pcr);
  108 + rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, CARD_PWR_CTL,
  109 + SD_POWER_MASK, SD_VCC_POWER_ON);
  110 + rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, PWR_GATE_CTRL,
  111 + LDO3318_PWR_MASK, 0x06);
  112 + err = rtsx_pci_send_cmd(pcr, 100);
  113 + if (err < 0)
  114 + return err;
  115 +
  116 + return 0;
  117 +}
  118 +
  119 +static int rts5249_card_power_off(struct rtsx_pcr *pcr, int card)
  120 +{
  121 + rtsx_pci_init_cmd(pcr);
  122 + rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, CARD_PWR_CTL,
  123 + SD_POWER_MASK, SD_POWER_OFF);
  124 + rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, PWR_GATE_CTRL,
  125 + LDO3318_PWR_MASK, 0x00);
  126 + return rtsx_pci_send_cmd(pcr, 100);
  127 +}
  128 +
  129 +static int rts5249_switch_output_voltage(struct rtsx_pcr *pcr, u8 voltage)
  130 +{
  131 + int err;
  132 + u8 clk_drive, cmd_drive, dat_drive;
  133 +
  134 + if (voltage == OUTPUT_3V3) {
  135 + err = rtsx_pci_write_phy_register(pcr, PHY_TUNE, 0x4FC0 | 0x24);
  136 + if (err < 0)
  137 + return err;
  138 + clk_drive = 0x99;
  139 + cmd_drive = 0x99;
  140 + dat_drive = 0x92;
  141 + } else if (voltage == OUTPUT_1V8) {
  142 + err = rtsx_pci_write_phy_register(pcr, PHY_BACR, 0x3C02);
  143 + if (err < 0)
  144 + return err;
  145 + err = rtsx_pci_write_phy_register(pcr, PHY_TUNE, 0x4C40 | 0x24);
  146 + if (err < 0)
  147 + return err;
  148 + clk_drive = 0xb3;
  149 + cmd_drive = 0xb3;
  150 + dat_drive = 0xb3;
  151 + } else {
  152 + return -EINVAL;
  153 + }
  154 +
  155 + /* set pad drive */
  156 + rtsx_pci_init_cmd(pcr);
  157 + rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, SD30_CLK_DRIVE_SEL,
  158 + 0xFF, clk_drive);
  159 + rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, SD30_CMD_DRIVE_SEL,
  160 + 0xFF, cmd_drive);
  161 + rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, SD30_DAT_DRIVE_SEL,
  162 + 0xFF, dat_drive);
  163 + return rtsx_pci_send_cmd(pcr, 100);
  164 +}
  165 +
  166 +static const struct pcr_ops rts5249_pcr_ops = {
  167 + .extra_init_hw = rts5249_extra_init_hw,
  168 + .optimize_phy = rts5249_optimize_phy,
  169 + .turn_on_led = rts5249_turn_on_led,
  170 + .turn_off_led = rts5249_turn_off_led,
  171 + .enable_auto_blink = rts5249_enable_auto_blink,
  172 + .disable_auto_blink = rts5249_disable_auto_blink,
  173 + .card_power_on = rts5249_card_power_on,
  174 + .card_power_off = rts5249_card_power_off,
  175 + .switch_output_voltage = rts5249_switch_output_voltage,
  176 +};
  177 +
  178 +/* SD Pull Control Enable:
  179 + * SD_DAT[3:0] ==> pull up
  180 + * SD_CD ==> pull up
  181 + * SD_WP ==> pull up
  182 + * SD_CMD ==> pull up
  183 + * SD_CLK ==> pull down
  184 + */
  185 +static const u32 rts5249_sd_pull_ctl_enable_tbl[] = {
  186 + RTSX_REG_PAIR(CARD_PULL_CTL1, 0x66),
  187 + RTSX_REG_PAIR(CARD_PULL_CTL2, 0xAA),
  188 + RTSX_REG_PAIR(CARD_PULL_CTL3, 0xE9),
  189 + RTSX_REG_PAIR(CARD_PULL_CTL4, 0xAA),
  190 + 0,
  191 +};
  192 +
  193 +/* SD Pull Control Disable:
  194 + * SD_DAT[3:0] ==> pull down
  195 + * SD_CD ==> pull up
  196 + * SD_WP ==> pull down
  197 + * SD_CMD ==> pull down
  198 + * SD_CLK ==> pull down
  199 + */
  200 +static const u32 rts5249_sd_pull_ctl_disable_tbl[] = {
  201 + RTSX_REG_PAIR(CARD_PULL_CTL1, 0x66),
  202 + RTSX_REG_PAIR(CARD_PULL_CTL2, 0x55),
  203 + RTSX_REG_PAIR(CARD_PULL_CTL3, 0xD5),
  204 + RTSX_REG_PAIR(CARD_PULL_CTL4, 0x55),
  205 + 0,
  206 +};
  207 +
  208 +/* MS Pull Control Enable:
  209 + * MS CD ==> pull up
  210 + * others ==> pull down
  211 + */
  212 +static const u32 rts5249_ms_pull_ctl_enable_tbl[] = {
  213 + RTSX_REG_PAIR(CARD_PULL_CTL4, 0x55),
  214 + RTSX_REG_PAIR(CARD_PULL_CTL5, 0x55),
  215 + RTSX_REG_PAIR(CARD_PULL_CTL6, 0x15),
  216 + 0,
  217 +};
  218 +
  219 +/* MS Pull Control Disable:
  220 + * MS CD ==> pull up
  221 + * others ==> pull down
  222 + */
  223 +static const u32 rts5249_ms_pull_ctl_disable_tbl[] = {
  224 + RTSX_REG_PAIR(CARD_PULL_CTL4, 0x55),
  225 + RTSX_REG_PAIR(CARD_PULL_CTL5, 0x55),
  226 + RTSX_REG_PAIR(CARD_PULL_CTL6, 0x15),
  227 + 0,
  228 +};
  229 +
  230 +void rts5249_init_params(struct rtsx_pcr *pcr)
  231 +{
  232 + pcr->extra_caps = EXTRA_CAPS_SD_SDR50 | EXTRA_CAPS_SD_SDR104;
  233 + pcr->num_slots = 2;
  234 + pcr->ops = &rts5249_pcr_ops;
  235 +
  236 + pcr->ic_version = rts5249_get_ic_version(pcr);
  237 + pcr->sd_pull_ctl_enable_tbl = rts5249_sd_pull_ctl_enable_tbl;
  238 + pcr->sd_pull_ctl_disable_tbl = rts5249_sd_pull_ctl_disable_tbl;
  239 + pcr->ms_pull_ctl_enable_tbl = rts5249_ms_pull_ctl_enable_tbl;
  240 + pcr->ms_pull_ctl_disable_tbl = rts5249_ms_pull_ctl_disable_tbl;
  241 +}
drivers/mfd/rtsx_pcr.c
... ... @@ -56,6 +56,7 @@
56 56 { PCI_DEVICE(0x10EC, 0x5229), PCI_CLASS_OTHERS << 16, 0xFF0000 },
57 57 { PCI_DEVICE(0x10EC, 0x5289), PCI_CLASS_OTHERS << 16, 0xFF0000 },
58 58 { PCI_DEVICE(0x10EC, 0x5227), PCI_CLASS_OTHERS << 16, 0xFF0000 },
  59 + { PCI_DEVICE(0x10EC, 0x5249), PCI_CLASS_OTHERS << 16, 0xFF0000 },
59 60 { 0, }
60 61 };
61 62  
... ... @@ -1032,6 +1033,10 @@
1032 1033  
1033 1034 case 0x5227:
1034 1035 rts5227_init_params(pcr);
  1036 + break;
  1037 +
  1038 + case 0x5249:
  1039 + rts5249_init_params(pcr);
1035 1040 break;
1036 1041 }
1037 1042  
drivers/mfd/rtsx_pcr.h
... ... @@ -32,6 +32,7 @@
32 32 void rts5229_init_params(struct rtsx_pcr *pcr);
33 33 void rtl8411_init_params(struct rtsx_pcr *pcr);
34 34 void rts5227_init_params(struct rtsx_pcr *pcr);
  35 +void rts5249_init_params(struct rtsx_pcr *pcr);
35 36  
36 37 #endif
include/linux/mfd/rtsx_pci.h
... ... @@ -500,6 +500,8 @@
500 500 #define BPP_POWER_15_PERCENT_ON 0x08
501 501 #define BPP_POWER_ON 0x00
502 502 #define BPP_POWER_MASK 0x0F
  503 +#define SD_VCC_PARTIAL_POWER_ON 0x02
  504 +#define SD_VCC_POWER_ON 0x00
503 505  
504 506 /* PWR_GATE_CTRL */
505 507 #define PWR_GATE_EN 0x01
... ... @@ -688,6 +690,40 @@
688 690 #define PPBUF_BASE2 0xFA00
689 691 #define IMAGE_FLAG_ADDR0 0xCE80
690 692 #define IMAGE_FLAG_ADDR1 0xCE81
  693 +
  694 +/* Phy register */
  695 +#define PHY_PCR 0x00
  696 +#define PHY_RCR0 0x01
  697 +#define PHY_RCR1 0x02
  698 +#define PHY_RCR2 0x03
  699 +#define PHY_RTCR 0x04
  700 +#define PHY_RDR 0x05
  701 +#define PHY_TCR0 0x06
  702 +#define PHY_TCR1 0x07
  703 +#define PHY_TUNE 0x08
  704 +#define PHY_IMR 0x09
  705 +#define PHY_BPCR 0x0A
  706 +#define PHY_BIST 0x0B
  707 +#define PHY_RAW_L 0x0C
  708 +#define PHY_RAW_H 0x0D
  709 +#define PHY_RAW_DATA 0x0E
  710 +#define PHY_HOST_CLK_CTRL 0x0F
  711 +#define PHY_DMR 0x10
  712 +#define PHY_BACR 0x11
  713 +#define PHY_IER 0x12
  714 +#define PHY_BCSR 0x13
  715 +#define PHY_BPR 0x14
  716 +#define PHY_BPNR2 0x15
  717 +#define PHY_BPNR 0x16
  718 +#define PHY_BRNR2 0x17
  719 +#define PHY_BENR 0x18
  720 +#define PHY_REG_REV 0x19
  721 +#define PHY_FLD0 0x1A
  722 +#define PHY_FLD1 0x1B
  723 +#define PHY_FLD2 0x1C
  724 +#define PHY_FLD3 0x1D
  725 +#define PHY_FLD4 0x1E
  726 +#define PHY_DUM_REG 0x1F
691 727  
692 728 #define rtsx_pci_init_cmd(pcr) ((pcr)->ci = 0)
693 729