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.8-rc3 251 lines 6.9 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/bitops.h> 25#include <linux/delay.h> 26#include <linux/mfd/rtsx_pci.h> 27 28#include "rtsx_pcr.h" 29 30static u8 rtl8411_get_ic_version(struct rtsx_pcr *pcr) 31{ 32 u8 val; 33 34 rtsx_pci_read_register(pcr, SYS_VER, &val); 35 return val & 0x0F; 36} 37 38static int rtl8411_extra_init_hw(struct rtsx_pcr *pcr) 39{ 40 return rtsx_pci_write_register(pcr, CD_PAD_CTL, 41 CD_DISABLE_MASK | CD_AUTO_DISABLE, CD_ENABLE); 42} 43 44static int rtl8411_turn_on_led(struct rtsx_pcr *pcr) 45{ 46 return rtsx_pci_write_register(pcr, CARD_GPIO, 0x01, 0x00); 47} 48 49static int rtl8411_turn_off_led(struct rtsx_pcr *pcr) 50{ 51 return rtsx_pci_write_register(pcr, CARD_GPIO, 0x01, 0x01); 52} 53 54static int rtl8411_enable_auto_blink(struct rtsx_pcr *pcr) 55{ 56 return rtsx_pci_write_register(pcr, CARD_AUTO_BLINK, 0xFF, 0x0D); 57} 58 59static int rtl8411_disable_auto_blink(struct rtsx_pcr *pcr) 60{ 61 return rtsx_pci_write_register(pcr, CARD_AUTO_BLINK, 0x08, 0x00); 62} 63 64static int rtl8411_card_power_on(struct rtsx_pcr *pcr, int card) 65{ 66 int err; 67 68 rtsx_pci_init_cmd(pcr); 69 rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, CARD_PWR_CTL, 70 BPP_POWER_MASK, BPP_POWER_5_PERCENT_ON); 71 rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, LDO_CTL, 72 BPP_LDO_POWB, BPP_LDO_SUSPEND); 73 err = rtsx_pci_send_cmd(pcr, 100); 74 if (err < 0) 75 return err; 76 77 /* To avoid too large in-rush current */ 78 udelay(150); 79 80 err = rtsx_pci_write_register(pcr, CARD_PWR_CTL, 81 BPP_POWER_MASK, BPP_POWER_10_PERCENT_ON); 82 if (err < 0) 83 return err; 84 85 udelay(150); 86 87 err = rtsx_pci_write_register(pcr, CARD_PWR_CTL, 88 BPP_POWER_MASK, BPP_POWER_15_PERCENT_ON); 89 if (err < 0) 90 return err; 91 92 udelay(150); 93 94 err = rtsx_pci_write_register(pcr, CARD_PWR_CTL, 95 BPP_POWER_MASK, BPP_POWER_ON); 96 if (err < 0) 97 return err; 98 99 return rtsx_pci_write_register(pcr, LDO_CTL, BPP_LDO_POWB, BPP_LDO_ON); 100} 101 102static int rtl8411_card_power_off(struct rtsx_pcr *pcr, int card) 103{ 104 int err; 105 106 err = rtsx_pci_write_register(pcr, CARD_PWR_CTL, 107 BPP_POWER_MASK, BPP_POWER_OFF); 108 if (err < 0) 109 return err; 110 111 return rtsx_pci_write_register(pcr, LDO_CTL, 112 BPP_LDO_POWB, BPP_LDO_SUSPEND); 113} 114 115static unsigned int rtl8411_cd_deglitch(struct rtsx_pcr *pcr) 116{ 117 unsigned int card_exist; 118 119 card_exist = rtsx_pci_readl(pcr, RTSX_BIPR); 120 card_exist &= CARD_EXIST; 121 if (!card_exist) { 122 /* Enable card CD */ 123 rtsx_pci_write_register(pcr, CD_PAD_CTL, 124 CD_DISABLE_MASK, CD_ENABLE); 125 /* Enable card interrupt */ 126 rtsx_pci_write_register(pcr, EFUSE_CONTENT, 0xe0, 0x00); 127 return 0; 128 } 129 130 if (hweight32(card_exist) > 1) { 131 rtsx_pci_write_register(pcr, CARD_PWR_CTL, 132 BPP_POWER_MASK, BPP_POWER_5_PERCENT_ON); 133 msleep(100); 134 135 card_exist = rtsx_pci_readl(pcr, RTSX_BIPR); 136 if (card_exist & MS_EXIST) 137 card_exist = MS_EXIST; 138 else if (card_exist & SD_EXIST) 139 card_exist = SD_EXIST; 140 else 141 card_exist = 0; 142 143 rtsx_pci_write_register(pcr, CARD_PWR_CTL, 144 BPP_POWER_MASK, BPP_POWER_OFF); 145 146 dev_dbg(&(pcr->pci->dev), 147 "After CD deglitch, card_exist = 0x%x\n", 148 card_exist); 149 } 150 151 if (card_exist & MS_EXIST) { 152 /* Disable SD interrupt */ 153 rtsx_pci_write_register(pcr, EFUSE_CONTENT, 0xe0, 0x40); 154 rtsx_pci_write_register(pcr, CD_PAD_CTL, 155 CD_DISABLE_MASK, MS_CD_EN_ONLY); 156 } else if (card_exist & SD_EXIST) { 157 /* Disable MS interrupt */ 158 rtsx_pci_write_register(pcr, EFUSE_CONTENT, 0xe0, 0x80); 159 rtsx_pci_write_register(pcr, CD_PAD_CTL, 160 CD_DISABLE_MASK, SD_CD_EN_ONLY); 161 } 162 163 return card_exist; 164} 165 166static const struct pcr_ops rtl8411_pcr_ops = { 167 .extra_init_hw = rtl8411_extra_init_hw, 168 .optimize_phy = NULL, 169 .turn_on_led = rtl8411_turn_on_led, 170 .turn_off_led = rtl8411_turn_off_led, 171 .enable_auto_blink = rtl8411_enable_auto_blink, 172 .disable_auto_blink = rtl8411_disable_auto_blink, 173 .card_power_on = rtl8411_card_power_on, 174 .card_power_off = rtl8411_card_power_off, 175 .cd_deglitch = rtl8411_cd_deglitch, 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 */ 185static const u32 rtl8411_sd_pull_ctl_enable_tbl[] = { 186 RTSX_REG_PAIR(CARD_PULL_CTL1, 0xAA), 187 RTSX_REG_PAIR(CARD_PULL_CTL2, 0xAA), 188 RTSX_REG_PAIR(CARD_PULL_CTL3, 0xA9), 189 RTSX_REG_PAIR(CARD_PULL_CTL4, 0x09), 190 RTSX_REG_PAIR(CARD_PULL_CTL5, 0x09), 191 RTSX_REG_PAIR(CARD_PULL_CTL6, 0x04), 192 0, 193}; 194 195/* SD Pull Control Disable: 196 * SD_DAT[3:0] ==> pull down 197 * SD_CD ==> pull up 198 * SD_WP ==> pull down 199 * SD_CMD ==> pull down 200 * SD_CLK ==> pull down 201 */ 202static const u32 rtl8411_sd_pull_ctl_disable_tbl[] = { 203 RTSX_REG_PAIR(CARD_PULL_CTL1, 0x65), 204 RTSX_REG_PAIR(CARD_PULL_CTL2, 0x55), 205 RTSX_REG_PAIR(CARD_PULL_CTL3, 0x95), 206 RTSX_REG_PAIR(CARD_PULL_CTL4, 0x09), 207 RTSX_REG_PAIR(CARD_PULL_CTL5, 0x05), 208 RTSX_REG_PAIR(CARD_PULL_CTL6, 0x04), 209 0, 210}; 211 212/* MS Pull Control Enable: 213 * MS CD ==> pull up 214 * others ==> pull down 215 */ 216static const u32 rtl8411_ms_pull_ctl_enable_tbl[] = { 217 RTSX_REG_PAIR(CARD_PULL_CTL1, 0x65), 218 RTSX_REG_PAIR(CARD_PULL_CTL2, 0x55), 219 RTSX_REG_PAIR(CARD_PULL_CTL3, 0x95), 220 RTSX_REG_PAIR(CARD_PULL_CTL4, 0x05), 221 RTSX_REG_PAIR(CARD_PULL_CTL5, 0x05), 222 RTSX_REG_PAIR(CARD_PULL_CTL6, 0x04), 223 0, 224}; 225 226/* MS Pull Control Disable: 227 * MS CD ==> pull up 228 * others ==> pull down 229 */ 230static const u32 rtl8411_ms_pull_ctl_disable_tbl[] = { 231 RTSX_REG_PAIR(CARD_PULL_CTL1, 0x65), 232 RTSX_REG_PAIR(CARD_PULL_CTL2, 0x55), 233 RTSX_REG_PAIR(CARD_PULL_CTL3, 0x95), 234 RTSX_REG_PAIR(CARD_PULL_CTL4, 0x09), 235 RTSX_REG_PAIR(CARD_PULL_CTL5, 0x05), 236 RTSX_REG_PAIR(CARD_PULL_CTL6, 0x04), 237 0, 238}; 239 240void rtl8411_init_params(struct rtsx_pcr *pcr) 241{ 242 pcr->extra_caps = EXTRA_CAPS_SD_SDR50 | EXTRA_CAPS_SD_SDR104; 243 pcr->num_slots = 2; 244 pcr->ops = &rtl8411_pcr_ops; 245 246 pcr->ic_version = rtl8411_get_ic_version(pcr); 247 pcr->sd_pull_ctl_enable_tbl = rtl8411_sd_pull_ctl_enable_tbl; 248 pcr->sd_pull_ctl_disable_tbl = rtl8411_sd_pull_ctl_disable_tbl; 249 pcr->ms_pull_ctl_enable_tbl = rtl8411_ms_pull_ctl_enable_tbl; 250 pcr->ms_pull_ctl_disable_tbl = rtl8411_ms_pull_ctl_disable_tbl; 251}