* [patch 00/11] s3cmci fixes and updates for current merge window
@ 2009-09-21 13:35 Ben Dooks
2009-09-21 13:35 ` [patch 01/11] s3cmci: Use resource_size() instead of local macro Ben Dooks
` (11 more replies)
0 siblings, 12 replies; 14+ messages in thread
From: Ben Dooks @ 2009-09-21 13:35 UTC (permalink / raw)
To: linux-mmc, akpm; +Cc: ben-linux
This is a set of the s3cmci updates and fixes for the current merge
window. It is a resend of an updated version of a series posted a
few weeks ago, which I could not find queued anywhere.
--
^ permalink raw reply [flat|nested] 14+ messages in thread
* [patch 01/11] s3cmci: Use resource_size() instead of local macro
2009-09-21 13:35 [patch 00/11] s3cmci fixes and updates for current merge window Ben Dooks
@ 2009-09-21 13:35 ` Ben Dooks
2009-09-21 13:35 ` [patch 02/11] s3cmci: update probe to use new platform id list Ben Dooks
` (10 subsequent siblings)
11 siblings, 0 replies; 14+ messages in thread
From: Ben Dooks @ 2009-09-21 13:35 UTC (permalink / raw)
To: linux-mmc, akpm; +Cc: ben-linux
[-- Attachment #1: simtec/pushed/s3cmci-fix-resource-size.patch --]
[-- Type: text/plain, Size: 1973 bytes --]
Replace the local definition RESSIZE() with the standard resource_size()
call for getting the size of a struct resource.
Signed-off-by: Ben Dooks <ben@simtec.co.uk>
---
drivers/mmc/host/s3cmci.c | 10 ++++------
1 file changed, 4 insertions(+), 6 deletions(-)
Index: b/drivers/mmc/host/s3cmci.c
===================================================================
--- a/drivers/mmc/host/s3cmci.c 2009-07-20 14:35:52.000000000 +0100
+++ b/drivers/mmc/host/s3cmci.c 2009-07-22 14:34:10.000000000 +0100
@@ -58,8 +58,6 @@ static const int dbgmap_debug = dbg_err
dev_dbg(&host->pdev->dev, args); \
} while (0)
-#define RESSIZE(ressource) (((ressource)->end - (ressource)->start)+1)
-
static struct s3c2410_dma_client s3cmci_dma_client = {
.name = "s3c-mci",
};
@@ -1298,7 +1296,7 @@ static int __devinit s3cmci_probe(struct
}
host->mem = request_mem_region(host->mem->start,
- RESSIZE(host->mem), pdev->name);
+ resource_size(host->mem), pdev->name);
if (!host->mem) {
dev_err(&pdev->dev, "failed to request io memory region.\n");
@@ -1306,7 +1304,7 @@ static int __devinit s3cmci_probe(struct
goto probe_free_host;
}
- host->base = ioremap(host->mem->start, RESSIZE(host->mem));
+ host->base = ioremap(host->mem->start, resource_size(host->mem));
if (!host->base) {
dev_err(&pdev->dev, "failed to ioremap() io memory region.\n");
ret = -EINVAL;
@@ -1433,7 +1431,7 @@ static int __devinit s3cmci_probe(struct
iounmap(host->base);
probe_free_mem_region:
- release_mem_region(host->mem->start, RESSIZE(host->mem));
+ release_mem_region(host->mem->start, resource_size(host->mem));
probe_free_host:
mmc_free_host(mmc);
@@ -1469,7 +1467,7 @@ static int __devexit s3cmci_remove(struc
free_irq(host->irq, host);
iounmap(host->base);
- release_mem_region(host->mem->start, RESSIZE(host->mem));
+ release_mem_region(host->mem->start, resource_size(host->mem));
mmc_free_host(mmc);
return 0;
--
^ permalink raw reply [flat|nested] 14+ messages in thread
* [patch 02/11] s3cmci: update probe to use new platform id list.
2009-09-21 13:35 [patch 00/11] s3cmci fixes and updates for current merge window Ben Dooks
2009-09-21 13:35 ` [patch 01/11] s3cmci: Use resource_size() instead of local macro Ben Dooks
@ 2009-09-21 13:35 ` Ben Dooks
2009-09-21 13:35 ` [patch 03/11] s3cmci: Change GPIO to gpiolib from S3C24XX specific calls Ben Dooks
` (9 subsequent siblings)
11 siblings, 0 replies; 14+ messages in thread
From: Ben Dooks @ 2009-09-21 13:35 UTC (permalink / raw)
To: linux-mmc, akpm; +Cc: ben-linux
[-- Attachment #1: simtec/pushed/s3cmci-update-probe.patch --]
[-- Type: text/plain, Size: 3791 bytes --]
Use the platform id list to match the three different versions of the
hardware block that this driver supports.
This will change the prefix of the console messages produced by this
driver to be prefixed by s3c-mci instead of the hardware block name,
such as s3c2440-mci.
Signed-off-by: Ben Dooks <ben@simtec.co.uk>
---
drivers/mmc/host/s3cmci.c | 71 +++++++++++++++-------------------------------
1 file changed, 24 insertions(+), 47 deletions(-)
Index: b/drivers/mmc/host/s3cmci.c
===================================================================
--- a/drivers/mmc/host/s3cmci.c 2009-07-20 14:47:21.000000000 +0100
+++ b/drivers/mmc/host/s3cmci.c 2009-07-22 14:33:54.000000000 +0100
@@ -1244,11 +1244,14 @@ static inline void s3cmci_cpufreq_deregi
}
#endif
-static int __devinit s3cmci_probe(struct platform_device *pdev, int is2440)
+static int __devinit s3cmci_probe(struct platform_device *pdev)
{
struct s3cmci_host *host;
struct mmc_host *mmc;
int ret;
+ int is2440;
+
+ is2440 = platform_get_device_id(pdev)->driver_data;
mmc = mmc_alloc_host(sizeof(struct s3cmci_host), &pdev->dev);
if (!mmc) {
@@ -1473,20 +1476,22 @@ static int __devexit s3cmci_remove(struc
return 0;
}
-static int __devinit s3cmci_2410_probe(struct platform_device *dev)
-{
- return s3cmci_probe(dev, 0);
-}
+static struct platform_device_id s3cmci_driver_ids[] = {
+ {
+ .name = "s3c2410-sdi",
+ .driver_data = 0,
+ }, {
+ .name = "s3c2412-sdi",
+ .driver_data = 1,
+ }, {
+ .name = "s3c2440-sdi",
+ .driver_data = 1,
+ },
+ { }
+};
-static int __devinit s3cmci_2412_probe(struct platform_device *dev)
-{
- return s3cmci_probe(dev, 1);
-}
+MODULE_DEVICE_TABLE(platform, s3cmci_driver_ids);
-static int __devinit s3cmci_2440_probe(struct platform_device *dev)
-{
- return s3cmci_probe(dev, 1);
-}
#ifdef CONFIG_PM
@@ -1510,50 +1515,25 @@ static int s3cmci_resume(struct platform
#endif /* CONFIG_PM */
-static struct platform_driver s3cmci_2410_driver = {
- .driver.name = "s3c2410-sdi",
- .driver.owner = THIS_MODULE,
- .probe = s3cmci_2410_probe,
- .remove = __devexit_p(s3cmci_remove),
- .shutdown = s3cmci_shutdown,
- .suspend = s3cmci_suspend,
- .resume = s3cmci_resume,
-};
-
-static struct platform_driver s3cmci_2412_driver = {
- .driver.name = "s3c2412-sdi",
- .driver.owner = THIS_MODULE,
- .probe = s3cmci_2412_probe,
- .remove = __devexit_p(s3cmci_remove),
- .shutdown = s3cmci_shutdown,
- .suspend = s3cmci_suspend,
- .resume = s3cmci_resume,
-};
-
-static struct platform_driver s3cmci_2440_driver = {
- .driver.name = "s3c2440-sdi",
+static struct platform_driver s3cmci_driver = {
+ .driver.name = "s3c-sdi",
.driver.owner = THIS_MODULE,
- .probe = s3cmci_2440_probe,
+ .id_table = s3cmci_driver_ids,
+ .probe = s3cmci_probe,
.remove = __devexit_p(s3cmci_remove),
.shutdown = s3cmci_shutdown,
.suspend = s3cmci_suspend,
.resume = s3cmci_resume,
};
-
static int __init s3cmci_init(void)
{
- platform_driver_register(&s3cmci_2410_driver);
- platform_driver_register(&s3cmci_2412_driver);
- platform_driver_register(&s3cmci_2440_driver);
- return 0;
+ return platform_driver_register(&s3cmci_driver);
}
static void __exit s3cmci_exit(void)
{
- platform_driver_unregister(&s3cmci_2410_driver);
- platform_driver_unregister(&s3cmci_2412_driver);
- platform_driver_unregister(&s3cmci_2440_driver);
+ platform_driver_unregister(&s3cmci_driver);
}
module_init(s3cmci_init);
@@ -1562,6 +1542,3 @@ module_exit(s3cmci_exit);
MODULE_DESCRIPTION("Samsung S3C MMC/SD Card Interface driver");
MODULE_LICENSE("GPL v2");
MODULE_AUTHOR("Thomas Kleffel <tk@maintech.de>, Ben Dooks <ben-linux@fluff.org>");
-MODULE_ALIAS("platform:s3c2410-sdi");
-MODULE_ALIAS("platform:s3c2412-sdi");
-MODULE_ALIAS("platform:s3c2440-sdi");
--
^ permalink raw reply [flat|nested] 14+ messages in thread
* [patch 03/11] s3cmci: Change GPIO to gpiolib from S3C24XX specific calls
2009-09-21 13:35 [patch 00/11] s3cmci fixes and updates for current merge window Ben Dooks
2009-09-21 13:35 ` [patch 01/11] s3cmci: Use resource_size() instead of local macro Ben Dooks
2009-09-21 13:35 ` [patch 02/11] s3cmci: update probe to use new platform id list Ben Dooks
@ 2009-09-21 13:35 ` Ben Dooks
2009-09-21 13:35 ` [patch 04/11] s3cmci: Change to use dev_pm_ops Ben Dooks
` (8 subsequent siblings)
11 siblings, 0 replies; 14+ messages in thread
From: Ben Dooks @ 2009-09-21 13:35 UTC (permalink / raw)
To: linux-mmc, akpm; +Cc: ben-linux
[-- Attachment #1: simtec/pushed/s3cmci-gpiolib-conversion.patch --]
[-- Type: text/plain, Size: 6207 bytes --]
Move to using gpiolib to access the card detect and write protect GPIO
lines instead of using the platform speicifc s3c2410_gpio calls.
Also ensure that the card lines are claimed the same way to avoid overlap
with any other drivers.
Signed-off-by: Ben Dooks <ben@simtec.co.uk>
---
drivers/mmc/host/s3cmci.c | 87 ++++++++++++++++++++++++++++++++++++----------
1 file changed, 69 insertions(+), 18 deletions(-)
Index: b/drivers/mmc/host/s3cmci.c
===================================================================
--- a/drivers/mmc/host/s3cmci.c 2009-09-04 11:03:53.000000000 +0100
+++ b/drivers/mmc/host/s3cmci.c 2009-09-04 12:06:45.000000000 +0100
@@ -1047,7 +1047,7 @@ static int s3cmci_card_present(struct mm
if (pdata->gpio_detect == 0)
return -ENOSYS;
- ret = s3c2410_gpio_getpin(pdata->gpio_detect) ? 0 : 1;
+ ret = gpio_get_value(pdata->gpio_detect) ? 0 : 1;
return ret ^ pdata->detect_invert;
}
@@ -1102,12 +1102,12 @@ static void s3cmci_set_ios(struct mmc_ho
switch (ios->power_mode) {
case MMC_POWER_ON:
case MMC_POWER_UP:
- s3c2410_gpio_cfgpin(S3C2410_GPE5, S3C2410_GPE5_SDCLK);
- s3c2410_gpio_cfgpin(S3C2410_GPE6, S3C2410_GPE6_SDCMD);
- s3c2410_gpio_cfgpin(S3C2410_GPE7, S3C2410_GPE7_SDDAT0);
- s3c2410_gpio_cfgpin(S3C2410_GPE8, S3C2410_GPE8_SDDAT1);
- s3c2410_gpio_cfgpin(S3C2410_GPE9, S3C2410_GPE9_SDDAT2);
- s3c2410_gpio_cfgpin(S3C2410_GPE10, S3C2410_GPE10_SDDAT3);
+ s3c2410_gpio_cfgpin(S3C2410_GPE(5), S3C2410_GPE5_SDCLK);
+ s3c2410_gpio_cfgpin(S3C2410_GPE(6), S3C2410_GPE6_SDCMD);
+ s3c2410_gpio_cfgpin(S3C2410_GPE(7), S3C2410_GPE7_SDDAT0);
+ s3c2410_gpio_cfgpin(S3C2410_GPE(8), S3C2410_GPE8_SDDAT1);
+ s3c2410_gpio_cfgpin(S3C2410_GPE(9), S3C2410_GPE9_SDDAT2);
+ s3c2410_gpio_cfgpin(S3C2410_GPE(10), S3C2410_GPE10_SDDAT3);
if (host->pdata->set_power)
host->pdata->set_power(ios->power_mode, ios->vdd);
@@ -1119,8 +1119,7 @@ static void s3cmci_set_ios(struct mmc_ho
case MMC_POWER_OFF:
default:
- s3c2410_gpio_setpin(S3C2410_GPE5, 0);
- s3c2410_gpio_cfgpin(S3C2410_GPE5, S3C2410_GPIO_OUTPUT);
+ gpio_direction_output(S3C2410_GPE(5), 0);
if (host->is2440)
mci_con |= S3C2440_SDICON_SDRESET;
@@ -1244,12 +1243,14 @@ static inline void s3cmci_cpufreq_deregi
}
#endif
+
static int __devinit s3cmci_probe(struct platform_device *pdev)
{
struct s3cmci_host *host;
struct mmc_host *mmc;
int ret;
int is2440;
+ int i;
is2440 = platform_get_device_id(pdev)->driver_data;
@@ -1259,6 +1260,18 @@ static int __devinit s3cmci_probe(struct
goto probe_out;
}
+ for (i = S3C2410_GPE(5); i <= S3C2410_GPE(10); i++) {
+ ret = gpio_request(i, dev_name(&pdev->dev));
+ if (ret) {
+ dev_err(&pdev->dev, "failed to get gpio %d\n", i);
+
+ for (i--; i >= S3C2410_GPE(5); i--)
+ gpio_free(i);
+
+ goto probe_free_host;
+ }
+ }
+
host = mmc_priv(mmc);
host->mmc = mmc;
host->pdev = pdev;
@@ -1295,7 +1308,7 @@ static int __devinit s3cmci_probe(struct
"failed to get io memory region resouce.\n");
ret = -ENOENT;
- goto probe_free_host;
+ goto probe_free_gpio;
}
host->mem = request_mem_region(host->mem->start,
@@ -1304,7 +1317,7 @@ static int __devinit s3cmci_probe(struct
if (!host->mem) {
dev_err(&pdev->dev, "failed to request io memory region.\n");
ret = -ENOENT;
- goto probe_free_host;
+ goto probe_free_gpio;
}
host->base = ioremap(host->mem->start, resource_size(host->mem));
@@ -1333,6 +1346,14 @@ static int __devinit s3cmci_probe(struct
disable_irq(host->irq);
+ if (host->pdata->gpio_detect) {
+ ret = gpio_request(host->pdata->gpio_detect, "s3cmci detect");
+ if (ret) {
+ dev_err(&pdev->dev, "failed to get detect gpio\n");
+ goto probe_free_irq;
+ }
+ }
+
host->irq_cd = s3c2410_gpio_getirq(host->pdata->gpio_detect);
if (host->irq_cd >= 0) {
@@ -1341,22 +1362,27 @@ static int __devinit s3cmci_probe(struct
DRIVER_NAME, host)) {
dev_err(&pdev->dev, "can't get card detect irq.\n");
ret = -ENOENT;
- goto probe_free_irq;
+ goto probe_free_gpio_cd;
}
} else {
dev_warn(&pdev->dev, "host detect has no irq available\n");
- s3c2410_gpio_cfgpin(host->pdata->gpio_detect,
- S3C2410_GPIO_INPUT);
+ gpio_direction_input(host->pdata->gpio_detect);
}
- if (host->pdata->gpio_wprotect)
- s3c2410_gpio_cfgpin(host->pdata->gpio_wprotect,
- S3C2410_GPIO_INPUT);
+ if (host->pdata->gpio_wprotect) {
+ ret = gpio_request(host->pdata->gpio_wprotect, "s3cmci wp");
+ if (ret) {
+ dev_err(&pdev->dev, "failed to get writeprotect\n");
+ goto probe_free_irq_cd;
+ }
+
+ gpio_direction_input(host->pdata->gpio_wprotect);
+ }
if (s3c2410_dma_request(S3CMCI_DMA, &s3cmci_dma_client, NULL) < 0) {
dev_err(&pdev->dev, "unable to get DMA channel.\n");
ret = -EBUSY;
- goto probe_free_irq_cd;
+ goto probe_free_gpio_wp;
}
host->clk = clk_get(&pdev->dev, "sdi");
@@ -1423,6 +1449,14 @@ static int __devinit s3cmci_probe(struct
clk_free:
clk_put(host->clk);
+ probe_free_gpio_wp:
+ if (host->pdata->gpio_wprotect)
+ gpio_free(host->pdata->gpio_wprotect);
+
+ probe_free_gpio_cd:
+ if (host->pdata->gpio_detect)
+ gpio_free(host->pdata->gpio_detect);
+
probe_free_irq_cd:
if (host->irq_cd >= 0)
free_irq(host->irq_cd, host);
@@ -1436,8 +1470,13 @@ static int __devinit s3cmci_probe(struct
probe_free_mem_region:
release_mem_region(host->mem->start, resource_size(host->mem));
+ probe_free_gpio:
+ for (i = S3C2410_GPE(5); i <= S3C2410_GPE(10); i++)
+ gpio_free(i);
+
probe_free_host:
mmc_free_host(mmc);
+
probe_out:
return ret;
}
@@ -1459,6 +1498,8 @@ static int __devexit s3cmci_remove(struc
{
struct mmc_host *mmc = platform_get_drvdata(pdev);
struct s3cmci_host *host = mmc_priv(mmc);
+ struct s3c24xx_mci_pdata *pd = host->pdata;
+ int i;
s3cmci_shutdown(pdev);
@@ -1469,6 +1510,16 @@ static int __devexit s3cmci_remove(struc
free_irq(host->irq, host);
+ if (pd->gpio_wprotect)
+ gpio_free(pd->gpio_wprotect);
+
+ if (pd->gpio_detect)
+ gpio_free(pd->gpio_detect);
+
+ for (i = S3C2410_GPE(5); i <= S3C2410_GPE(10); i++)
+ gpio_free(i);
+
+
iounmap(host->base);
release_mem_region(host->mem->start, resource_size(host->mem));
--
^ permalink raw reply [flat|nested] 14+ messages in thread
* [patch 04/11] s3cmci: Change to use dev_pm_ops
2009-09-21 13:35 [patch 00/11] s3cmci fixes and updates for current merge window Ben Dooks
` (2 preceding siblings ...)
2009-09-21 13:35 ` [patch 03/11] s3cmci: Change GPIO to gpiolib from S3C24XX specific calls Ben Dooks
@ 2009-09-21 13:35 ` Ben Dooks
2009-09-21 13:36 ` [patch 05/11] s3cmci: Fix direct write to interrupt mask Ben Dooks
` (7 subsequent siblings)
11 siblings, 0 replies; 14+ messages in thread
From: Ben Dooks @ 2009-09-21 13:35 UTC (permalink / raw)
To: linux-mmc, akpm; +Cc: ben-linux
[-- Attachment #1: simtec/pushed/s3cmci-use-pmops.patch --]
[-- Type: text/plain, Size: 1899 bytes --]
Move to using dev_pm_ops for suspend and resume.
Signed-off-by: Ben Dooks <ben@simtec.co.uk>
---
drivers/mmc/host/s3cmci.c | 29 ++++++++++++++++++-----------
1 file changed, 18 insertions(+), 11 deletions(-)
Index: b/drivers/mmc/host/s3cmci.c
===================================================================
--- a/drivers/mmc/host/s3cmci.c 2009-08-04 12:14:05.000000000 +0100
+++ b/drivers/mmc/host/s3cmci.c 2009-08-04 12:23:03.000000000 +0100
@@ -1546,35 +1546,42 @@ MODULE_DEVICE_TABLE(platform, s3cmci_dri
#ifdef CONFIG_PM
-static int s3cmci_suspend(struct platform_device *dev, pm_message_t state)
+static int s3cmci_suspend(struct device *dev)
{
- struct mmc_host *mmc = platform_get_drvdata(dev);
+ struct mmc_host *mmc = platform_get_drvdata(to_platform_device(dev));
+ struct pm_message event = { PM_EVENT_SUSPEND };
- return mmc_suspend_host(mmc, state);
+ return mmc_suspend_host(mmc, event);
}
-static int s3cmci_resume(struct platform_device *dev)
+static int s3cmci_resume(struct device *dev)
{
- struct mmc_host *mmc = platform_get_drvdata(dev);
+ struct mmc_host *mmc = platform_get_drvdata(to_platform_device(dev));
return mmc_resume_host(mmc);
}
+static struct dev_pm_ops s3cmci_pm = {
+ .suspend = s3cmci_suspend,
+ .resume = s3cmci_resume,
+};
+
+#define s3cmci_pm_ops &s3cmci_pm
#else /* CONFIG_PM */
-#define s3cmci_suspend NULL
-#define s3cmci_resume NULL
+#define s3cmci_pm_ops NULL
#endif /* CONFIG_PM */
static struct platform_driver s3cmci_driver = {
- .driver.name = "s3c-sdi",
- .driver.owner = THIS_MODULE,
+ .driver = {
+ .name = "s3c-sdi",
+ .owner = THIS_MODULE,
+ .pm = s3cmci_pm_ops,
+ },
.id_table = s3cmci_driver_ids,
.probe = s3cmci_probe,
.remove = __devexit_p(s3cmci_remove),
.shutdown = s3cmci_shutdown,
- .suspend = s3cmci_suspend,
- .resume = s3cmci_resume,
};
static int __init s3cmci_init(void)
--
^ permalink raw reply [flat|nested] 14+ messages in thread
* [patch 05/11] s3cmci: Fix direct write to interrupt mask
2009-09-21 13:35 [patch 00/11] s3cmci fixes and updates for current merge window Ben Dooks
` (3 preceding siblings ...)
2009-09-21 13:35 ` [patch 04/11] s3cmci: Change to use dev_pm_ops Ben Dooks
@ 2009-09-21 13:36 ` Ben Dooks
2009-09-21 13:36 ` [patch 06/11] s3cmci: Add debugfs support for examining driver and hardware state Ben Dooks
` (6 subsequent siblings)
11 siblings, 0 replies; 14+ messages in thread
From: Ben Dooks @ 2009-09-21 13:36 UTC (permalink / raw)
To: linux-mmc, akpm; +Cc: ben-linux
[-- Attachment #1: simtec/pushed/s3cmci-fix-clear-imask.patch --]
[-- Type: text/plain, Size: 1147 bytes --]
The clear_imask() call should be used to clear the interrupt mask
register, as it may end up clearing the SDIO interrupt bit if this
is enabled.
Change all writes of zero to SDIIMSK register to use clear_imask()
ready for the SDIO updates.
Signed-off-by: Ben Dooks <ben@simtec.co.uk>
---
Index: b/drivers/mmc/host/s3cmci.c
===================================================================
--- a/drivers/mmc/host/s3cmci.c 2009-07-22 14:55:13.000000000 +0100
+++ b/drivers/mmc/host/s3cmci.c 2009-07-22 14:57:07.000000000 +0100
@@ -681,9 +681,9 @@ out:
fail_request:
host->mrq->data->error = -EINVAL;
host->complete_what = COMPLETION_FINALIZE;
- writel(0, host->base + host->sdiimsk);
- goto out;
+ clear_imask(host);
+ goto out;
}
static void finalize_request(struct s3cmci_host *host)
@@ -726,7 +726,7 @@ static void finalize_request(struct s3cm
writel(0, host->base + S3C2410_SDICMDARG);
writel(S3C2410_SDIDCON_STOP, host->base + S3C2410_SDIDCON);
writel(0, host->base + S3C2410_SDICMDCON);
- writel(0, host->base + host->sdiimsk);
+ clear_imask(host);
if (cmd->data && cmd->error)
cmd->data->error = cmd->error;
--
^ permalink raw reply [flat|nested] 14+ messages in thread
* [patch 06/11] s3cmci: Add debugfs support for examining driver and hardware state.
2009-09-21 13:35 [patch 00/11] s3cmci fixes and updates for current merge window Ben Dooks
` (4 preceding siblings ...)
2009-09-21 13:36 ` [patch 05/11] s3cmci: Fix direct write to interrupt mask Ben Dooks
@ 2009-09-21 13:36 ` Ben Dooks
2009-09-21 13:36 ` [patch 07/11] s3cmci: Add SDIO IRQ support Ben Dooks
` (5 subsequent siblings)
11 siblings, 0 replies; 14+ messages in thread
From: Ben Dooks @ 2009-09-21 13:36 UTC (permalink / raw)
To: linux-mmc, akpm; +Cc: ben-linux
[-- Attachment #1: simtec/pushed/s3cmci-add-debugfs.patch --]
[-- Type: text/plain, Size: 5173 bytes --]
Export driver state and hardware register state via debugfs entries
created under a directory formed from dev_name() on the probed device
when CONFIG_DEBUG_FS is set.
Signed-off-by: Ben Dooks <ben@simtec.co.uk>
---
drivers/mmc/host/s3cmci.c | 126 ++++++++++++++++++++++++++++++++++++++++++++++
drivers/mmc/host/s3cmci.h | 6 ++
2 files changed, 132 insertions(+)
Index: b/drivers/mmc/host/s3cmci.c
===================================================================
--- a/drivers/mmc/host/s3cmci.c 2009-08-04 12:24:02.000000000 +0100
+++ b/drivers/mmc/host/s3cmci.c 2009-08-04 12:24:04.000000000 +0100
@@ -17,6 +17,8 @@
#include <linux/mmc/host.h>
#include <linux/platform_device.h>
#include <linux/cpufreq.h>
+#include <linux/debugfs.h>
+#include <linux/seq_file.h>
#include <linux/gpio.h>
#include <linux/irq.h>
#include <linux/io.h>
@@ -1244,6 +1246,127 @@ static inline void s3cmci_cpufreq_deregi
#endif
+#ifdef CONFIG_DEBUG_FS
+
+static int s3cmci_state_show(struct seq_file *seq, void *v)
+{
+ struct s3cmci_host *host = seq->private;
+
+ seq_printf(seq, "Register base = 0x%08x\n", (u32)host->base);
+ seq_printf(seq, "Clock rate = %ld\n", host->clk_rate);
+ seq_printf(seq, "Prescale = %d\n", host->prescaler);
+ seq_printf(seq, "is2440 = %d\n", host->is2440);
+ seq_printf(seq, "IRQ = %d\n", host->irq);
+ seq_printf(seq, "CD IRQ = %d\n", host->irq_cd);
+ seq_printf(seq, "Do DMA = %d\n", host->dodma);
+ seq_printf(seq, "SDIIMSK at %d\n", host->sdiimsk);
+ seq_printf(seq, "SDIDATA at %d\n", host->sdidata);
+
+ return 0;
+}
+
+static int s3cmci_state_open(struct inode *inode, struct file *file)
+{
+ return single_open(file, s3cmci_state_show, inode->i_private);
+}
+
+static const struct file_operations s3cmci_fops_state = {
+ .owner = THIS_MODULE,
+ .open = s3cmci_state_open,
+ .read = seq_read,
+ .llseek = seq_lseek,
+ .release = single_release,
+};
+
+#define DBG_REG(_r) { .addr = S3C2410_SDI##_r, .name = #_r }
+
+struct s3cmci_reg {
+ unsigned short addr;
+ unsigned char *name;
+} debug_regs[] = {
+ DBG_REG(CON),
+ DBG_REG(PRE),
+ DBG_REG(CMDARG),
+ DBG_REG(CMDCON),
+ DBG_REG(CMDSTAT),
+ DBG_REG(RSP0),
+ DBG_REG(RSP1),
+ DBG_REG(RSP2),
+ DBG_REG(RSP3),
+ DBG_REG(TIMER),
+ DBG_REG(BSIZE),
+ DBG_REG(DCON),
+ DBG_REG(DCNT),
+ DBG_REG(DSTA),
+ DBG_REG(FSTA),
+ {}
+};
+
+static int s3cmci_regs_show(struct seq_file *seq, void *v)
+{
+ struct s3cmci_host *host = seq->private;
+ struct s3cmci_reg *rptr = debug_regs;
+
+ for (; rptr->name; rptr++)
+ seq_printf(seq, "SDI%s\t=0x%08x\n", rptr->name,
+ readl(host->base + rptr->addr));
+
+ seq_printf(seq, "SDIIMSK\t=0x%08x\n", readl(host->base + host->sdiimsk));
+
+ return 0;
+}
+
+static int s3cmci_regs_open(struct inode *inode, struct file *file)
+{
+ return single_open(file, s3cmci_regs_show, inode->i_private);
+}
+
+static const struct file_operations s3cmci_fops_regs = {
+ .owner = THIS_MODULE,
+ .open = s3cmci_regs_open,
+ .read = seq_read,
+ .llseek = seq_lseek,
+ .release = single_release,
+};
+
+static void s3cmci_debugfs_attach(struct s3cmci_host *host)
+{
+ struct device *dev = &host->pdev->dev;
+
+ host->debug_root = debugfs_create_dir(dev_name(dev), NULL);
+ if (IS_ERR(host->debug_root)) {
+ dev_err(dev, "failed to create debugfs root\n");
+ return;
+ }
+
+ host->debug_state = debugfs_create_file("state", 0444,
+ host->debug_root, host,
+ &s3cmci_fops_state);
+
+ if (IS_ERR(host->debug_state))
+ dev_err(dev, "failed to create debug state file\n");
+
+ host->debug_regs = debugfs_create_file("regs", 0444,
+ host->debug_root, host,
+ &s3cmci_fops_regs);
+
+ if (IS_ERR(host->debug_regs))
+ dev_err(dev, "failed to create debug regs file\n");
+}
+
+static void s3cmci_debugfs_remove(struct s3cmci_host *host)
+{
+ debugfs_remove(host->debug_regs);
+ debugfs_remove(host->debug_state);
+ debugfs_remove(host->debug_root);
+}
+
+#else
+static inline void s3cmci_debugfs_attach(struct s3cmci_host *host) { }
+static inline void s3cmci_debugfs_remove(struct s3cmci_host *host) { }
+
+#endif /* CONFIG_DEBUG_FS */
+
static int __devinit s3cmci_probe(struct platform_device *pdev)
{
struct s3cmci_host *host;
@@ -1435,6 +1558,8 @@ static int __devinit s3cmci_probe(struct
goto free_cpufreq;
}
+ s3cmci_debugfs_attach(host);
+
platform_set_drvdata(pdev, mmc);
dev_info(&pdev->dev, "initialisation done.\n");
@@ -1489,6 +1614,7 @@ static void s3cmci_shutdown(struct platf
if (host->irq_cd >= 0)
free_irq(host->irq_cd, host);
+ s3cmci_debugfs_remove(host);
s3cmci_cpufreq_deregister(host);
mmc_remove_host(mmc);
clk_disable(host->clk);
Index: b/drivers/mmc/host/s3cmci.h
===================================================================
--- a/drivers/mmc/host/s3cmci.h 2009-08-04 12:06:01.000000000 +0100
+++ b/drivers/mmc/host/s3cmci.h 2009-08-04 12:24:04.000000000 +0100
@@ -68,6 +68,12 @@ struct s3cmci_host {
unsigned int ccnt, dcnt;
struct tasklet_struct pio_tasklet;
+#ifdef CONFIG_DEBUG_FS
+ struct dentry *debug_root;
+ struct dentry *debug_state;
+ struct dentry *debug_regs;
+#endif
+
#ifdef CONFIG_CPU_FREQ
struct notifier_block freq_transition;
#endif
--
^ permalink raw reply [flat|nested] 14+ messages in thread
* [patch 07/11] s3cmci: Add SDIO IRQ support
2009-09-21 13:35 [patch 00/11] s3cmci fixes and updates for current merge window Ben Dooks
` (5 preceding siblings ...)
2009-09-21 13:36 ` [patch 06/11] s3cmci: Add debugfs support for examining driver and hardware state Ben Dooks
@ 2009-09-21 13:36 ` Ben Dooks
2009-09-21 13:36 ` [patch 08/11] s3cmci: Kconfig selection for PIO/DMA/Both Ben Dooks
` (4 subsequent siblings)
11 siblings, 0 replies; 14+ messages in thread
From: Ben Dooks @ 2009-09-21 13:36 UTC (permalink / raw)
To: linux-mmc, akpm; +Cc: ben-linux
[-- Attachment #1: simtec/pushed/s3cmci-add-sdio-irq.patch --]
[-- Type: text/plain, Size: 8251 bytes --]
The controller supports SDIO IRQ detection so add support for hardware
assisted SDIO interrupt detection for the SDIO core. This improves the
response time for SDIO interrupts and thus the transfer rate from devices
such as the Marvel 8686.
As a note, it does seem that the controller will miss an IRQ than is held
asserted, so there are some manual checks to see if the SDIO interrupt is
active after a transfer.
Major testing on the S3C2440.
Signed-off-by: Ben Dooks <ben@simtec.co.uk>
---
drivers/mmc/host/s3cmci.c | 161 +++++++++++++++++++++++++++++++++++++++++++---
drivers/mmc/host/s3cmci.h | 5 +
2 files changed, 156 insertions(+), 10 deletions(-)
Index: b/drivers/mmc/host/s3cmci.c
===================================================================
--- a/drivers/mmc/host/s3cmci.c 2009-08-12 13:48:31.000000000 +0100
+++ b/drivers/mmc/host/s3cmci.c 2009-08-12 13:55:36.000000000 +0100
@@ -190,7 +190,33 @@ static inline u32 disable_imask(struct s
static inline void clear_imask(struct s3cmci_host *host)
{
- writel(0, host->base + host->sdiimsk);
+ u32 mask = readl(host->base + host->sdiimsk);
+
+ /* preserve the SDIO IRQ mask state */
+ mask &= S3C2410_SDIIMSK_SDIOIRQ;
+ writel(mask, host->base + host->sdiimsk);
+}
+
+/**
+ * s3cmci_check_sdio_irq - test whether the SDIO IRQ is being signalled
+ * @host: The host to check.
+ *
+ * Test to see if the SDIO interrupt is being signalled in case the
+ * controller has failed to re-detect a card interrupt. Read GPE8 and
+ * see if it is low and if so, signal a SDIO interrupt.
+ *
+ * This is currently called if a request is finished (we assume that the
+ * bus is now idle) and when the SDIO IRQ is enabled in case the IRQ is
+ * already being indicated.
+*/
+static void s3cmci_check_sdio_irq(struct s3cmci_host *host)
+{
+ if (host->sdio_irqen) {
+ if (gpio_get_value(S3C2410_GPE(8)) == 0) {
+ printk(KERN_DEBUG "%s: signalling irq\n", __func__);
+ mmc_signal_sdio_irq(host->mmc);
+ }
+ }
}
static inline int get_data_buffer(struct s3cmci_host *host,
@@ -238,6 +264,64 @@ static inline u32 fifo_free(struct s3cmc
return 63 - fifostat;
}
+/**
+ * s3cmci_enable_irq - enable IRQ, after having disabled it.
+ * @host: The device state.
+ * @more: True if more IRQs are expected from transfer.
+ *
+ * Enable the main IRQ if needed after it has been disabled.
+ *
+ * The IRQ can be one of the following states:
+ * - disabled during IDLE
+ * - disabled whilst processing data
+ * - enabled during transfer
+ * - enabled whilst awaiting SDIO interrupt detection
+ */
+static void s3cmci_enable_irq(struct s3cmci_host *host, bool more)
+{
+ unsigned long flags;
+ bool enable = false;
+
+ local_irq_save(flags);
+
+ host->irq_enabled = more;
+ host->irq_disabled = false;
+
+ enable = more | host->sdio_irqen;
+
+ if (host->irq_state != enable) {
+ host->irq_state = enable;
+
+ if (enable)
+ enable_irq(host->irq);
+ else
+ disable_irq(host->irq);
+ }
+
+ local_irq_restore(flags);
+}
+
+/**
+ *
+ */
+static void s3cmci_disable_irq(struct s3cmci_host *host, bool transfer)
+{
+ unsigned long flags;
+
+ local_irq_save(flags);
+
+ //printk(KERN_DEBUG "%s: transfer %d\n", __func__, transfer);
+
+ host->irq_disabled = transfer;
+
+ if (transfer && host->irq_state) {
+ host->irq_state = false;
+ disable_irq(host->irq);
+ }
+
+ local_irq_restore(flags);
+}
+
static void do_pio_read(struct s3cmci_host *host)
{
int res;
@@ -374,8 +458,7 @@ static void pio_tasklet(unsigned long da
{
struct s3cmci_host *host = (struct s3cmci_host *) data;
-
- disable_irq(host->irq);
+ s3cmci_disable_irq(host, true);
if (host->pio_active == XFER_WRITE)
do_pio_write(host);
@@ -395,9 +478,10 @@ static void pio_tasklet(unsigned long da
host->mrq->data->error = -EINVAL;
}
+ s3cmci_enable_irq(host, false);
finalize_request(host);
} else
- enable_irq(host->irq);
+ s3cmci_enable_irq(host, true);
}
/*
@@ -432,17 +516,27 @@ static irqreturn_t s3cmci_irq(int irq, v
struct s3cmci_host *host = dev_id;
struct mmc_command *cmd;
u32 mci_csta, mci_dsta, mci_fsta, mci_dcnt, mci_imsk;
- u32 mci_cclear, mci_dclear;
+ u32 mci_cclear = 0, mci_dclear;
unsigned long iflags;
+ mci_dsta = readl(host->base + S3C2410_SDIDSTA);
+ mci_imsk = readl(host->base + host->sdiimsk);
+
+ if (mci_dsta & S3C2410_SDIDSTA_SDIOIRQDETECT) {
+ if (mci_imsk & S3C2410_SDIIMSK_SDIOIRQ) {
+ mci_dclear = S3C2410_SDIDSTA_SDIOIRQDETECT;
+ writel(mci_dclear, host->base + S3C2410_SDIDSTA);
+
+ mmc_signal_sdio_irq(host->mmc);
+ return IRQ_HANDLED;
+ }
+ }
+
spin_lock_irqsave(&host->complete_lock, iflags);
mci_csta = readl(host->base + S3C2410_SDICMDSTAT);
- mci_dsta = readl(host->base + S3C2410_SDIDSTA);
mci_dcnt = readl(host->base + S3C2410_SDIDCNT);
mci_fsta = readl(host->base + S3C2410_SDIFSTA);
- mci_imsk = readl(host->base + host->sdiimsk);
- mci_cclear = 0;
mci_dclear = 0;
if ((host->complete_what == COMPLETION_NONE) ||
@@ -776,6 +870,8 @@ static void finalize_request(struct s3cm
request_done:
host->complete_what = COMPLETION_NONE;
host->mrq = NULL;
+
+ s3cmci_check_sdio_irq(host);
mmc_request_done(host->mmc, mrq);
}
@@ -1037,7 +1133,7 @@ static void s3cmci_send_request(struct m
s3cmci_send_command(host, cmd);
/* Enable Interrupt */
- enable_irq(host->irq);
+ s3cmci_enable_irq(host, true);
}
static int s3cmci_card_present(struct mmc_host *mmc)
@@ -1178,11 +1274,52 @@ static int s3cmci_get_ro(struct mmc_host
return ret;
}
+static void s3cmci_enable_sdio_irq(struct mmc_host *mmc, int enable)
+{
+ struct s3cmci_host *host = mmc_priv(mmc);
+ unsigned long flags;
+ u32 con;
+
+ local_irq_save(flags);
+
+ con = readl(host->base + S3C2410_SDICON);
+ host->sdio_irqen = enable;
+
+ if (enable == host->sdio_irqen)
+ goto same_state;
+
+ if (enable) {
+ con |= S3C2410_SDICON_SDIOIRQ;
+ enable_imask(host, S3C2410_SDIIMSK_SDIOIRQ);
+
+ if (!host->irq_state && !host->irq_disabled) {
+ host->irq_state = true;
+ enable_irq(host->irq);
+ }
+ } else {
+ disable_imask(host, S3C2410_SDIIMSK_SDIOIRQ);
+ con &= ~S3C2410_SDICON_SDIOIRQ;
+
+ if (!host->irq_enabled && host->irq_state) {
+ disable_irq_nosync(host->irq);
+ host->irq_state = false;
+ }
+ }
+
+ writel(con, host->base + S3C2410_SDICON);
+
+ same_state:
+ local_irq_restore(flags);
+
+ s3cmci_check_sdio_irq(host);
+}
+
static struct mmc_host_ops s3cmci_ops = {
.request = s3cmci_request,
.set_ios = s3cmci_set_ios,
.get_ro = s3cmci_get_ro,
.get_cd = s3cmci_card_present,
+ .enable_sdio_irq = s3cmci_enable_sdio_irq,
};
static struct s3c24xx_mci_pdata s3cmci_def_pdata = {
@@ -1257,6 +1394,9 @@ static int s3cmci_state_show(struct seq_
seq_printf(seq, "Prescale = %d\n", host->prescaler);
seq_printf(seq, "is2440 = %d\n", host->is2440);
seq_printf(seq, "IRQ = %d\n", host->irq);
+ seq_printf(seq, "IRQ enabled = %d\n", host->irq_enabled);
+ seq_printf(seq, "IRQ disabled = %d\n", host->irq_disabled);
+ seq_printf(seq, "IRQ state = %d\n", host->irq_state);
seq_printf(seq, "CD IRQ = %d\n", host->irq_cd);
seq_printf(seq, "Do DMA = %d\n", host->dodma);
seq_printf(seq, "SDIIMSK at %d\n", host->sdiimsk);
@@ -1468,6 +1608,7 @@ static int __devinit s3cmci_probe(struct
* ensure we don't lock the system with un-serviceable requests. */
disable_irq(host->irq);
+ host->irq_state = false;
if (host->pdata->gpio_detect) {
ret = gpio_request(host->pdata->gpio_detect, "s3cmci detect");
@@ -1526,7 +1667,7 @@ static int __devinit s3cmci_probe(struct
mmc->ops = &s3cmci_ops;
mmc->ocr_avail = MMC_VDD_32_33 | MMC_VDD_33_34;
- mmc->caps = MMC_CAP_4_BIT_DATA;
+ mmc->caps = MMC_CAP_4_BIT_DATA | MMC_CAP_SDIO_IRQ;
mmc->f_min = host->clk_rate / (host->clk_div * 256);
mmc->f_max = host->clk_rate / host->clk_div;
Index: b/drivers/mmc/host/s3cmci.h
===================================================================
--- a/drivers/mmc/host/s3cmci.h 2009-08-12 13:48:31.000000000 +0100
+++ b/drivers/mmc/host/s3cmci.h 2009-08-12 13:54:49.000000000 +0100
@@ -42,6 +42,11 @@ struct s3cmci_host {
int dodma;
int dmatogo;
+ bool irq_disabled;
+ bool irq_enabled;
+ bool irq_state;
+ int sdio_irqen;
+
struct mmc_request *mrq;
int cmd_is_stop;
--
^ permalink raw reply [flat|nested] 14+ messages in thread
* [patch 08/11] s3cmci: Kconfig selection for PIO/DMA/Both
2009-09-21 13:35 [patch 00/11] s3cmci fixes and updates for current merge window Ben Dooks
` (6 preceding siblings ...)
2009-09-21 13:36 ` [patch 07/11] s3cmci: Add SDIO IRQ support Ben Dooks
@ 2009-09-21 13:36 ` Ben Dooks
2009-09-21 13:36 ` [patch 09/11] s3cmci: DMA fixes Ben Dooks
` (3 subsequent siblings)
11 siblings, 0 replies; 14+ messages in thread
From: Ben Dooks @ 2009-09-21 13:36 UTC (permalink / raw)
To: linux-mmc, akpm; +Cc: ben-linux
[-- Attachment #1: simtec/pushed/s3cmci-dma-selection.patch --]
[-- Type: text/plain, Size: 5850 bytes --]
Add a selection for the data transfer mode of the s3cmci driver, allowing
for either a configuration or rumtime selection of the use of the DMA or
PIO transfer code.
The PIO only mode is 476 bytes smaller than the driver with both methods
compiled in.
Signed-off-by: Ben Dooks <ben@simtec.co.uk>
---
arch/arm/plat-s3c24xx/include/plat/mci.h | 1
drivers/mmc/host/Kconfig | 34 +++++++++++++++++++++++++++
drivers/mmc/host/s3cmci.c | 39 ++++++++++++++++++++++++-------
3 files changed, 66 insertions(+), 8 deletions(-)
Index: b/drivers/mmc/host/Kconfig
===================================================================
--- a/drivers/mmc/host/Kconfig 2009-09-04 11:03:39.000000000 +0100
+++ b/drivers/mmc/host/Kconfig 2009-09-04 11:26:46.000000000 +0100
@@ -261,6 +261,40 @@ config MMC_S3C
If unsure, say N.
+choice
+ prompt "Samsung S3C SD/MMC transfer code"
+ depends on MMC_S3C
+
+config MMC_S3C_PIO
+ bool "Use PIO transfers only"
+ help
+ Use PIO to transfer data between memory and the hardware.
+
+ PIO is slower than DMA as it requires CPU instructions to
+ move the data. This has been the traditional default for
+ the S3C MCI driver.
+
+config MMC_S3C_DMA
+ bool "Use DMA transfers only (EXPERIMENTAL)"
+ depends on EXPERIMENTAL
+ help
+ Use DMA to transfer data between memory and the hardare.
+
+ Currently, the DMA support in this driver seems to not be
+ working properly and needs to be debugged before this
+ option is useful.
+
+config MMC_S3C_PIODMA
+ bool "Support for both PIO and DMA (EXPERIMENTAL)"
+ help
+ Compile both the PIO and DMA transfer routines into the
+ driver and let the platform select at run-time which one
+ is best.
+
+ See notes for the DMA option.
+
+endchoice
+
config MMC_SDRICOH_CS
tristate "MMC/SD driver for Ricoh Bay1Controllers (EXPERIMENTAL)"
depends on EXPERIMENTAL && PCI && PCMCIA
Index: b/drivers/mmc/host/s3cmci.c
===================================================================
--- a/drivers/mmc/host/s3cmci.c 2009-09-04 11:03:53.000000000 +0100
+++ b/drivers/mmc/host/s3cmci.c 2009-09-04 11:26:17.000000000 +0100
@@ -164,6 +164,25 @@ static void dbg_dumpregs(struct s3cmci_h
#endif /* CONFIG_MMC_DEBUG */
+/**
+ * s3cmci_host_usedma - return whether the host is using dma or pio
+ * @host: The host state
+ *
+ * Return true if the host is using DMA to transfer data, else false
+ * to use PIO mode. Will return static data depending on the driver
+ * configuration.
+ */
+static inline bool s3cmci_host_usedma(struct s3cmci_host *host)
+{
+#ifdef CONFIG_MMC_S3C_PIO
+ return false;
+#elif defined(CONFIG_MMC_S3C_DMA)
+ return true;
+#else
+ return host->dodma;
+#endif
+}
+
static inline u32 enable_imask(struct s3cmci_host *host, u32 imask)
{
u32 newmask;
@@ -560,7 +579,7 @@ static irqreturn_t s3cmci_irq(int irq, v
goto irq_out;
}
- if (!host->dodma) {
+ if (!s3cmci_host_usedma(host)) {
if ((host->pio_active == XFER_WRITE) &&
(mci_fsta & S3C2410_SDIFSTA_TFDET)) {
@@ -796,7 +815,7 @@ static void finalize_request(struct s3cm
if (cmd->data && (cmd->error == 0) &&
(cmd->data->error == 0)) {
- if (host->dodma && (!host->dma_complete)) {
+ if (s3cmci_host_usedma(host) && (!host->dma_complete)) {
dbg(host, dbg_dma, "DMA Missing!\n");
return;
}
@@ -848,7 +867,7 @@ static void finalize_request(struct s3cm
/* If we had an error while transfering data we flush the
* DMA channel and the fifo to clear out any garbage. */
if (mrq->data->error != 0) {
- if (host->dodma)
+ if (s3cmci_host_usedma(host))
s3c2410_dma_ctrl(host->dma, S3C2410_DMAOP_FLUSH);
if (host->is2440) {
@@ -968,7 +987,7 @@ static int s3cmci_setup_data(struct s3cm
dcon = data->blocks & S3C2410_SDIDCON_BLKNUM_MASK;
- if (host->dodma)
+ if (s3cmci_host_usedma(host))
dcon |= S3C2410_SDIDCON_DMAEN;
if (host->bus_width == MMC_BUS_WIDTH_4)
@@ -1114,7 +1133,7 @@ static void s3cmci_send_request(struct m
return;
}
- if (host->dodma)
+ if (s3cmci_host_usedma(host))
res = s3cmci_prepare_dma(host, cmd->data);
else
res = s3cmci_prepare_pio(host, cmd->data);
@@ -1398,7 +1417,7 @@ static int s3cmci_state_show(struct seq_
seq_printf(seq, "IRQ disabled = %d\n", host->irq_disabled);
seq_printf(seq, "IRQ state = %d\n", host->irq_state);
seq_printf(seq, "CD IRQ = %d\n", host->irq_cd);
- seq_printf(seq, "Do DMA = %d\n", host->dodma);
+ seq_printf(seq, "Do DMA = %d\n", s3cmci_host_usedma(host));
seq_printf(seq, "SDIIMSK at %d\n", host->sdiimsk);
seq_printf(seq, "SDIDATA at %d\n", host->sdidata);
@@ -1559,12 +1578,15 @@ static int __devinit s3cmci_probe(struct
host->clk_div = 2;
}
- host->dodma = 0;
host->complete_what = COMPLETION_NONE;
host->pio_active = XFER_NONE;
host->dma = S3CMCI_DMA;
+#ifdef CONFIG_MMC_S3C_PIODMA
+ host->dodma = host->pdata->dma;
+#endif
+
host->mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
if (!host->mem) {
dev_err(&pdev->dev,
@@ -1702,7 +1724,8 @@ static int __devinit s3cmci_probe(struct
s3cmci_debugfs_attach(host);
platform_set_drvdata(pdev, mmc);
- dev_info(&pdev->dev, "initialisation done.\n");
+ dev_info(&pdev->dev, "%s - using %s\n", mmc_hostname(mmc),
+ s3cmci_host_usedma(host) ? "dma" : "pio");
return 0;
Index: b/arch/arm/plat-s3c24xx/include/plat/mci.h
===================================================================
--- a/arch/arm/plat-s3c24xx/include/plat/mci.h 2009-06-10 04:05:27.000000000 +0100
+++ b/arch/arm/plat-s3c24xx/include/plat/mci.h 2009-09-04 11:03:53.000000000 +0100
@@ -4,6 +4,7 @@
struct s3c24xx_mci_pdata {
unsigned int wprotect_invert : 1;
unsigned int detect_invert : 1; /* set => detect active high. */
+ unsigned int use_dma : 1;
unsigned int gpio_detect;
unsigned int gpio_wprotect;
--
^ permalink raw reply [flat|nested] 14+ messages in thread
* [patch 09/11] s3cmci: DMA fixes
2009-09-21 13:35 [patch 00/11] s3cmci fixes and updates for current merge window Ben Dooks
` (7 preceding siblings ...)
2009-09-21 13:36 ` [patch 08/11] s3cmci: Kconfig selection for PIO/DMA/Both Ben Dooks
@ 2009-09-21 13:36 ` Ben Dooks
2009-09-21 13:36 ` [patch 10/11] s3cmci: Make SDIO IRQ hardware IRQ support build-time configurable Ben Dooks
` (2 subsequent siblings)
11 siblings, 0 replies; 14+ messages in thread
From: Ben Dooks @ 2009-09-21 13:36 UTC (permalink / raw)
To: linux-mmc, akpm; +Cc: ben-linux
[-- Attachment #1: simtec/pushed/s3cmci-dma-fixes.patch --]
[-- Type: text/plain, Size: 5885 bytes --]
Fixes for the DMA transfer mode of the driver to try and improve the
state of the code:
- Ensure that dma_complete is set during the end of the command phase
so that transfers do not stall awaiting the completion
- Update the DMA debugging to provide a bit more useful information
such as how many DMA descriptors where not processed and print the
DMA addresses in hexadecimal.
- Fix the DMA channel request code to actually request DMA for the
S3CMCI block instead of whatever '0' signified.
- Add fallback to PIO if we cannot get the DMA channel, as many of the
devices with this block only have a limited number of DMA channels.
- Only try and claim and free the DMA channel if we are trying to use it.
This improves the driver DMA code to the point where it can now identify
a card and read the partition table. However the DMA can still stall when
trying to move data between the host and memory.
Signed-off-by: Ben Dooks <ben@simtec.co.uk>
---
drivers/mmc/host/s3cmci.c | 62 ++++++++++++++++++++++++++++++++++------------
drivers/mmc/host/s3cmci.h | 3 --
2 files changed, 47 insertions(+), 18 deletions(-)
Index: b/drivers/mmc/host/s3cmci.c
===================================================================
--- a/drivers/mmc/host/s3cmci.c 2009-08-12 13:55:53.000000000 +0100
+++ b/drivers/mmc/host/s3cmci.c 2009-08-12 13:59:28.000000000 +0100
@@ -183,6 +183,21 @@ static inline bool s3cmci_host_usedma(st
#endif
}
+/**
+ * s3cmci_host_canpio - return true if host has pio code available
+ *
+ * Return true if the driver has been compiled with the PIO support code
+ * available.
+ */
+static inline bool s3cmci_host_canpio(void)
+{
+#ifdef CONFIG_MMC_S3C_PIO
+ return true;
+#else
+ return false;
+#endif
+}
+
static inline u32 enable_imask(struct s3cmci_host *host, u32 imask)
{
u32 newmask;
@@ -786,6 +801,7 @@ static void s3cmci_dma_done_callback(str
dbg(host, dbg_dma, "DMA FINISHED Size:%i DSTA:%08x DCNT:%08x\n",
size, mci_dsta, mci_dcnt);
+ host->dma_complete = 1;
host->complete_what = COMPLETION_FINALIZE;
out:
@@ -816,7 +832,8 @@ static void finalize_request(struct s3cm
if (cmd->data && (cmd->error == 0) &&
(cmd->data->error == 0)) {
if (s3cmci_host_usedma(host) && (!host->dma_complete)) {
- dbg(host, dbg_dma, "DMA Missing!\n");
+ dbg(host, dbg_dma, "DMA Missing (%d)!\n",
+ host->dma_complete);
return;
}
}
@@ -1065,7 +1082,7 @@ static int s3cmci_prepare_pio(struct s3c
static int s3cmci_prepare_dma(struct s3cmci_host *host, struct mmc_data *data)
{
int dma_len, i;
- int rw = (data->flags & MMC_DATA_WRITE) ? 1 : 0;
+ int rw = data->flags & MMC_DATA_WRITE;
BUG_ON((data->flags & BOTH_DIR) == BOTH_DIR);
@@ -1073,7 +1090,7 @@ static int s3cmci_prepare_dma(struct s3c
s3c2410_dma_ctrl(host->dma, S3C2410_DMAOP_FLUSH);
dma_len = dma_map_sg(mmc_dev(host->mmc), data->sg, data->sg_len,
- (rw) ? DMA_TO_DEVICE : DMA_FROM_DEVICE);
+ rw ? DMA_TO_DEVICE : DMA_FROM_DEVICE);
if (dma_len == 0)
return -ENOMEM;
@@ -1084,11 +1101,11 @@ static int s3cmci_prepare_dma(struct s3c
for (i = 0; i < dma_len; i++) {
int res;
- dbg(host, dbg_dma, "enqueue %i:%u@%u\n", i,
- sg_dma_address(&data->sg[i]),
- sg_dma_len(&data->sg[i]));
+ dbg(host, dbg_dma, "enqueue %i: %08x@%u\n", i,
+ sg_dma_address(&data->sg[i]),
+ sg_dma_len(&data->sg[i]));
- res = s3c2410_dma_enqueue(host->dma, (void *) host,
+ res = s3c2410_dma_enqueue(host->dma, host,
sg_dma_address(&data->sg[i]),
sg_dma_len(&data->sg[i]));
@@ -1581,8 +1598,6 @@ static int __devinit s3cmci_probe(struct
host->complete_what = COMPLETION_NONE;
host->pio_active = XFER_NONE;
- host->dma = S3CMCI_DMA;
-
#ifdef CONFIG_MMC_S3C_PIODMA
host->dodma = host->pdata->dma;
#endif
@@ -1665,10 +1680,21 @@ static int __devinit s3cmci_probe(struct
gpio_direction_input(host->pdata->gpio_wprotect);
}
- if (s3c2410_dma_request(S3CMCI_DMA, &s3cmci_dma_client, NULL) < 0) {
- dev_err(&pdev->dev, "unable to get DMA channel.\n");
- ret = -EBUSY;
- goto probe_free_gpio_wp;
+ /* depending on the dma state, get a dma channel to use. */
+
+ if (s3cmci_host_usedma(host)) {
+ host->dma = s3c2410_dma_request(DMACH_SDI, &s3cmci_dma_client,
+ host);
+ if (host->dma < 0) {
+ dev_err(&pdev->dev, "cannot get DMA channel.\n");
+ if (!s3cmci_host_canpio()) {
+ ret = -EBUSY;
+ goto probe_free_gpio_wp;
+ } else {
+ dev_warn(&pdev->dev, "falling back to PIO.\n");
+ host->dodma = 0;
+ }
+ }
}
host->clk = clk_get(&pdev->dev, "sdi");
@@ -1676,7 +1702,7 @@ static int __devinit s3cmci_probe(struct
dev_err(&pdev->dev, "failed to find clock source.\n");
ret = PTR_ERR(host->clk);
host->clk = NULL;
- goto probe_free_host;
+ goto probe_free_dma;
}
ret = clk_enable(host->clk);
@@ -1738,6 +1764,10 @@ static int __devinit s3cmci_probe(struct
clk_free:
clk_put(host->clk);
+ probe_free_dma:
+ if (s3cmci_host_usedma(host))
+ s3c2410_dma_free(host->dma, &s3cmci_dma_client);
+
probe_free_gpio_wp:
if (host->pdata->gpio_wprotect)
gpio_free(host->pdata->gpio_wprotect);
@@ -1796,7 +1826,9 @@ static int __devexit s3cmci_remove(struc
clk_put(host->clk);
tasklet_disable(&host->pio_tasklet);
- s3c2410_dma_free(S3CMCI_DMA, &s3cmci_dma_client);
+
+ if (s3cmci_host_usedma(host))
+ s3c2410_dma_free(host->dma, &s3cmci_dma_client);
free_irq(host->irq, host);
Index: b/drivers/mmc/host/s3cmci.h
===================================================================
--- a/drivers/mmc/host/s3cmci.h 2009-08-12 13:54:49.000000000 +0100
+++ b/drivers/mmc/host/s3cmci.h 2009-08-12 13:59:28.000000000 +0100
@@ -8,9 +8,6 @@
* published by the Free Software Foundation.
*/
-/* FIXME: DMA Resource management ?! */
-#define S3CMCI_DMA 0
-
enum s3cmci_waitfor {
COMPLETION_NONE,
COMPLETION_FINALIZE,
--
^ permalink raw reply [flat|nested] 14+ messages in thread
* [patch 10/11] s3cmci: Make SDIO IRQ hardware IRQ support build-time configurable.
2009-09-21 13:35 [patch 00/11] s3cmci fixes and updates for current merge window Ben Dooks
` (8 preceding siblings ...)
2009-09-21 13:36 ` [patch 09/11] s3cmci: DMA fixes Ben Dooks
@ 2009-09-21 13:36 ` Ben Dooks
2009-09-21 13:36 ` [patch 11/11] s3cmci: Add better support for no card detect or write protect available Ben Dooks
2009-09-29 22:56 ` [patch 00/11] s3cmci fixes and updates for current merge window Andrew Morton
11 siblings, 0 replies; 14+ messages in thread
From: Ben Dooks @ 2009-09-21 13:36 UTC (permalink / raw)
To: linux-mmc, akpm; +Cc: ben-linux
[-- Attachment #1: simtec/ready/s3cmci-build-configurable-sdio-hwirq.patch --]
[-- Type: text/plain, Size: 2014 bytes --]
We have found a couple of boards where the SDIO IRQ hardware support
has failed to work properly, and thus we should make it configurable
whether or not to be included in the driver.
Signed-off-by: Ben Dooks <ben@simtec.co.uk>
---
drivers/mmc/host/Kconfig | 7 +++++++
drivers/mmc/host/s3cmci.c | 9 +++++++--
2 files changed, 14 insertions(+), 2 deletions(-)
Index: b/drivers/mmc/host/s3cmci.c
===================================================================
--- a/drivers/mmc/host/s3cmci.c 2009-09-10 12:27:38.000000000 +0100
+++ b/drivers/mmc/host/s3cmci.c 2009-09-10 15:48:15.000000000 +0100
@@ -1715,7 +1715,11 @@ static int __devinit s3cmci_probe(struct
mmc->ops = &s3cmci_ops;
mmc->ocr_avail = MMC_VDD_32_33 | MMC_VDD_33_34;
+#ifdef CONFIG_MMC_S3C_HW_SDIO_IRQ
mmc->caps = MMC_CAP_4_BIT_DATA | MMC_CAP_SDIO_IRQ;
+#else
+ mmc->caps = MMC_CAP_4_BIT_DATA;
+#endif
mmc->f_min = host->clk_rate / (host->clk_div * 256);
mmc->f_max = host->clk_rate / host->clk_div;
@@ -1750,8 +1754,9 @@ static int __devinit s3cmci_probe(struct
s3cmci_debugfs_attach(host);
platform_set_drvdata(pdev, mmc);
- dev_info(&pdev->dev, "%s - using %s\n", mmc_hostname(mmc),
- s3cmci_host_usedma(host) ? "dma" : "pio");
+ dev_info(&pdev->dev, "%s - using %s, %s SDIO IRQ\n", mmc_hostname(mmc),
+ s3cmci_host_usedma(host) ? "dma" : "pio",
+ mmc->caps & MMC_CAP_SDIO_IRQ ? "hw" : "sw");
return 0;
Index: b/drivers/mmc/host/Kconfig
===================================================================
--- a/drivers/mmc/host/Kconfig 2009-09-10 15:43:29.000000000 +0100
+++ b/drivers/mmc/host/Kconfig 2009-09-10 15:45:10.000000000 +0100
@@ -261,6 +261,13 @@ config MMC_S3C
If unsure, say N.
+config MMC_S3C_HW_SDIO_IRQ
+ bool "Hardware support for SDIO IRQ"
+ depends on MMC_S3C
+ help
+ Enable the hardware support for SDIO interrupts instead of using
+ the generic polling code.
+
choice
prompt "Samsung S3C SD/MMC transfer code"
depends on MMC_S3C
--
^ permalink raw reply [flat|nested] 14+ messages in thread
* [patch 11/11] s3cmci: Add better support for no card detect or write protect available.
2009-09-21 13:35 [patch 00/11] s3cmci fixes and updates for current merge window Ben Dooks
` (9 preceding siblings ...)
2009-09-21 13:36 ` [patch 10/11] s3cmci: Make SDIO IRQ hardware IRQ support build-time configurable Ben Dooks
@ 2009-09-21 13:36 ` Ben Dooks
2009-09-29 22:56 ` [patch 00/11] s3cmci fixes and updates for current merge window Andrew Morton
11 siblings, 0 replies; 14+ messages in thread
From: Ben Dooks @ 2009-09-21 13:36 UTC (permalink / raw)
To: linux-mmc, akpm; +Cc: ben-linux
[-- Attachment #1: simtec/ready/s3cmci-add-nogpio.patch --]
[-- Type: text/plain, Size: 3862 bytes --]
Add better support for omitting either the card detect or the write protect
GPIOs if the board does not support it. Add the fields no_wprotect and
no_detect to the platform data which when set indicate the absence of the
respective GPIOs.
Note, this also fixes a minor bug where it tries to free IRQ0 if there is
no detect gpio available.
Signed-off-by: Ben Dooks <ben@simtec.co.uk>
---
arch/arm/plat-s3c24xx/include/plat/mci.h | 2 +
drivers/mmc/host/s3cmci.c | 44 ++++++++++++++++---------------
2 files changed, 26 insertions(+), 20 deletions(-)
Index: b/arch/arm/plat-s3c24xx/include/plat/mci.h
===================================================================
--- a/arch/arm/plat-s3c24xx/include/plat/mci.h 2009-09-16 16:03:32.000000000 +0100
+++ b/arch/arm/plat-s3c24xx/include/plat/mci.h 2009-09-16 16:04:15.000000000 +0100
@@ -2,6 +2,8 @@
#define _ARCH_MCI_H
struct s3c24xx_mci_pdata {
+ unsigned int no_wprotect : 1;
+ unsigned int no_detect : 1;
unsigned int wprotect_invert : 1;
unsigned int detect_invert : 1; /* set => detect active high. */
unsigned int use_dma : 1;
Index: b/drivers/mmc/host/s3cmci.c
===================================================================
--- a/drivers/mmc/host/s3cmci.c 2009-09-16 16:03:32.000000000 +0100
+++ b/drivers/mmc/host/s3cmci.c 2009-09-16 16:10:15.000000000 +0100
@@ -1299,7 +1299,7 @@ static int s3cmci_get_ro(struct mmc_host
struct s3c24xx_mci_pdata *pdata = host->pdata;
int ret;
- if (pdata->gpio_wprotect == 0)
+ if (pdata->no_wprotect)
return 0;
ret = s3c2410_gpio_getpin(pdata->gpio_wprotect);
@@ -1647,30 +1647,34 @@ static int __devinit s3cmci_probe(struct
disable_irq(host->irq);
host->irq_state = false;
- if (host->pdata->gpio_detect) {
+ if (!host->pdata->no_detect) {
ret = gpio_request(host->pdata->gpio_detect, "s3cmci detect");
if (ret) {
dev_err(&pdev->dev, "failed to get detect gpio\n");
goto probe_free_irq;
}
- }
- host->irq_cd = s3c2410_gpio_getirq(host->pdata->gpio_detect);
+ host->irq_cd = s3c2410_gpio_getirq(host->pdata->gpio_detect);
- if (host->irq_cd >= 0) {
- if (request_irq(host->irq_cd, s3cmci_irq_cd,
- IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING,
- DRIVER_NAME, host)) {
- dev_err(&pdev->dev, "can't get card detect irq.\n");
- ret = -ENOENT;
- goto probe_free_gpio_cd;
+ if (host->irq_cd >= 0) {
+ if (request_irq(host->irq_cd, s3cmci_irq_cd,
+ IRQF_TRIGGER_RISING |
+ IRQF_TRIGGER_FALLING,
+ DRIVER_NAME, host)) {
+ dev_err(&pdev->dev,
+ "can't get card detect irq.\n");
+ ret = -ENOENT;
+ goto probe_free_gpio_cd;
+ }
+ } else {
+ dev_warn(&pdev->dev,
+ "host detect has no irq available\n");
+ gpio_direction_input(host->pdata->gpio_detect);
}
- } else {
- dev_warn(&pdev->dev, "host detect has no irq available\n");
- gpio_direction_input(host->pdata->gpio_detect);
- }
+ } else
+ host->irq_cd = -1;
- if (host->pdata->gpio_wprotect) {
+ if (!host->pdata->no_wprotect) {
ret = gpio_request(host->pdata->gpio_wprotect, "s3cmci wp");
if (ret) {
dev_err(&pdev->dev, "failed to get writeprotect\n");
@@ -1774,11 +1778,11 @@ static int __devinit s3cmci_probe(struct
s3c2410_dma_free(host->dma, &s3cmci_dma_client);
probe_free_gpio_wp:
- if (host->pdata->gpio_wprotect)
+ if (!host->pdata->no_wprotect)
gpio_free(host->pdata->gpio_wprotect);
probe_free_gpio_cd:
- if (host->pdata->gpio_detect)
+ if (!host->pdata->no_detect)
gpio_free(host->pdata->gpio_detect);
probe_free_irq_cd:
@@ -1837,10 +1841,10 @@ static int __devexit s3cmci_remove(struc
free_irq(host->irq, host);
- if (pd->gpio_wprotect)
+ if (!pd->no_wprotect)
gpio_free(pd->gpio_wprotect);
- if (pd->gpio_detect)
+ if (!pd->no_detect)
gpio_free(pd->gpio_detect);
for (i = S3C2410_GPE(5); i <= S3C2410_GPE(10); i++)
--
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [patch 00/11] s3cmci fixes and updates for current merge window
2009-09-21 13:35 [patch 00/11] s3cmci fixes and updates for current merge window Ben Dooks
` (10 preceding siblings ...)
2009-09-21 13:36 ` [patch 11/11] s3cmci: Add better support for no card detect or write protect available Ben Dooks
@ 2009-09-29 22:56 ` Andrew Morton
2009-10-02 6:50 ` Ben Dooks
11 siblings, 1 reply; 14+ messages in thread
From: Andrew Morton @ 2009-09-29 22:56 UTC (permalink / raw)
To: Ben Dooks; +Cc: linux-mmc, ben-linux
On Mon, 21 Sep 2009 14:35:55 +0100
Ben Dooks <ben@simtec.co.uk> wrote:
> This is a set of the s3cmci updates and fixes for the current merge
> window. It is a resend of an updated version of a series posted a
> few weeks ago, which I could not find queued anywhere.
>
Sending a pile of stuff in the middle of the merge window is rather
late for "the current merge window"!
And this patch series is a mishmash of features and bugfixes.
Ho hum, OK, I'll slam it in. It's not good practice though.
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [patch 00/11] s3cmci fixes and updates for current merge window
2009-09-29 22:56 ` [patch 00/11] s3cmci fixes and updates for current merge window Andrew Morton
@ 2009-10-02 6:50 ` Ben Dooks
0 siblings, 0 replies; 14+ messages in thread
From: Ben Dooks @ 2009-10-02 6:50 UTC (permalink / raw)
To: Andrew Morton; +Cc: linux-mmc, ben-linux
Andrew Morton wrote:
> On Mon, 21 Sep 2009 14:35:55 +0100
> Ben Dooks <ben@simtec.co.uk> wrote:
>
>> This is a set of the s3cmci updates and fixes for the current merge
>> window. It is a resend of an updated version of a series posted a
>> few weeks ago, which I could not find queued anywhere.
>>
>
> Sending a pile of stuff in the middle of the merge window is rather
> late for "the current merge window"!
Sorry, but pretty much all of this was posted on the 18th of August
and no-one bothered to comment.
> And this patch series is a mishmash of features and bugfixes.
Since none of this was regression fixes I thought it wasn't
stuff that should have been submitted earlier.
For example, the DMA fixes are in code that hasn't been used in the driver
for ages, the rest are more cleanup than fix.
--
Ben Dooks, Software Engineer, Simtec Electronics
http://www.simtec.co.uk/
^ permalink raw reply [flat|nested] 14+ messages in thread
end of thread, other threads:[~2009-10-02 6:50 UTC | newest]
Thread overview: 14+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2009-09-21 13:35 [patch 00/11] s3cmci fixes and updates for current merge window Ben Dooks
2009-09-21 13:35 ` [patch 01/11] s3cmci: Use resource_size() instead of local macro Ben Dooks
2009-09-21 13:35 ` [patch 02/11] s3cmci: update probe to use new platform id list Ben Dooks
2009-09-21 13:35 ` [patch 03/11] s3cmci: Change GPIO to gpiolib from S3C24XX specific calls Ben Dooks
2009-09-21 13:35 ` [patch 04/11] s3cmci: Change to use dev_pm_ops Ben Dooks
2009-09-21 13:36 ` [patch 05/11] s3cmci: Fix direct write to interrupt mask Ben Dooks
2009-09-21 13:36 ` [patch 06/11] s3cmci: Add debugfs support for examining driver and hardware state Ben Dooks
2009-09-21 13:36 ` [patch 07/11] s3cmci: Add SDIO IRQ support Ben Dooks
2009-09-21 13:36 ` [patch 08/11] s3cmci: Kconfig selection for PIO/DMA/Both Ben Dooks
2009-09-21 13:36 ` [patch 09/11] s3cmci: DMA fixes Ben Dooks
2009-09-21 13:36 ` [patch 10/11] s3cmci: Make SDIO IRQ hardware IRQ support build-time configurable Ben Dooks
2009-09-21 13:36 ` [patch 11/11] s3cmci: Add better support for no card detect or write protect available Ben Dooks
2009-09-29 22:56 ` [patch 00/11] s3cmci fixes and updates for current merge window Andrew Morton
2009-10-02 6:50 ` Ben Dooks
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).