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 v5.4-rc4 352 lines 11 kB view raw
1// SPDX-License-Identifier: GPL-2.0+ 2/* 3 * Copyright (C) 2019 Genesys Logic, Inc. 4 * 5 * Authors: Ben Chuang <ben.chuang@genesyslogic.com.tw> 6 * 7 * Version: v0.9.0 (2019-08-08) 8 */ 9 10#include <linux/bitfield.h> 11#include <linux/bits.h> 12#include <linux/pci.h> 13#include <linux/mmc/mmc.h> 14#include <linux/delay.h> 15#include "sdhci.h" 16#include "sdhci-pci.h" 17 18/* Genesys Logic extra registers */ 19#define SDHCI_GLI_9750_WT 0x800 20#define SDHCI_GLI_9750_WT_EN BIT(0) 21#define GLI_9750_WT_EN_ON 0x1 22#define GLI_9750_WT_EN_OFF 0x0 23 24#define SDHCI_GLI_9750_DRIVING 0x860 25#define SDHCI_GLI_9750_DRIVING_1 GENMASK(11, 0) 26#define SDHCI_GLI_9750_DRIVING_2 GENMASK(27, 26) 27#define GLI_9750_DRIVING_1_VALUE 0xFFF 28#define GLI_9750_DRIVING_2_VALUE 0x3 29 30#define SDHCI_GLI_9750_PLL 0x864 31#define SDHCI_GLI_9750_PLL_TX2_INV BIT(23) 32#define SDHCI_GLI_9750_PLL_TX2_DLY GENMASK(22, 20) 33#define GLI_9750_PLL_TX2_INV_VALUE 0x1 34#define GLI_9750_PLL_TX2_DLY_VALUE 0x0 35 36#define SDHCI_GLI_9750_SW_CTRL 0x874 37#define SDHCI_GLI_9750_SW_CTRL_4 GENMASK(7, 6) 38#define GLI_9750_SW_CTRL_4_VALUE 0x3 39 40#define SDHCI_GLI_9750_MISC 0x878 41#define SDHCI_GLI_9750_MISC_TX1_INV BIT(2) 42#define SDHCI_GLI_9750_MISC_RX_INV BIT(3) 43#define SDHCI_GLI_9750_MISC_TX1_DLY GENMASK(6, 4) 44#define GLI_9750_MISC_TX1_INV_VALUE 0x0 45#define GLI_9750_MISC_RX_INV_ON 0x1 46#define GLI_9750_MISC_RX_INV_OFF 0x0 47#define GLI_9750_MISC_RX_INV_VALUE GLI_9750_MISC_RX_INV_OFF 48#define GLI_9750_MISC_TX1_DLY_VALUE 0x5 49 50#define SDHCI_GLI_9750_TUNING_CONTROL 0x540 51#define SDHCI_GLI_9750_TUNING_CONTROL_EN BIT(4) 52#define GLI_9750_TUNING_CONTROL_EN_ON 0x1 53#define GLI_9750_TUNING_CONTROL_EN_OFF 0x0 54#define SDHCI_GLI_9750_TUNING_CONTROL_GLITCH_1 BIT(16) 55#define SDHCI_GLI_9750_TUNING_CONTROL_GLITCH_2 GENMASK(20, 19) 56#define GLI_9750_TUNING_CONTROL_GLITCH_1_VALUE 0x1 57#define GLI_9750_TUNING_CONTROL_GLITCH_2_VALUE 0x2 58 59#define SDHCI_GLI_9750_TUNING_PARAMETERS 0x544 60#define SDHCI_GLI_9750_TUNING_PARAMETERS_RX_DLY GENMASK(2, 0) 61#define GLI_9750_TUNING_PARAMETERS_RX_DLY_VALUE 0x1 62 63#define GLI_MAX_TUNING_LOOP 40 64 65/* Genesys Logic chipset */ 66static inline void gl9750_wt_on(struct sdhci_host *host) 67{ 68 u32 wt_value; 69 u32 wt_enable; 70 71 wt_value = sdhci_readl(host, SDHCI_GLI_9750_WT); 72 wt_enable = FIELD_GET(SDHCI_GLI_9750_WT_EN, wt_value); 73 74 if (wt_enable == GLI_9750_WT_EN_ON) 75 return; 76 77 wt_value &= ~SDHCI_GLI_9750_WT_EN; 78 wt_value |= FIELD_PREP(SDHCI_GLI_9750_WT_EN, GLI_9750_WT_EN_ON); 79 80 sdhci_writel(host, wt_value, SDHCI_GLI_9750_WT); 81} 82 83static inline void gl9750_wt_off(struct sdhci_host *host) 84{ 85 u32 wt_value; 86 u32 wt_enable; 87 88 wt_value = sdhci_readl(host, SDHCI_GLI_9750_WT); 89 wt_enable = FIELD_GET(SDHCI_GLI_9750_WT_EN, wt_value); 90 91 if (wt_enable == GLI_9750_WT_EN_OFF) 92 return; 93 94 wt_value &= ~SDHCI_GLI_9750_WT_EN; 95 wt_value |= FIELD_PREP(SDHCI_GLI_9750_WT_EN, GLI_9750_WT_EN_OFF); 96 97 sdhci_writel(host, wt_value, SDHCI_GLI_9750_WT); 98} 99 100static void gli_set_9750(struct sdhci_host *host) 101{ 102 u32 driving_value; 103 u32 pll_value; 104 u32 sw_ctrl_value; 105 u32 misc_value; 106 u32 parameter_value; 107 u32 control_value; 108 u16 ctrl2; 109 110 gl9750_wt_on(host); 111 112 driving_value = sdhci_readl(host, SDHCI_GLI_9750_DRIVING); 113 pll_value = sdhci_readl(host, SDHCI_GLI_9750_PLL); 114 sw_ctrl_value = sdhci_readl(host, SDHCI_GLI_9750_SW_CTRL); 115 misc_value = sdhci_readl(host, SDHCI_GLI_9750_MISC); 116 parameter_value = sdhci_readl(host, SDHCI_GLI_9750_TUNING_PARAMETERS); 117 control_value = sdhci_readl(host, SDHCI_GLI_9750_TUNING_CONTROL); 118 119 driving_value &= ~(SDHCI_GLI_9750_DRIVING_1); 120 driving_value &= ~(SDHCI_GLI_9750_DRIVING_2); 121 driving_value |= FIELD_PREP(SDHCI_GLI_9750_DRIVING_1, 122 GLI_9750_DRIVING_1_VALUE); 123 driving_value |= FIELD_PREP(SDHCI_GLI_9750_DRIVING_2, 124 GLI_9750_DRIVING_2_VALUE); 125 sdhci_writel(host, driving_value, SDHCI_GLI_9750_DRIVING); 126 127 sw_ctrl_value &= ~SDHCI_GLI_9750_SW_CTRL_4; 128 sw_ctrl_value |= FIELD_PREP(SDHCI_GLI_9750_SW_CTRL_4, 129 GLI_9750_SW_CTRL_4_VALUE); 130 sdhci_writel(host, sw_ctrl_value, SDHCI_GLI_9750_SW_CTRL); 131 132 /* reset the tuning flow after reinit and before starting tuning */ 133 pll_value &= ~SDHCI_GLI_9750_PLL_TX2_INV; 134 pll_value &= ~SDHCI_GLI_9750_PLL_TX2_DLY; 135 pll_value |= FIELD_PREP(SDHCI_GLI_9750_PLL_TX2_INV, 136 GLI_9750_PLL_TX2_INV_VALUE); 137 pll_value |= FIELD_PREP(SDHCI_GLI_9750_PLL_TX2_DLY, 138 GLI_9750_PLL_TX2_DLY_VALUE); 139 140 misc_value &= ~SDHCI_GLI_9750_MISC_TX1_INV; 141 misc_value &= ~SDHCI_GLI_9750_MISC_RX_INV; 142 misc_value &= ~SDHCI_GLI_9750_MISC_TX1_DLY; 143 misc_value |= FIELD_PREP(SDHCI_GLI_9750_MISC_TX1_INV, 144 GLI_9750_MISC_TX1_INV_VALUE); 145 misc_value |= FIELD_PREP(SDHCI_GLI_9750_MISC_RX_INV, 146 GLI_9750_MISC_RX_INV_VALUE); 147 misc_value |= FIELD_PREP(SDHCI_GLI_9750_MISC_TX1_DLY, 148 GLI_9750_MISC_TX1_DLY_VALUE); 149 150 parameter_value &= ~SDHCI_GLI_9750_TUNING_PARAMETERS_RX_DLY; 151 parameter_value |= FIELD_PREP(SDHCI_GLI_9750_TUNING_PARAMETERS_RX_DLY, 152 GLI_9750_TUNING_PARAMETERS_RX_DLY_VALUE); 153 154 control_value &= ~SDHCI_GLI_9750_TUNING_CONTROL_GLITCH_1; 155 control_value &= ~SDHCI_GLI_9750_TUNING_CONTROL_GLITCH_2; 156 control_value |= FIELD_PREP(SDHCI_GLI_9750_TUNING_CONTROL_GLITCH_1, 157 GLI_9750_TUNING_CONTROL_GLITCH_1_VALUE); 158 control_value |= FIELD_PREP(SDHCI_GLI_9750_TUNING_CONTROL_GLITCH_2, 159 GLI_9750_TUNING_CONTROL_GLITCH_2_VALUE); 160 161 sdhci_writel(host, pll_value, SDHCI_GLI_9750_PLL); 162 sdhci_writel(host, misc_value, SDHCI_GLI_9750_MISC); 163 164 /* disable tuned clk */ 165 ctrl2 = sdhci_readw(host, SDHCI_HOST_CONTROL2); 166 ctrl2 &= ~SDHCI_CTRL_TUNED_CLK; 167 sdhci_writew(host, ctrl2, SDHCI_HOST_CONTROL2); 168 169 /* enable tuning parameters control */ 170 control_value &= ~SDHCI_GLI_9750_TUNING_CONTROL_EN; 171 control_value |= FIELD_PREP(SDHCI_GLI_9750_TUNING_CONTROL_EN, 172 GLI_9750_TUNING_CONTROL_EN_ON); 173 sdhci_writel(host, control_value, SDHCI_GLI_9750_TUNING_CONTROL); 174 175 /* write tuning parameters */ 176 sdhci_writel(host, parameter_value, SDHCI_GLI_9750_TUNING_PARAMETERS); 177 178 /* disable tuning parameters control */ 179 control_value &= ~SDHCI_GLI_9750_TUNING_CONTROL_EN; 180 control_value |= FIELD_PREP(SDHCI_GLI_9750_TUNING_CONTROL_EN, 181 GLI_9750_TUNING_CONTROL_EN_OFF); 182 sdhci_writel(host, control_value, SDHCI_GLI_9750_TUNING_CONTROL); 183 184 /* clear tuned clk */ 185 ctrl2 = sdhci_readw(host, SDHCI_HOST_CONTROL2); 186 ctrl2 &= ~SDHCI_CTRL_TUNED_CLK; 187 sdhci_writew(host, ctrl2, SDHCI_HOST_CONTROL2); 188 189 gl9750_wt_off(host); 190} 191 192static void gli_set_9750_rx_inv(struct sdhci_host *host, bool b) 193{ 194 u32 misc_value; 195 196 gl9750_wt_on(host); 197 198 misc_value = sdhci_readl(host, SDHCI_GLI_9750_MISC); 199 misc_value &= ~SDHCI_GLI_9750_MISC_RX_INV; 200 if (b) { 201 misc_value |= FIELD_PREP(SDHCI_GLI_9750_MISC_RX_INV, 202 GLI_9750_MISC_RX_INV_ON); 203 } else { 204 misc_value |= FIELD_PREP(SDHCI_GLI_9750_MISC_RX_INV, 205 GLI_9750_MISC_RX_INV_OFF); 206 } 207 sdhci_writel(host, misc_value, SDHCI_GLI_9750_MISC); 208 209 gl9750_wt_off(host); 210} 211 212static int __sdhci_execute_tuning_9750(struct sdhci_host *host, u32 opcode) 213{ 214 int i; 215 int rx_inv; 216 217 for (rx_inv = 0; rx_inv < 2; rx_inv++) { 218 gli_set_9750_rx_inv(host, !!rx_inv); 219 sdhci_start_tuning(host); 220 221 for (i = 0; i < GLI_MAX_TUNING_LOOP; i++) { 222 u16 ctrl; 223 224 sdhci_send_tuning(host, opcode); 225 226 if (!host->tuning_done) { 227 sdhci_abort_tuning(host, opcode); 228 break; 229 } 230 231 ctrl = sdhci_readw(host, SDHCI_HOST_CONTROL2); 232 if (!(ctrl & SDHCI_CTRL_EXEC_TUNING)) { 233 if (ctrl & SDHCI_CTRL_TUNED_CLK) 234 return 0; /* Success! */ 235 break; 236 } 237 } 238 } 239 if (!host->tuning_done) { 240 pr_info("%s: Tuning timeout, falling back to fixed sampling clock\n", 241 mmc_hostname(host->mmc)); 242 return -ETIMEDOUT; 243 } 244 245 pr_info("%s: Tuning failed, falling back to fixed sampling clock\n", 246 mmc_hostname(host->mmc)); 247 sdhci_reset_tuning(host); 248 249 return -EAGAIN; 250} 251 252static int gl9750_execute_tuning(struct sdhci_host *host, u32 opcode) 253{ 254 host->mmc->retune_period = 0; 255 if (host->tuning_mode == SDHCI_TUNING_MODE_1) 256 host->mmc->retune_period = host->tuning_count; 257 258 gli_set_9750(host); 259 host->tuning_err = __sdhci_execute_tuning_9750(host, opcode); 260 sdhci_end_tuning(host); 261 262 return 0; 263} 264 265static int gli_probe_slot_gl9750(struct sdhci_pci_slot *slot) 266{ 267 struct sdhci_host *host = slot->host; 268 269 slot->host->mmc->caps2 |= MMC_CAP2_NO_SDIO; 270 sdhci_enable_v4_mode(host); 271 272 return 0; 273} 274 275static int gli_probe_slot_gl9755(struct sdhci_pci_slot *slot) 276{ 277 struct sdhci_host *host = slot->host; 278 279 slot->host->mmc->caps2 |= MMC_CAP2_NO_SDIO; 280 sdhci_enable_v4_mode(host); 281 282 return 0; 283} 284 285static void sdhci_gli_voltage_switch(struct sdhci_host *host) 286{ 287 /* 288 * According to Section 3.6.1 signal voltage switch procedure in 289 * SD Host Controller Simplified Spec. 4.20, steps 6~8 are as 290 * follows: 291 * (6) Set 1.8V Signal Enable in the Host Control 2 register. 292 * (7) Wait 5ms. 1.8V voltage regulator shall be stable within this 293 * period. 294 * (8) If 1.8V Signal Enable is cleared by Host Controller, go to 295 * step (12). 296 * 297 * Wait 5ms after set 1.8V signal enable in Host Control 2 register 298 * to ensure 1.8V signal enable bit is set by GL9750/GL9755. 299 */ 300 usleep_range(5000, 5500); 301} 302 303static void sdhci_gl9750_reset(struct sdhci_host *host, u8 mask) 304{ 305 sdhci_reset(host, mask); 306 gli_set_9750(host); 307} 308 309static u32 sdhci_gl9750_readl(struct sdhci_host *host, int reg) 310{ 311 u32 value; 312 313 value = readl(host->ioaddr + reg); 314 if (unlikely(reg == SDHCI_MAX_CURRENT && !(value & 0xff))) 315 value |= 0xc8; 316 317 return value; 318} 319 320static const struct sdhci_ops sdhci_gl9755_ops = { 321 .set_clock = sdhci_set_clock, 322 .enable_dma = sdhci_pci_enable_dma, 323 .set_bus_width = sdhci_set_bus_width, 324 .reset = sdhci_reset, 325 .set_uhs_signaling = sdhci_set_uhs_signaling, 326 .voltage_switch = sdhci_gli_voltage_switch, 327}; 328 329const struct sdhci_pci_fixes sdhci_gl9755 = { 330 .quirks = SDHCI_QUIRK_NO_ENDATTR_IN_NOPDESC, 331 .quirks2 = SDHCI_QUIRK2_BROKEN_DDR50, 332 .probe_slot = gli_probe_slot_gl9755, 333 .ops = &sdhci_gl9755_ops, 334}; 335 336static const struct sdhci_ops sdhci_gl9750_ops = { 337 .read_l = sdhci_gl9750_readl, 338 .set_clock = sdhci_set_clock, 339 .enable_dma = sdhci_pci_enable_dma, 340 .set_bus_width = sdhci_set_bus_width, 341 .reset = sdhci_gl9750_reset, 342 .set_uhs_signaling = sdhci_set_uhs_signaling, 343 .voltage_switch = sdhci_gli_voltage_switch, 344 .platform_execute_tuning = gl9750_execute_tuning, 345}; 346 347const struct sdhci_pci_fixes sdhci_gl9750 = { 348 .quirks = SDHCI_QUIRK_NO_ENDATTR_IN_NOPDESC, 349 .quirks2 = SDHCI_QUIRK2_BROKEN_DDR50, 350 .probe_slot = gli_probe_slot_gl9750, 351 .ops = &sdhci_gl9750_ops, 352};