1 // SPDX-License-Identifier: GPL-2.0 2 /* 3 * sdhci-pci-arasan.c - Driver for Arasan PCI Controller with 4 * integrated phy. 5 * 6 * Copyright (C) 2017 Arasan Chip Systems Inc. 7 * 8 * Author: Atul Garg <agarg@arasan.com> 9 */ 10 11 #include <linux/pci.h> 12 #include <linux/delay.h> 13 14 #include "sdhci.h" 15 #include "sdhci-pci.h" 16 17 /* Extra registers for Arasan SD/SDIO/MMC Host Controller with PHY */ 18 #define PHY_ADDR_REG 0x300 19 #define PHY_DAT_REG 0x304 20 21 #define PHY_WRITE BIT(8) 22 #define PHY_BUSY BIT(9) 23 #define DATA_MASK 0xFF 24 25 /* PHY Specific Registers */ 26 #define DLL_STATUS 0x00 27 #define IPAD_CTRL1 0x01 28 #define IPAD_CTRL2 0x02 29 #define IPAD_STS 0x03 30 #define IOREN_CTRL1 0x06 31 #define IOREN_CTRL2 0x07 32 #define IOPU_CTRL1 0x08 33 #define IOPU_CTRL2 0x09 34 #define ITAP_DELAY 0x0C 35 #define OTAP_DELAY 0x0D 36 #define STRB_SEL 0x0E 37 #define CLKBUF_SEL 0x0F 38 #define MODE_CTRL 0x11 39 #define DLL_TRIM 0x12 40 #define CMD_CTRL 0x20 41 #define DATA_CTRL 0x21 42 #define STRB_CTRL 0x22 43 #define CLK_CTRL 0x23 44 #define PHY_CTRL 0x24 45 46 #define DLL_ENBL BIT(3) 47 #define RTRIM_EN BIT(1) 48 #define PDB_ENBL BIT(1) 49 #define RETB_ENBL BIT(6) 50 #define ODEN_CMD BIT(1) 51 #define ODEN_DAT 0xFF 52 #define REN_STRB BIT(0) 53 #define REN_CMND BIT(1) 54 #define REN_DATA 0xFF 55 #define PU_CMD BIT(1) 56 #define PU_DAT 0xFF 57 #define ITAPDLY_EN BIT(0) 58 #define OTAPDLY_EN BIT(0) 59 #define OD_REL_CMD BIT(1) 60 #define OD_REL_DAT 0xFF 61 #define DLLTRM_ICP 0x8 62 #define PDB_CMND BIT(0) 63 #define PDB_DATA 0xFF 64 #define PDB_STRB BIT(0) 65 #define PDB_CLOCK BIT(0) 66 #define CALDONE_MASK 0x10 67 #define DLL_RDY_MASK 0x10 68 #define MAX_CLK_BUF 0x7 69 70 /* Mode Controls */ 71 #define ENHSTRB_MODE BIT(0) 72 #define HS400_MODE BIT(1) 73 #define LEGACY_MODE BIT(2) 74 #define DDR50_MODE BIT(3) 75 76 /* 77 * Controller has no specific bits for HS200/HS. 78 * Used BIT(4), BIT(5) for software programming. 79 */ 80 #define HS200_MODE BIT(4) 81 #define HISPD_MODE BIT(5) 82 83 #define OTAPDLY(x) (((x) << 1) | OTAPDLY_EN) 84 #define ITAPDLY(x) (((x) << 1) | ITAPDLY_EN) 85 #define FREQSEL(x) (((x) << 5) | DLL_ENBL) 86 #define IOPAD(x, y) ((x) | ((y) << 2)) 87 88 /* Arasan private data */ 89 struct arasan_host { 90 u32 chg_clk; 91 }; 92 93 static int arasan_phy_addr_poll(struct sdhci_host *host, u32 offset, u32 mask) 94 { 95 ktime_t timeout = ktime_add_us(ktime_get(), 100); 96 bool failed; 97 u8 val = 0; 98 99 while (1) { 100 failed = ktime_after(ktime_get(), timeout); 101 val = sdhci_readw(host, PHY_ADDR_REG); 102 if (!(val & mask)) 103 return 0; 104 if (failed) 105 return -EBUSY; 106 } 107 } 108 109 static int arasan_phy_write(struct sdhci_host *host, u8 data, u8 offset) 110 { 111 sdhci_writew(host, data, PHY_DAT_REG); 112 sdhci_writew(host, (PHY_WRITE | offset), PHY_ADDR_REG); 113 return arasan_phy_addr_poll(host, PHY_ADDR_REG, PHY_BUSY); 114 } 115 116 static int arasan_phy_read(struct sdhci_host *host, u8 offset, u8 *data) 117 { 118 int ret; 119 120 sdhci_writew(host, 0, PHY_DAT_REG); 121 sdhci_writew(host, offset, PHY_ADDR_REG); 122 ret = arasan_phy_addr_poll(host, PHY_ADDR_REG, PHY_BUSY); 123 124 /* Masking valid data bits */ 125 *data = sdhci_readw(host, PHY_DAT_REG) & DATA_MASK; 126 return ret; 127 } 128 129 static int arasan_phy_sts_poll(struct sdhci_host *host, u32 offset, u32 mask) 130 { 131 int ret; 132 ktime_t timeout = ktime_add_us(ktime_get(), 100); 133 bool failed; 134 u8 val = 0; 135 136 while (1) { 137 failed = ktime_after(ktime_get(), timeout); 138 ret = arasan_phy_read(host, offset, &val); 139 if (ret) 140 return -EBUSY; 141 else if (val & mask) 142 return 0; 143 if (failed) 144 return -EBUSY; 145 } 146 } 147 148 /* Initialize the Arasan PHY */ 149 static int arasan_phy_init(struct sdhci_host *host) 150 { 151 int ret; 152 u8 val; 153 154 /* Program IOPADs and wait for calibration to be done */ 155 if (arasan_phy_read(host, IPAD_CTRL1, &val) || 156 arasan_phy_write(host, val | RETB_ENBL | PDB_ENBL, IPAD_CTRL1) || 157 arasan_phy_read(host, IPAD_CTRL2, &val) || 158 arasan_phy_write(host, val | RTRIM_EN, IPAD_CTRL2)) 159 return -EBUSY; 160 ret = arasan_phy_sts_poll(host, IPAD_STS, CALDONE_MASK); 161 if (ret) 162 return -EBUSY; 163 164 /* Program CMD/Data lines */ 165 if (arasan_phy_read(host, IOREN_CTRL1, &val) || 166 arasan_phy_write(host, val | REN_CMND | REN_STRB, IOREN_CTRL1) || 167 arasan_phy_read(host, IOPU_CTRL1, &val) || 168 arasan_phy_write(host, val | PU_CMD, IOPU_CTRL1) || 169 arasan_phy_read(host, CMD_CTRL, &val) || 170 arasan_phy_write(host, val | PDB_CMND, CMD_CTRL) || 171 arasan_phy_read(host, IOREN_CTRL2, &val) || 172 arasan_phy_write(host, val | REN_DATA, IOREN_CTRL2) || 173 arasan_phy_read(host, IOPU_CTRL2, &val) || 174 arasan_phy_write(host, val | PU_DAT, IOPU_CTRL2) || 175 arasan_phy_read(host, DATA_CTRL, &val) || 176 arasan_phy_write(host, val | PDB_DATA, DATA_CTRL) || 177 arasan_phy_read(host, STRB_CTRL, &val) || 178 arasan_phy_write(host, val | PDB_STRB, STRB_CTRL) || 179 arasan_phy_read(host, CLK_CTRL, &val) || 180 arasan_phy_write(host, val | PDB_CLOCK, CLK_CTRL) || 181 arasan_phy_read(host, CLKBUF_SEL, &val) || 182 arasan_phy_write(host, val | MAX_CLK_BUF, CLKBUF_SEL) || 183 arasan_phy_write(host, LEGACY_MODE, MODE_CTRL)) 184 return -EBUSY; 185 return 0; 186 } 187 188 /* Set Arasan PHY for different modes */ 189 static int arasan_phy_set(struct sdhci_host *host, u8 mode, u8 otap, 190 u8 drv_type, u8 itap, u8 trim, u8 clk) 191 { 192 u8 val; 193 int ret; 194 195 if (mode == HISPD_MODE || mode == HS200_MODE) 196 ret = arasan_phy_write(host, 0x0, MODE_CTRL); 197 else 198 ret = arasan_phy_write(host, mode, MODE_CTRL); 199 if (ret) 200 return ret; 201 if (mode == HS400_MODE || mode == HS200_MODE) { 202 ret = arasan_phy_read(host, IPAD_CTRL1, &val); 203 if (ret) 204 return ret; 205 ret = arasan_phy_write(host, IOPAD(val, drv_type), IPAD_CTRL1); 206 if (ret) 207 return ret; 208 } 209 if (mode == LEGACY_MODE) { 210 ret = arasan_phy_write(host, 0x0, OTAP_DELAY); 211 if (ret) 212 return ret; 213 ret = arasan_phy_write(host, 0x0, ITAP_DELAY); 214 } else { 215 ret = arasan_phy_write(host, OTAPDLY(otap), OTAP_DELAY); 216 if (ret) 217 return ret; 218 if (mode != HS200_MODE) 219 ret = arasan_phy_write(host, ITAPDLY(itap), ITAP_DELAY); 220 else 221 ret = arasan_phy_write(host, 0x0, ITAP_DELAY); 222 } 223 if (ret) 224 return ret; 225 if (mode != LEGACY_MODE) { 226 ret = arasan_phy_write(host, trim, DLL_TRIM); 227 if (ret) 228 return ret; 229 } 230 ret = arasan_phy_write(host, 0, DLL_STATUS); 231 if (ret) 232 return ret; 233 if (mode != LEGACY_MODE) { 234 ret = arasan_phy_write(host, FREQSEL(clk), DLL_STATUS); 235 if (ret) 236 return ret; 237 ret = arasan_phy_sts_poll(host, DLL_STATUS, DLL_RDY_MASK); 238 if (ret) 239 return -EBUSY; 240 } 241 return 0; 242 } 243 244 static int arasan_select_phy_clock(struct sdhci_host *host) 245 { 246 struct sdhci_pci_slot *slot = sdhci_priv(host); 247 struct arasan_host *arasan_host = sdhci_pci_priv(slot); 248 u8 clk; 249 250 if (arasan_host->chg_clk == host->mmc->ios.clock) 251 return 0; 252 253 arasan_host->chg_clk = host->mmc->ios.clock; 254 if (host->mmc->ios.clock == 200000000) 255 clk = 0x0; 256 else if (host->mmc->ios.clock == 100000000) 257 clk = 0x2; 258 else if (host->mmc->ios.clock == 50000000) 259 clk = 0x1; 260 else 261 clk = 0x0; 262 263 if (host->mmc_host_ops.hs400_enhanced_strobe) { 264 arasan_phy_set(host, ENHSTRB_MODE, 1, 0x0, 0x0, 265 DLLTRM_ICP, clk); 266 } else { 267 switch (host->mmc->ios.timing) { 268 case MMC_TIMING_LEGACY: 269 arasan_phy_set(host, LEGACY_MODE, 0x0, 0x0, 0x0, 270 0x0, 0x0); 271 break; 272 case MMC_TIMING_MMC_HS: 273 case MMC_TIMING_SD_HS: 274 arasan_phy_set(host, HISPD_MODE, 0x3, 0x0, 0x2, 275 DLLTRM_ICP, clk); 276 break; 277 case MMC_TIMING_MMC_HS200: 278 case MMC_TIMING_UHS_SDR104: 279 arasan_phy_set(host, HS200_MODE, 0x2, 280 host->mmc->ios.drv_type, 0x0, 281 DLLTRM_ICP, clk); 282 break; 283 case MMC_TIMING_MMC_DDR52: 284 case MMC_TIMING_UHS_DDR50: 285 arasan_phy_set(host, DDR50_MODE, 0x1, 0x0, 286 0x0, DLLTRM_ICP, clk); 287 break; 288 case MMC_TIMING_MMC_HS400: 289 arasan_phy_set(host, HS400_MODE, 0x1, 290 host->mmc->ios.drv_type, 0xa, 291 DLLTRM_ICP, clk); 292 break; 293 default: 294 break; 295 } 296 } 297 return 0; 298 } 299 300 static int arasan_pci_probe_slot(struct sdhci_pci_slot *slot) 301 { 302 int err; 303 304 slot->host->mmc->caps |= MMC_CAP_NONREMOVABLE | MMC_CAP_8_BIT_DATA; 305 err = arasan_phy_init(slot->host); 306 if (err) 307 return -ENODEV; 308 return 0; 309 } 310 311 static void arasan_sdhci_set_clock(struct sdhci_host *host, unsigned int clock) 312 { 313 sdhci_set_clock(host, clock); 314 315 /* Change phy settings for the new clock */ 316 arasan_select_phy_clock(host); 317 } 318 319 static const struct sdhci_ops arasan_sdhci_pci_ops = { 320 .set_clock = arasan_sdhci_set_clock, 321 .enable_dma = sdhci_pci_enable_dma, 322 .set_bus_width = sdhci_set_bus_width, 323 .reset = sdhci_reset, 324 .set_uhs_signaling = sdhci_set_uhs_signaling, 325 }; 326 327 const struct sdhci_pci_fixes sdhci_arasan = { 328 .probe_slot = arasan_pci_probe_slot, 329 .ops = &arasan_sdhci_pci_ops, 330 .priv_size = sizeof(struct arasan_host), 331 }; 332