sdhci-tegra.c (de25fa5a1a7732a144af0e2da2447b116604dc1f) sdhci-tegra.c (3c4019f979783575c50db35eae80f30b382e9e49)
1/*
2 * Copyright (C) 2010 Google, Inc.
3 *
4 * This software is licensed under the terms of the GNU General Public
5 * License version 2, as published by the Free Software Foundation, and
6 * may be copied, distributed, and modified under those terms.
7 *
8 * This program is distributed in the hope that it will be useful,

--- 19 unchanged lines hidden (view full) ---

28#include <linux/mmc/card.h>
29#include <linux/mmc/host.h>
30#include <linux/mmc/mmc.h>
31#include <linux/mmc/slot-gpio.h>
32#include <linux/gpio/consumer.h>
33#include <linux/ktime.h>
34
35#include "sdhci-pltfm.h"
1/*
2 * Copyright (C) 2010 Google, Inc.
3 *
4 * This software is licensed under the terms of the GNU General Public
5 * License version 2, as published by the Free Software Foundation, and
6 * may be copied, distributed, and modified under those terms.
7 *
8 * This program is distributed in the hope that it will be useful,

--- 19 unchanged lines hidden (view full) ---

28#include <linux/mmc/card.h>
29#include <linux/mmc/host.h>
30#include <linux/mmc/mmc.h>
31#include <linux/mmc/slot-gpio.h>
32#include <linux/gpio/consumer.h>
33#include <linux/ktime.h>
34
35#include "sdhci-pltfm.h"
36#include "cqhci.h"
36
37/* Tegra SDHOST controller vendor register definitions */
38#define SDHCI_TEGRA_VENDOR_CLOCK_CTRL 0x100
39#define SDHCI_CLOCK_CTRL_TAP_MASK 0x00ff0000
40#define SDHCI_CLOCK_CTRL_TAP_SHIFT 16
41#define SDHCI_CLOCK_CTRL_TRIM_MASK 0x1f000000
42#define SDHCI_CLOCK_CTRL_TRIM_SHIFT 24
43#define SDHCI_CLOCK_CTRL_SDR50_TUNING_OVERRIDE BIT(5)

--- 41 unchanged lines hidden (view full) ---

85#define NVQUIRK_ENABLE_SDHCI_SPEC_300 BIT(2)
86#define NVQUIRK_ENABLE_SDR50 BIT(3)
87#define NVQUIRK_ENABLE_SDR104 BIT(4)
88#define NVQUIRK_ENABLE_DDR50 BIT(5)
89#define NVQUIRK_HAS_PADCALIB BIT(6)
90#define NVQUIRK_NEEDS_PAD_CONTROL BIT(7)
91#define NVQUIRK_DIS_CARD_CLK_CONFIG_TAP BIT(8)
92
37
38/* Tegra SDHOST controller vendor register definitions */
39#define SDHCI_TEGRA_VENDOR_CLOCK_CTRL 0x100
40#define SDHCI_CLOCK_CTRL_TAP_MASK 0x00ff0000
41#define SDHCI_CLOCK_CTRL_TAP_SHIFT 16
42#define SDHCI_CLOCK_CTRL_TRIM_MASK 0x1f000000
43#define SDHCI_CLOCK_CTRL_TRIM_SHIFT 24
44#define SDHCI_CLOCK_CTRL_SDR50_TUNING_OVERRIDE BIT(5)

--- 41 unchanged lines hidden (view full) ---

