1 // SPDX-License-Identifier: GPL-2.0-or-later
3 * SDHCI support for SiRF primaII and marco SoCs
5 * Copyright (c) 2011 Cambridge Silicon Radio Limited, a CSR plc group company.
8 #include <linux/delay.h>
9 #include <linux/device.h>
10 #include <linux/mmc/host.h>
11 #include <linux/module.h>
13 #include <linux/mmc/slot-gpio.h>
14 #include "sdhci-pltfm.h"
16 #define SDHCI_CLK_DELAY_SETTING 0x4C
17 #define SDHCI_SIRF_8BITBUS BIT(3)
18 #define SIRF_TUNING_COUNT 16384
20 static void sdhci_sirf_set_bus_width(struct sdhci_host
*host
, int width
)
24 ctrl
= sdhci_readb(host
, SDHCI_HOST_CONTROL
);
25 ctrl
&= ~(SDHCI_CTRL_4BITBUS
| SDHCI_SIRF_8BITBUS
);
28 * CSR atlas7 and prima2 SD host version is not 3.0
29 * 8bit-width enable bit of CSR SD hosts is 3,
30 * while stardard hosts use bit 5
32 if (width
== MMC_BUS_WIDTH_8
)
33 ctrl
|= SDHCI_SIRF_8BITBUS
;
34 else if (width
== MMC_BUS_WIDTH_4
)
35 ctrl
|= SDHCI_CTRL_4BITBUS
;
37 sdhci_writeb(host
, ctrl
, SDHCI_HOST_CONTROL
);
40 static u32
sdhci_sirf_readl_le(struct sdhci_host
*host
, int reg
)
42 u32 val
= readl(host
->ioaddr
+ reg
);
44 if (unlikely((reg
== SDHCI_CAPABILITIES_1
) &&
45 (host
->mmc
->caps
& MMC_CAP_UHS_SDR50
))) {
46 /* fake CAP_1 register */
47 val
= SDHCI_SUPPORT_DDR50
|
48 SDHCI_SUPPORT_SDR50
| SDHCI_USE_SDR50_TUNING
;
51 if (unlikely(reg
== SDHCI_SLOT_INT_STATUS
)) {
53 /* fake chips as V3.0 host conreoller */
54 prss
&= ~(0xFF << 16);
55 val
= prss
| (SDHCI_SPEC_300
<< 16);
60 static u16
sdhci_sirf_readw_le(struct sdhci_host
*host
, int reg
)
64 ret
= readw(host
->ioaddr
+ reg
);
66 if (unlikely(reg
== SDHCI_HOST_VERSION
)) {
67 ret
= readw(host
->ioaddr
+ SDHCI_HOST_VERSION
);
68 ret
|= SDHCI_SPEC_300
;
74 static int sdhci_sirf_execute_tuning(struct sdhci_host
*host
, u32 opcode
)
76 int tuning_seq_cnt
= 3;
78 u8 tuned_phase_cnt
= 0;
79 int rc
= 0, longest_range
= 0;
80 int start
= -1, end
= 0, tuning_value
= -1, range
= 0;
82 struct mmc_host
*mmc
= host
->mmc
;
84 clock_setting
= sdhci_readw(host
, SDHCI_CLK_DELAY_SETTING
);
85 clock_setting
&= ~0x3fff;
92 clock_setting
| phase
,
93 SDHCI_CLK_DELAY_SETTING
);
95 if (!mmc_send_tuning(mmc
, opcode
, NULL
)) {
96 /* Tuning is successful at this tuning point */
98 dev_dbg(mmc_dev(mmc
), "%s: Found good phase = %d\n",
99 mmc_hostname(mmc
), phase
);
104 if (phase
== (SIRF_TUNING_COUNT
- 1)
105 && range
> longest_range
)
106 tuning_value
= (start
+ end
) / 2;
108 dev_dbg(mmc_dev(mmc
), "%s: Found bad phase = %d\n",
109 mmc_hostname(mmc
), phase
);
110 if (range
> longest_range
) {
111 tuning_value
= (start
+ end
) / 2;
112 longest_range
= range
;
117 } while (++phase
< SIRF_TUNING_COUNT
);
119 if (tuned_phase_cnt
&& tuning_value
> 0) {
121 * Finally set the selected phase in delay
124 phase
= tuning_value
;
126 clock_setting
| phase
,
127 SDHCI_CLK_DELAY_SETTING
);
129 dev_dbg(mmc_dev(mmc
), "%s: Setting the tuning phase to %d\n",
130 mmc_hostname(mmc
), phase
);
132 if (--tuning_seq_cnt
)
135 dev_dbg(mmc_dev(mmc
), "%s: No tuning point found\n",
143 static const struct sdhci_ops sdhci_sirf_ops
= {
144 .read_l
= sdhci_sirf_readl_le
,
145 .read_w
= sdhci_sirf_readw_le
,
146 .platform_execute_tuning
= sdhci_sirf_execute_tuning
,
147 .set_clock
= sdhci_set_clock
,
148 .get_max_clock
= sdhci_pltfm_clk_get_max_clock
,
149 .set_bus_width
= sdhci_sirf_set_bus_width
,
150 .reset
= sdhci_reset
,
151 .set_uhs_signaling
= sdhci_set_uhs_signaling
,
154 static const struct sdhci_pltfm_data sdhci_sirf_pdata
= {
155 .ops
= &sdhci_sirf_ops
,
156 .quirks
= SDHCI_QUIRK_BROKEN_TIMEOUT_VAL
|
157 SDHCI_QUIRK_DATA_TIMEOUT_USES_SDCLK
|
158 SDHCI_QUIRK_CAP_CLOCK_BASE_BROKEN
|
159 SDHCI_QUIRK_RESET_CMD_DATA_ON_IOS
,
160 .quirks2
= SDHCI_QUIRK2_PRESET_VALUE_BROKEN
,
163 static int sdhci_sirf_probe(struct platform_device
*pdev
)
165 struct sdhci_host
*host
;
166 struct sdhci_pltfm_host
*pltfm_host
;
170 clk
= devm_clk_get(&pdev
->dev
, NULL
);
172 dev_err(&pdev
->dev
, "unable to get clock");
176 host
= sdhci_pltfm_init(pdev
, &sdhci_sirf_pdata
, 0);
178 return PTR_ERR(host
);
180 pltfm_host
= sdhci_priv(host
);
181 pltfm_host
->clk
= clk
;
183 sdhci_get_of_property(pdev
);
185 ret
= clk_prepare_enable(pltfm_host
->clk
);
187 goto err_clk_prepare
;
189 ret
= sdhci_add_host(host
);
194 * We must request the IRQ after sdhci_add_host(), as the tasklet only
195 * gets setup in sdhci_add_host() and we oops.
197 ret
= mmc_gpiod_request_cd(host
->mmc
, "cd", 0, false, 0);
198 if (ret
== -EPROBE_DEFER
)
201 mmc_gpiod_request_cd_irq(host
->mmc
);
206 sdhci_remove_host(host
, 0);
208 clk_disable_unprepare(pltfm_host
->clk
);
210 sdhci_pltfm_free(pdev
);
214 static const struct of_device_id sdhci_sirf_of_match
[] = {
215 { .compatible
= "sirf,prima2-sdhc" },
218 MODULE_DEVICE_TABLE(of
, sdhci_sirf_of_match
);
220 static struct platform_driver sdhci_sirf_driver
= {
222 .name
= "sdhci-sirf",
223 .of_match_table
= sdhci_sirf_of_match
,
224 .pm
= &sdhci_pltfm_pmops
,
226 .probe
= sdhci_sirf_probe
,
227 .remove
= sdhci_pltfm_unregister
,
230 module_platform_driver(sdhci_sirf_driver
);
232 MODULE_DESCRIPTION("SDHCI driver for SiRFprimaII/SiRFmarco");
233 MODULE_AUTHOR("Barry Song <21cnbao@gmail.com>");
234 MODULE_LICENSE("GPL v2");