From: David Brownell <[EMAIL PROTECTED]>
Inital support for new MMC init logic, where boards can say how
to initialize what, and also provide functions to sense card
detect and writeprotect switches. This also removes some
static driver configuration forcing it to always use 4-bit
parallel data channels; boards can now override that.
This patch stubs in support for the two EVM boards with MMC/SD
support, equivalent to current behavior ... later patches will
update these. SFFSDR presumably needs something too.
Note that this doesn't currently handle card detect IRQs.
Signed-off-by: David Brownell <[EMAIL PROTECTED]>
---
Goes on top of other patches I've posted, notably the devices.c
update to create both mmc0 and mmc1 on dm355, and the watchdog
device creation patch.
arch/arm/mach-davinci/board-dm355-evm.c | 2 +
arch/arm/mach-davinci/board-dm644x-evm.c | 3 +
arch/arm/mach-davinci/devices.c | 42 +++++++++++++++++----------
arch/arm/mach-davinci/include/mach/board.h | 9 +++++
drivers/mmc/host/davinci_mmc.c | 40 ++++++++++++++++++-------
drivers/mmc/host/davinci_mmc.h | 3 -
6 files changed, 70 insertions(+), 29 deletions(-)
--- a/arch/arm/mach-davinci/board-dm355-evm.c
+++ b/arch/arm/mach-davinci/board-dm355-evm.c
@@ -65,6 +65,8 @@ static __init void dm355_evm_init(void)
davinci_board_config_size = ARRAY_SIZE(davinci_evm_config);
davinci_serial_init();
+ davinci_setup_mmc(0, NULL);
+ davinci_setup_mmc(1, NULL);
}
static __init void dm355_evm_irq_init(void)
--- a/arch/arm/mach-davinci/board-dm644x-evm.c
+++ b/arch/arm/mach-davinci/board-dm644x-evm.c
@@ -508,6 +508,9 @@ static __init void davinci_evm_init(void
platform_add_devices(davinci_evm_devices,
ARRAY_SIZE(davinci_evm_devices));
evm_init_i2c();
+
+ davinci_setup_mmc(0, NULL);
+
davinci_board_config = davinci_evm_config;
davinci_board_config_size = ARRAY_SIZE(davinci_evm_config);
davinci_serial_init();
--- a/arch/arm/mach-davinci/devices.c
+++ b/arch/arm/mach-davinci/devices.c
@@ -22,6 +22,7 @@
#include <asm/mach-types.h>
#include <asm/mach/map.h>
+#include <mach/board.h>
#include <mach/hardware.h>
#include <mach/edma.h>
#include <mach/emac.h>
@@ -138,35 +139,47 @@ static struct platform_device davinci_mm
};
-static void davinci_init_mmcsd(void)
+void __init davinci_setup_mmc(int module, struct davinci_mmc_config *config)
{
- if (cpu_is_davinci_dm646x())
+ struct platform_device *pdev = NULL;
+ const char *clockname;
+
+ if (WARN_ON(cpu_is_davinci_dm646x()))
return;
- /* FIXME: only register devices the board tells are wired up.
- * And update PINMUX, ARM_IRQMUX, and EDMA_EVTMUX here too;
+ /* REVISIT: update PINMUX, ARM_IRQMUX, and EDMA_EVTMUX here too;
* for example if MMCSD1 is used for SDIO, maybe DAT2 is unused.
*
* FIXME dm6441 (no MMC/SD), dm357 (one), and dm335 (two) are
* not handled right here ...
*/
- if (cpu_is_davinci_dm355()) {
- davinci_clk_associate(&davinci_mmcsd1_device.dev, "mmc",
- "MMCSDCLK1");
- platform_device_register(&davinci_mmcsd1_device);
+ switch (module) {
+ case 1:
+ if (!cpu_is_davinci_dm355())
+ break;
mmcsd0_resources[2].start = IRQ_DM355_SDIOINT0;
+ pdev = &davinci_mmcsd1_device;
+ clockname = "MMCSDCLK1";
+ break;
+ case 0:
+ pdev = &davinci_mmcsd0_device;
+ clockname = cpu_is_davinci_dm355() ? "MMCSDCLK0" : "MMCSDCLK";
+ break;
}
- davinci_clk_associate(&davinci_mmcsd0_device.dev, "mmc",
- cpu_is_davinci_dm355()
- ? "MMCSDCLK0"
- : "MMCSDCLK");
- platform_device_register(&davinci_mmcsd0_device);
+ if (WARN_ON(!pdev))
+ return;
+
+ pdev->dev.platform_data = config;
+ davinci_clk_associate(&pdev->dev, "mmc", clockname);
+ platform_device_register(pdev);
}
#else
-static void davinci_init_mmcsd(void) {}
+void __init davinci_setup_mmc(int module, struct davinci_mmc_config *config)
+{
+}
#endif
@@ -303,7 +316,6 @@ static int __init davinci_init_devices(v
/* please keep these calls, and their implementations above,
* in alphabetical order so they're easier to sort through.
*/
- davinci_init_mmcsd();
davinci_init_wdt();
return 0;
--- a/arch/arm/mach-davinci/include/mach/board.h
+++ b/arch/arm/mach-davinci/include/mach/board.h
@@ -25,6 +25,15 @@ struct davinci_uart_config {
unsigned int enabled_uarts;
};
+struct davinci_mmc_config {
+ /* get_cd()/get_wp() may sleep */
+ int (*get_cd)(int module);
+ int (*get_ro)(int module);
+ /* wires == 0 is equivalent to wires == 4 (4-bit parallel) */
+ u8 wires;
+};
+void davinci_setup_mmc(int module, struct davinci_mmc_config *config);
+
struct davinci_board_config_entry {
u16 tag;
u16 len;
--- a/drivers/mmc/host/davinci_mmc.c
+++ b/drivers/mmc/host/davinci_mmc.c
@@ -42,6 +42,7 @@
#include <linux/delay.h>
#include <linux/dma-mapping.h>
+#include <mach/board.h>
#include <mach/hardware.h>
#include <mach/irqs.h>
#include <mach/hardware.h>
@@ -68,8 +69,6 @@ static struct mmcsd_config_def mmcsd_cfg
32,
/* To use the DMA or not-- 1- Use DMA, 0-Interrupt mode */
1,
-/* flag Indicates 1bit/4bit mode */
- 1
};
#define RSP_TYPE(x) ((x) & ~(MMC_RSP_BUSY|MMC_RSP_OPCODE))
@@ -1189,17 +1188,33 @@ static irqreturn_t mmc_davinci_irq(int i
return IRQ_HANDLED;
}
-static struct mmc_host_ops mmc_davinci_ops = {
- .request = mmc_davinci_request,
- .set_ios = mmc_davinci_set_ios,
- .get_ro = mmc_davinci_get_ro
-};
+static int mmc_davinci_get_cd(struct mmc_host *mmc)
+{
+ struct platform_device *pdev = to_platform_device(mmc->parent);
+ struct davinci_mmc_config *config = pdev->dev.platform_data;
+
+ if (!config || !config->get_cd)
+ return -ENOSYS;
+ return config->get_cd(pdev->id);
+}
static int mmc_davinci_get_ro(struct mmc_host *mmc)
{
- return 0;
+ struct platform_device *pdev = to_platform_device(mmc->parent);
+ struct davinci_mmc_config *config = pdev->dev.platform_data;
+
+ if (!config || !config->get_ro)
+ return -ENOSYS;
+ return config->get_ro(pdev->id);
}
+static struct mmc_host_ops mmc_davinci_ops = {
+ .request = mmc_davinci_request,
+ .set_ios = mmc_davinci_set_ios,
+ .get_cd = mmc_davinci_get_cd,
+ .get_ro = mmc_davinci_get_ro,
+};
+
static void mmc_check_card(unsigned long data)
{
struct mmc_davinci_host *host = (struct mmc_davinci_host *)data;
@@ -1290,12 +1305,15 @@ static void init_mmcsd_host(struct mmc_d
static int davinci_mmcsd_probe(struct platform_device *pdev)
{
+ struct davinci_mmc_config *pdata = pdev->dev.platform_data;
struct mmc_davinci_host *host = NULL;
struct mmc_host *mmc = NULL;
struct resource *r, *mem = NULL;
int ret = 0, irq = 0;
size_t mem_size;
+ /* REVISIT: when we're fully converted, fail if pdata is NULL */
+
ret = -ENODEV;
r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
irq = platform_get_irq(pdev, 0);
@@ -1345,7 +1363,7 @@ static int davinci_mmcsd_probe(struct pl
init_mmcsd_host(host);
- if (mmcsd_cfg.use_4bit_mode)
+ if (!pdata || pdata->wires == 4 || pdata->wires == 0)
mmc->caps |= MMC_CAP_4_BIT_DATA;
mmc->ops = &mmc_davinci_ops;
@@ -1401,8 +1419,8 @@ static int davinci_mmcsd_probe(struct pl
mod_timer(&host->timer, jiffies + MULTIPILER_TO_HZ * HZ);
dev_info(mmc_dev(host->mmc), "Using %s, %d-bit mode\n",
- mmcsd_cfg.use_dma ? "DMA" : "PIO",
- mmcsd_cfg.use_4bit_mode ? 4 : 1);
+ mmcsd_cfg.use_dma ? "DMA" : "PIO",
+ (mmc->caps & MMC_CAP_4_BIT_DATA) ? 4 : 1);
return 0;
--- a/drivers/mmc/host/davinci_mmc.h
+++ b/drivers/mmc/host/davinci_mmc.h
@@ -230,7 +230,6 @@ struct mmc_davinci_host {
struct mmcsd_config_def {
unsigned short rw_threshold;
unsigned short use_dma;
- unsigned short use_4bit_mode;
};
enum mmcsdevent {
@@ -257,8 +256,6 @@ static int mmc_davinci_send_dma_request(
static void mmc_davinci_xfer_done(struct mmc_davinci_host *host,
struct mmc_data *data);
-static int mmc_davinci_get_ro(struct mmc_host *mmc);
-
static void davinci_abort_dma(struct mmc_davinci_host *host);
#endif /* DAVINCI_MMC_H_ */
_______________________________________________
Davinci-linux-open-source mailing list
[email protected]
http://linux.davincidsp.com/mailman/listinfo/davinci-linux-open-source