86#define NVQUIRK_ENABLE_SDHCI_SPEC_300 BIT(2)
87#define NVQUIRK_ENABLE_SDR50 BIT(3)
88#define NVQUIRK_ENABLE_SDR104 BIT(4)
89#define NVQUIRK_ENABLE_DDR50 BIT(5)
90#define NVQUIRK_HAS_PADCALIB BIT(6)
91#define NVQUIRK_NEEDS_PAD_CONTROL BIT(7)
92#define NVQUIRK_DIS_CARD_CLK_CONFIG_TAP BIT(8)
93
94/* SDMMC CQE Base Address for Tegra Host Ver 4.1 and Higher */
95#define SDHCI_TEGRA_CQE_BASE_ADDR 0xF000
96
93struct sdhci_tegra_soc_data {
94 const struct sdhci_pltfm_data *pdata;
95 u32 nvquirks;
96};
97
98/* Magic pull up and pull down pad calibration offsets */
99struct sdhci_tegra_autocal_offsets {
100 u32 pull_up_3v3;

--- 25 unchanged lines hidden (view full) ---

126 struct pinctrl_state *pinctrl_state_1v8_drv;
127
128 struct sdhci_tegra_autocal_offsets autocal_offsets;
129 ktime_t last_calib;
130
131 u32 default_tap;
132 u32 default_trim;
133 u32 dqs_trim;
97struct sdhci_tegra_soc_data {
98 const struct sdhci_pltfm_data *pdata;
99 u32 nvquirks;
100};
101
102/* Magic pull up and pull down pad calibration offsets */
103struct sdhci_tegra_autocal_offsets {
104 u32 pull_up_3v3;

--- 25 unchanged lines hidden (view full) ---

130 struct pinctrl_state *pinctrl_state_1v8_drv;
131
132 struct sdhci_tegra_autocal_offsets autocal_offsets;
133 ktime_t last_calib;
134
135 u32 default_tap;
136 u32 default_trim;
137 u32 dqs_trim;
138 bool enable_hwcq;
134};
135
136static u16 tegra_sdhci_readw(struct sdhci_host *host, int reg)
137{
138 struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
139 struct sdhci_tegra *tegra_host = sdhci_pltfm_priv(pltfm_host);
140 const struct sdhci_tegra_soc_data *soc_data = tegra_host->soc_data;
141

--- 538 unchanged lines hidden (view full) ---

680 tegra_host->default_trim = 0;
681
682 err = device_property_read_u32(host->mmc->parent, "nvidia,dqs-trim",
683 &tegra_host->dqs_trim);
684 if (err)
685 tegra_host->dqs_trim = 0x11;
686}
687
139};
140
141static u16 tegra_sdhci_readw(struct sdhci_host *host, int reg)
142{
143 struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
144 struct sdhci_tegra *tegra_host = sdhci_pltfm_priv(pltfm_host);
145 const struct sdhci_tegra_soc_data *soc_data = tegra_host->soc_data;
146

--- 538 unchanged lines hidden (view full) ---

685 tegra_host->default_trim = 0;
686
687 err = device_property_read_u32(host->mmc->parent, "nvidia,dqs-trim",
688 &tegra_host->dqs_trim);
689 if (err)
690 tegra_host->dqs_trim = 0x11;
691}
692
693static void tegra_sdhci_parse_dt(struct sdhci_host *host)
694{
695 struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
696 struct sdhci_tegra *tegra_host = sdhci_pltfm_priv(pltfm_host);
697
698 if (device_property_read_bool(host->mmc->parent, "supports-cqe"))
699 tegra_host->enable_hwcq = true;
700 else
701 tegra_host->enable_hwcq = false;
702
703 tegra_sdhci_parse_pad_autocal_dt(host);
704 tegra_sdhci_parse_tap_and_trim(host);
705}
706
688static void tegra_sdhci_set_clock(struct sdhci_host *host, unsigned int clock)
689{
690 struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
691 struct sdhci_tegra *tegra_host = sdhci_pltfm_priv(pltfm_host);
692 unsigned long host_clk;
693
694 if (!clock)
695 return sdhci_set_clock(host, clock);

--- 213 unchanged lines hidden (view full) ---

909 struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
910 struct sdhci_tegra *tegra_host = sdhci_pltfm_priv(pltfm_host);
911 const struct sdhci_tegra_soc_data *soc_data = tegra_host->soc_data;
912
913 if (soc_data->nvquirks & NVQUIRK_HAS_PADCALIB)
914 tegra_host->pad_calib_required = true;
915}
916
707static void tegra_sdhci_set_clock(struct sdhci_host *host, unsigned int clock)
708{
709 struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
710 struct sdhci_tegra *tegra_host = sdhci_pltfm_priv(pltfm_host);
711 unsigned long host_clk;
712
713 if (!clock)
714 return sdhci_set_clock(host, clock);

--- 213 unchanged lines hidden (view full) ---

928 struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
929 struct sdhci_tegra *tegra_host = sdhci_pltfm_priv(pltfm_host);
930 const struct sdhci_tegra_soc_data *soc_data = tegra_host->soc_data;
931
932 if (soc_data->nvquirks & NVQUIRK_HAS_PADCALIB)
933 tegra_host->pad_calib_required = true;
934}
935
936static void sdhci_tegra_cqe_enable(struct mmc_host *mmc)
937{
938 struct cqhci_host *cq_host = mmc->cqe_private;
939 u32 cqcfg = 0;
940
941 /*
942 * Tegra SDMMC Controller design prevents write access to BLOCK_COUNT
943 * registers when CQE is enabled.
944 */
945 cqcfg = cqhci_readl(cq_host, CQHCI_CFG);
946 if (cqcfg & CQHCI_ENABLE)
947 cqhci_writel(cq_host, (cqcfg & ~CQHCI_ENABLE), CQHCI_CFG);
948
949 sdhci_cqe_enable(mmc);
950
951 if (cqcfg & CQHCI_ENABLE)
952 cqhci_writel(cq_host, cqcfg, CQHCI_CFG);
953}
954
955static void sdhci_tegra_dumpregs(struct mmc_host *mmc)
956{
957 sdhci_dumpregs(mmc_priv(mmc));
958}
959
960static u32 sdhci_tegra_cqhci_irq(struct sdhci_host *host, u32 intmask)
961{
962 int cmd_error = 0;
963 int data_error = 0;
964
965 if (!sdhci_cqe_irq(host, intmask, &cmd_error, &data_error))
966 return intmask;
967
968 cqhci_irq(host->mmc, intmask, cmd_error, data_error);
969
970 return 0;
971}
972
973static const struct cqhci_host_ops sdhci_tegra_cqhci_ops = {
974 .enable = sdhci_tegra_cqe_enable,
975 .disable = sdhci_cqe_disable,
976 .dumpregs = sdhci_tegra_dumpregs,
977};
978
917static const struct sdhci_ops tegra_sdhci_ops = {
918 .get_ro = tegra_sdhci_get_ro,
919 .read_w = tegra_sdhci_readw,
920 .write_l = tegra_sdhci_writel,
921 .set_clock = tegra_sdhci_set_clock,
922 .set_bus_width = sdhci_set_bus_width,
923 .reset = tegra_sdhci_reset,
924 .platform_execute_tuning = tegra_sdhci_execute_tuning,

--- 137 unchanged lines hidden (view full) ---

1062 .read_w = tegra_sdhci_readw,
1063 .write_l = tegra_sdhci_writel,
1064 .set_clock = tegra_sdhci_set_clock,
1065 .set_bus_width = sdhci_set_bus_width,
1066 .reset = tegra_sdhci_reset,
1067 .set_uhs_signaling = tegra_sdhci_set_uhs_signaling,
1068 .voltage_switch = tegra_sdhci_voltage_switch,
1069 .get_max_clock = tegra_sdhci_get_max_clock,
979static const struct sdhci_ops tegra_sdhci_ops = {
980 .get_ro = tegra_sdhci_get_ro,
981 .read_w = tegra_sdhci_readw,
982 .write_l = tegra_sdhci_writel,
983 .set_clock = tegra_sdhci_set_clock,
984 .set_bus_width = sdhci_set_bus_width,
985 .reset = tegra_sdhci_reset,
986 .platform_execute_tuning = tegra_sdhci_execute_tuning,

--- 137 unchanged lines hidden (view full) ---

1124 .read_w = tegra_sdhci_readw,
1125 .write_l = tegra_sdhci_writel,
1126 .set_clock = tegra_sdhci_set_clock,
1127 .set_bus_width = sdhci_set_bus_width,
1128 .reset = tegra_sdhci_reset,
1129 .set_uhs_signaling = tegra_sdhci_set_uhs_signaling,
1130 .voltage_switch = tegra_sdhci_voltage_switch,
1131 .get_max_clock = tegra_sdhci_get_max_clock,
1132 .irq = sdhci_tegra_cqhci_irq,
1070};
1071
1072static const struct sdhci_pltfm_data sdhci_tegra186_pdata = {
1073 .quirks = SDHCI_QUIRK_BROKEN_TIMEOUT_VAL |
1074 SDHCI_QUIRK_DATA_TIMEOUT_USES_SDCLK |
1075 SDHCI_QUIRK_SINGLE_POWER_WRITE |
1076 SDHCI_QUIRK_NO_HISPD_BIT |
1077 SDHCI_QUIRK_BROKEN_ADMA_ZEROLEN_DESC |

--- 25 unchanged lines hidden (view full) ---

1103 { .compatible = "nvidia,tegra124-sdhci", .data = &soc_data_tegra124 },
1104 { .compatible = "nvidia,tegra114-sdhci", .data = &soc_data_tegra114 },
1105 { .compatible = "nvidia,tegra30-sdhci", .data = &soc_data_tegra30 },
1106 { .compatible = "nvidia,tegra20-sdhci", .data = &soc_data_tegra20 },
1107 {}
1108};
1109MODULE_DEVICE_TABLE(of, sdhci_tegra_dt_match);
1110
1133};
1134
1135static const struct sdhci_pltfm_data sdhci_tegra186_pdata = {
1136 .quirks = SDHCI_QUIRK_BROKEN_TIMEOUT_VAL |
1137 SDHCI_QUIRK_DATA_TIMEOUT_USES_SDCLK |
1138 SDHCI_QUIRK_SINGLE_POWER_WRITE |
1139 SDHCI_QUIRK_NO_HISPD_BIT |
1140 SDHCI_QUIRK_BROKEN_ADMA_ZEROLEN_DESC |

--- 25 unchanged lines hidden (view full) ---

1166 { .compatible = "nvidia,tegra124-sdhci", .data = &soc_data_tegra124 },
1167 { .compatible = "nvidia,tegra114-sdhci", .data = &soc_data_tegra114 },
1168 { .compatible = "nvidia,tegra30-sdhci", .data = &soc_data_tegra30 },
1169 { .compatible = "nvidia,tegra20-sdhci", .data = &soc_data_tegra20 },
1170 {}
1171};
1172MODULE_DEVICE_TABLE(of, sdhci_tegra_dt_match);
1173
1174static int sdhci_tegra_add_host(struct sdhci_host *host)
1175{
1176 struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
1177 struct sdhci_tegra *tegra_host = sdhci_pltfm_priv(pltfm_host);
1178 struct cqhci_host *cq_host;
1179 bool dma64;
1180 int ret;
1181
1182 if (!tegra_host->enable_hwcq)
1183 return sdhci_add_host(host);
1184
1185 sdhci_enable_v4_mode(host);
1186
1187 ret = sdhci_setup_host(host);
1188 if (ret)
1189 return ret;
1190
1191 host->mmc->caps2 |= MMC_CAP2_CQE | MMC_CAP2_CQE_DCMD;
1192
1193 cq_host = devm_kzalloc(host->mmc->parent,
1194 sizeof(*cq_host), GFP_KERNEL);
1195 if (!cq_host) {
1196 ret = -ENOMEM;
1197 goto cleanup;
1198 }
1199
1200 cq_host->mmio = host->ioaddr + SDHCI_TEGRA_CQE_BASE_ADDR;
1201 cq_host->ops = &sdhci_tegra_cqhci_ops;
1202
1203 dma64 = host->flags & SDHCI_USE_64_BIT_DMA;
1204 if (dma64)
1205 cq_host->caps |= CQHCI_TASK_DESC_SZ_128;
1206
1207 ret = cqhci_init(cq_host, host->mmc, dma64);
1208 if (ret)
1209 goto cleanup;
1210
1211 ret = __sdhci_add_host(host);
1212 if (ret)
1213 goto cleanup;
1214
1215 return 0;
1216
1217cleanup:
1218 sdhci_cleanup_host(host);
1219 return ret;
1220}
1221
1111static int sdhci_tegra_probe(struct platform_device *pdev)
1112{
1113 const struct of_device_id *match;
1114 const struct sdhci_tegra_soc_data *soc_data;
1115 struct sdhci_host *host;
1116 struct sdhci_pltfm_host *pltfm_host;
1117 struct sdhci_tegra *tegra_host;
1118 struct clk *clk;

--- 31 unchanged lines hidden (view full) ---

1150
1151 rc = mmc_of_parse(host->mmc);
1152 if (rc)
1153 goto err_parse_dt;
1154
1155 if (tegra_host->soc_data->nvquirks & NVQUIRK_ENABLE_DDR50)
1156 host->mmc->caps |= MMC_CAP_1_8V_DDR;
1157
1222static int sdhci_tegra_probe(struct platform_device *pdev)
1223{
1224 const struct of_device_id *match;
1225 const struct sdhci_tegra_soc_data *soc_data;
1226 struct sdhci_host *host;
1227 struct sdhci_pltfm_host *pltfm_host;
1228 struct sdhci_tegra *tegra_host;
1229 struct clk *clk;

--- 31 unchanged lines hidden (view full) ---

1261
1262 rc = mmc_of_parse(host->mmc);
1263 if (rc)
1264 goto err_parse_dt;
1265
1266 if (tegra_host->soc_data->nvquirks & NVQUIRK_ENABLE_DDR50)
1267 host->mmc->caps |= MMC_CAP_1_8V_DDR;
1268
1158 tegra_sdhci_parse_pad_autocal_dt(host);
1269 tegra_sdhci_parse_dt(host);
1159
1270
1160 tegra_sdhci_parse_tap_and_trim(host);
1161
1162 tegra_host->power_gpio = devm_gpiod_get_optional(&pdev->dev, "power",
1163 GPIOD_OUT_HIGH);
1164 if (IS_ERR(tegra_host->power_gpio)) {
1165 rc = PTR_ERR(tegra_host->power_gpio);
1166 goto err_power_req;
1167 }
1168
1169 clk = devm_clk_get(mmc_dev(host->mmc), NULL);

--- 20 unchanged lines hidden (view full) ---

1190 usleep_range(2000, 4000);
1191
1192 rc = reset_control_deassert(tegra_host->rst);
1193 if (rc)
1194 goto err_rst_get;
1195
1196 usleep_range(2000, 4000);
1197
1271 tegra_host->power_gpio = devm_gpiod_get_optional(&pdev->dev, "power",
1272 GPIOD_OUT_HIGH);
1273 if (IS_ERR(tegra_host->power_gpio)) {
1274 rc = PTR_ERR(tegra_host->power_gpio);
1275 goto err_power_req;
1276 }
1277
1278 clk = devm_clk_get(mmc_dev(host->mmc), NULL);

--- 20 unchanged lines hidden (view full) ---

1299 usleep_range(2000, 4000);
1300
1301 rc = reset_control_deassert(tegra_host->rst);
1302 if (rc)
1303 goto err_rst_get;
1304
1305 usleep_range(2000, 4000);
1306
1198 rc = sdhci_add_host(host);
1307 rc = sdhci_tegra_add_host(host);
1199 if (rc)
1200 goto err_add_host;
1201
1202 return 0;
1203
1204err_add_host:
1205 reset_control_assert(tegra_host->rst);
1206err_rst_get:

--- 40 unchanged lines hidden ---
1308 if (rc)
1309 goto err_add_host;
1310
1311 return 0;
1312
1313err_add_host:
1314 reset_control_assert(tegra_host->rst);
1315err_rst_get:

--- 40 unchanged lines hidden ---