diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2016-07-31 21:36:58 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2016-07-31 21:36:58 -0400 |
commit | 07f00f06ba9a5533d6650d46d3e938f6cbeee97e (patch) | |
tree | 854142fbef263efe8c5b3e9d7450cb44b7fb84c6 /drivers/phy | |
parent | 27acbec338113a75b9d72aeb53149a3538031dda (diff) | |
parent | 6ea6257945188ff7f5d1670d5adc964ac78c590c (diff) |
Merge tag 'mmc-v4.8' of git://git.linaro.org/people/ulf.hansson/mmc
Pull MMC updates from Ulf Hansson:
"MMC core:
- A couple of changes to improve the support for erase/discard/trim cmds
- Add eMMC HS400 enhanced strobe support
- Show OCR and DSR registers in SYSFS for MMC/SD cards
- Correct and improve busy detection logic for MMC switch (CMD6) cmds
- Disable HPI cmds for certain broken Hynix eMMC cards
- Allow MMC hosts to specify non-support for SD and MMC cmds
- Some minor additional fixes
MMC host:
- sdhci: Re-works, fixes and clean-ups
- sdhci: Add HW auto re-tuning support
- sdhci: Re-factor code to prepare for adding support for eMMC CMDQ
- sdhci-esdhc-imx: Fixes and clean-ups
- sdhci-esdhc-imx: Update system PM support
- sdhci-esdhc-imx: Enable HW auto re-tuning
- sdhci-bcm2835: Remove driver as sdhci-iproc is used instead
- sdhci-brcmstb: Add new driver for Broadcom BRCMSTB SoCs
- sdhci-msm: Add support for UHS cards
- sdhci-tegra: Improve support for UHS cards
- sdhci-of-arasan: Update phy support for Rockchip SoCs
- sdhci-of-arasan: Deploy enhanced strobe support
- dw_mmc: Some fixes and clean-ups
- dw_mmc: Enable support for erase/discard/trim cmds
- dw_mmc: Enable CMD23 support
- mediatek: Some fixes related to the eMMC HS400 support
- sh_mmcif: Improve support for HW busy detection
- rtsx_pci: Enable support for erase/discard/trim cmds"
* tag 'mmc-v4.8' of git://git.linaro.org/people/ulf.hansson/mmc: (135 commits)
mmc: rtsx_pci: Remove deprecated create_singlethread_workqueue
mmc: rtsx_pci: Enable MMC_CAP_ERASE to allow erase/discard/trim requests
mmc: rtsx_pci: Use the provided busy timeout from the mmc core
mmc: sdhci-pltfm: Drop define for SDHCI_PLTFM_PMOPS
mmc: sdhci-pltfm: Convert to use the SET_SYSTEM_SLEEP_PM_OPS
mmc: sdhci-pltfm: Make sdhci_pltfm_suspend|resume() static
mmc: sdhci-esdhc-imx: Use common sdhci_suspend|resume_host()
mmc: sdhci-esdhc-imx: Assign system PM ops within #ifdef CONFIG_PM_SLEEP
mmc: sdhci-sirf: Remove non needed #ifdef CONFIG_PM* for dev_pm_ops
mmc: sdhci-s3c: Remove non needed #ifdef CONFIG_PM for dev_pm_ops
mmc: sdhci-pxav3: Remove non needed #ifdef CONFIG_PM for dev_pm_ops
mmc: sdhci-of-esdhc: Simplify code by using SIMPLE_DEV_PM_OPS
mmc: sdhci-acpi: Simplify code by using SET_SYSTEM_SLEEP_PM_OPS
mmc: sdhci-pci-core: Simplify code by using SET_SYSTEM_SLEEP_PM_OPS
mmc: Change the max discard sectors and erase response when HW busy detect
phy: rockchip-emmc: Wait even longer for the DLL to lock
phy: rockchip-emmc: Be tolerant to card clock of 0 in power on
mmc: sdhci-of-arasan: Revert: Always power the PHY off/on when clock changes
mmc: sdhci-msm: Add support for UHS cards
mmc: sdhci-msm: Add set_uhs_signaling() implementation
...
Diffstat (limited to 'drivers/phy')
-rw-r--r-- | drivers/phy/phy-rockchip-emmc.c | 241 |
1 files changed, 196 insertions, 45 deletions
diff --git a/drivers/phy/phy-rockchip-emmc.c b/drivers/phy/phy-rockchip-emmc.c index 6ebcf3e41c46..fd57345ffed2 100644 --- a/drivers/phy/phy-rockchip-emmc.c +++ b/drivers/phy/phy-rockchip-emmc.c | |||
@@ -14,6 +14,7 @@ | |||
14 | * GNU General Public License for more details. | 14 | * GNU General Public License for more details. |
15 | */ | 15 | */ |
16 | 16 | ||
17 | #include <linux/clk.h> | ||
17 | #include <linux/delay.h> | 18 | #include <linux/delay.h> |
18 | #include <linux/mfd/syscon.h> | 19 | #include <linux/mfd/syscon.h> |
19 | #include <linux/module.h> | 20 | #include <linux/module.h> |
@@ -31,42 +32,64 @@ | |||
31 | ((val) << (shift) | (mask) << ((shift) + 16)) | 32 | ((val) << (shift) | (mask) << ((shift) + 16)) |
32 | 33 | ||
33 | /* Register definition */ | 34 | /* Register definition */ |
34 | #define GRF_EMMCPHY_CON0 0x0 | 35 | #define GRF_EMMCPHY_CON0 0x0 |
35 | #define GRF_EMMCPHY_CON1 0x4 | 36 | #define GRF_EMMCPHY_CON1 0x4 |
36 | #define GRF_EMMCPHY_CON2 0x8 | 37 | #define GRF_EMMCPHY_CON2 0x8 |
37 | #define GRF_EMMCPHY_CON3 0xc | 38 | #define GRF_EMMCPHY_CON3 0xc |
38 | #define GRF_EMMCPHY_CON4 0x10 | 39 | #define GRF_EMMCPHY_CON4 0x10 |
39 | #define GRF_EMMCPHY_CON5 0x14 | 40 | #define GRF_EMMCPHY_CON5 0x14 |
40 | #define GRF_EMMCPHY_CON6 0x18 | 41 | #define GRF_EMMCPHY_CON6 0x18 |
41 | #define GRF_EMMCPHY_STATUS 0x20 | 42 | #define GRF_EMMCPHY_STATUS 0x20 |
42 | 43 | ||
43 | #define PHYCTRL_PDB_MASK 0x1 | 44 | #define PHYCTRL_PDB_MASK 0x1 |
44 | #define PHYCTRL_PDB_SHIFT 0x0 | 45 | #define PHYCTRL_PDB_SHIFT 0x0 |
45 | #define PHYCTRL_PDB_PWR_ON 0x1 | 46 | #define PHYCTRL_PDB_PWR_ON 0x1 |
46 | #define PHYCTRL_PDB_PWR_OFF 0x0 | 47 | #define PHYCTRL_PDB_PWR_OFF 0x0 |
47 | #define PHYCTRL_ENDLL_MASK 0x1 | 48 | #define PHYCTRL_ENDLL_MASK 0x1 |
48 | #define PHYCTRL_ENDLL_SHIFT 0x1 | 49 | #define PHYCTRL_ENDLL_SHIFT 0x1 |
49 | #define PHYCTRL_ENDLL_ENABLE 0x1 | 50 | #define PHYCTRL_ENDLL_ENABLE 0x1 |
50 | #define PHYCTRL_ENDLL_DISABLE 0x0 | 51 | #define PHYCTRL_ENDLL_DISABLE 0x0 |
51 | #define PHYCTRL_CALDONE_MASK 0x1 | 52 | #define PHYCTRL_CALDONE_MASK 0x1 |
52 | #define PHYCTRL_CALDONE_SHIFT 0x6 | 53 | #define PHYCTRL_CALDONE_SHIFT 0x6 |
53 | #define PHYCTRL_CALDONE_DONE 0x1 | 54 | #define PHYCTRL_CALDONE_DONE 0x1 |
54 | #define PHYCTRL_CALDONE_GOING 0x0 | 55 | #define PHYCTRL_CALDONE_GOING 0x0 |
55 | #define PHYCTRL_DLLRDY_MASK 0x1 | 56 | #define PHYCTRL_DLLRDY_MASK 0x1 |
56 | #define PHYCTRL_DLLRDY_SHIFT 0x5 | 57 | #define PHYCTRL_DLLRDY_SHIFT 0x5 |
57 | #define PHYCTRL_DLLRDY_DONE 0x1 | 58 | #define PHYCTRL_DLLRDY_DONE 0x1 |
58 | #define PHYCTRL_DLLRDY_GOING 0x0 | 59 | #define PHYCTRL_DLLRDY_GOING 0x0 |
60 | #define PHYCTRL_FREQSEL_200M 0x0 | ||
61 | #define PHYCTRL_FREQSEL_50M 0x1 | ||
62 | #define PHYCTRL_FREQSEL_100M 0x2 | ||
63 | #define PHYCTRL_FREQSEL_150M 0x3 | ||
64 | #define PHYCTRL_FREQSEL_MASK 0x3 | ||
65 | #define PHYCTRL_FREQSEL_SHIFT 0xc | ||
66 | #define PHYCTRL_DR_MASK 0x7 | ||
67 | #define PHYCTRL_DR_SHIFT 0x4 | ||
68 | #define PHYCTRL_DR_50OHM 0x0 | ||
69 | #define PHYCTRL_DR_33OHM 0x1 | ||
70 | #define PHYCTRL_DR_66OHM 0x2 | ||
71 | #define PHYCTRL_DR_100OHM 0x3 | ||
72 | #define PHYCTRL_DR_40OHM 0x4 | ||
73 | #define PHYCTRL_OTAPDLYENA 0x1 | ||
74 | #define PHYCTRL_OTAPDLYENA_MASK 0x1 | ||
75 | #define PHYCTRL_OTAPDLYENA_SHIFT 0xb | ||
76 | #define PHYCTRL_OTAPDLYSEL_MASK 0xf | ||
77 | #define PHYCTRL_OTAPDLYSEL_SHIFT 0x7 | ||
59 | 78 | ||
60 | struct rockchip_emmc_phy { | 79 | struct rockchip_emmc_phy { |
61 | unsigned int reg_offset; | 80 | unsigned int reg_offset; |
62 | struct regmap *reg_base; | 81 | struct regmap *reg_base; |
82 | struct clk *emmcclk; | ||
63 | }; | 83 | }; |
64 | 84 | ||
65 | static int rockchip_emmc_phy_power(struct rockchip_emmc_phy *rk_phy, | 85 | static int rockchip_emmc_phy_power(struct phy *phy, bool on_off) |
66 | bool on_off) | ||
67 | { | 86 | { |
87 | struct rockchip_emmc_phy *rk_phy = phy_get_drvdata(phy); | ||
68 | unsigned int caldone; | 88 | unsigned int caldone; |
69 | unsigned int dllrdy; | 89 | unsigned int dllrdy; |
90 | unsigned int freqsel = PHYCTRL_FREQSEL_200M; | ||
91 | unsigned long rate; | ||
92 | unsigned long timeout; | ||
70 | 93 | ||
71 | /* | 94 | /* |
72 | * Keep phyctrl_pdb and phyctrl_endll low to allow | 95 | * Keep phyctrl_pdb and phyctrl_endll low to allow |
@@ -87,6 +110,43 @@ static int rockchip_emmc_phy_power(struct rockchip_emmc_phy *rk_phy, | |||
87 | if (on_off == PHYCTRL_PDB_PWR_OFF) | 110 | if (on_off == PHYCTRL_PDB_PWR_OFF) |
88 | return 0; | 111 | return 0; |
89 | 112 | ||
113 | rate = clk_get_rate(rk_phy->emmcclk); | ||
114 | |||
115 | if (rate != 0) { | ||
116 | unsigned long ideal_rate; | ||
117 | unsigned long diff; | ||
118 | |||
119 | switch (rate) { | ||
120 | case 1 ... 74999999: | ||
121 | ideal_rate = 50000000; | ||
122 | freqsel = PHYCTRL_FREQSEL_50M; | ||
123 | break; | ||
124 | case 75000000 ... 124999999: | ||
125 | ideal_rate = 100000000; | ||
126 | freqsel = PHYCTRL_FREQSEL_100M; | ||
127 | break; | ||
128 | case 125000000 ... 174999999: | ||
129 | ideal_rate = 150000000; | ||
130 | freqsel = PHYCTRL_FREQSEL_150M; | ||
131 | break; | ||
132 | default: | ||
133 | ideal_rate = 200000000; | ||
134 | break; | ||
135 | }; | ||
136 | |||
137 | diff = (rate > ideal_rate) ? | ||
138 | rate - ideal_rate : ideal_rate - rate; | ||
139 | |||
140 | /* | ||
141 | * In order for tuning delays to be accurate we need to be | ||
142 | * pretty spot on for the DLL range, so warn if we're too | ||
143 | * far off. Also warn if we're above the 200 MHz max. Don't | ||
144 | * warn for really slow rates since we won't be tuning then. | ||
145 | */ | ||
146 | if ((rate > 50000000 && diff > 15000000) || (rate > 200000000)) | ||
147 | dev_warn(&phy->dev, "Unsupported rate: %lu\n", rate); | ||
148 | } | ||
149 | |||
90 | /* | 150 | /* |
91 | * According to the user manual, calpad calibration | 151 | * According to the user manual, calpad calibration |
92 | * cycle takes more than 2us without the minimal recommended | 152 | * cycle takes more than 2us without the minimal recommended |
@@ -113,20 +173,62 @@ static int rockchip_emmc_phy_power(struct rockchip_emmc_phy *rk_phy, | |||
113 | return -ETIMEDOUT; | 173 | return -ETIMEDOUT; |
114 | } | 174 | } |
115 | 175 | ||
176 | /* Set the frequency of the DLL operation */ | ||
177 | regmap_write(rk_phy->reg_base, | ||
178 | rk_phy->reg_offset + GRF_EMMCPHY_CON0, | ||
179 | HIWORD_UPDATE(freqsel, PHYCTRL_FREQSEL_MASK, | ||
180 | PHYCTRL_FREQSEL_SHIFT)); | ||
181 | |||
182 | /* Turn on the DLL */ | ||
116 | regmap_write(rk_phy->reg_base, | 183 | regmap_write(rk_phy->reg_base, |
117 | rk_phy->reg_offset + GRF_EMMCPHY_CON6, | 184 | rk_phy->reg_offset + GRF_EMMCPHY_CON6, |
118 | HIWORD_UPDATE(PHYCTRL_ENDLL_ENABLE, | 185 | HIWORD_UPDATE(PHYCTRL_ENDLL_ENABLE, |
119 | PHYCTRL_ENDLL_MASK, | 186 | PHYCTRL_ENDLL_MASK, |
120 | PHYCTRL_ENDLL_SHIFT)); | 187 | PHYCTRL_ENDLL_SHIFT)); |
188 | |||
121 | /* | 189 | /* |
122 | * After enable analog DLL circuits, we need extra 10.2us | 190 | * We turned on the DLL even though the rate was 0 because we the |
123 | * for dll to be ready for work. | 191 | * clock might be turned on later. ...but we can't wait for the DLL |
192 | * to lock when the rate is 0 because it will never lock with no | ||
193 | * input clock. | ||
194 | * | ||
195 | * Technically we should be checking the lock later when the clock | ||
196 | * is turned on, but for now we won't. | ||
124 | */ | 197 | */ |
125 | udelay(11); | 198 | if (rate == 0) |
126 | regmap_read(rk_phy->reg_base, | 199 | return 0; |
127 | rk_phy->reg_offset + GRF_EMMCPHY_STATUS, | 200 | |
128 | &dllrdy); | 201 | /* |
129 | dllrdy = (dllrdy >> PHYCTRL_DLLRDY_SHIFT) & PHYCTRL_DLLRDY_MASK; | 202 | * After enabling analog DLL circuits docs say that we need 10.2 us if |
203 | * our source clock is at 50 MHz and that lock time scales linearly | ||
204 | * with clock speed. If we are powering on the PHY and the card clock | ||
205 | * is super slow (like 100 kHZ) this could take as long as 5.1 ms as | ||
206 | * per the math: 10.2 us * (50000000 Hz / 100000 Hz) => 5.1 ms | ||
207 | * Hopefully we won't be running at 100 kHz, but we should still make | ||
208 | * sure we wait long enough. | ||
209 | * | ||
210 | * NOTE: There appear to be corner cases where the DLL seems to take | ||
211 | * extra long to lock for reasons that aren't understood. In some | ||
212 | * extreme cases we've seen it take up to over 10ms (!). We'll be | ||
213 | * generous and give it 50ms. We still busy wait here because: | ||
214 | * - In most cases it should be super fast. | ||
215 | * - This is not called lots during normal operation so it shouldn't | ||
216 | * be a power or performance problem to busy wait. We expect it | ||
217 | * only at boot / resume. In both cases, eMMC is probably on the | ||
218 | * critical path so busy waiting a little extra time should be OK. | ||
219 | */ | ||
220 | timeout = jiffies + msecs_to_jiffies(50); | ||
221 | do { | ||
222 | udelay(1); | ||
223 | |||
224 | regmap_read(rk_phy->reg_base, | ||
225 | rk_phy->reg_offset + GRF_EMMCPHY_STATUS, | ||
226 | &dllrdy); | ||
227 | dllrdy = (dllrdy >> PHYCTRL_DLLRDY_SHIFT) & PHYCTRL_DLLRDY_MASK; | ||
228 | if (dllrdy == PHYCTRL_DLLRDY_DONE) | ||
229 | break; | ||
230 | } while (!time_after(jiffies, timeout)); | ||
231 | |||
130 | if (dllrdy != PHYCTRL_DLLRDY_DONE) { | 232 | if (dllrdy != PHYCTRL_DLLRDY_DONE) { |
131 | pr_err("rockchip_emmc_phy_power: dllrdy timeout.\n"); | 233 | pr_err("rockchip_emmc_phy_power: dllrdy timeout.\n"); |
132 | return -ETIMEDOUT; | 234 | return -ETIMEDOUT; |
@@ -135,33 +237,82 @@ static int rockchip_emmc_phy_power(struct rockchip_emmc_phy *rk_phy, | |||
135 | return 0; | 237 | return 0; |
136 | } | 238 | } |
137 | 239 | ||
138 | static int rockchip_emmc_phy_power_off(struct phy *phy) | 240 | static int rockchip_emmc_phy_init(struct phy *phy) |
139 | { | 241 | { |
140 | struct rockchip_emmc_phy *rk_phy = phy_get_drvdata(phy); | 242 | struct rockchip_emmc_phy *rk_phy = phy_get_drvdata(phy); |
141 | int ret = 0; | 243 | int ret = 0; |
142 | 244 | ||
143 | /* Power down emmc phy analog blocks */ | 245 | /* |
144 | ret = rockchip_emmc_phy_power(rk_phy, PHYCTRL_PDB_PWR_OFF); | 246 | * We purposely get the clock here and not in probe to avoid the |
145 | if (ret) | 247 | * circular dependency problem. We expect: |
146 | return ret; | 248 | * - PHY driver to probe |
249 | * - SDHCI driver to start probe | ||
250 | * - SDHCI driver to register it's clock | ||
251 | * - SDHCI driver to get the PHY | ||
252 | * - SDHCI driver to init the PHY | ||
253 | * | ||
254 | * The clock is optional, so upon any error we just set to NULL. | ||
255 | * | ||
256 | * NOTE: we don't do anything special for EPROBE_DEFER here. Given the | ||
257 | * above expected use case, EPROBE_DEFER isn't sensible to expect, so | ||
258 | * it's just like any other error. | ||
259 | */ | ||
260 | rk_phy->emmcclk = clk_get(&phy->dev, "emmcclk"); | ||
261 | if (IS_ERR(rk_phy->emmcclk)) { | ||
262 | dev_dbg(&phy->dev, "Error getting emmcclk: %d\n", ret); | ||
263 | rk_phy->emmcclk = NULL; | ||
264 | } | ||
265 | |||
266 | return ret; | ||
267 | } | ||
268 | |||
269 | static int rockchip_emmc_phy_exit(struct phy *phy) | ||
270 | { | ||
271 | struct rockchip_emmc_phy *rk_phy = phy_get_drvdata(phy); | ||
272 | |||
273 | clk_put(rk_phy->emmcclk); | ||
147 | 274 | ||
148 | return 0; | 275 | return 0; |
149 | } | 276 | } |
150 | 277 | ||
278 | static int rockchip_emmc_phy_power_off(struct phy *phy) | ||
279 | { | ||
280 | /* Power down emmc phy analog blocks */ | ||
281 | return rockchip_emmc_phy_power(phy, PHYCTRL_PDB_PWR_OFF); | ||
282 | } | ||
283 | |||
151 | static int rockchip_emmc_phy_power_on(struct phy *phy) | 284 | static int rockchip_emmc_phy_power_on(struct phy *phy) |
152 | { | 285 | { |
153 | struct rockchip_emmc_phy *rk_phy = phy_get_drvdata(phy); | 286 | struct rockchip_emmc_phy *rk_phy = phy_get_drvdata(phy); |
154 | int ret = 0; | ||
155 | 287 | ||
156 | /* Power up emmc phy analog blocks */ | 288 | /* Drive impedance: 50 Ohm */ |
157 | ret = rockchip_emmc_phy_power(rk_phy, PHYCTRL_PDB_PWR_ON); | 289 | regmap_write(rk_phy->reg_base, |
158 | if (ret) | 290 | rk_phy->reg_offset + GRF_EMMCPHY_CON6, |
159 | return ret; | 291 | HIWORD_UPDATE(PHYCTRL_DR_50OHM, |
292 | PHYCTRL_DR_MASK, | ||
293 | PHYCTRL_DR_SHIFT)); | ||
160 | 294 | ||
161 | return 0; | 295 | /* Output tap delay: enable */ |
296 | regmap_write(rk_phy->reg_base, | ||
297 | rk_phy->reg_offset + GRF_EMMCPHY_CON0, | ||
298 | HIWORD_UPDATE(PHYCTRL_OTAPDLYENA, | ||
299 | PHYCTRL_OTAPDLYENA_MASK, | ||
300 | PHYCTRL_OTAPDLYENA_SHIFT)); | ||
301 | |||
302 | /* Output tap delay */ | ||
303 | regmap_write(rk_phy->reg_base, | ||
304 | rk_phy->reg_offset + GRF_EMMCPHY_CON0, | ||
305 | HIWORD_UPDATE(4, | ||
306 | PHYCTRL_OTAPDLYSEL_MASK, | ||
307 | PHYCTRL_OTAPDLYSEL_SHIFT)); | ||
308 | |||
309 | /* Power up emmc phy analog blocks */ | ||
310 | return rockchip_emmc_phy_power(phy, PHYCTRL_PDB_PWR_ON); | ||
162 | } | 311 | } |
163 | 312 | ||
164 | static const struct phy_ops ops = { | 313 | static const struct phy_ops ops = { |
314 | .init = rockchip_emmc_phy_init, | ||
315 | .exit = rockchip_emmc_phy_exit, | ||
165 | .power_on = rockchip_emmc_phy_power_on, | 316 | .power_on = rockchip_emmc_phy_power_on, |
166 | .power_off = rockchip_emmc_phy_power_off, | 317 | .power_off = rockchip_emmc_phy_power_off, |
167 | .owner = THIS_MODULE, | 318 | .owner = THIS_MODULE, |