* [PATCH V1] Add Quirk for Broken Configuration
@ 2012-07-18 8:38 Girish K S
2012-07-18 8:38 ` [PATCH V1] mmc: dwmmc: Add quirk for broken Hardware Config Girish K S
0 siblings, 1 reply; 5+ messages in thread
From: Girish K S @ 2012-07-18 8:38 UTC (permalink / raw)
To: linux-mmc
Cc: cjb, will.newton, patches, linux-samsung-soc, shashidharh,
thomas.abraham, jh80.chung, Girish K S
This patch is based on the device tree support of dw_mmc host controller
posted by Thomas Abraham. Below is the list of his patch in review stage
mmc: dw_mmc: convert copy of struct device in struct dw_mci to a reference
mmc: dw_mmc: allow probe to succeed even if one slot is initialized
mmc: dw_mmc: lookup for optional biu and ciu clocks
mmc: dw_mmc: add quirk to indicate missing write protect line
mmc: dw_mmc: add device tree support
mmc: dw_mmc: add samsung exynos5250 specific extentions
Girish K S (1):
mmc: dwmmc: Add quirk for broken Hardware Config
drivers/mmc/host/dw_mmc-pltfm.c | 10 +++-
drivers/mmc/host/dw_mmc.c | 150 ++++++++++++++++++++++++---------------
drivers/mmc/host/dw_mmc.h | 1 +
include/linux/mmc/dw_mmc.h | 2 +-
include/linux/mmc/host.h | 1 +
5 files changed, 106 insertions(+), 58 deletions(-)
--
1.7.4.1
^ permalink raw reply [flat|nested] 5+ messages in thread
* [PATCH V1] mmc: dwmmc: Add quirk for broken Hardware Config
2012-07-18 8:38 [PATCH V1] Add Quirk for Broken Configuration Girish K S
@ 2012-07-18 8:38 ` Girish K S
2012-07-18 12:55 ` S, Venkatraman
2012-07-20 11:55 ` Girish K S
0 siblings, 2 replies; 5+ messages in thread
From: Girish K S @ 2012-07-18 8:38 UTC (permalink / raw)
To: linux-mmc
Cc: cjb, will.newton, patches, linux-samsung-soc, shashidharh,
thomas.abraham, jh80.chung, Girish K S
In some Soc'S that integrate Designware mmc host controllers, the
HCON register is broken. The hardware configuration is not
updated. One specific usecase is the IDMAC. In Exysons5 SoC
there exist a internal DMA, but the HCON register's DMA_INTERFACE
field is not set to indicate its existance.
This quirk can be used in such case to force the existance broken
HCON field.
changes in v1:
-modified the caps2 field access per controller index.Reported
by Jaehoon Chung <jh80.chung@samsung.com>.
-replaced the pointer to device with the pointer to platform
device in struct dw_mci.
-updated driver data for all 4 mmc controllers of exynos5 SoC.
-added non device-tree support for ctrl_id access.
Signed-off-by: Girish K S <girish.shivananjappa@linaro.org>
---
drivers/mmc/host/dw_mmc-pltfm.c | 10 +++-
drivers/mmc/host/dw_mmc.c | 150 ++++++++++++++++++++++++---------------
drivers/mmc/host/dw_mmc.h | 1 +
include/linux/mmc/dw_mmc.h | 2 +-
include/linux/mmc/host.h | 1 +
5 files changed, 106 insertions(+), 58 deletions(-)
diff --git a/drivers/mmc/host/dw_mmc-pltfm.c b/drivers/mmc/host/dw_mmc-pltfm.c
index 900f412..c8eb573 100644
--- a/drivers/mmc/host/dw_mmc-pltfm.c
+++ b/drivers/mmc/host/dw_mmc-pltfm.c
@@ -35,9 +35,17 @@ static unsigned long exynos5250_dwmmc_caps[4] = {
MMC_CAP_CMD23,
};
+static unsigned long exynos5250_dwmmc_caps2[4] = {
+ MMC_CAP2_CONFIG_BROKEN,
+ MMC_CAP2_CONFIG_BROKEN,
+ MMC_CAP2_CONFIG_BROKEN,
+ MMC_CAP2_CONFIG_BROKEN,
+};
+
static struct dw_mci_drv_data exynos5250_drv_data = {
.ctrl_type = DW_MCI_TYPE_EXYNOS5250,
.caps = exynos5250_dwmmc_caps,
+ .caps2 = exynos5250_dwmmc_caps2,
};
static const struct of_device_id dw_mci_pltfm_match[] = {
@@ -74,7 +82,7 @@ static int dw_mci_pltfm_probe(struct platform_device *pdev)
goto err_free;
}
- host->dev = &pdev->dev;
+ host->pdev = pdev;
host->irq_flags = 0;
host->pdata = pdev->dev.platform_data;
ret = -ENOMEM;
diff --git a/drivers/mmc/host/dw_mmc.c b/drivers/mmc/host/dw_mmc.c
index 000da16..fd9233d 100644
--- a/drivers/mmc/host/dw_mmc.c
+++ b/drivers/mmc/host/dw_mmc.c
@@ -283,8 +283,10 @@ static u32 dw_mci_prepare_command(struct mmc_host *mmc, struct mmc_command *cmd)
static void dw_mci_start_command(struct dw_mci *host,
struct mmc_command *cmd, u32 cmd_flags)
{
+ struct device *dev = &host->pdev->dev;
+
host->cmd = cmd;
- dev_vdbg(host->dev,
+ dev_vdbg(dev,
"start command: ARGR=0x%08x CMDR=0x%08x\n",
cmd->arg, cmd_flags);
@@ -323,10 +325,11 @@ static int dw_mci_get_dma_dir(struct mmc_data *data)
static void dw_mci_dma_cleanup(struct dw_mci *host)
{
struct mmc_data *data = host->data;
+ struct device *dev = &host->pdev->dev;
if (data)
if (!data->host_cookie)
- dma_unmap_sg(host->dev,
+ dma_unmap_sg(dev,
data->sg,
data->sg_len,
dw_mci_get_dma_dir(data));
@@ -351,8 +354,9 @@ static void dw_mci_idmac_stop_dma(struct dw_mci *host)
static void dw_mci_idmac_complete_dma(struct dw_mci *host)
{
struct mmc_data *data = host->data;
+ struct device *dev = &host->pdev->dev;
- dev_vdbg(host->dev, "DMA complete\n");
+ dev_vdbg(dev, "DMA complete\n");
host->dma_ops->cleanup(host);
@@ -420,10 +424,27 @@ static void dw_mci_idmac_start_dma(struct dw_mci *host, unsigned int sg_len)
mci_writel(host, PLDMND, 1);
}
+static int dw_get_platform_device_id(struct dw_mci *host)
+{
+ int ctrl_id;
+ struct device *dev = &host->pdev->dev;
+
+ if (dev->of_node)
+ ctrl_id = of_alias_get_id(dev->of_node, "mshc");
+ else
+ ctrl_id = host->pdev->id;
+
+ if (ctrl_id < 0)
+ ctrl_id = 0;
+
+ return ctrl_id;
+}
+
static int dw_mci_idmac_init(struct dw_mci *host)
{
struct idmac_desc *p;
- int i, dma_support;
+ int i, dma_support, ctrl_id;
+ struct device *dev = &host->pdev->dev;
/* Number of descriptors in the ring buffer */
host->ring_size = PAGE_SIZE / sizeof(struct idmac_desc);
@@ -431,14 +452,23 @@ static int dw_mci_idmac_init(struct dw_mci *host)
/* Check if Hardware Configuration Register has support for DMA */
dma_support = (mci_readl(host, HCON) >> 16) & 0x3;
- if (!dma_support || dma_support > 2) {
- dev_err(&host->dev,
+ /*
+ * In Some of the Soc's the HCON Register is broken. Even though the
+ * Soc's has a internal DMA the HCON register's DMA field doesnt
+ * show it. So additional quirk is added for such Soc's
+ */
+ ctrl_id = dw_get_platform_device_id(host);
+
+ if ((!dma_support || dma_support > 2) &&
+ host->drv_data && host->drv_data->caps2 &&
+ !(host->drv_data->caps2[ctrl_id] & MMC_CAP2_CONFIG_BROKEN)) {
+ dev_err(dev,
"Host Controller does not support IDMA Tx.\n");
host->dma_ops = NULL;
return -ENODEV;
}
- dev_info(&host->dev, "Using internal DMA controller.\n");
+ dev_info(dev, "Using internal DMA controller.\n");
/* Forward link the descriptor list */
for (i = 0, p = host->sg_cpu; i < host->ring_size - 1; i++, p++)
@@ -474,6 +504,7 @@ static int dw_mci_pre_dma_transfer(struct dw_mci *host,
{
struct scatterlist *sg;
unsigned int i, sg_len;
+ struct device *dev = &host->pdev->dev;
if (!next && data->host_cookie)
return data->host_cookie;
@@ -494,7 +525,7 @@ static int dw_mci_pre_dma_transfer(struct dw_mci *host,
return -EINVAL;
}
- sg_len = dma_map_sg(host->dev,
+ sg_len = dma_map_sg(dev,
data->sg,
data->sg_len,
dw_mci_get_dma_dir(data));
@@ -532,12 +563,13 @@ static void dw_mci_post_req(struct mmc_host *mmc,
{
struct dw_mci_slot *slot = mmc_priv(mmc);
struct mmc_data *data = mrq->data;
+ struct device *dev = &slot->host->pdev->dev;
if (!slot->host->use_dma || !data)
return;
if (data->host_cookie)
- dma_unmap_sg(slot->host->dev,
+ dma_unmap_sg(dev,
data->sg,
data->sg_len,
dw_mci_get_dma_dir(data));
@@ -548,6 +580,7 @@ static int dw_mci_submit_data_dma(struct dw_mci *host, struct mmc_data *data)
{
int sg_len;
u32 temp;
+ struct device *dev = &host->pdev->dev;
host->using_dma = 0;
@@ -563,7 +596,7 @@ static int dw_mci_submit_data_dma(struct dw_mci *host, struct mmc_data *data)
host->using_dma = 1;
- dev_vdbg(host->dev,
+ dev_vdbg(dev,
"sd sg_cpu: %#lx sg_dma: %#lx sg_len: %d\n",
(unsigned long)host->sg_cpu, (unsigned long)host->sg_dma,
sg_len);
@@ -928,6 +961,7 @@ static void dw_mci_request_end(struct dw_mci *host, struct mmc_request *mrq)
{
struct dw_mci_slot *slot;
struct mmc_host *prev_mmc = host->cur_slot->mmc;
+ struct device *dev = &host->pdev->dev;
WARN_ON(host->cmd || host->data);
@@ -937,12 +971,12 @@ static void dw_mci_request_end(struct dw_mci *host, struct mmc_request *mrq)
slot = list_entry(host->queue.next,
struct dw_mci_slot, queue_node);
list_del(&slot->queue_node);
- dev_vdbg(host->dev, "list not empty: %s is next\n",
+ dev_vdbg(dev, "list not empty: %s is next\n",
mmc_hostname(slot->mmc));
host->state = STATE_SENDING_CMD;
dw_mci_start_request(host, slot);
} else {
- dev_vdbg(host->dev, "list empty\n");
+ dev_vdbg(dev, "list empty\n");
host->state = STATE_IDLE;
}
@@ -1081,7 +1115,7 @@ static void dw_mci_tasklet_func(unsigned long priv)
data->bytes_xfered = 0;
data->error = -ETIMEDOUT;
} else {
- dev_err(host->dev,
+ dev_err(&host->pdev->dev,
"data FIFO error "
"(status=%08x)\n",
status);
@@ -1829,7 +1863,8 @@ static u32 dw_mci_of_get_bus_wd(struct device *dev, u8 slot)
static int dw_mci_of_setup_bus(struct dw_mci *host, u8 slot, u32 bus_wd)
{
- struct device_node *np = dw_mci_of_find_slot_node(host->dev, slot);
+ struct device *dev = &host->pdev->dev;
+ struct device_node *np = dw_mci_of_find_slot_node(dev, slot);
int idx, gpio, ret;
if (!np)
@@ -1838,13 +1873,13 @@ static int dw_mci_of_setup_bus(struct dw_mci *host, u8 slot, u32 bus_wd)
for (idx = 0; idx < NUM_PINS(bus_wd); idx++) {
gpio = of_get_gpio(np, idx);
if (!gpio_is_valid(gpio)) {
- dev_err(host->dev, "invalid gpio: %d\n", gpio);
+ dev_err(dev, "invalid gpio: %d\n", gpio);
return -EINVAL;
}
- ret = devm_gpio_request(host->dev, gpio, "dw-mci-bus");
+ ret = devm_gpio_request(dev, gpio, "dw-mci-bus");
if (ret) {
- dev_err(host->dev, "gpio [%d] request failed\n", gpio);
+ dev_err(dev, "gpio [%d] request failed\n", gpio);
return -EBUSY;
}
}
@@ -1852,11 +1887,11 @@ static int dw_mci_of_setup_bus(struct dw_mci *host, u8 slot, u32 bus_wd)
host->slot[slot]->wp_gpio = -1;
gpio = of_get_named_gpio(np, "wp-gpios", 0);
if (!gpio_is_valid(gpio)) {
- dev_info(host->dev, "wp gpio not available");
+ dev_info(dev, "wp gpio not available");
} else {
- ret = devm_gpio_request(host->dev, gpio, "dw-mci-wp");
+ ret = devm_gpio_request(dev, gpio, "dw-mci-wp");
if (ret)
- dev_info(host->dev, "gpio [%d] request failed\n",
+ dev_info(dev, "gpio [%d] request failed\n",
gpio);
else
host->slot[slot]->wp_gpio = gpio;
@@ -1865,11 +1900,11 @@ static int dw_mci_of_setup_bus(struct dw_mci *host, u8 slot, u32 bus_wd)
host->slot[slot]->cd_gpio = -1;
gpio = of_get_named_gpio(np, "cd-gpios", 0);
if (!gpio_is_valid(gpio)) {
- dev_info(host->dev, "cd gpio not available");
+ dev_info(dev, "cd gpio not available");
} else {
- ret = devm_gpio_request(host->dev, gpio, "dw-mci-cd");
+ ret = devm_gpio_request(dev, gpio, "dw-mci-cd");
if (ret)
- dev_err(host->dev, "gpio [%d] request failed\n", gpio);
+ dev_err(dev, "gpio [%d] request failed\n", gpio);
else
host->slot[slot]->cd_gpio = gpio;
}
@@ -1893,8 +1928,9 @@ static int __init dw_mci_init_slot(struct dw_mci *host, unsigned int id)
struct mmc_host *mmc;
struct dw_mci_slot *slot;
int ctrl_id, ret;
+ struct device *dev = &host->pdev->dev;
- mmc = mmc_alloc_host(sizeof(struct dw_mci_slot), host->dev);
+ mmc = mmc_alloc_host(sizeof(struct dw_mci_slot), dev);
if (!mmc)
return -ENOMEM;
@@ -1923,23 +1959,23 @@ static int __init dw_mci_init_slot(struct dw_mci *host, unsigned int id)
if (host->pdata->caps)
mmc->caps = host->pdata->caps;
- if (host->dev->of_node) {
- ctrl_id = of_alias_get_id(host->dev->of_node, "mshc");
- if (ctrl_id < 0)
- ctrl_id = 0;
- }
+ ctrl_id = dw_get_platform_device_id(host);
+
if (host->drv_data->caps)
mmc->caps |= host->drv_data->caps[ctrl_id];
if (host->pdata->caps2)
mmc->caps2 = host->pdata->caps2;
+ if (host->drv_data->caps2)
+ mmc->caps2 |= host->drv_data->caps2[ctrl_id];
+
if (host->pdata->get_bus_wd) {
if (host->pdata->get_bus_wd(slot->id) >= 4)
mmc->caps |= MMC_CAP_4_BIT_DATA;
- } else if (host->dev->of_node) {
+ } else if (dev->of_node) {
unsigned int bus_width;
- bus_width = dw_mci_of_get_bus_wd(host->dev, slot->id);
+ bus_width = dw_mci_of_get_bus_wd(dev, slot->id);
switch (bus_width) {
case 8:
mmc->caps |= MMC_CAP_8_BIT_DATA;
@@ -2030,11 +2066,12 @@ static void dw_mci_cleanup_slot(struct dw_mci_slot *slot, unsigned int id)
static void dw_mci_init_dma(struct dw_mci *host)
{
+ struct device *dev = &host->pdev->dev;
/* Alloc memory for sg translation */
- host->sg_cpu = dma_alloc_coherent(host->dev, PAGE_SIZE,
+ host->sg_cpu = dma_alloc_coherent(dev, PAGE_SIZE,
&host->sg_dma, GFP_KERNEL);
if (!host->sg_cpu) {
- dev_err(host->dev, "%s: could not alloc DMA memory\n",
+ dev_err(dev, "%s: could not alloc DMA memory\n",
__func__);
goto no_dma;
}
@@ -2050,12 +2087,12 @@ static void dw_mci_init_dma(struct dw_mci *host)
if (host->dma_ops->init && host->dma_ops->start &&
host->dma_ops->stop && host->dma_ops->cleanup) {
if (host->dma_ops->init(host)) {
- dev_err(host->dev, "%s: Unable to initialize "
+ dev_err(dev, "%s: Unable to initialize "
"DMA Controller.\n", __func__);
goto no_dma;
}
} else {
- dev_err(host->dev, "DMA initialization not found.\n");
+ dev_err(dev, "DMA initialization not found.\n");
goto no_dma;
}
@@ -2063,7 +2100,7 @@ static void dw_mci_init_dma(struct dw_mci *host)
return;
no_dma:
- dev_info(host->dev, "Using PIO mode.\n");
+ dev_info(dev, "Using PIO mode.\n");
host->use_dma = 0;
return;
}
@@ -2109,7 +2146,7 @@ static struct dw_mci_of_quirks {
static struct dw_mci_board *dw_mci_parse_dt(struct dw_mci *host)
{
struct dw_mci_board *pdata;
- struct device *dev = host->dev;
+ struct device *dev = &host->pdev->dev;
struct device_node *np = dev->of_node;
u32 timing[3];
int idx, cnt;
@@ -2169,30 +2206,31 @@ int dw_mci_probe(struct dw_mci *host)
int width, i, ret = 0;
u32 fifo_size;
int init_slots = 0;
+ struct device *dev = &host->pdev->dev;
if (!host->pdata) {
host->pdata = dw_mci_parse_dt(host);
if (IS_ERR(host->pdata)) {
- dev_err(host->dev, "platform data not available\n");
+ dev_err(dev, "platform data not available\n");
return -EINVAL;
}
}
if (!host->pdata->select_slot && host->pdata->num_slots > 1) {
- dev_err(host->dev,
+ dev_err(dev,
"Platform data must supply select_slot function\n");
return -ENODEV;
}
- host->biu_clk = clk_get(host->dev, "biu");
+ host->biu_clk = clk_get(dev, "biu");
if (IS_ERR(host->biu_clk))
- dev_dbg(host->dev, "biu clock not available\n");
+ dev_dbg(dev, "biu clock not available\n");
else
clk_prepare_enable(host->biu_clk);
- host->ciu_clk = clk_get(host->dev, "ciu");
+ host->ciu_clk = clk_get(dev, "ciu");
if (IS_ERR(host->ciu_clk))
- dev_dbg(host->dev, "ciu clock not available\n");
+ dev_dbg(dev, "ciu clock not available\n");
else
clk_prepare_enable(host->ciu_clk);
@@ -2202,7 +2240,7 @@ int dw_mci_probe(struct dw_mci *host)
host->bus_hz = clk_get_rate(host->ciu_clk);
if (!host->bus_hz) {
- dev_err(host->dev,
+ dev_err(dev,
"Platform data must supply bus speed\n");
ret = -ENODEV;
goto err_clk;
@@ -2243,7 +2281,7 @@ int dw_mci_probe(struct dw_mci *host)
}
/* Reset all blocks */
- if (!mci_wait_reset(host->dev, host))
+ if (!mci_wait_reset(dev, host))
return -ENODEV;
host->dma_ops = host->pdata->dma_ops;
@@ -2300,15 +2338,15 @@ int dw_mci_probe(struct dw_mci *host)
for (i = 0; i < host->num_slots; i++) {
ret = dw_mci_init_slot(host, i);
if (ret)
- dev_dbg(host->dev, "slot %d init failed\n", i);
+ dev_dbg(dev, "slot %d init failed\n", i);
else
init_slots++;
}
if (init_slots) {
- dev_info(host->dev, "%d slots initialized\n", init_slots);
+ dev_info(dev, "%d slots initialized\n", init_slots);
} else {
- dev_dbg(host->dev, "attempted to initialize %d slots, "
+ dev_dbg(dev, "attempted to initialize %d slots, "
"but failed on all\n", host->num_slots);
goto err_init_slot;
}
@@ -2318,7 +2356,7 @@ int dw_mci_probe(struct dw_mci *host)
* Need to check the version-id and set data-offset for DATA register.
*/
host->verid = SDMMC_GET_VERID(mci_readl(host, VERID));
- dev_info(host->dev, "Version ID is %04x\n", host->verid);
+ dev_info(dev, "Version ID is %04x\n", host->verid);
if (host->verid < DW_MMC_240A)
host->data_offset = DATA_OFFSET;
@@ -2335,12 +2373,12 @@ int dw_mci_probe(struct dw_mci *host)
DW_MCI_ERROR_FLAGS | SDMMC_INT_CD);
mci_writel(host, CTRL, SDMMC_CTRL_INT_ENABLE); /* Enable mci interrupt */
- dev_info(host->dev, "DW MMC controller at irq %d, "
+ dev_info(dev, "DW MMC controller at irq %d, "
"%d bit host data width, "
"%u deep fifo\n",
host->irq, width, fifo_size);
if (host->quirks & DW_MCI_QUIRK_IDMAC_DTO)
- dev_info(host->dev, "Internal DMAC interrupt fix enabled.\n");
+ dev_info(dev, "Internal DMAC interrupt fix enabled.\n");
return 0;
@@ -2353,7 +2391,7 @@ err_workqueue:
err_dmaunmap:
if (host->use_dma && host->dma_ops->exit)
host->dma_ops->exit(host);
- dma_free_coherent(host->dev, PAGE_SIZE,
+ dma_free_coherent(dev, PAGE_SIZE,
host->sg_cpu, host->sg_dma);
if (host->vmmc) {
@@ -2377,23 +2415,23 @@ EXPORT_SYMBOL(dw_mci_probe);
void dw_mci_remove(struct dw_mci *host)
{
int i;
+ struct device *dev = &host->pdev->dev;
mci_writel(host, RINTSTS, 0xFFFFFFFF);
mci_writel(host, INTMASK, 0); /* disable all mmc interrupt first */
for (i = 0; i < host->num_slots; i++) {
- dev_dbg(host->dev, "remove slot %d\n", i);
+ dev_dbg(dev, "remove slot %d\n", i);
if (host->slot[i])
dw_mci_cleanup_slot(host->slot[i], i);
}
-
/* disable clock to CIU */
mci_writel(host, CLKENA, 0);
mci_writel(host, CLKSRC, 0);
free_irq(host->irq, host);
destroy_workqueue(host->card_workqueue);
- dma_free_coherent(host->dev, PAGE_SIZE, host->sg_cpu, host->sg_dma);
+ dma_free_coherent(dev, PAGE_SIZE, host->sg_cpu, host->sg_dma);
if (host->use_dma && host->dma_ops->exit)
host->dma_ops->exit(host);
@@ -2451,7 +2489,7 @@ int dw_mci_resume(struct dw_mci *host)
if (host->vmmc)
regulator_enable(host->vmmc);
- if (!mci_wait_reset(host->dev, host)) {
+ if (!mci_wait_reset(&host->pdev->dev, host)) {
ret = -ENODEV;
return ret;
}
diff --git a/drivers/mmc/host/dw_mmc.h b/drivers/mmc/host/dw_mmc.h
index 6c17282..8c4810a 100644
--- a/drivers/mmc/host/dw_mmc.h
+++ b/drivers/mmc/host/dw_mmc.h
@@ -203,6 +203,7 @@ extern int dw_mci_resume(struct dw_mci *host);
struct dw_mci_drv_data {
unsigned long ctrl_type;
unsigned long *caps;
+ unsigned long *caps2;
};
#endif /* _DW_MMC_H_ */
diff --git a/include/linux/mmc/dw_mmc.h b/include/linux/mmc/dw_mmc.h
index 32c778f..71de160 100644
--- a/include/linux/mmc/dw_mmc.h
+++ b/include/linux/mmc/dw_mmc.h
@@ -161,7 +161,7 @@ struct dw_mci {
u32 fifoth_val;
u16 verid;
u16 data_offset;
- struct device *dev;
+ struct platform_device *pdev;
struct dw_mci_board *pdata;
struct dw_mci_drv_data *drv_data;
struct clk *biu_clk;
diff --git a/include/linux/mmc/host.h b/include/linux/mmc/host.h
index 79d8921..b3e35fd 100644
--- a/include/linux/mmc/host.h
+++ b/include/linux/mmc/host.h
@@ -273,6 +273,7 @@ struct mmc_host {
#define MMC_CAP2_PACKED_WR (1 << 21) /* Allow packed write */
#define MMC_CAP2_PACKED_CMD (MMC_CAP2_PACKED_RD | \
MMC_CAP2_PACKED_WR) /* Allow packed commands */
+#define MMC_CAP2_CONFIG_BROKEN (1 << 22) /* Broken Config Register */
mmc_pm_flag_t pm_caps; /* supported pm features */
unsigned int power_notify_type;
--
1.7.4.1
^ permalink raw reply related [flat|nested] 5+ messages in thread
* Re: [PATCH V1] mmc: dwmmc: Add quirk for broken Hardware Config
2012-07-18 8:38 ` [PATCH V1] mmc: dwmmc: Add quirk for broken Hardware Config Girish K S
@ 2012-07-18 12:55 ` S, Venkatraman
2012-07-19 5:24 ` Girish K S
2012-07-20 11:55 ` Girish K S
1 sibling, 1 reply; 5+ messages in thread
From: S, Venkatraman @ 2012-07-18 12:55 UTC (permalink / raw)
To: Girish K S
Cc: linux-mmc, cjb, will.newton, patches, linux-samsung-soc,
shashidharh, thomas.abraham, jh80.chung
On Wed, Jul 18, 2012 at 2:08 PM, Girish K S
<girish.shivananjappa@linaro.org> wrote:
> In some Soc'S that integrate Designware mmc host controllers, the
> HCON register is broken. The hardware configuration is not
> updated. One specific usecase is the IDMAC. In Exysons5 SoC
> there exist a internal DMA, but the HCON register's DMA_INTERFACE
> field is not set to indicate its existance.
>
> This quirk can be used in such case to force the existance broken
> HCON field.
>
> changes in v1:
> -modified the caps2 field access per controller index.Reported
> by Jaehoon Chung <jh80.chung@samsung.com>.
> -replaced the pointer to device with the pointer to platform
> device in struct dw_mci.
> -updated driver data for all 4 mmc controllers of exynos5 SoC.
> -added non device-tree support for ctrl_id access.
>
> Signed-off-by: Girish K S <girish.shivananjappa@linaro.org>
> ---
> drivers/mmc/host/dw_mmc-pltfm.c | 10 +++-
> drivers/mmc/host/dw_mmc.c | 150 ++++++++++++++++++++++++---------------
> drivers/mmc/host/dw_mmc.h | 1 +
> include/linux/mmc/dw_mmc.h | 2 +-
> include/linux/mmc/host.h | 1 +
> 5 files changed, 106 insertions(+), 58 deletions(-)
>
> diff --git a/drivers/mmc/host/dw_mmc-pltfm.c b/drivers/mmc/host/dw_mmc-pltfm.c
> index 900f412..c8eb573 100644
> --- a/drivers/mmc/host/dw_mmc-pltfm.c
> +++ b/drivers/mmc/host/dw_mmc-pltfm.c
> @@ -35,9 +35,17 @@ static unsigned long exynos5250_dwmmc_caps[4] = {
> MMC_CAP_CMD23,
> };
>
> +static unsigned long exynos5250_dwmmc_caps2[4] = {
> + MMC_CAP2_CONFIG_BROKEN,
> + MMC_CAP2_CONFIG_BROKEN,
> + MMC_CAP2_CONFIG_BROKEN,
> + MMC_CAP2_CONFIG_BROKEN,
> +};
> +
> static struct dw_mci_drv_data exynos5250_drv_data = {
> .ctrl_type = DW_MCI_TYPE_EXYNOS5250,
> .caps = exynos5250_dwmmc_caps,
> + .caps2 = exynos5250_dwmmc_caps2,
> };
>
> static const struct of_device_id dw_mci_pltfm_match[] = {
> @@ -74,7 +82,7 @@ static int dw_mci_pltfm_probe(struct platform_device *pdev)
> goto err_free;
> }
>
> - host->dev = &pdev->dev;
> + host->pdev = pdev;
> host->irq_flags = 0;
> host->pdata = pdev->dev.platform_data;
> ret = -ENOMEM;
> diff --git a/drivers/mmc/host/dw_mmc.c b/drivers/mmc/host/dw_mmc.c
> index 000da16..fd9233d 100644
> --- a/drivers/mmc/host/dw_mmc.c
> +++ b/drivers/mmc/host/dw_mmc.c
> @@ -283,8 +283,10 @@ static u32 dw_mci_prepare_command(struct mmc_host *mmc, struct mmc_command *cmd)
> static void dw_mci_start_command(struct dw_mci *host,
> struct mmc_command *cmd, u32 cmd_flags)
> {
> + struct device *dev = &host->pdev->dev;
> +
> host->cmd = cmd;
> - dev_vdbg(host->dev,
> + dev_vdbg(dev,
> "start command: ARGR=0x%08x CMDR=0x%08x\n",
> cmd->arg, cmd_flags);
>
> @@ -323,10 +325,11 @@ static int dw_mci_get_dma_dir(struct mmc_data *data)
> static void dw_mci_dma_cleanup(struct dw_mci *host)
> {
> struct mmc_data *data = host->data;
> + struct device *dev = &host->pdev->dev;
>
> if (data)
> if (!data->host_cookie)
> - dma_unmap_sg(host->dev,
> + dma_unmap_sg(dev,
> data->sg,
> data->sg_len,
> dw_mci_get_dma_dir(data));
> @@ -351,8 +354,9 @@ static void dw_mci_idmac_stop_dma(struct dw_mci *host)
> static void dw_mci_idmac_complete_dma(struct dw_mci *host)
> {
> struct mmc_data *data = host->data;
> + struct device *dev = &host->pdev->dev;
>
> - dev_vdbg(host->dev, "DMA complete\n");
> + dev_vdbg(dev, "DMA complete\n");
>
> host->dma_ops->cleanup(host);
>
> @@ -420,10 +424,27 @@ static void dw_mci_idmac_start_dma(struct dw_mci *host, unsigned int sg_len)
> mci_writel(host, PLDMND, 1);
> }
>
> +static int dw_get_platform_device_id(struct dw_mci *host)
> +{
> + int ctrl_id;
> + struct device *dev = &host->pdev->dev;
> +
> + if (dev->of_node)
> + ctrl_id = of_alias_get_id(dev->of_node, "mshc");
> + else
> + ctrl_id = host->pdev->id;
> +
> + if (ctrl_id < 0)
> + ctrl_id = 0;
> +
> + return ctrl_id;
> +}
> +
> static int dw_mci_idmac_init(struct dw_mci *host)
> {
> struct idmac_desc *p;
> - int i, dma_support;
> + int i, dma_support, ctrl_id;
> + struct device *dev = &host->pdev->dev;
>
> /* Number of descriptors in the ring buffer */
> host->ring_size = PAGE_SIZE / sizeof(struct idmac_desc);
> @@ -431,14 +452,23 @@ static int dw_mci_idmac_init(struct dw_mci *host)
> /* Check if Hardware Configuration Register has support for DMA */
> dma_support = (mci_readl(host, HCON) >> 16) & 0x3;
>
> - if (!dma_support || dma_support > 2) {
> - dev_err(&host->dev,
> + /*
> + * In Some of the Soc's the HCON Register is broken. Even though the
> + * Soc's has a internal DMA the HCON register's DMA field doesnt
> + * show it. So additional quirk is added for such Soc's
> + */
> + ctrl_id = dw_get_platform_device_id(host);
> +
> + if ((!dma_support || dma_support > 2) &&
> + host->drv_data && host->drv_data->caps2 &&
> + !(host->drv_data->caps2[ctrl_id] & MMC_CAP2_CONFIG_BROKEN)) {
> + dev_err(dev,
> "Host Controller does not support IDMA Tx.\n");
> host->dma_ops = NULL;
> return -ENODEV;
> }
>
> - dev_info(&host->dev, "Using internal DMA controller.\n");
> + dev_info(dev, "Using internal DMA controller.\n");
>
> /* Forward link the descriptor list */
> for (i = 0, p = host->sg_cpu; i < host->ring_size - 1; i++, p++)
> @@ -474,6 +504,7 @@ static int dw_mci_pre_dma_transfer(struct dw_mci *host,
> {
> struct scatterlist *sg;
> unsigned int i, sg_len;
> + struct device *dev = &host->pdev->dev;
>
> if (!next && data->host_cookie)
> return data->host_cookie;
> @@ -494,7 +525,7 @@ static int dw_mci_pre_dma_transfer(struct dw_mci *host,
> return -EINVAL;
> }
>
> - sg_len = dma_map_sg(host->dev,
> + sg_len = dma_map_sg(dev,
> data->sg,
> data->sg_len,
> dw_mci_get_dma_dir(data));
> @@ -532,12 +563,13 @@ static void dw_mci_post_req(struct mmc_host *mmc,
> {
> struct dw_mci_slot *slot = mmc_priv(mmc);
> struct mmc_data *data = mrq->data;
> + struct device *dev = &slot->host->pdev->dev;
>
> if (!slot->host->use_dma || !data)
> return;
>
> if (data->host_cookie)
> - dma_unmap_sg(slot->host->dev,
> + dma_unmap_sg(dev,
> data->sg,
> data->sg_len,
> dw_mci_get_dma_dir(data));
> @@ -548,6 +580,7 @@ static int dw_mci_submit_data_dma(struct dw_mci *host, struct mmc_data *data)
> {
> int sg_len;
> u32 temp;
> + struct device *dev = &host->pdev->dev;
>
> host->using_dma = 0;
>
> @@ -563,7 +596,7 @@ static int dw_mci_submit_data_dma(struct dw_mci *host, struct mmc_data *data)
>
> host->using_dma = 1;
>
> - dev_vdbg(host->dev,
> + dev_vdbg(dev,
> "sd sg_cpu: %#lx sg_dma: %#lx sg_len: %d\n",
> (unsigned long)host->sg_cpu, (unsigned long)host->sg_dma,
> sg_len);
> @@ -928,6 +961,7 @@ static void dw_mci_request_end(struct dw_mci *host, struct mmc_request *mrq)
> {
> struct dw_mci_slot *slot;
> struct mmc_host *prev_mmc = host->cur_slot->mmc;
> + struct device *dev = &host->pdev->dev;
>
> WARN_ON(host->cmd || host->data);
>
> @@ -937,12 +971,12 @@ static void dw_mci_request_end(struct dw_mci *host, struct mmc_request *mrq)
> slot = list_entry(host->queue.next,
> struct dw_mci_slot, queue_node);
> list_del(&slot->queue_node);
> - dev_vdbg(host->dev, "list not empty: %s is next\n",
> + dev_vdbg(dev, "list not empty: %s is next\n",
> mmc_hostname(slot->mmc));
> host->state = STATE_SENDING_CMD;
> dw_mci_start_request(host, slot);
> } else {
> - dev_vdbg(host->dev, "list empty\n");
> + dev_vdbg(dev, "list empty\n");
> host->state = STATE_IDLE;
> }
>
> @@ -1081,7 +1115,7 @@ static void dw_mci_tasklet_func(unsigned long priv)
> data->bytes_xfered = 0;
> data->error = -ETIMEDOUT;
> } else {
> - dev_err(host->dev,
> + dev_err(&host->pdev->dev,
> "data FIFO error "
> "(status=%08x)\n",
> status);
> @@ -1829,7 +1863,8 @@ static u32 dw_mci_of_get_bus_wd(struct device *dev, u8 slot)
>
> static int dw_mci_of_setup_bus(struct dw_mci *host, u8 slot, u32 bus_wd)
> {
> - struct device_node *np = dw_mci_of_find_slot_node(host->dev, slot);
> + struct device *dev = &host->pdev->dev;
> + struct device_node *np = dw_mci_of_find_slot_node(dev, slot);
> int idx, gpio, ret;
>
> if (!np)
> @@ -1838,13 +1873,13 @@ static int dw_mci_of_setup_bus(struct dw_mci *host, u8 slot, u32 bus_wd)
> for (idx = 0; idx < NUM_PINS(bus_wd); idx++) {
> gpio = of_get_gpio(np, idx);
> if (!gpio_is_valid(gpio)) {
> - dev_err(host->dev, "invalid gpio: %d\n", gpio);
> + dev_err(dev, "invalid gpio: %d\n", gpio);
> return -EINVAL;
> }
>
> - ret = devm_gpio_request(host->dev, gpio, "dw-mci-bus");
> + ret = devm_gpio_request(dev, gpio, "dw-mci-bus");
> if (ret) {
> - dev_err(host->dev, "gpio [%d] request failed\n", gpio);
> + dev_err(dev, "gpio [%d] request failed\n", gpio);
> return -EBUSY;
> }
> }
> @@ -1852,11 +1887,11 @@ static int dw_mci_of_setup_bus(struct dw_mci *host, u8 slot, u32 bus_wd)
> host->slot[slot]->wp_gpio = -1;
> gpio = of_get_named_gpio(np, "wp-gpios", 0);
> if (!gpio_is_valid(gpio)) {
> - dev_info(host->dev, "wp gpio not available");
> + dev_info(dev, "wp gpio not available");
> } else {
> - ret = devm_gpio_request(host->dev, gpio, "dw-mci-wp");
> + ret = devm_gpio_request(dev, gpio, "dw-mci-wp");
> if (ret)
> - dev_info(host->dev, "gpio [%d] request failed\n",
> + dev_info(dev, "gpio [%d] request failed\n",
> gpio);
> else
> host->slot[slot]->wp_gpio = gpio;
> @@ -1865,11 +1900,11 @@ static int dw_mci_of_setup_bus(struct dw_mci *host, u8 slot, u32 bus_wd)
> host->slot[slot]->cd_gpio = -1;
> gpio = of_get_named_gpio(np, "cd-gpios", 0);
> if (!gpio_is_valid(gpio)) {
> - dev_info(host->dev, "cd gpio not available");
> + dev_info(dev, "cd gpio not available");
> } else {
> - ret = devm_gpio_request(host->dev, gpio, "dw-mci-cd");
> + ret = devm_gpio_request(dev, gpio, "dw-mci-cd");
> if (ret)
> - dev_err(host->dev, "gpio [%d] request failed\n", gpio);
> + dev_err(dev, "gpio [%d] request failed\n", gpio);
> else
> host->slot[slot]->cd_gpio = gpio;
> }
> @@ -1893,8 +1928,9 @@ static int __init dw_mci_init_slot(struct dw_mci *host, unsigned int id)
> struct mmc_host *mmc;
> struct dw_mci_slot *slot;
> int ctrl_id, ret;
> + struct device *dev = &host->pdev->dev;
>
> - mmc = mmc_alloc_host(sizeof(struct dw_mci_slot), host->dev);
> + mmc = mmc_alloc_host(sizeof(struct dw_mci_slot), dev);
> if (!mmc)
> return -ENOMEM;
>
> @@ -1923,23 +1959,23 @@ static int __init dw_mci_init_slot(struct dw_mci *host, unsigned int id)
> if (host->pdata->caps)
> mmc->caps = host->pdata->caps;
>
> - if (host->dev->of_node) {
> - ctrl_id = of_alias_get_id(host->dev->of_node, "mshc");
> - if (ctrl_id < 0)
> - ctrl_id = 0;
> - }
> + ctrl_id = dw_get_platform_device_id(host);
> +
> if (host->drv_data->caps)
> mmc->caps |= host->drv_data->caps[ctrl_id];
>
> if (host->pdata->caps2)
> mmc->caps2 = host->pdata->caps2;
>
> + if (host->drv_data->caps2)
> + mmc->caps2 |= host->drv_data->caps2[ctrl_id];
> +
> if (host->pdata->get_bus_wd) {
> if (host->pdata->get_bus_wd(slot->id) >= 4)
> mmc->caps |= MMC_CAP_4_BIT_DATA;
> - } else if (host->dev->of_node) {
> + } else if (dev->of_node) {
> unsigned int bus_width;
> - bus_width = dw_mci_of_get_bus_wd(host->dev, slot->id);
> + bus_width = dw_mci_of_get_bus_wd(dev, slot->id);
> switch (bus_width) {
> case 8:
> mmc->caps |= MMC_CAP_8_BIT_DATA;
> @@ -2030,11 +2066,12 @@ static void dw_mci_cleanup_slot(struct dw_mci_slot *slot, unsigned int id)
>
> static void dw_mci_init_dma(struct dw_mci *host)
> {
> + struct device *dev = &host->pdev->dev;
> /* Alloc memory for sg translation */
> - host->sg_cpu = dma_alloc_coherent(host->dev, PAGE_SIZE,
> + host->sg_cpu = dma_alloc_coherent(dev, PAGE_SIZE,
> &host->sg_dma, GFP_KERNEL);
> if (!host->sg_cpu) {
> - dev_err(host->dev, "%s: could not alloc DMA memory\n",
> + dev_err(dev, "%s: could not alloc DMA memory\n",
> __func__);
> goto no_dma;
> }
> @@ -2050,12 +2087,12 @@ static void dw_mci_init_dma(struct dw_mci *host)
> if (host->dma_ops->init && host->dma_ops->start &&
> host->dma_ops->stop && host->dma_ops->cleanup) {
> if (host->dma_ops->init(host)) {
> - dev_err(host->dev, "%s: Unable to initialize "
> + dev_err(dev, "%s: Unable to initialize "
> "DMA Controller.\n", __func__);
> goto no_dma;
> }
> } else {
> - dev_err(host->dev, "DMA initialization not found.\n");
> + dev_err(dev, "DMA initialization not found.\n");
> goto no_dma;
> }
>
> @@ -2063,7 +2100,7 @@ static void dw_mci_init_dma(struct dw_mci *host)
> return;
>
> no_dma:
> - dev_info(host->dev, "Using PIO mode.\n");
> + dev_info(dev, "Using PIO mode.\n");
> host->use_dma = 0;
> return;
> }
> @@ -2109,7 +2146,7 @@ static struct dw_mci_of_quirks {
> static struct dw_mci_board *dw_mci_parse_dt(struct dw_mci *host)
> {
> struct dw_mci_board *pdata;
> - struct device *dev = host->dev;
> + struct device *dev = &host->pdev->dev;
> struct device_node *np = dev->of_node;
> u32 timing[3];
> int idx, cnt;
> @@ -2169,30 +2206,31 @@ int dw_mci_probe(struct dw_mci *host)
> int width, i, ret = 0;
> u32 fifo_size;
> int init_slots = 0;
> + struct device *dev = &host->pdev->dev;
>
> if (!host->pdata) {
> host->pdata = dw_mci_parse_dt(host);
> if (IS_ERR(host->pdata)) {
> - dev_err(host->dev, "platform data not available\n");
> + dev_err(dev, "platform data not available\n");
> return -EINVAL;
> }
> }
>
> if (!host->pdata->select_slot && host->pdata->num_slots > 1) {
> - dev_err(host->dev,
> + dev_err(dev,
> "Platform data must supply select_slot function\n");
> return -ENODEV;
> }
>
> - host->biu_clk = clk_get(host->dev, "biu");
> + host->biu_clk = clk_get(dev, "biu");
> if (IS_ERR(host->biu_clk))
> - dev_dbg(host->dev, "biu clock not available\n");
> + dev_dbg(dev, "biu clock not available\n");
> else
> clk_prepare_enable(host->biu_clk);
>
> - host->ciu_clk = clk_get(host->dev, "ciu");
> + host->ciu_clk = clk_get(dev, "ciu");
> if (IS_ERR(host->ciu_clk))
> - dev_dbg(host->dev, "ciu clock not available\n");
> + dev_dbg(dev, "ciu clock not available\n");
> else
> clk_prepare_enable(host->ciu_clk);
>
> @@ -2202,7 +2240,7 @@ int dw_mci_probe(struct dw_mci *host)
> host->bus_hz = clk_get_rate(host->ciu_clk);
>
> if (!host->bus_hz) {
> - dev_err(host->dev,
> + dev_err(dev,
> "Platform data must supply bus speed\n");
> ret = -ENODEV;
> goto err_clk;
> @@ -2243,7 +2281,7 @@ int dw_mci_probe(struct dw_mci *host)
> }
>
> /* Reset all blocks */
> - if (!mci_wait_reset(host->dev, host))
> + if (!mci_wait_reset(dev, host))
> return -ENODEV;
>
> host->dma_ops = host->pdata->dma_ops;
> @@ -2300,15 +2338,15 @@ int dw_mci_probe(struct dw_mci *host)
> for (i = 0; i < host->num_slots; i++) {
> ret = dw_mci_init_slot(host, i);
> if (ret)
> - dev_dbg(host->dev, "slot %d init failed\n", i);
> + dev_dbg(dev, "slot %d init failed\n", i);
> else
> init_slots++;
> }
>
> if (init_slots) {
> - dev_info(host->dev, "%d slots initialized\n", init_slots);
> + dev_info(dev, "%d slots initialized\n", init_slots);
> } else {
> - dev_dbg(host->dev, "attempted to initialize %d slots, "
> + dev_dbg(dev, "attempted to initialize %d slots, "
> "but failed on all\n", host->num_slots);
> goto err_init_slot;
> }
> @@ -2318,7 +2356,7 @@ int dw_mci_probe(struct dw_mci *host)
> * Need to check the version-id and set data-offset for DATA register.
> */
> host->verid = SDMMC_GET_VERID(mci_readl(host, VERID));
> - dev_info(host->dev, "Version ID is %04x\n", host->verid);
> + dev_info(dev, "Version ID is %04x\n", host->verid);
>
> if (host->verid < DW_MMC_240A)
> host->data_offset = DATA_OFFSET;
> @@ -2335,12 +2373,12 @@ int dw_mci_probe(struct dw_mci *host)
> DW_MCI_ERROR_FLAGS | SDMMC_INT_CD);
> mci_writel(host, CTRL, SDMMC_CTRL_INT_ENABLE); /* Enable mci interrupt */
>
> - dev_info(host->dev, "DW MMC controller at irq %d, "
> + dev_info(dev, "DW MMC controller at irq %d, "
> "%d bit host data width, "
> "%u deep fifo\n",
> host->irq, width, fifo_size);
> if (host->quirks & DW_MCI_QUIRK_IDMAC_DTO)
> - dev_info(host->dev, "Internal DMAC interrupt fix enabled.\n");
> + dev_info(dev, "Internal DMAC interrupt fix enabled.\n");
>
> return 0;
>
> @@ -2353,7 +2391,7 @@ err_workqueue:
> err_dmaunmap:
> if (host->use_dma && host->dma_ops->exit)
> host->dma_ops->exit(host);
> - dma_free_coherent(host->dev, PAGE_SIZE,
> + dma_free_coherent(dev, PAGE_SIZE,
> host->sg_cpu, host->sg_dma);
>
> if (host->vmmc) {
> @@ -2377,23 +2415,23 @@ EXPORT_SYMBOL(dw_mci_probe);
> void dw_mci_remove(struct dw_mci *host)
> {
> int i;
> + struct device *dev = &host->pdev->dev;
>
> mci_writel(host, RINTSTS, 0xFFFFFFFF);
> mci_writel(host, INTMASK, 0); /* disable all mmc interrupt first */
>
> for (i = 0; i < host->num_slots; i++) {
> - dev_dbg(host->dev, "remove slot %d\n", i);
> + dev_dbg(dev, "remove slot %d\n", i);
> if (host->slot[i])
> dw_mci_cleanup_slot(host->slot[i], i);
> }
> -
> /* disable clock to CIU */
> mci_writel(host, CLKENA, 0);
> mci_writel(host, CLKSRC, 0);
>
> free_irq(host->irq, host);
> destroy_workqueue(host->card_workqueue);
> - dma_free_coherent(host->dev, PAGE_SIZE, host->sg_cpu, host->sg_dma);
> + dma_free_coherent(dev, PAGE_SIZE, host->sg_cpu, host->sg_dma);
>
> if (host->use_dma && host->dma_ops->exit)
> host->dma_ops->exit(host);
> @@ -2451,7 +2489,7 @@ int dw_mci_resume(struct dw_mci *host)
> if (host->vmmc)
> regulator_enable(host->vmmc);
>
> - if (!mci_wait_reset(host->dev, host)) {
> + if (!mci_wait_reset(&host->pdev->dev, host)) {
> ret = -ENODEV;
> return ret;
> }
> diff --git a/drivers/mmc/host/dw_mmc.h b/drivers/mmc/host/dw_mmc.h
> index 6c17282..8c4810a 100644
> --- a/drivers/mmc/host/dw_mmc.h
> +++ b/drivers/mmc/host/dw_mmc.h
> @@ -203,6 +203,7 @@ extern int dw_mci_resume(struct dw_mci *host);
> struct dw_mci_drv_data {
> unsigned long ctrl_type;
> unsigned long *caps;
> + unsigned long *caps2;
> };
>
> #endif /* _DW_MMC_H_ */
> diff --git a/include/linux/mmc/dw_mmc.h b/include/linux/mmc/dw_mmc.h
> index 32c778f..71de160 100644
> --- a/include/linux/mmc/dw_mmc.h
> +++ b/include/linux/mmc/dw_mmc.h
> @@ -161,7 +161,7 @@ struct dw_mci {
> u32 fifoth_val;
> u16 verid;
> u16 data_offset;
> - struct device *dev;
> + struct platform_device *pdev;
> struct dw_mci_board *pdata;
> struct dw_mci_drv_data *drv_data;
> struct clk *biu_clk;
> diff --git a/include/linux/mmc/host.h b/include/linux/mmc/host.h
> index 79d8921..b3e35fd 100644
> --- a/include/linux/mmc/host.h
> +++ b/include/linux/mmc/host.h
> @@ -273,6 +273,7 @@ struct mmc_host {
> #define MMC_CAP2_PACKED_WR (1 << 21) /* Allow packed write */
> #define MMC_CAP2_PACKED_CMD (MMC_CAP2_PACKED_RD | \
> MMC_CAP2_PACKED_WR) /* Allow packed commands */
> +#define MMC_CAP2_CONFIG_BROKEN (1 << 22) /* Broken Config Register */
What, broken hardware gets defined as a CAPability these days ?
Please use the QUIRK framework for this.. CAP2 is definitely not the
right place.
Thanks,
Venkat.
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: [PATCH V1] mmc: dwmmc: Add quirk for broken Hardware Config
2012-07-18 12:55 ` S, Venkatraman
@ 2012-07-19 5:24 ` Girish K S
0 siblings, 0 replies; 5+ messages in thread
From: Girish K S @ 2012-07-19 5:24 UTC (permalink / raw)
To: S, Venkatraman
Cc: linux-mmc, cjb, will.newton, patches, linux-samsung-soc,
shashidharh, thomas.abraham, jh80.chung
On 18 July 2012 18:25, S, Venkatraman <svenkatr@ti.com> wrote:
> On Wed, Jul 18, 2012 at 2:08 PM, Girish K S
> <girish.shivananjappa@linaro.org> wrote:
>> In some Soc'S that integrate Designware mmc host controllers, the
>> HCON register is broken. The hardware configuration is not
>> updated. One specific usecase is the IDMAC. In Exysons5 SoC
>> there exist a internal DMA, but the HCON register's DMA_INTERFACE
>> field is not set to indicate its existance.
>>
>> This quirk can be used in such case to force the existance broken
>> HCON field.
>>
>> changes in v1:
>> -modified the caps2 field access per controller index.Reported
>> by Jaehoon Chung <jh80.chung@samsung.com>.
>> -replaced the pointer to device with the pointer to platform
>> device in struct dw_mci.
>> -updated driver data for all 4 mmc controllers of exynos5 SoC.
>> -added non device-tree support for ctrl_id access.
>>
>> Signed-off-by: Girish K S <girish.shivananjappa@linaro.org>
>> ---
>> drivers/mmc/host/dw_mmc-pltfm.c | 10 +++-
>> drivers/mmc/host/dw_mmc.c | 150 ++++++++++++++++++++++++---------------
>> drivers/mmc/host/dw_mmc.h | 1 +
>> include/linux/mmc/dw_mmc.h | 2 +-
>> include/linux/mmc/host.h | 1 +
>> 5 files changed, 106 insertions(+), 58 deletions(-)
>>
>> diff --git a/drivers/mmc/host/dw_mmc-pltfm.c b/drivers/mmc/host/dw_mmc-pltfm.c
>> index 900f412..c8eb573 100644
>> --- a/drivers/mmc/host/dw_mmc-pltfm.c
>> +++ b/drivers/mmc/host/dw_mmc-pltfm.c
>> @@ -35,9 +35,17 @@ static unsigned long exynos5250_dwmmc_caps[4] = {
>> MMC_CAP_CMD23,
>> };
>>
>> +static unsigned long exynos5250_dwmmc_caps2[4] = {
>> + MMC_CAP2_CONFIG_BROKEN,
>> + MMC_CAP2_CONFIG_BROKEN,
>> + MMC_CAP2_CONFIG_BROKEN,
>> + MMC_CAP2_CONFIG_BROKEN,
>> +};
>> +
>> static struct dw_mci_drv_data exynos5250_drv_data = {
>> .ctrl_type = DW_MCI_TYPE_EXYNOS5250,
>> .caps = exynos5250_dwmmc_caps,
>> + .caps2 = exynos5250_dwmmc_caps2,
>> };
>>
>> static const struct of_device_id dw_mci_pltfm_match[] = {
>> @@ -74,7 +82,7 @@ static int dw_mci_pltfm_probe(struct platform_device *pdev)
>> goto err_free;
>> }
>>
>> - host->dev = &pdev->dev;
>> + host->pdev = pdev;
>> host->irq_flags = 0;
>> host->pdata = pdev->dev.platform_data;
>> ret = -ENOMEM;
>> diff --git a/drivers/mmc/host/dw_mmc.c b/drivers/mmc/host/dw_mmc.c
>> index 000da16..fd9233d 100644
>> --- a/drivers/mmc/host/dw_mmc.c
>> +++ b/drivers/mmc/host/dw_mmc.c
>> @@ -283,8 +283,10 @@ static u32 dw_mci_prepare_command(struct mmc_host *mmc, struct mmc_command *cmd)
>> static void dw_mci_start_command(struct dw_mci *host,
>> struct mmc_command *cmd, u32 cmd_flags)
>> {
>> + struct device *dev = &host->pdev->dev;
>> +
>> host->cmd = cmd;
>> - dev_vdbg(host->dev,
>> + dev_vdbg(dev,
>> "start command: ARGR=0x%08x CMDR=0x%08x\n",
>> cmd->arg, cmd_flags);
>>
>> @@ -323,10 +325,11 @@ static int dw_mci_get_dma_dir(struct mmc_data *data)
>> static void dw_mci_dma_cleanup(struct dw_mci *host)
>> {
>> struct mmc_data *data = host->data;
>> + struct device *dev = &host->pdev->dev;
>>
>> if (data)
>> if (!data->host_cookie)
>> - dma_unmap_sg(host->dev,
>> + dma_unmap_sg(dev,
>> data->sg,
>> data->sg_len,
>> dw_mci_get_dma_dir(data));
>> @@ -351,8 +354,9 @@ static void dw_mci_idmac_stop_dma(struct dw_mci *host)
>> static void dw_mci_idmac_complete_dma(struct dw_mci *host)
>> {
>> struct mmc_data *data = host->data;
>> + struct device *dev = &host->pdev->dev;
>>
>> - dev_vdbg(host->dev, "DMA complete\n");
>> + dev_vdbg(dev, "DMA complete\n");
>>
>> host->dma_ops->cleanup(host);
>>
>> @@ -420,10 +424,27 @@ static void dw_mci_idmac_start_dma(struct dw_mci *host, unsigned int sg_len)
>> mci_writel(host, PLDMND, 1);
>> }
>>
>> +static int dw_get_platform_device_id(struct dw_mci *host)
>> +{
>> + int ctrl_id;
>> + struct device *dev = &host->pdev->dev;
>> +
>> + if (dev->of_node)
>> + ctrl_id = of_alias_get_id(dev->of_node, "mshc");
>> + else
>> + ctrl_id = host->pdev->id;
>> +
>> + if (ctrl_id < 0)
>> + ctrl_id = 0;
>> +
>> + return ctrl_id;
>> +}
>> +
>> static int dw_mci_idmac_init(struct dw_mci *host)
>> {
>> struct idmac_desc *p;
>> - int i, dma_support;
>> + int i, dma_support, ctrl_id;
>> + struct device *dev = &host->pdev->dev;
>>
>> /* Number of descriptors in the ring buffer */
>> host->ring_size = PAGE_SIZE / sizeof(struct idmac_desc);
>> @@ -431,14 +452,23 @@ static int dw_mci_idmac_init(struct dw_mci *host)
>> /* Check if Hardware Configuration Register has support for DMA */
>> dma_support = (mci_readl(host, HCON) >> 16) & 0x3;
>>
>> - if (!dma_support || dma_support > 2) {
>> - dev_err(&host->dev,
>> + /*
>> + * In Some of the Soc's the HCON Register is broken. Even though the
>> + * Soc's has a internal DMA the HCON register's DMA field doesnt
>> + * show it. So additional quirk is added for such Soc's
>> + */
>> + ctrl_id = dw_get_platform_device_id(host);
>> +
>> + if ((!dma_support || dma_support > 2) &&
>> + host->drv_data && host->drv_data->caps2 &&
>> + !(host->drv_data->caps2[ctrl_id] & MMC_CAP2_CONFIG_BROKEN)) {
>> + dev_err(dev,
>> "Host Controller does not support IDMA Tx.\n");
>> host->dma_ops = NULL;
>> return -ENODEV;
>> }
>>
>> - dev_info(&host->dev, "Using internal DMA controller.\n");
>> + dev_info(dev, "Using internal DMA controller.\n");
>>
>> /* Forward link the descriptor list */
>> for (i = 0, p = host->sg_cpu; i < host->ring_size - 1; i++, p++)
>> @@ -474,6 +504,7 @@ static int dw_mci_pre_dma_transfer(struct dw_mci *host,
>> {
>> struct scatterlist *sg;
>> unsigned int i, sg_len;
>> + struct device *dev = &host->pdev->dev;
>>
>> if (!next && data->host_cookie)
>> return data->host_cookie;
>> @@ -494,7 +525,7 @@ static int dw_mci_pre_dma_transfer(struct dw_mci *host,
>> return -EINVAL;
>> }
>>
>> - sg_len = dma_map_sg(host->dev,
>> + sg_len = dma_map_sg(dev,
>> data->sg,
>> data->sg_len,
>> dw_mci_get_dma_dir(data));
>> @@ -532,12 +563,13 @@ static void dw_mci_post_req(struct mmc_host *mmc,
>> {
>> struct dw_mci_slot *slot = mmc_priv(mmc);
>> struct mmc_data *data = mrq->data;
>> + struct device *dev = &slot->host->pdev->dev;
>>
>> if (!slot->host->use_dma || !data)
>> return;
>>
>> if (data->host_cookie)
>> - dma_unmap_sg(slot->host->dev,
>> + dma_unmap_sg(dev,
>> data->sg,
>> data->sg_len,
>> dw_mci_get_dma_dir(data));
>> @@ -548,6 +580,7 @@ static int dw_mci_submit_data_dma(struct dw_mci *host, struct mmc_data *data)
>> {
>> int sg_len;
>> u32 temp;
>> + struct device *dev = &host->pdev->dev;
>>
>> host->using_dma = 0;
>>
>> @@ -563,7 +596,7 @@ static int dw_mci_submit_data_dma(struct dw_mci *host, struct mmc_data *data)
>>
>> host->using_dma = 1;
>>
>> - dev_vdbg(host->dev,
>> + dev_vdbg(dev,
>> "sd sg_cpu: %#lx sg_dma: %#lx sg_len: %d\n",
>> (unsigned long)host->sg_cpu, (unsigned long)host->sg_dma,
>> sg_len);
>> @@ -928,6 +961,7 @@ static void dw_mci_request_end(struct dw_mci *host, struct mmc_request *mrq)
>> {
>> struct dw_mci_slot *slot;
>> struct mmc_host *prev_mmc = host->cur_slot->mmc;
>> + struct device *dev = &host->pdev->dev;
>>
>> WARN_ON(host->cmd || host->data);
>>
>> @@ -937,12 +971,12 @@ static void dw_mci_request_end(struct dw_mci *host, struct mmc_request *mrq)
>> slot = list_entry(host->queue.next,
>> struct dw_mci_slot, queue_node);
>> list_del(&slot->queue_node);
>> - dev_vdbg(host->dev, "list not empty: %s is next\n",
>> + dev_vdbg(dev, "list not empty: %s is next\n",
>> mmc_hostname(slot->mmc));
>> host->state = STATE_SENDING_CMD;
>> dw_mci_start_request(host, slot);
>> } else {
>> - dev_vdbg(host->dev, "list empty\n");
>> + dev_vdbg(dev, "list empty\n");
>> host->state = STATE_IDLE;
>> }
>>
>> @@ -1081,7 +1115,7 @@ static void dw_mci_tasklet_func(unsigned long priv)
>> data->bytes_xfered = 0;
>> data->error = -ETIMEDOUT;
>> } else {
>> - dev_err(host->dev,
>> + dev_err(&host->pdev->dev,
>> "data FIFO error "
>> "(status=%08x)\n",
>> status);
>> @@ -1829,7 +1863,8 @@ static u32 dw_mci_of_get_bus_wd(struct device *dev, u8 slot)
>>
>> static int dw_mci_of_setup_bus(struct dw_mci *host, u8 slot, u32 bus_wd)
>> {
>> - struct device_node *np = dw_mci_of_find_slot_node(host->dev, slot);
>> + struct device *dev = &host->pdev->dev;
>> + struct device_node *np = dw_mci_of_find_slot_node(dev, slot);
>> int idx, gpio, ret;
>>
>> if (!np)
>> @@ -1838,13 +1873,13 @@ static int dw_mci_of_setup_bus(struct dw_mci *host, u8 slot, u32 bus_wd)
>> for (idx = 0; idx < NUM_PINS(bus_wd); idx++) {
>> gpio = of_get_gpio(np, idx);
>> if (!gpio_is_valid(gpio)) {
>> - dev_err(host->dev, "invalid gpio: %d\n", gpio);
>> + dev_err(dev, "invalid gpio: %d\n", gpio);
>> return -EINVAL;
>> }
>>
>> - ret = devm_gpio_request(host->dev, gpio, "dw-mci-bus");
>> + ret = devm_gpio_request(dev, gpio, "dw-mci-bus");
>> if (ret) {
>> - dev_err(host->dev, "gpio [%d] request failed\n", gpio);
>> + dev_err(dev, "gpio [%d] request failed\n", gpio);
>> return -EBUSY;
>> }
>> }
>> @@ -1852,11 +1887,11 @@ static int dw_mci_of_setup_bus(struct dw_mci *host, u8 slot, u32 bus_wd)
>> host->slot[slot]->wp_gpio = -1;
>> gpio = of_get_named_gpio(np, "wp-gpios", 0);
>> if (!gpio_is_valid(gpio)) {
>> - dev_info(host->dev, "wp gpio not available");
>> + dev_info(dev, "wp gpio not available");
>> } else {
>> - ret = devm_gpio_request(host->dev, gpio, "dw-mci-wp");
>> + ret = devm_gpio_request(dev, gpio, "dw-mci-wp");
>> if (ret)
>> - dev_info(host->dev, "gpio [%d] request failed\n",
>> + dev_info(dev, "gpio [%d] request failed\n",
>> gpio);
>> else
>> host->slot[slot]->wp_gpio = gpio;
>> @@ -1865,11 +1900,11 @@ static int dw_mci_of_setup_bus(struct dw_mci *host, u8 slot, u32 bus_wd)
>> host->slot[slot]->cd_gpio = -1;
>> gpio = of_get_named_gpio(np, "cd-gpios", 0);
>> if (!gpio_is_valid(gpio)) {
>> - dev_info(host->dev, "cd gpio not available");
>> + dev_info(dev, "cd gpio not available");
>> } else {
>> - ret = devm_gpio_request(host->dev, gpio, "dw-mci-cd");
>> + ret = devm_gpio_request(dev, gpio, "dw-mci-cd");
>> if (ret)
>> - dev_err(host->dev, "gpio [%d] request failed\n", gpio);
>> + dev_err(dev, "gpio [%d] request failed\n", gpio);
>> else
>> host->slot[slot]->cd_gpio = gpio;
>> }
>> @@ -1893,8 +1928,9 @@ static int __init dw_mci_init_slot(struct dw_mci *host, unsigned int id)
>> struct mmc_host *mmc;
>> struct dw_mci_slot *slot;
>> int ctrl_id, ret;
>> + struct device *dev = &host->pdev->dev;
>>
>> - mmc = mmc_alloc_host(sizeof(struct dw_mci_slot), host->dev);
>> + mmc = mmc_alloc_host(sizeof(struct dw_mci_slot), dev);
>> if (!mmc)
>> return -ENOMEM;
>>
>> @@ -1923,23 +1959,23 @@ static int __init dw_mci_init_slot(struct dw_mci *host, unsigned int id)
>> if (host->pdata->caps)
>> mmc->caps = host->pdata->caps;
>>
>> - if (host->dev->of_node) {
>> - ctrl_id = of_alias_get_id(host->dev->of_node, "mshc");
>> - if (ctrl_id < 0)
>> - ctrl_id = 0;
>> - }
>> + ctrl_id = dw_get_platform_device_id(host);
>> +
>> if (host->drv_data->caps)
>> mmc->caps |= host->drv_data->caps[ctrl_id];
>>
>> if (host->pdata->caps2)
>> mmc->caps2 = host->pdata->caps2;
>>
>> + if (host->drv_data->caps2)
>> + mmc->caps2 |= host->drv_data->caps2[ctrl_id];
>> +
>> if (host->pdata->get_bus_wd) {
>> if (host->pdata->get_bus_wd(slot->id) >= 4)
>> mmc->caps |= MMC_CAP_4_BIT_DATA;
>> - } else if (host->dev->of_node) {
>> + } else if (dev->of_node) {
>> unsigned int bus_width;
>> - bus_width = dw_mci_of_get_bus_wd(host->dev, slot->id);
>> + bus_width = dw_mci_of_get_bus_wd(dev, slot->id);
>> switch (bus_width) {
>> case 8:
>> mmc->caps |= MMC_CAP_8_BIT_DATA;
>> @@ -2030,11 +2066,12 @@ static void dw_mci_cleanup_slot(struct dw_mci_slot *slot, unsigned int id)
>>
>> static void dw_mci_init_dma(struct dw_mci *host)
>> {
>> + struct device *dev = &host->pdev->dev;
>> /* Alloc memory for sg translation */
>> - host->sg_cpu = dma_alloc_coherent(host->dev, PAGE_SIZE,
>> + host->sg_cpu = dma_alloc_coherent(dev, PAGE_SIZE,
>> &host->sg_dma, GFP_KERNEL);
>> if (!host->sg_cpu) {
>> - dev_err(host->dev, "%s: could not alloc DMA memory\n",
>> + dev_err(dev, "%s: could not alloc DMA memory\n",
>> __func__);
>> goto no_dma;
>> }
>> @@ -2050,12 +2087,12 @@ static void dw_mci_init_dma(struct dw_mci *host)
>> if (host->dma_ops->init && host->dma_ops->start &&
>> host->dma_ops->stop && host->dma_ops->cleanup) {
>> if (host->dma_ops->init(host)) {
>> - dev_err(host->dev, "%s: Unable to initialize "
>> + dev_err(dev, "%s: Unable to initialize "
>> "DMA Controller.\n", __func__);
>> goto no_dma;
>> }
>> } else {
>> - dev_err(host->dev, "DMA initialization not found.\n");
>> + dev_err(dev, "DMA initialization not found.\n");
>> goto no_dma;
>> }
>>
>> @@ -2063,7 +2100,7 @@ static void dw_mci_init_dma(struct dw_mci *host)
>> return;
>>
>> no_dma:
>> - dev_info(host->dev, "Using PIO mode.\n");
>> + dev_info(dev, "Using PIO mode.\n");
>> host->use_dma = 0;
>> return;
>> }
>> @@ -2109,7 +2146,7 @@ static struct dw_mci_of_quirks {
>> static struct dw_mci_board *dw_mci_parse_dt(struct dw_mci *host)
>> {
>> struct dw_mci_board *pdata;
>> - struct device *dev = host->dev;
>> + struct device *dev = &host->pdev->dev;
>> struct device_node *np = dev->of_node;
>> u32 timing[3];
>> int idx, cnt;
>> @@ -2169,30 +2206,31 @@ int dw_mci_probe(struct dw_mci *host)
>> int width, i, ret = 0;
>> u32 fifo_size;
>> int init_slots = 0;
>> + struct device *dev = &host->pdev->dev;
>>
>> if (!host->pdata) {
>> host->pdata = dw_mci_parse_dt(host);
>> if (IS_ERR(host->pdata)) {
>> - dev_err(host->dev, "platform data not available\n");
>> + dev_err(dev, "platform data not available\n");
>> return -EINVAL;
>> }
>> }
>>
>> if (!host->pdata->select_slot && host->pdata->num_slots > 1) {
>> - dev_err(host->dev,
>> + dev_err(dev,
>> "Platform data must supply select_slot function\n");
>> return -ENODEV;
>> }
>>
>> - host->biu_clk = clk_get(host->dev, "biu");
>> + host->biu_clk = clk_get(dev, "biu");
>> if (IS_ERR(host->biu_clk))
>> - dev_dbg(host->dev, "biu clock not available\n");
>> + dev_dbg(dev, "biu clock not available\n");
>> else
>> clk_prepare_enable(host->biu_clk);
>>
>> - host->ciu_clk = clk_get(host->dev, "ciu");
>> + host->ciu_clk = clk_get(dev, "ciu");
>> if (IS_ERR(host->ciu_clk))
>> - dev_dbg(host->dev, "ciu clock not available\n");
>> + dev_dbg(dev, "ciu clock not available\n");
>> else
>> clk_prepare_enable(host->ciu_clk);
>>
>> @@ -2202,7 +2240,7 @@ int dw_mci_probe(struct dw_mci *host)
>> host->bus_hz = clk_get_rate(host->ciu_clk);
>>
>> if (!host->bus_hz) {
>> - dev_err(host->dev,
>> + dev_err(dev,
>> "Platform data must supply bus speed\n");
>> ret = -ENODEV;
>> goto err_clk;
>> @@ -2243,7 +2281,7 @@ int dw_mci_probe(struct dw_mci *host)
>> }
>>
>> /* Reset all blocks */
>> - if (!mci_wait_reset(host->dev, host))
>> + if (!mci_wait_reset(dev, host))
>> return -ENODEV;
>>
>> host->dma_ops = host->pdata->dma_ops;
>> @@ -2300,15 +2338,15 @@ int dw_mci_probe(struct dw_mci *host)
>> for (i = 0; i < host->num_slots; i++) {
>> ret = dw_mci_init_slot(host, i);
>> if (ret)
>> - dev_dbg(host->dev, "slot %d init failed\n", i);
>> + dev_dbg(dev, "slot %d init failed\n", i);
>> else
>> init_slots++;
>> }
>>
>> if (init_slots) {
>> - dev_info(host->dev, "%d slots initialized\n", init_slots);
>> + dev_info(dev, "%d slots initialized\n", init_slots);
>> } else {
>> - dev_dbg(host->dev, "attempted to initialize %d slots, "
>> + dev_dbg(dev, "attempted to initialize %d slots, "
>> "but failed on all\n", host->num_slots);
>> goto err_init_slot;
>> }
>> @@ -2318,7 +2356,7 @@ int dw_mci_probe(struct dw_mci *host)
>> * Need to check the version-id and set data-offset for DATA register.
>> */
>> host->verid = SDMMC_GET_VERID(mci_readl(host, VERID));
>> - dev_info(host->dev, "Version ID is %04x\n", host->verid);
>> + dev_info(dev, "Version ID is %04x\n", host->verid);
>>
>> if (host->verid < DW_MMC_240A)
>> host->data_offset = DATA_OFFSET;
>> @@ -2335,12 +2373,12 @@ int dw_mci_probe(struct dw_mci *host)
>> DW_MCI_ERROR_FLAGS | SDMMC_INT_CD);
>> mci_writel(host, CTRL, SDMMC_CTRL_INT_ENABLE); /* Enable mci interrupt */
>>
>> - dev_info(host->dev, "DW MMC controller at irq %d, "
>> + dev_info(dev, "DW MMC controller at irq %d, "
>> "%d bit host data width, "
>> "%u deep fifo\n",
>> host->irq, width, fifo_size);
>> if (host->quirks & DW_MCI_QUIRK_IDMAC_DTO)
>> - dev_info(host->dev, "Internal DMAC interrupt fix enabled.\n");
>> + dev_info(dev, "Internal DMAC interrupt fix enabled.\n");
>>
>> return 0;
>>
>> @@ -2353,7 +2391,7 @@ err_workqueue:
>> err_dmaunmap:
>> if (host->use_dma && host->dma_ops->exit)
>> host->dma_ops->exit(host);
>> - dma_free_coherent(host->dev, PAGE_SIZE,
>> + dma_free_coherent(dev, PAGE_SIZE,
>> host->sg_cpu, host->sg_dma);
>>
>> if (host->vmmc) {
>> @@ -2377,23 +2415,23 @@ EXPORT_SYMBOL(dw_mci_probe);
>> void dw_mci_remove(struct dw_mci *host)
>> {
>> int i;
>> + struct device *dev = &host->pdev->dev;
>>
>> mci_writel(host, RINTSTS, 0xFFFFFFFF);
>> mci_writel(host, INTMASK, 0); /* disable all mmc interrupt first */
>>
>> for (i = 0; i < host->num_slots; i++) {
>> - dev_dbg(host->dev, "remove slot %d\n", i);
>> + dev_dbg(dev, "remove slot %d\n", i);
>> if (host->slot[i])
>> dw_mci_cleanup_slot(host->slot[i], i);
>> }
>> -
>> /* disable clock to CIU */
>> mci_writel(host, CLKENA, 0);
>> mci_writel(host, CLKSRC, 0);
>>
>> free_irq(host->irq, host);
>> destroy_workqueue(host->card_workqueue);
>> - dma_free_coherent(host->dev, PAGE_SIZE, host->sg_cpu, host->sg_dma);
>> + dma_free_coherent(dev, PAGE_SIZE, host->sg_cpu, host->sg_dma);
>>
>> if (host->use_dma && host->dma_ops->exit)
>> host->dma_ops->exit(host);
>> @@ -2451,7 +2489,7 @@ int dw_mci_resume(struct dw_mci *host)
>> if (host->vmmc)
>> regulator_enable(host->vmmc);
>>
>> - if (!mci_wait_reset(host->dev, host)) {
>> + if (!mci_wait_reset(&host->pdev->dev, host)) {
>> ret = -ENODEV;
>> return ret;
>> }
>> diff --git a/drivers/mmc/host/dw_mmc.h b/drivers/mmc/host/dw_mmc.h
>> index 6c17282..8c4810a 100644
>> --- a/drivers/mmc/host/dw_mmc.h
>> +++ b/drivers/mmc/host/dw_mmc.h
>> @@ -203,6 +203,7 @@ extern int dw_mci_resume(struct dw_mci *host);
>> struct dw_mci_drv_data {
>> unsigned long ctrl_type;
>> unsigned long *caps;
>> + unsigned long *caps2;
>> };
>>
>> #endif /* _DW_MMC_H_ */
>> diff --git a/include/linux/mmc/dw_mmc.h b/include/linux/mmc/dw_mmc.h
>> index 32c778f..71de160 100644
>> --- a/include/linux/mmc/dw_mmc.h
>> +++ b/include/linux/mmc/dw_mmc.h
>> @@ -161,7 +161,7 @@ struct dw_mci {
>> u32 fifoth_val;
>> u16 verid;
>> u16 data_offset;
>> - struct device *dev;
>> + struct platform_device *pdev;
>> struct dw_mci_board *pdata;
>> struct dw_mci_drv_data *drv_data;
>> struct clk *biu_clk;
>> diff --git a/include/linux/mmc/host.h b/include/linux/mmc/host.h
>> index 79d8921..b3e35fd 100644
>> --- a/include/linux/mmc/host.h
>> +++ b/include/linux/mmc/host.h
>> @@ -273,6 +273,7 @@ struct mmc_host {
>> #define MMC_CAP2_PACKED_WR (1 << 21) /* Allow packed write */
>> #define MMC_CAP2_PACKED_CMD (MMC_CAP2_PACKED_RD | \
>> MMC_CAP2_PACKED_WR) /* Allow packed commands */
>> +#define MMC_CAP2_CONFIG_BROKEN (1 << 22) /* Broken Config Register */
>
> What, broken hardware gets defined as a CAPability these days ?
> Please use the QUIRK framework for this.. CAP2 is definitely not the
> right place.
Definitely will move to quirk framework.
Thanks venkat
>
> Thanks,
> Venkat.
> --
> To unsubscribe from this list: send the line "unsubscribe linux-mmc" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: [PATCH V1] mmc: dwmmc: Add quirk for broken Hardware Config
2012-07-18 8:38 ` [PATCH V1] mmc: dwmmc: Add quirk for broken Hardware Config Girish K S
2012-07-18 12:55 ` S, Venkatraman
@ 2012-07-20 11:55 ` Girish K S
1 sibling, 0 replies; 5+ messages in thread
From: Girish K S @ 2012-07-20 11:55 UTC (permalink / raw)
To: linux-mmc
Cc: cjb, will.newton, patches, linux-samsung-soc, shashidharh,
thomas.abraham, jh80.chung, Girish K S
Any other feedback on this?
On 18 July 2012 14:08, Girish K S <girish.shivananjappa@linaro.org> wrote:
> In some Soc'S that integrate Designware mmc host controllers, the
> HCON register is broken. The hardware configuration is not
> updated. One specific usecase is the IDMAC. In Exysons5 SoC
> there exist a internal DMA, but the HCON register's DMA_INTERFACE
> field is not set to indicate its existance.
>
> This quirk can be used in such case to force the existance broken
> HCON field.
>
> changes in v1:
> -modified the caps2 field access per controller index.Reported
> by Jaehoon Chung <jh80.chung@samsung.com>.
> -replaced the pointer to device with the pointer to platform
> device in struct dw_mci.
> -updated driver data for all 4 mmc controllers of exynos5 SoC.
> -added non device-tree support for ctrl_id access.
>
> Signed-off-by: Girish K S <girish.shivananjappa@linaro.org>
> ---
> drivers/mmc/host/dw_mmc-pltfm.c | 10 +++-
> drivers/mmc/host/dw_mmc.c | 150 ++++++++++++++++++++++++---------------
> drivers/mmc/host/dw_mmc.h | 1 +
> include/linux/mmc/dw_mmc.h | 2 +-
> include/linux/mmc/host.h | 1 +
> 5 files changed, 106 insertions(+), 58 deletions(-)
>
> diff --git a/drivers/mmc/host/dw_mmc-pltfm.c b/drivers/mmc/host/dw_mmc-pltfm.c
> index 900f412..c8eb573 100644
> --- a/drivers/mmc/host/dw_mmc-pltfm.c
> +++ b/drivers/mmc/host/dw_mmc-pltfm.c
> @@ -35,9 +35,17 @@ static unsigned long exynos5250_dwmmc_caps[4] = {
> MMC_CAP_CMD23,
> };
>
> +static unsigned long exynos5250_dwmmc_caps2[4] = {
> + MMC_CAP2_CONFIG_BROKEN,
> + MMC_CAP2_CONFIG_BROKEN,
> + MMC_CAP2_CONFIG_BROKEN,
> + MMC_CAP2_CONFIG_BROKEN,
> +};
> +
> static struct dw_mci_drv_data exynos5250_drv_data = {
> .ctrl_type = DW_MCI_TYPE_EXYNOS5250,
> .caps = exynos5250_dwmmc_caps,
> + .caps2 = exynos5250_dwmmc_caps2,
> };
>
> static const struct of_device_id dw_mci_pltfm_match[] = {
> @@ -74,7 +82,7 @@ static int dw_mci_pltfm_probe(struct platform_device *pdev)
> goto err_free;
> }
>
> - host->dev = &pdev->dev;
> + host->pdev = pdev;
> host->irq_flags = 0;
> host->pdata = pdev->dev.platform_data;
> ret = -ENOMEM;
> diff --git a/drivers/mmc/host/dw_mmc.c b/drivers/mmc/host/dw_mmc.c
> index 000da16..fd9233d 100644
> --- a/drivers/mmc/host/dw_mmc.c
> +++ b/drivers/mmc/host/dw_mmc.c
> @@ -283,8 +283,10 @@ static u32 dw_mci_prepare_command(struct mmc_host *mmc, struct mmc_command *cmd)
> static void dw_mci_start_command(struct dw_mci *host,
> struct mmc_command *cmd, u32 cmd_flags)
> {
> + struct device *dev = &host->pdev->dev;
> +
> host->cmd = cmd;
> - dev_vdbg(host->dev,
> + dev_vdbg(dev,
> "start command: ARGR=0x%08x CMDR=0x%08x\n",
> cmd->arg, cmd_flags);
>
> @@ -323,10 +325,11 @@ static int dw_mci_get_dma_dir(struct mmc_data *data)
> static void dw_mci_dma_cleanup(struct dw_mci *host)
> {
> struct mmc_data *data = host->data;
> + struct device *dev = &host->pdev->dev;
>
> if (data)
> if (!data->host_cookie)
> - dma_unmap_sg(host->dev,
> + dma_unmap_sg(dev,
> data->sg,
> data->sg_len,
> dw_mci_get_dma_dir(data));
> @@ -351,8 +354,9 @@ static void dw_mci_idmac_stop_dma(struct dw_mci *host)
> static void dw_mci_idmac_complete_dma(struct dw_mci *host)
> {
> struct mmc_data *data = host->data;
> + struct device *dev = &host->pdev->dev;
>
> - dev_vdbg(host->dev, "DMA complete\n");
> + dev_vdbg(dev, "DMA complete\n");
>
> host->dma_ops->cleanup(host);
>
> @@ -420,10 +424,27 @@ static void dw_mci_idmac_start_dma(struct dw_mci *host, unsigned int sg_len)
> mci_writel(host, PLDMND, 1);
> }
>
> +static int dw_get_platform_device_id(struct dw_mci *host)
> +{
> + int ctrl_id;
> + struct device *dev = &host->pdev->dev;
> +
> + if (dev->of_node)
> + ctrl_id = of_alias_get_id(dev->of_node, "mshc");
> + else
> + ctrl_id = host->pdev->id;
> +
> + if (ctrl_id < 0)
> + ctrl_id = 0;
> +
> + return ctrl_id;
> +}
> +
> static int dw_mci_idmac_init(struct dw_mci *host)
> {
> struct idmac_desc *p;
> - int i, dma_support;
> + int i, dma_support, ctrl_id;
> + struct device *dev = &host->pdev->dev;
>
> /* Number of descriptors in the ring buffer */
> host->ring_size = PAGE_SIZE / sizeof(struct idmac_desc);
> @@ -431,14 +452,23 @@ static int dw_mci_idmac_init(struct dw_mci *host)
> /* Check if Hardware Configuration Register has support for DMA */
> dma_support = (mci_readl(host, HCON) >> 16) & 0x3;
>
> - if (!dma_support || dma_support > 2) {
> - dev_err(&host->dev,
> + /*
> + * In Some of the Soc's the HCON Register is broken. Even though the
> + * Soc's has a internal DMA the HCON register's DMA field doesnt
> + * show it. So additional quirk is added for such Soc's
> + */
> + ctrl_id = dw_get_platform_device_id(host);
> +
> + if ((!dma_support || dma_support > 2) &&
> + host->drv_data && host->drv_data->caps2 &&
> + !(host->drv_data->caps2[ctrl_id] & MMC_CAP2_CONFIG_BROKEN)) {
> + dev_err(dev,
> "Host Controller does not support IDMA Tx.\n");
> host->dma_ops = NULL;
> return -ENODEV;
> }
>
> - dev_info(&host->dev, "Using internal DMA controller.\n");
> + dev_info(dev, "Using internal DMA controller.\n");
>
> /* Forward link the descriptor list */
> for (i = 0, p = host->sg_cpu; i < host->ring_size - 1; i++, p++)
> @@ -474,6 +504,7 @@ static int dw_mci_pre_dma_transfer(struct dw_mci *host,
> {
> struct scatterlist *sg;
> unsigned int i, sg_len;
> + struct device *dev = &host->pdev->dev;
>
> if (!next && data->host_cookie)
> return data->host_cookie;
> @@ -494,7 +525,7 @@ static int dw_mci_pre_dma_transfer(struct dw_mci *host,
> return -EINVAL;
> }
>
> - sg_len = dma_map_sg(host->dev,
> + sg_len = dma_map_sg(dev,
> data->sg,
> data->sg_len,
> dw_mci_get_dma_dir(data));
> @@ -532,12 +563,13 @@ static void dw_mci_post_req(struct mmc_host *mmc,
> {
> struct dw_mci_slot *slot = mmc_priv(mmc);
> struct mmc_data *data = mrq->data;
> + struct device *dev = &slot->host->pdev->dev;
>
> if (!slot->host->use_dma || !data)
> return;
>
> if (data->host_cookie)
> - dma_unmap_sg(slot->host->dev,
> + dma_unmap_sg(dev,
> data->sg,
> data->sg_len,
> dw_mci_get_dma_dir(data));
> @@ -548,6 +580,7 @@ static int dw_mci_submit_data_dma(struct dw_mci *host, struct mmc_data *data)
> {
> int sg_len;
> u32 temp;
> + struct device *dev = &host->pdev->dev;
>
> host->using_dma = 0;
>
> @@ -563,7 +596,7 @@ static int dw_mci_submit_data_dma(struct dw_mci *host, struct mmc_data *data)
>
> host->using_dma = 1;
>
> - dev_vdbg(host->dev,
> + dev_vdbg(dev,
> "sd sg_cpu: %#lx sg_dma: %#lx sg_len: %d\n",
> (unsigned long)host->sg_cpu, (unsigned long)host->sg_dma,
> sg_len);
> @@ -928,6 +961,7 @@ static void dw_mci_request_end(struct dw_mci *host, struct mmc_request *mrq)
> {
> struct dw_mci_slot *slot;
> struct mmc_host *prev_mmc = host->cur_slot->mmc;
> + struct device *dev = &host->pdev->dev;
>
> WARN_ON(host->cmd || host->data);
>
> @@ -937,12 +971,12 @@ static void dw_mci_request_end(struct dw_mci *host, struct mmc_request *mrq)
> slot = list_entry(host->queue.next,
> struct dw_mci_slot, queue_node);
> list_del(&slot->queue_node);
> - dev_vdbg(host->dev, "list not empty: %s is next\n",
> + dev_vdbg(dev, "list not empty: %s is next\n",
> mmc_hostname(slot->mmc));
> host->state = STATE_SENDING_CMD;
> dw_mci_start_request(host, slot);
> } else {
> - dev_vdbg(host->dev, "list empty\n");
> + dev_vdbg(dev, "list empty\n");
> host->state = STATE_IDLE;
> }
>
> @@ -1081,7 +1115,7 @@ static void dw_mci_tasklet_func(unsigned long priv)
> data->bytes_xfered = 0;
> data->error = -ETIMEDOUT;
> } else {
> - dev_err(host->dev,
> + dev_err(&host->pdev->dev,
> "data FIFO error "
> "(status=%08x)\n",
> status);
> @@ -1829,7 +1863,8 @@ static u32 dw_mci_of_get_bus_wd(struct device *dev, u8 slot)
>
> static int dw_mci_of_setup_bus(struct dw_mci *host, u8 slot, u32 bus_wd)
> {
> - struct device_node *np = dw_mci_of_find_slot_node(host->dev, slot);
> + struct device *dev = &host->pdev->dev;
> + struct device_node *np = dw_mci_of_find_slot_node(dev, slot);
> int idx, gpio, ret;
>
> if (!np)
> @@ -1838,13 +1873,13 @@ static int dw_mci_of_setup_bus(struct dw_mci *host, u8 slot, u32 bus_wd)
> for (idx = 0; idx < NUM_PINS(bus_wd); idx++) {
> gpio = of_get_gpio(np, idx);
> if (!gpio_is_valid(gpio)) {
> - dev_err(host->dev, "invalid gpio: %d\n", gpio);
> + dev_err(dev, "invalid gpio: %d\n", gpio);
> return -EINVAL;
> }
>
> - ret = devm_gpio_request(host->dev, gpio, "dw-mci-bus");
> + ret = devm_gpio_request(dev, gpio, "dw-mci-bus");
> if (ret) {
> - dev_err(host->dev, "gpio [%d] request failed\n", gpio);
> + dev_err(dev, "gpio [%d] request failed\n", gpio);
> return -EBUSY;
> }
> }
> @@ -1852,11 +1887,11 @@ static int dw_mci_of_setup_bus(struct dw_mci *host, u8 slot, u32 bus_wd)
> host->slot[slot]->wp_gpio = -1;
> gpio = of_get_named_gpio(np, "wp-gpios", 0);
> if (!gpio_is_valid(gpio)) {
> - dev_info(host->dev, "wp gpio not available");
> + dev_info(dev, "wp gpio not available");
> } else {
> - ret = devm_gpio_request(host->dev, gpio, "dw-mci-wp");
> + ret = devm_gpio_request(dev, gpio, "dw-mci-wp");
> if (ret)
> - dev_info(host->dev, "gpio [%d] request failed\n",
> + dev_info(dev, "gpio [%d] request failed\n",
> gpio);
> else
> host->slot[slot]->wp_gpio = gpio;
> @@ -1865,11 +1900,11 @@ static int dw_mci_of_setup_bus(struct dw_mci *host, u8 slot, u32 bus_wd)
> host->slot[slot]->cd_gpio = -1;
> gpio = of_get_named_gpio(np, "cd-gpios", 0);
> if (!gpio_is_valid(gpio)) {
> - dev_info(host->dev, "cd gpio not available");
> + dev_info(dev, "cd gpio not available");
> } else {
> - ret = devm_gpio_request(host->dev, gpio, "dw-mci-cd");
> + ret = devm_gpio_request(dev, gpio, "dw-mci-cd");
> if (ret)
> - dev_err(host->dev, "gpio [%d] request failed\n", gpio);
> + dev_err(dev, "gpio [%d] request failed\n", gpio);
> else
> host->slot[slot]->cd_gpio = gpio;
> }
> @@ -1893,8 +1928,9 @@ static int __init dw_mci_init_slot(struct dw_mci *host, unsigned int id)
> struct mmc_host *mmc;
> struct dw_mci_slot *slot;
> int ctrl_id, ret;
> + struct device *dev = &host->pdev->dev;
>
> - mmc = mmc_alloc_host(sizeof(struct dw_mci_slot), host->dev);
> + mmc = mmc_alloc_host(sizeof(struct dw_mci_slot), dev);
> if (!mmc)
> return -ENOMEM;
>
> @@ -1923,23 +1959,23 @@ static int __init dw_mci_init_slot(struct dw_mci *host, unsigned int id)
> if (host->pdata->caps)
> mmc->caps = host->pdata->caps;
>
> - if (host->dev->of_node) {
> - ctrl_id = of_alias_get_id(host->dev->of_node, "mshc");
> - if (ctrl_id < 0)
> - ctrl_id = 0;
> - }
> + ctrl_id = dw_get_platform_device_id(host);
> +
> if (host->drv_data->caps)
> mmc->caps |= host->drv_data->caps[ctrl_id];
>
> if (host->pdata->caps2)
> mmc->caps2 = host->pdata->caps2;
>
> + if (host->drv_data->caps2)
> + mmc->caps2 |= host->drv_data->caps2[ctrl_id];
> +
> if (host->pdata->get_bus_wd) {
> if (host->pdata->get_bus_wd(slot->id) >= 4)
> mmc->caps |= MMC_CAP_4_BIT_DATA;
> - } else if (host->dev->of_node) {
> + } else if (dev->of_node) {
> unsigned int bus_width;
> - bus_width = dw_mci_of_get_bus_wd(host->dev, slot->id);
> + bus_width = dw_mci_of_get_bus_wd(dev, slot->id);
> switch (bus_width) {
> case 8:
> mmc->caps |= MMC_CAP_8_BIT_DATA;
> @@ -2030,11 +2066,12 @@ static void dw_mci_cleanup_slot(struct dw_mci_slot *slot, unsigned int id)
>
> static void dw_mci_init_dma(struct dw_mci *host)
> {
> + struct device *dev = &host->pdev->dev;
> /* Alloc memory for sg translation */
> - host->sg_cpu = dma_alloc_coherent(host->dev, PAGE_SIZE,
> + host->sg_cpu = dma_alloc_coherent(dev, PAGE_SIZE,
> &host->sg_dma, GFP_KERNEL);
> if (!host->sg_cpu) {
> - dev_err(host->dev, "%s: could not alloc DMA memory\n",
> + dev_err(dev, "%s: could not alloc DMA memory\n",
> __func__);
> goto no_dma;
> }
> @@ -2050,12 +2087,12 @@ static void dw_mci_init_dma(struct dw_mci *host)
> if (host->dma_ops->init && host->dma_ops->start &&
> host->dma_ops->stop && host->dma_ops->cleanup) {
> if (host->dma_ops->init(host)) {
> - dev_err(host->dev, "%s: Unable to initialize "
> + dev_err(dev, "%s: Unable to initialize "
> "DMA Controller.\n", __func__);
> goto no_dma;
> }
> } else {
> - dev_err(host->dev, "DMA initialization not found.\n");
> + dev_err(dev, "DMA initialization not found.\n");
> goto no_dma;
> }
>
> @@ -2063,7 +2100,7 @@ static void dw_mci_init_dma(struct dw_mci *host)
> return;
>
> no_dma:
> - dev_info(host->dev, "Using PIO mode.\n");
> + dev_info(dev, "Using PIO mode.\n");
> host->use_dma = 0;
> return;
> }
> @@ -2109,7 +2146,7 @@ static struct dw_mci_of_quirks {
> static struct dw_mci_board *dw_mci_parse_dt(struct dw_mci *host)
> {
> struct dw_mci_board *pdata;
> - struct device *dev = host->dev;
> + struct device *dev = &host->pdev->dev;
> struct device_node *np = dev->of_node;
> u32 timing[3];
> int idx, cnt;
> @@ -2169,30 +2206,31 @@ int dw_mci_probe(struct dw_mci *host)
> int width, i, ret = 0;
> u32 fifo_size;
> int init_slots = 0;
> + struct device *dev = &host->pdev->dev;
>
> if (!host->pdata) {
> host->pdata = dw_mci_parse_dt(host);
> if (IS_ERR(host->pdata)) {
> - dev_err(host->dev, "platform data not available\n");
> + dev_err(dev, "platform data not available\n");
> return -EINVAL;
> }
> }
>
> if (!host->pdata->select_slot && host->pdata->num_slots > 1) {
> - dev_err(host->dev,
> + dev_err(dev,
> "Platform data must supply select_slot function\n");
> return -ENODEV;
> }
>
> - host->biu_clk = clk_get(host->dev, "biu");
> + host->biu_clk = clk_get(dev, "biu");
> if (IS_ERR(host->biu_clk))
> - dev_dbg(host->dev, "biu clock not available\n");
> + dev_dbg(dev, "biu clock not available\n");
> else
> clk_prepare_enable(host->biu_clk);
>
> - host->ciu_clk = clk_get(host->dev, "ciu");
> + host->ciu_clk = clk_get(dev, "ciu");
> if (IS_ERR(host->ciu_clk))
> - dev_dbg(host->dev, "ciu clock not available\n");
> + dev_dbg(dev, "ciu clock not available\n");
> else
> clk_prepare_enable(host->ciu_clk);
>
> @@ -2202,7 +2240,7 @@ int dw_mci_probe(struct dw_mci *host)
> host->bus_hz = clk_get_rate(host->ciu_clk);
>
> if (!host->bus_hz) {
> - dev_err(host->dev,
> + dev_err(dev,
> "Platform data must supply bus speed\n");
> ret = -ENODEV;
> goto err_clk;
> @@ -2243,7 +2281,7 @@ int dw_mci_probe(struct dw_mci *host)
> }
>
> /* Reset all blocks */
> - if (!mci_wait_reset(host->dev, host))
> + if (!mci_wait_reset(dev, host))
> return -ENODEV;
>
> host->dma_ops = host->pdata->dma_ops;
> @@ -2300,15 +2338,15 @@ int dw_mci_probe(struct dw_mci *host)
> for (i = 0; i < host->num_slots; i++) {
> ret = dw_mci_init_slot(host, i);
> if (ret)
> - dev_dbg(host->dev, "slot %d init failed\n", i);
> + dev_dbg(dev, "slot %d init failed\n", i);
> else
> init_slots++;
> }
>
> if (init_slots) {
> - dev_info(host->dev, "%d slots initialized\n", init_slots);
> + dev_info(dev, "%d slots initialized\n", init_slots);
> } else {
> - dev_dbg(host->dev, "attempted to initialize %d slots, "
> + dev_dbg(dev, "attempted to initialize %d slots, "
> "but failed on all\n", host->num_slots);
> goto err_init_slot;
> }
> @@ -2318,7 +2356,7 @@ int dw_mci_probe(struct dw_mci *host)
> * Need to check the version-id and set data-offset for DATA register.
> */
> host->verid = SDMMC_GET_VERID(mci_readl(host, VERID));
> - dev_info(host->dev, "Version ID is %04x\n", host->verid);
> + dev_info(dev, "Version ID is %04x\n", host->verid);
>
> if (host->verid < DW_MMC_240A)
> host->data_offset = DATA_OFFSET;
> @@ -2335,12 +2373,12 @@ int dw_mci_probe(struct dw_mci *host)
> DW_MCI_ERROR_FLAGS | SDMMC_INT_CD);
> mci_writel(host, CTRL, SDMMC_CTRL_INT_ENABLE); /* Enable mci interrupt */
>
> - dev_info(host->dev, "DW MMC controller at irq %d, "
> + dev_info(dev, "DW MMC controller at irq %d, "
> "%d bit host data width, "
> "%u deep fifo\n",
> host->irq, width, fifo_size);
> if (host->quirks & DW_MCI_QUIRK_IDMAC_DTO)
> - dev_info(host->dev, "Internal DMAC interrupt fix enabled.\n");
> + dev_info(dev, "Internal DMAC interrupt fix enabled.\n");
>
> return 0;
>
> @@ -2353,7 +2391,7 @@ err_workqueue:
> err_dmaunmap:
> if (host->use_dma && host->dma_ops->exit)
> host->dma_ops->exit(host);
> - dma_free_coherent(host->dev, PAGE_SIZE,
> + dma_free_coherent(dev, PAGE_SIZE,
> host->sg_cpu, host->sg_dma);
>
> if (host->vmmc) {
> @@ -2377,23 +2415,23 @@ EXPORT_SYMBOL(dw_mci_probe);
> void dw_mci_remove(struct dw_mci *host)
> {
> int i;
> + struct device *dev = &host->pdev->dev;
>
> mci_writel(host, RINTSTS, 0xFFFFFFFF);
> mci_writel(host, INTMASK, 0); /* disable all mmc interrupt first */
>
> for (i = 0; i < host->num_slots; i++) {
> - dev_dbg(host->dev, "remove slot %d\n", i);
> + dev_dbg(dev, "remove slot %d\n", i);
> if (host->slot[i])
> dw_mci_cleanup_slot(host->slot[i], i);
> }
> -
> /* disable clock to CIU */
> mci_writel(host, CLKENA, 0);
> mci_writel(host, CLKSRC, 0);
>
> free_irq(host->irq, host);
> destroy_workqueue(host->card_workqueue);
> - dma_free_coherent(host->dev, PAGE_SIZE, host->sg_cpu, host->sg_dma);
> + dma_free_coherent(dev, PAGE_SIZE, host->sg_cpu, host->sg_dma);
>
> if (host->use_dma && host->dma_ops->exit)
> host->dma_ops->exit(host);
> @@ -2451,7 +2489,7 @@ int dw_mci_resume(struct dw_mci *host)
> if (host->vmmc)
> regulator_enable(host->vmmc);
>
> - if (!mci_wait_reset(host->dev, host)) {
> + if (!mci_wait_reset(&host->pdev->dev, host)) {
> ret = -ENODEV;
> return ret;
> }
> diff --git a/drivers/mmc/host/dw_mmc.h b/drivers/mmc/host/dw_mmc.h
> index 6c17282..8c4810a 100644
> --- a/drivers/mmc/host/dw_mmc.h
> +++ b/drivers/mmc/host/dw_mmc.h
> @@ -203,6 +203,7 @@ extern int dw_mci_resume(struct dw_mci *host);
> struct dw_mci_drv_data {
> unsigned long ctrl_type;
> unsigned long *caps;
> + unsigned long *caps2;
> };
>
> #endif /* _DW_MMC_H_ */
> diff --git a/include/linux/mmc/dw_mmc.h b/include/linux/mmc/dw_mmc.h
> index 32c778f..71de160 100644
> --- a/include/linux/mmc/dw_mmc.h
> +++ b/include/linux/mmc/dw_mmc.h
> @@ -161,7 +161,7 @@ struct dw_mci {
> u32 fifoth_val;
> u16 verid;
> u16 data_offset;
> - struct device *dev;
> + struct platform_device *pdev;
> struct dw_mci_board *pdata;
> struct dw_mci_drv_data *drv_data;
> struct clk *biu_clk;
> diff --git a/include/linux/mmc/host.h b/include/linux/mmc/host.h
> index 79d8921..b3e35fd 100644
> --- a/include/linux/mmc/host.h
> +++ b/include/linux/mmc/host.h
> @@ -273,6 +273,7 @@ struct mmc_host {
> #define MMC_CAP2_PACKED_WR (1 << 21) /* Allow packed write */
> #define MMC_CAP2_PACKED_CMD (MMC_CAP2_PACKED_RD | \
> MMC_CAP2_PACKED_WR) /* Allow packed commands */
> +#define MMC_CAP2_CONFIG_BROKEN (1 << 22) /* Broken Config Register */
>
> mmc_pm_flag_t pm_caps; /* supported pm features */
> unsigned int power_notify_type;
> --
> 1.7.4.1
>
^ permalink raw reply [flat|nested] 5+ messages in thread
end of thread, other threads:[~2012-07-20 11:55 UTC | newest]
Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2012-07-18 8:38 [PATCH V1] Add Quirk for Broken Configuration Girish K S
2012-07-18 8:38 ` [PATCH V1] mmc: dwmmc: Add quirk for broken Hardware Config Girish K S
2012-07-18 12:55 ` S, Venkatraman
2012-07-19 5:24 ` Girish K S
2012-07-20 11:55 ` Girish K S
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.