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

Configure Feed

Select the types of activity you want to include in your feed.

at v3.11-rc3 252 lines 6.6 kB view raw
1/* Driver for Realtek PCI-Express card reader 2 * 3 * Copyright(c) 2009 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. 450, 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 29static u8 rts5209_get_ic_version(struct rtsx_pcr *pcr) 30{ 31 u8 val; 32 33 val = rtsx_pci_readb(pcr, 0x1C); 34 return val & 0x0F; 35} 36 37static void rts5209_init_vendor_cfg(struct rtsx_pcr *pcr) 38{ 39 u32 val; 40 41 rtsx_pci_read_config_dword(pcr, 0x724, &val); 42 dev_dbg(&(pcr->pci->dev), "Cfg 0x724: 0x%x\n", val); 43 44 if (!(val & 0x80)) { 45 if (val & 0x08) 46 pcr->ms_pmos = false; 47 else 48 pcr->ms_pmos = true; 49 } 50} 51 52static int rts5209_extra_init_hw(struct rtsx_pcr *pcr) 53{ 54 rtsx_pci_init_cmd(pcr); 55 56 /* Turn off LED */ 57 rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, CARD_GPIO, 0xFF, 0x03); 58 /* Configure GPIO as output */ 59 rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, CARD_GPIO_DIR, 0xFF, 0x03); 60 61 return rtsx_pci_send_cmd(pcr, 100); 62} 63 64static int rts5209_optimize_phy(struct rtsx_pcr *pcr) 65{ 66 return rtsx_pci_write_phy_register(pcr, 0x00, 0xB966); 67} 68 69static int rts5209_turn_on_led(struct rtsx_pcr *pcr) 70{ 71 return rtsx_pci_write_register(pcr, CARD_GPIO, 0x01, 0x00); 72} 73 74static int rts5209_turn_off_led(struct rtsx_pcr *pcr) 75{ 76 return rtsx_pci_write_register(pcr, CARD_GPIO, 0x01, 0x01); 77} 78 79static int rts5209_enable_auto_blink(struct rtsx_pcr *pcr) 80{ 81 return rtsx_pci_write_register(pcr, CARD_AUTO_BLINK, 0xFF, 0x0D); 82} 83 84static int rts5209_disable_auto_blink(struct rtsx_pcr *pcr) 85{ 86 return rtsx_pci_write_register(pcr, CARD_AUTO_BLINK, 0x08, 0x00); 87} 88 89static int rts5209_card_power_on(struct rtsx_pcr *pcr, int card) 90{ 91 int err; 92 u8 pwr_mask, partial_pwr_on, pwr_on; 93 94 pwr_mask = SD_POWER_MASK; 95 partial_pwr_on = SD_PARTIAL_POWER_ON; 96 pwr_on = SD_POWER_ON; 97 98 if (pcr->ms_pmos && (card == RTSX_MS_CARD)) { 99 pwr_mask = MS_POWER_MASK; 100 partial_pwr_on = MS_PARTIAL_POWER_ON; 101 pwr_on = MS_POWER_ON; 102 } 103 104 rtsx_pci_init_cmd(pcr); 105 rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, CARD_PWR_CTL, 106 pwr_mask, partial_pwr_on); 107 rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, PWR_GATE_CTRL, 108 LDO3318_PWR_MASK, 0x04); 109 err = rtsx_pci_send_cmd(pcr, 100); 110 if (err < 0) 111 return err; 112 113 /* To avoid too large in-rush current */ 114 udelay(150); 115 116 rtsx_pci_init_cmd(pcr); 117 rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, CARD_PWR_CTL, pwr_mask, pwr_on); 118 rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, PWR_GATE_CTRL, 119 LDO3318_PWR_MASK, 0x00); 120 err = rtsx_pci_send_cmd(pcr, 100); 121 if (err < 0) 122 return err; 123 124 return 0; 125} 126 127static int rts5209_card_power_off(struct rtsx_pcr *pcr, int card) 128{ 129 u8 pwr_mask, pwr_off; 130 131 pwr_mask = SD_POWER_MASK; 132 pwr_off = SD_POWER_OFF; 133 134 if (pcr->ms_pmos && (card == RTSX_MS_CARD)) { 135 pwr_mask = MS_POWER_MASK; 136 pwr_off = MS_POWER_OFF; 137 } 138 139 rtsx_pci_init_cmd(pcr); 140 rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, CARD_PWR_CTL, 141 pwr_mask | PMOS_STRG_MASK, pwr_off | PMOS_STRG_400mA); 142 rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, PWR_GATE_CTRL, 143 LDO3318_PWR_MASK, 0X06); 144 return rtsx_pci_send_cmd(pcr, 100); 145} 146 147static int rts5209_switch_output_voltage(struct rtsx_pcr *pcr, u8 voltage) 148{ 149 int err; 150 151 if (voltage == OUTPUT_3V3) { 152 err = rtsx_pci_write_register(pcr, 153 SD30_DRIVE_SEL, 0x07, DRIVER_TYPE_D); 154 if (err < 0) 155 return err; 156 err = rtsx_pci_write_phy_register(pcr, 0x08, 0x4FC0 | 0x24); 157 if (err < 0) 158 return err; 159 } else if (voltage == OUTPUT_1V8) { 160 err = rtsx_pci_write_register(pcr, 161 SD30_DRIVE_SEL, 0x07, DRIVER_TYPE_B); 162 if (err < 0) 163 return err; 164 err = rtsx_pci_write_phy_register(pcr, 0x08, 0x4C40 | 0x24); 165 if (err < 0) 166 return err; 167 } else { 168 return -EINVAL; 169 } 170 171 return 0; 172} 173 174static const struct pcr_ops rts5209_pcr_ops = { 175 .extra_init_hw = rts5209_extra_init_hw, 176 .optimize_phy = rts5209_optimize_phy, 177 .turn_on_led = rts5209_turn_on_led, 178 .turn_off_led = rts5209_turn_off_led, 179 .enable_auto_blink = rts5209_enable_auto_blink, 180 .disable_auto_blink = rts5209_disable_auto_blink, 181 .card_power_on = rts5209_card_power_on, 182 .card_power_off = rts5209_card_power_off, 183 .switch_output_voltage = rts5209_switch_output_voltage, 184 .cd_deglitch = NULL, 185 .conv_clk_and_div_n = NULL, 186}; 187 188/* SD Pull Control Enable: 189 * SD_DAT[3:0] ==> pull up 190 * SD_CD ==> pull up 191 * SD_WP ==> pull up 192 * SD_CMD ==> pull up 193 * SD_CLK ==> pull down 194 */ 195static const u32 rts5209_sd_pull_ctl_enable_tbl[] = { 196 RTSX_REG_PAIR(CARD_PULL_CTL1, 0xAA), 197 RTSX_REG_PAIR(CARD_PULL_CTL2, 0xAA), 198 RTSX_REG_PAIR(CARD_PULL_CTL3, 0xE9), 199 0, 200}; 201 202/* SD Pull Control Disable: 203 * SD_DAT[3:0] ==> pull down 204 * SD_CD ==> pull up 205 * SD_WP ==> pull down 206 * SD_CMD ==> pull down 207 * SD_CLK ==> pull down 208 */ 209static const u32 rts5209_sd_pull_ctl_disable_tbl[] = { 210 RTSX_REG_PAIR(CARD_PULL_CTL1, 0x55), 211 RTSX_REG_PAIR(CARD_PULL_CTL2, 0x55), 212 RTSX_REG_PAIR(CARD_PULL_CTL3, 0xD5), 213 0, 214}; 215 216/* MS Pull Control Enable: 217 * MS CD ==> pull up 218 * others ==> pull down 219 */ 220static const u32 rts5209_ms_pull_ctl_enable_tbl[] = { 221 RTSX_REG_PAIR(CARD_PULL_CTL4, 0x55), 222 RTSX_REG_PAIR(CARD_PULL_CTL5, 0x55), 223 RTSX_REG_PAIR(CARD_PULL_CTL6, 0x15), 224 0, 225}; 226 227/* MS Pull Control Disable: 228 * MS CD ==> pull up 229 * others ==> pull down 230 */ 231static const u32 rts5209_ms_pull_ctl_disable_tbl[] = { 232 RTSX_REG_PAIR(CARD_PULL_CTL4, 0x55), 233 RTSX_REG_PAIR(CARD_PULL_CTL5, 0x55), 234 RTSX_REG_PAIR(CARD_PULL_CTL6, 0x15), 235 0, 236}; 237 238void rts5209_init_params(struct rtsx_pcr *pcr) 239{ 240 pcr->extra_caps = EXTRA_CAPS_SD_SDR50 | 241 EXTRA_CAPS_SD_SDR104 | EXTRA_CAPS_MMC_8BIT; 242 pcr->num_slots = 2; 243 pcr->ops = &rts5209_pcr_ops; 244 245 rts5209_init_vendor_cfg(pcr); 246 247 pcr->ic_version = rts5209_get_ic_version(pcr); 248 pcr->sd_pull_ctl_enable_tbl = rts5209_sd_pull_ctl_enable_tbl; 249 pcr->sd_pull_ctl_disable_tbl = rts5209_sd_pull_ctl_disable_tbl; 250 pcr->ms_pull_ctl_enable_tbl = rts5209_ms_pull_ctl_enable_tbl; 251 pcr->ms_pull_ctl_disable_tbl = rts5209_ms_pull_ctl_disable_tbl; 252}