Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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>

authored by

Wei WANG and committed by
Samuel Ortiz
4c4b8c10 95e50f6a

+284 -1
+1 -1
drivers/mfd/Makefile
··· 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
+241
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 + }
+5
drivers/mfd/rtsx_pcr.c
··· 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 ··· 1033 1032 1034 1033 case 0x5227: 1035 1034 rts5227_init_params(pcr); 1035 + break; 1036 + 1037 + case 0x5249: 1038 + rts5249_init_params(pcr); 1036 1039 break; 1037 1040 } 1038 1041
+1
drivers/mfd/rtsx_pcr.h
··· 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
+36
include/linux/mfd/rtsx_pci.h
··· 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 ··· 690 688 #define PPBUF_BASE2 0xFA00 691 689 #define IMAGE_FLAG_ADDR0 0xCE80 692 690 #define IMAGE_FLAG_ADDR1 0xCE81 691 + 692 + /* Phy register */ 693 + #define PHY_PCR 0x00 694 + #define PHY_RCR0 0x01 695 + #define PHY_RCR1 0x02 696 + #define PHY_RCR2 0x03 697 + #define PHY_RTCR 0x04 698 + #define PHY_RDR 0x05 699 + #define PHY_TCR0 0x06 700 + #define PHY_TCR1 0x07 701 + #define PHY_TUNE 0x08 702 + #define PHY_IMR 0x09 703 + #define PHY_BPCR 0x0A 704 + #define PHY_BIST 0x0B 705 + #define PHY_RAW_L 0x0C 706 + #define PHY_RAW_H 0x0D 707 + #define PHY_RAW_DATA 0x0E 708 + #define PHY_HOST_CLK_CTRL 0x0F 709 + #define PHY_DMR 0x10 710 + #define PHY_BACR 0x11 711 + #define PHY_IER 0x12 712 + #define PHY_BCSR 0x13 713 + #define PHY_BPR 0x14 714 + #define PHY_BPNR2 0x15 715 + #define PHY_BPNR 0x16 716 + #define PHY_BRNR2 0x17 717 + #define PHY_BENR 0x18 718 + #define PHY_REG_REV 0x19 719 + #define PHY_FLD0 0x1A 720 + #define PHY_FLD1 0x1B 721 + #define PHY_FLD2 0x1C 722 + #define PHY_FLD3 0x1D 723 + #define PHY_FLD4 0x1E 724 + #define PHY_DUM_REG 0x1F 693 725 694 726 #define rtsx_pci_init_cmd(pcr) ((pcr)->ci = 0) 695 727