linux/drivers/mfd/rts5249.c
<<
>>
Prefs
   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 */
  21
  22#include <linux/module.h>
  23#include <linux/delay.h>
  24#include <linux/mfd/rtsx_pci.h>
  25
  26#include "rtsx_pcr.h"
  27
  28static u8 rts5249_get_ic_version(struct rtsx_pcr *pcr)
  29{
  30        u8 val;
  31
  32        rtsx_pci_read_register(pcr, DUMMY_REG_RESET_0, &val);
  33        return val & 0x0F;
  34}
  35
  36static void rts5249_fill_driving(struct rtsx_pcr *pcr, u8 voltage)
  37{
  38        u8 driving_3v3[4][3] = {
  39                {0x11, 0x11, 0x11},
  40                {0x55, 0x55, 0x5C},
  41                {0x99, 0x99, 0x92},
  42                {0x99, 0x99, 0x92},
  43        };
  44        u8 driving_1v8[4][3] = {
  45                {0x3C, 0x3C, 0x3C},
  46                {0xB3, 0xB3, 0xB3},
  47                {0xFE, 0xFE, 0xFE},
  48                {0xC4, 0xC4, 0xC4},
  49        };
  50        u8 (*driving)[3], drive_sel;
  51
  52        if (voltage == OUTPUT_3V3) {
  53                driving = driving_3v3;
  54                drive_sel = pcr->sd30_drive_sel_3v3;
  55        } else {
  56                driving = driving_1v8;
  57                drive_sel = pcr->sd30_drive_sel_1v8;
  58        }
  59
  60        rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, SD30_CLK_DRIVE_SEL,
  61                        0xFF, driving[drive_sel][0]);
  62        rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, SD30_CMD_DRIVE_SEL,
  63                        0xFF, driving[drive_sel][1]);
  64        rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, SD30_DAT_DRIVE_SEL,
  65                        0xFF, driving[drive_sel][2]);
  66}
  67
  68static void rts5249_fetch_vendor_settings(struct rtsx_pcr *pcr)
  69{
  70        u32 reg;
  71
  72        rtsx_pci_read_config_dword(pcr, PCR_SETTING_REG1, &reg);
  73        dev_dbg(&(pcr->pci->dev), "Cfg 0x%x: 0x%x\n", PCR_SETTING_REG1, reg);
  74
  75        if (!rtsx_vendor_setting_valid(reg))
  76                return;
  77
  78        pcr->aspm_en = rtsx_reg_to_aspm(reg);
  79        pcr->sd30_drive_sel_1v8 = rtsx_reg_to_sd30_drive_sel_1v8(reg);
  80        pcr->card_drive_sel &= 0x3F;
  81        pcr->card_drive_sel |= rtsx_reg_to_card_drive_sel(reg);
  82
  83        rtsx_pci_read_config_dword(pcr, PCR_SETTING_REG2, &reg);
  84        dev_dbg(&(pcr->pci->dev), "Cfg 0x%x: 0x%x\n", PCR_SETTING_REG2, reg);
  85        pcr->sd30_drive_sel_3v3 = rtsx_reg_to_sd30_drive_sel_3v3(reg);
  86        if (rtsx_reg_check_reverse_socket(reg))
  87                pcr->flags |= PCR_REVERSE_SOCKET;
  88}
  89
  90static void rts5249_force_power_down(struct rtsx_pcr *pcr, u8 pm_state)
  91{
  92        /* Set relink_time to 0 */
  93        rtsx_pci_write_register(pcr, AUTOLOAD_CFG_BASE + 1, 0xFF, 0);
  94        rtsx_pci_write_register(pcr, AUTOLOAD_CFG_BASE + 2, 0xFF, 0);
  95        rtsx_pci_write_register(pcr, AUTOLOAD_CFG_BASE + 3, 0x01, 0);
  96
  97        if (pm_state == HOST_ENTER_S3)
  98                rtsx_pci_write_register(pcr, PM_CTRL3, 0x10, 0x10);
  99
 100        rtsx_pci_write_register(pcr, FPDCTL, 0x03, 0x03);
 101}
 102
 103static int rts5249_extra_init_hw(struct rtsx_pcr *pcr)
 104{
 105        rtsx_pci_init_cmd(pcr);
 106
 107        /* Configure GPIO as output */
 108        rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, GPIO_CTL, 0x02, 0x02);
 109        /* Reset ASPM state to default value */
 110        rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, ASPM_FORCE_CTL, 0x3F, 0);
 111        /* Switch LDO3318 source from DV33 to card_3v3 */
 112        rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, LDO_PWR_SEL, 0x03, 0x00);
 113        rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, LDO_PWR_SEL, 0x03, 0x01);
 114        /* LED shine disabled, set initial shine cycle period */
 115        rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, OLT_LED_CTL, 0x0F, 0x02);
 116        /* Configure driving */
 117        rts5249_fill_driving(pcr, OUTPUT_3V3);
 118        if (pcr->flags & PCR_REVERSE_SOCKET)
 119                rtsx_pci_add_cmd(pcr, WRITE_REG_CMD,
 120                                AUTOLOAD_CFG_BASE + 3, 0xB0, 0xB0);
 121        else
 122                rtsx_pci_add_cmd(pcr, WRITE_REG_CMD,
 123                                AUTOLOAD_CFG_BASE + 3, 0xB0, 0x80);
 124        rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, PM_CTRL3, 0x10, 0x00);
 125
 126        return rtsx_pci_send_cmd(pcr, 100);
 127}
 128
 129static int rts5249_optimize_phy(struct rtsx_pcr *pcr)
 130{
 131        int err;
 132
 133        err = rtsx_gops_pm_reset(pcr);
 134        if (err < 0)
 135                return err;
 136
 137        err = rtsx_pci_write_phy_register(pcr, PHY_REG_REV,
 138                        PHY_REG_REV_RESV | PHY_REG_REV_RXIDLE_LATCHED |
 139                        PHY_REG_REV_P1_EN | PHY_REG_REV_RXIDLE_EN |
 140                        PHY_REG_REV_RX_PWST | PHY_REG_REV_CLKREQ_DLY_TIMER_1_0 |
 141                        PHY_REG_REV_STOP_CLKRD | PHY_REG_REV_STOP_CLKWR);
 142        if (err < 0)
 143                return err;
 144
 145        msleep(1);
 146
 147        err = rtsx_pci_write_phy_register(pcr, PHY_BPCR,
 148                        PHY_BPCR_IBRXSEL | PHY_BPCR_IBTXSEL |
 149                        PHY_BPCR_IB_FILTER | PHY_BPCR_CMIRROR_EN);
 150        if (err < 0)
 151                return err;
 152        err = rtsx_pci_write_phy_register(pcr, PHY_PCR,
 153                        PHY_PCR_FORCE_CODE | PHY_PCR_OOBS_CALI_50 |
 154                        PHY_PCR_OOBS_VCM_08 | PHY_PCR_OOBS_SEN_90 |
 155                        PHY_PCR_RSSI_EN);
 156        if (err < 0)
 157                return err;
 158        err = rtsx_pci_write_phy_register(pcr, PHY_RCR2,
 159                        PHY_RCR2_EMPHASE_EN | PHY_RCR2_NADJR |
 160                        PHY_RCR2_CDR_CP_10 | PHY_RCR2_CDR_SR_2 |
 161                        PHY_RCR2_FREQSEL_12 | PHY_RCR2_CPADJEN |
 162                        PHY_RCR2_CDR_SC_8 | PHY_RCR2_CALIB_LATE);
 163        if (err < 0)
 164                return err;
 165        err = rtsx_pci_write_phy_register(pcr, PHY_FLD4,
 166                        PHY_FLD4_FLDEN_SEL | PHY_FLD4_REQ_REF |
 167                        PHY_FLD4_RXAMP_OFF | PHY_FLD4_REQ_ADDA |
 168                        PHY_FLD4_BER_COUNT | PHY_FLD4_BER_TIMER |
 169                        PHY_FLD4_BER_CHK_EN);
 170        if (err < 0)
 171                return err;
 172        err = rtsx_pci_write_phy_register(pcr, PHY_RDR, PHY_RDR_RXDSEL_1_9);
 173        if (err < 0)
 174                return err;
 175        err = rtsx_pci_write_phy_register(pcr, PHY_RCR1,
 176                        PHY_RCR1_ADP_TIME | PHY_RCR1_VCO_COARSE);
 177        if (err < 0)
 178                return err;
 179        err = rtsx_pci_write_phy_register(pcr, PHY_FLD3,
 180                        PHY_FLD3_TIMER_4 | PHY_FLD3_TIMER_6 |
 181                        PHY_FLD3_RXDELINK);
 182        if (err < 0)
 183                return err;
 184        return rtsx_pci_write_phy_register(pcr, PHY_TUNE,
 185                        PHY_TUNE_TUNEREF_1_0 | PHY_TUNE_VBGSEL_1252 |
 186                        PHY_TUNE_SDBUS_33 | PHY_TUNE_TUNED18 |
 187                        PHY_TUNE_TUNED12);
 188}
 189
 190static int rts5249_turn_on_led(struct rtsx_pcr *pcr)
 191{
 192        return rtsx_pci_write_register(pcr, GPIO_CTL, 0x02, 0x02);
 193}
 194
 195static int rts5249_turn_off_led(struct rtsx_pcr *pcr)
 196{
 197        return rtsx_pci_write_register(pcr, GPIO_CTL, 0x02, 0x00);
 198}
 199
 200static int rts5249_enable_auto_blink(struct rtsx_pcr *pcr)
 201{
 202        return rtsx_pci_write_register(pcr, OLT_LED_CTL, 0x08, 0x08);
 203}
 204
 205static int rts5249_disable_auto_blink(struct rtsx_pcr *pcr)
 206{
 207        return rtsx_pci_write_register(pcr, OLT_LED_CTL, 0x08, 0x00);
 208}
 209
 210static int rts5249_card_power_on(struct rtsx_pcr *pcr, int card)
 211{
 212        int err;
 213
 214        rtsx_pci_init_cmd(pcr);
 215        rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, CARD_PWR_CTL,
 216                        SD_POWER_MASK, SD_VCC_PARTIAL_POWER_ON);
 217        rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, PWR_GATE_CTRL,
 218                        LDO3318_PWR_MASK, 0x02);
 219        err = rtsx_pci_send_cmd(pcr, 100);
 220        if (err < 0)
 221                return err;
 222
 223        msleep(5);
 224
 225        rtsx_pci_init_cmd(pcr);
 226        rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, CARD_PWR_CTL,
 227                        SD_POWER_MASK, SD_VCC_POWER_ON);
 228        rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, PWR_GATE_CTRL,
 229                        LDO3318_PWR_MASK, 0x06);
 230        err = rtsx_pci_send_cmd(pcr, 100);
 231        if (err < 0)
 232                return err;
 233
 234        return 0;
 235}
 236
 237static int rts5249_card_power_off(struct rtsx_pcr *pcr, int card)
 238{
 239        rtsx_pci_init_cmd(pcr);
 240        rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, CARD_PWR_CTL,
 241                        SD_POWER_MASK, SD_POWER_OFF);
 242        rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, PWR_GATE_CTRL,
 243                        LDO3318_PWR_MASK, 0x00);
 244        return rtsx_pci_send_cmd(pcr, 100);
 245}
 246
 247static int rts5249_switch_output_voltage(struct rtsx_pcr *pcr, u8 voltage)
 248{
 249        int err;
 250
 251        if (voltage == OUTPUT_3V3) {
 252                err = rtsx_pci_write_phy_register(pcr, PHY_TUNE, 0x4FC0 | 0x24);
 253                if (err < 0)
 254                        return err;
 255        } else if (voltage == OUTPUT_1V8) {
 256                err = rtsx_pci_write_phy_register(pcr, PHY_BACR, 0x3C02);
 257                if (err < 0)
 258                        return err;
 259                err = rtsx_pci_write_phy_register(pcr, PHY_TUNE, 0x4C40 | 0x24);
 260                if (err < 0)
 261                        return err;
 262        } else {
 263                return -EINVAL;
 264        }
 265
 266        /* set pad drive */
 267        rtsx_pci_init_cmd(pcr);
 268        rts5249_fill_driving(pcr, voltage);
 269        return rtsx_pci_send_cmd(pcr, 100);
 270}
 271
 272static const struct pcr_ops rts5249_pcr_ops = {
 273        .fetch_vendor_settings = rts5249_fetch_vendor_settings,
 274        .extra_init_hw = rts5249_extra_init_hw,
 275        .optimize_phy = rts5249_optimize_phy,
 276        .turn_on_led = rts5249_turn_on_led,
 277        .turn_off_led = rts5249_turn_off_led,
 278        .enable_auto_blink = rts5249_enable_auto_blink,
 279        .disable_auto_blink = rts5249_disable_auto_blink,
 280        .card_power_on = rts5249_card_power_on,
 281        .card_power_off = rts5249_card_power_off,
 282        .switch_output_voltage = rts5249_switch_output_voltage,
 283        .force_power_down = rts5249_force_power_down,
 284};
 285
 286/* SD Pull Control Enable:
 287 *     SD_DAT[3:0] ==> pull up
 288 *     SD_CD       ==> pull up
 289 *     SD_WP       ==> pull up
 290 *     SD_CMD      ==> pull up
 291 *     SD_CLK      ==> pull down
 292 */
 293static const u32 rts5249_sd_pull_ctl_enable_tbl[] = {
 294        RTSX_REG_PAIR(CARD_PULL_CTL1, 0x66),
 295        RTSX_REG_PAIR(CARD_PULL_CTL2, 0xAA),
 296        RTSX_REG_PAIR(CARD_PULL_CTL3, 0xE9),
 297        RTSX_REG_PAIR(CARD_PULL_CTL4, 0xAA),
 298        0,
 299};
 300
 301/* SD Pull Control Disable:
 302 *     SD_DAT[3:0] ==> pull down
 303 *     SD_CD       ==> pull up
 304 *     SD_WP       ==> pull down
 305 *     SD_CMD      ==> pull down
 306 *     SD_CLK      ==> pull down
 307 */
 308static const u32 rts5249_sd_pull_ctl_disable_tbl[] = {
 309        RTSX_REG_PAIR(CARD_PULL_CTL1, 0x66),
 310        RTSX_REG_PAIR(CARD_PULL_CTL2, 0x55),
 311        RTSX_REG_PAIR(CARD_PULL_CTL3, 0xD5),
 312        RTSX_REG_PAIR(CARD_PULL_CTL4, 0x55),
 313        0,
 314};
 315
 316/* MS Pull Control Enable:
 317 *     MS CD       ==> pull up
 318 *     others      ==> pull down
 319 */
 320static const u32 rts5249_ms_pull_ctl_enable_tbl[] = {
 321        RTSX_REG_PAIR(CARD_PULL_CTL4, 0x55),
 322        RTSX_REG_PAIR(CARD_PULL_CTL5, 0x55),
 323        RTSX_REG_PAIR(CARD_PULL_CTL6, 0x15),
 324        0,
 325};
 326
 327/* MS Pull Control Disable:
 328 *     MS CD       ==> pull up
 329 *     others      ==> pull down
 330 */
 331static const u32 rts5249_ms_pull_ctl_disable_tbl[] = {
 332        RTSX_REG_PAIR(CARD_PULL_CTL4, 0x55),
 333        RTSX_REG_PAIR(CARD_PULL_CTL5, 0x55),
 334        RTSX_REG_PAIR(CARD_PULL_CTL6, 0x15),
 335        0,
 336};
 337
 338void rts5249_init_params(struct rtsx_pcr *pcr)
 339{
 340        pcr->extra_caps = EXTRA_CAPS_SD_SDR50 | EXTRA_CAPS_SD_SDR104;
 341        pcr->num_slots = 2;
 342        pcr->ops = &rts5249_pcr_ops;
 343
 344        pcr->flags = 0;
 345        pcr->card_drive_sel = RTSX_CARD_DRIVE_DEFAULT;
 346        pcr->sd30_drive_sel_1v8 = CFG_DRIVER_TYPE_C;
 347        pcr->sd30_drive_sel_3v3 = CFG_DRIVER_TYPE_B;
 348        pcr->aspm_en = ASPM_L1_EN;
 349        pcr->tx_initial_phase = SET_CLOCK_PHASE(1, 29, 16);
 350        pcr->rx_initial_phase = SET_CLOCK_PHASE(24, 6, 5);
 351
 352        pcr->ic_version = rts5249_get_ic_version(pcr);
 353        pcr->sd_pull_ctl_enable_tbl = rts5249_sd_pull_ctl_enable_tbl;
 354        pcr->sd_pull_ctl_disable_tbl = rts5249_sd_pull_ctl_disable_tbl;
 355        pcr->ms_pull_ctl_enable_tbl = rts5249_ms_pull_ctl_enable_tbl;
 356        pcr->ms_pull_ctl_disable_tbl = rts5249_ms_pull_ctl_disable_tbl;
 357}
 358