diff options
-rw-r--r-- | arch/sh/boards/board-ap325rxa.c | 52 | ||||
-rw-r--r-- | arch/sh/boards/mach-ecovec24/setup.c | 79 | ||||
-rw-r--r-- | arch/sh/boards/mach-kfr2r09/setup.c | 33 | ||||
-rw-r--r-- | arch/sh/boards/mach-migor/setup.c | 52 | ||||
-rw-r--r-- | arch/sh/boards/mach-se/7724/setup.c | 33 | ||||
-rw-r--r-- | drivers/mfd/Kconfig | 8 | ||||
-rw-r--r-- | drivers/mfd/Makefile | 1 | ||||
-rw-r--r-- | drivers/mfd/sh_mobile_sdhi.c | 145 | ||||
-rw-r--r-- | drivers/mmc/host/Kconfig | 2 |
9 files changed, 355 insertions, 50 deletions
diff --git a/arch/sh/boards/board-ap325rxa.c b/arch/sh/boards/board-ap325rxa.c index 2d080732a96..b95deee35e0 100644 --- a/arch/sh/boards/board-ap325rxa.c +++ b/arch/sh/boards/board-ap325rxa.c @@ -20,8 +20,6 @@ #include <linux/i2c.h> #include <linux/smsc911x.h> #include <linux/gpio.h> -#include <linux/spi/spi.h> -#include <linux/spi/spi_gpio.h> #include <media/ov772x.h> #include <media/soc_camera.h> #include <media/soc_camera_platform.h> @@ -409,17 +407,25 @@ static struct platform_device ceu_device = { }, }; -struct spi_gpio_platform_data sdcard_cn3_platform_data = { - .sck = GPIO_PTD0, - .mosi = GPIO_PTD1, - .miso = GPIO_PTD2, - .num_chipselect = 1, +static struct resource sdhi0_cn3_resources[] = { + [0] = { + .name = "SDHI0", + .start = 0x04ce0000, + .end = 0x04ce01ff, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = 101, + .flags = IORESOURCE_IRQ, + }, }; -static struct platform_device sdcard_cn3_device = { - .name = "spi_gpio", - .dev = { - .platform_data = &sdcard_cn3_platform_data, +static struct platform_device sdhi0_cn3_device = { + .name = "sh_mobile_sdhi", + .num_resources = ARRAY_SIZE(sdhi0_cn3_resources), + .resource = sdhi0_cn3_resources, + .archdata = { + .hwblk_id = HWBLK_SDHI0, }, }; @@ -470,20 +476,11 @@ static struct platform_device *ap325rxa_devices[] __initdata = { &lcdc_device, &ceu_device, &nand_flash_device, - &sdcard_cn3_device, + &sdhi0_cn3_device, &ap325rxa_camera[0], &ap325rxa_camera[1], }; -static struct spi_board_info ap325rxa_spi_devices[] = { - { - .modalias = "mmc_spi", - .max_speed_hz = 5000000, - .chip_select = 0, - .controller_data = (void *) GPIO_PTD5, - }, -}; - static int __init ap325rxa_devices_setup(void) { /* LD3 and LD4 LEDs */ @@ -578,12 +575,19 @@ static int __init ap325rxa_devices_setup(void) platform_resource_setup_memory(&ceu_device, "ceu", 4 << 20); + /* SDHI0 */ + gpio_request(GPIO_FN_SDHI0CD_PTD, NULL); + gpio_request(GPIO_FN_SDHI0WP_PTD, NULL); + gpio_request(GPIO_FN_SDHI0D3_PTD, NULL); + gpio_request(GPIO_FN_SDHI0D2_PTD, NULL); + gpio_request(GPIO_FN_SDHI0D1_PTD, NULL); + gpio_request(GPIO_FN_SDHI0D0_PTD, NULL); + gpio_request(GPIO_FN_SDHI0CMD_PTD, NULL); + gpio_request(GPIO_FN_SDHI0CLK_PTD, NULL); + i2c_register_board_info(0, ap325rxa_i2c_devices, ARRAY_SIZE(ap325rxa_i2c_devices)); - spi_register_board_info(ap325rxa_spi_devices, - ARRAY_SIZE(ap325rxa_spi_devices)); - return platform_add_devices(ap325rxa_devices, ARRAY_SIZE(ap325rxa_devices)); } diff --git a/arch/sh/boards/mach-ecovec24/setup.c b/arch/sh/boards/mach-ecovec24/setup.c index 3b1ceb46fa5..9d15196952a 100644 --- a/arch/sh/boards/mach-ecovec24/setup.c +++ b/arch/sh/boards/mach-ecovec24/setup.c @@ -428,6 +428,54 @@ static struct i2c_board_info ts_i2c_clients = { .irq = IRQ0, }; +/* SHDI0 */ +static struct resource sdhi0_resources[] = { + [0] = { + .name = "SDHI0", + .start = 0x04ce0000, + .end = 0x04ce01ff, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = 101, + .flags = IORESOURCE_IRQ, + }, +}; + +static struct platform_device sdhi0_device = { + .name = "sh_mobile_sdhi", + .num_resources = ARRAY_SIZE(sdhi0_resources), + .resource = sdhi0_resources, + .id = 0, + .archdata = { + .hwblk_id = HWBLK_SDHI0, + }, +}; + +/* SHDI1 */ +static struct resource sdhi1_resources[] = { + [0] = { + .name = "SDHI1", + .start = 0x04cf0000, + .end = 0x04cf01ff, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = 24, + .flags = IORESOURCE_IRQ, + }, +}; + +static struct platform_device sdhi1_device = { + .name = "sh_mobile_sdhi", + .num_resources = ARRAY_SIZE(sdhi1_resources), + .resource = sdhi1_resources, + .id = 1, + .archdata = { + .hwblk_id = HWBLK_SDHI1, + }, +}; + static struct platform_device *ecovec_devices[] __initdata = { &heartbeat_device, &nor_flash_device, @@ -438,6 +486,8 @@ static struct platform_device *ecovec_devices[] __initdata = { &ceu0_device, &ceu1_device, &keysc_device, + &sdhi0_device, + &sdhi1_device, }; #define EEPROM_ADDR 0x50 @@ -710,6 +760,34 @@ static int __init arch_setup(void) gpio_direction_input(GPIO_PTR5); gpio_direction_input(GPIO_PTR6); + /* enable SDHI0 */ + gpio_request(GPIO_FN_SDHI0CD, NULL); + gpio_request(GPIO_FN_SDHI0WP, NULL); + gpio_request(GPIO_FN_SDHI0CMD, NULL); + gpio_request(GPIO_FN_SDHI0CLK, NULL); + gpio_request(GPIO_FN_SDHI0D3, NULL); + gpio_request(GPIO_FN_SDHI0D2, NULL); + gpio_request(GPIO_FN_SDHI0D1, NULL); + gpio_request(GPIO_FN_SDHI0D0, NULL); + + /* enable SDHI1 */ + gpio_request(GPIO_FN_SDHI1CD, NULL); + gpio_request(GPIO_FN_SDHI1WP, NULL); + gpio_request(GPIO_FN_SDHI1CMD, NULL); + gpio_request(GPIO_FN_SDHI1CLK, NULL); + gpio_request(GPIO_FN_SDHI1D3, NULL); + gpio_request(GPIO_FN_SDHI1D2, NULL); + gpio_request(GPIO_FN_SDHI1D1, NULL); + gpio_request(GPIO_FN_SDHI1D0, NULL); + + gpio_request(GPIO_PTB6, NULL); + gpio_request(GPIO_PTB7, NULL); + gpio_direction_output(GPIO_PTB6, 1); + gpio_direction_output(GPIO_PTB7, 1); + + /* I/O buffer drive ability is high for SDHI1 */ + ctrl_outw((ctrl_inw(IODRIVEA) & ~0x3000) | 0x2000 , IODRIVEA); + /* enable I2C device */ i2c_register_board_info(1, i2c1_devices, ARRAY_SIZE(i2c1_devices)); @@ -726,7 +804,6 @@ static int __init devices_setup(void) } device_initcall(devices_setup); - static struct sh_machine_vector mv_ecovec __initmv = { .mv_name = "R0P7724 (EcoVec)", }; diff --git a/arch/sh/boards/mach-kfr2r09/setup.c b/arch/sh/boards/mach-kfr2r09/setup.c index ce01d6a953b..43d75ee9335 100644 --- a/arch/sh/boards/mach-kfr2r09/setup.c +++ b/arch/sh/boards/mach-kfr2r09/setup.c @@ -332,6 +332,28 @@ static struct platform_device kfr2r09_camera = { }, }; +static struct resource kfr2r09_sh_sdhi0_resources[] = { + [0] = { + .name = "SDHI0", + .start = 0x04ce0000, + .end = 0x04ce01ff, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = 101, + .flags = IORESOURCE_IRQ, + }, +}; + +static struct platform_device kfr2r09_sh_sdhi0_device = { + .name = "sh_mobile_sdhi", + .num_resources = ARRAY_SIZE(kfr2r09_sh_sdhi0_resources), + .resource = kfr2r09_sh_sdhi0_resources, + .archdata = { + .hwblk_id = HWBLK_SDHI0, + }, +}; + static struct platform_device *kfr2r09_devices[] __initdata = { &kfr2r09_nor_flash_device, &kfr2r09_nand_flash_device, @@ -339,6 +361,7 @@ static struct platform_device *kfr2r09_devices[] __initdata = { &kfr2r09_sh_lcdc_device, &kfr2r09_ceu_device, &kfr2r09_camera, + &kfr2r09_sh_sdhi0_device, }; #define BSC_CS0BCR 0xfec10004 @@ -500,6 +523,16 @@ static int __init kfr2r09_devices_setup(void) platform_resource_setup_memory(&kfr2r09_ceu_device, "ceu", 4 << 20); + /* SDHI0 connected to yc304 */ + gpio_request(GPIO_FN_SDHI0CD, NULL); + gpio_request(GPIO_FN_SDHI0WP, NULL); + gpio_request(GPIO_FN_SDHI0D3, NULL); + gpio_request(GPIO_FN_SDHI0D2, NULL); + gpio_request(GPIO_FN_SDHI0D1, NULL); + gpio_request(GPIO_FN_SDHI0D0, NULL); + gpio_request(GPIO_FN_SDHI0CMD, NULL); + gpio_request(GPIO_FN_SDHI0CLK, NULL); + return platform_add_devices(kfr2r09_devices, ARRAY_SIZE(kfr2r09_devices)); } diff --git a/arch/sh/boards/mach-migor/setup.c b/arch/sh/boards/mach-migor/setup.c index 6ed1fd32369..8e911360c91 100644 --- a/arch/sh/boards/mach-migor/setup.c +++ b/arch/sh/boards/mach-migor/setup.c @@ -18,8 +18,6 @@ #include <linux/delay.h> #include <linux/clk.h> #include <linux/gpio.h> -#include <linux/spi/spi.h> -#include <linux/spi/spi_gpio.h> #include <video/sh_mobile_lcdc.h> #include <media/sh_mobile_ceu.h> #include <media/ov772x.h> @@ -390,17 +388,25 @@ static struct platform_device migor_ceu_device = { }, }; -struct spi_gpio_platform_data sdcard_cn9_platform_data = { - .sck = GPIO_PTD0, - .mosi = GPIO_PTD1, - .miso = GPIO_PTD2, - .num_chipselect = 1, +static struct resource sdhi_cn9_resources[] = { + [0] = { + .name = "SDHI", + .start = 0x04ce0000, + .end = 0x04ce01ff, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = 101, + .flags = IORESOURCE_IRQ, + }, }; -static struct platform_device sdcard_cn9_device = { - .name = "spi_gpio", - .dev = { - .platform_data = &sdcard_cn9_platform_data, +static struct platform_device sdhi_cn9_device = { + .name = "sh_mobile_sdhi", + .num_resources = ARRAY_SIZE(sdhi_cn9_resources), + .resource = sdhi_cn9_resources, + .archdata = { + .hwblk_id = HWBLK_SDHI, }, }; @@ -467,20 +473,11 @@ static struct platform_device *migor_devices[] __initdata = { &migor_ceu_device, &migor_nor_flash_device, &migor_nand_flash_device, - &sdcard_cn9_device, + &sdhi_cn9_device, &migor_camera[0], &migor_camera[1], }; -static struct spi_board_info migor_spi_devices[] = { - { - .modalias = "mmc_spi", - .max_speed_hz = 5000000, - .chip_select = 0, - .controller_data = (void *) GPIO_PTD5, - }, -}; - static int __init migor_devices_setup(void) { @@ -525,6 +522,16 @@ static int __init migor_devices_setup(void) gpio_request(GPIO_PTA1, NULL); gpio_direction_input(GPIO_PTA1); + /* SDHI */ + gpio_request(GPIO_FN_SDHICD, NULL); + gpio_request(GPIO_FN_SDHIWP, NULL); + gpio_request(GPIO_FN_SDHID3, NULL); + gpio_request(GPIO_FN_SDHID2, NULL); + gpio_request(GPIO_FN_SDHID1, NULL); + gpio_request(GPIO_FN_SDHID0, NULL); + gpio_request(GPIO_FN_SDHICMD, NULL); + gpio_request(GPIO_FN_SDHICLK, NULL); + /* Touch Panel */ gpio_request(GPIO_FN_IRQ6, NULL); @@ -612,9 +619,6 @@ static int __init migor_devices_setup(void) i2c_register_board_info(0, migor_i2c_devices, ARRAY_SIZE(migor_i2c_devices)); - spi_register_board_info(migor_spi_devices, - ARRAY_SIZE(migor_spi_devices)); - return platform_add_devices(migor_devices, ARRAY_SIZE(migor_devices)); } arch_initcall(migor_devices_setup); diff --git a/arch/sh/boards/mach-se/7724/setup.c b/arch/sh/boards/mach-se/7724/setup.c index e78c3be8ad2..ce6b36ebe64 100644 --- a/arch/sh/boards/mach-se/7724/setup.c +++ b/arch/sh/boards/mach-se/7724/setup.c @@ -448,6 +448,28 @@ static struct platform_device sh7724_usb1_gadget_device = { .resource = sh7724_usb1_gadget_resources, }; +static struct resource sdhi0_cn7_resources[] = { + [0] = { + .name = "SDHI0", + .start = 0x04ce0000, + .end = 0x04ce01ff, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = 101, + .flags = IORESOURCE_IRQ, + }, +}; + +static struct platform_device sdhi0_cn7_device = { + .name = "sh_mobile_sdhi", + .num_resources = ARRAY_SIZE(sdhi0_cn7_resources), + .resource = sdhi0_cn7_resources, + .archdata = { + .hwblk_id = HWBLK_SDHI0, + }, +}; + static struct platform_device *ms7724se_devices[] __initdata = { &heartbeat_device, &smc91x_eth_device, @@ -460,6 +482,7 @@ static struct platform_device *ms7724se_devices[] __initdata = { &sh7724_usb0_host_device, &sh7724_usb1_gadget_device, &fsi_device, + &sdhi0_cn7_device, }; #define EEPROM_OP 0xBA206000 @@ -698,6 +721,16 @@ static int __init devices_setup(void) clk_set_rate(&fsimcka_clk, 11000); clk_put(fsia_clk); + /* SDHI0 connected to cn7 */ + gpio_request(GPIO_FN_SDHI0CD, NULL); + gpio_request(GPIO_FN_SDHI0WP, NULL); + gpio_request(GPIO_FN_SDHI0D3, NULL); + gpio_request(GPIO_FN_SDHI0D2, NULL); + gpio_request(GPIO_FN_SDHI0D1, NULL); + gpio_request(GPIO_FN_SDHI0D0, NULL); + gpio_request(GPIO_FN_SDHI0CMD, NULL); + gpio_request(GPIO_FN_SDHI0CLK, NULL); + /* * enable SH-Eth * diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig index 570be139f9d..96956b3cc17 100644 --- a/drivers/mfd/Kconfig +++ b/drivers/mfd/Kconfig @@ -35,6 +35,14 @@ config MFD_ASIC3 This driver supports the ASIC3 multifunction chip found on many PDAs (mainly iPAQ and HTC based ones) +config MFD_SH_MOBILE_SDHI + bool "Support for SuperH Mobile SDHI" + depends on SUPERH + select MFD_CORE + ---help--- + This driver supports the SDHI hardware block found in many + SuperH Mobile SoCs. + config MFD_DM355EVM_MSP bool "DaVinci DM355 EVM microcontroller" depends on I2C && MACH_DAVINCI_DM355_EVM diff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile index f3b277b90d4..d9522943d2f 100644 --- a/drivers/mfd/Makefile +++ b/drivers/mfd/Makefile @@ -4,6 +4,7 @@ obj-$(CONFIG_MFD_SM501) += sm501.o obj-$(CONFIG_MFD_ASIC3) += asic3.o +obj-$(CONFIG_MFD_SH_MOBILE_SDHI) += sh_mobile_sdhi.o obj-$(CONFIG_HTC_EGPIO) += htc-egpio.o obj-$(CONFIG_HTC_PASIC3) += htc-pasic3.o diff --git a/drivers/mfd/sh_mobile_sdhi.c b/drivers/mfd/sh_mobile_sdhi.c new file mode 100644 index 00000000000..56f72cc1d56 --- /dev/null +++ b/drivers/mfd/sh_mobile_sdhi.c @@ -0,0 +1,145 @@ +/* + * SuperH Mobile SDHI + * + * Copyright (C) 2009 Magnus Damm + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * Based on "Compaq ASIC3 support": + * + * Copyright 2001 Compaq Computer Corporation. + * Copyright 2004-2005 Phil Blundell + * Copyright 2007-2008 OpenedHand Ltd. + * + * Authors: Phil Blundell <pb@handhelds.org>, + * Samuel Ortiz <sameo@openedhand.com> + * + */ + +#include <linux/kernel.h> +#include <linux/clk.h> +#include <linux/platform_device.h> + +#include <linux/mfd/core.h> +#include <linux/mfd/tmio.h> + +struct sh_mobile_sdhi { + struct clk *clk; + struct tmio_mmc_data mmc_data; + struct mfd_cell cell_mmc; +}; + +static struct resource sh_mobile_sdhi_resources[] = { + { + .start = 0x000, + .end = 0x1ff, + .flags = IORESOURCE_MEM, + }, + { + .start = 0, + .end = 0, + .flags = IORESOURCE_IRQ, + }, +}; + +static struct mfd_cell sh_mobile_sdhi_cell = { + .name = "tmio-mmc", + .num_resources = ARRAY_SIZE(sh_mobile_sdhi_resources), + .resources = sh_mobile_sdhi_resources, +}; + +static int __init sh_mobile_sdhi_probe(struct platform_device *pdev) +{ + struct sh_mobile_sdhi *priv; + struct resource *mem; + char clk_name[8]; + int ret, irq; + + mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (!mem) + dev_err(&pdev->dev, "missing MEM resource\n"); + + irq = platform_get_irq(pdev, 0); + if (irq < 0) + dev_err(&pdev->dev, "missing IRQ resource\n"); + + if (!mem || (irq < 0)) + return -EINVAL; + + priv = kzalloc(sizeof(struct sh_mobile_sdhi), GFP_KERNEL); + if (priv == NULL) { + dev_err(&pdev->dev, "kzalloc failed\n"); + return -ENOMEM; + } + + snprintf(clk_name, sizeof(clk_name), "sdhi%d", pdev->id); + priv->clk = clk_get(&pdev->dev, clk_name); + if (IS_ERR(priv->clk)) { + dev_err(&pdev->dev, "cannot get clock \"%s\"\n", clk_name); + ret = PTR_ERR(priv->clk); + kfree(priv); + return ret; + } + + clk_enable(priv->clk); + + /* FIXME: silly const unsigned int hclk */ + *(unsigned int *)&priv->mmc_data.hclk = clk_get_rate(priv->clk); + + memcpy(&priv->cell_mmc, &sh_mobile_sdhi_cell, sizeof(priv->cell_mmc)); + priv->cell_mmc.driver_data = &priv->mmc_data; + priv->cell_mmc.platform_data = &priv->cell_mmc; + priv->cell_mmc.data_size = sizeof(priv->cell_mmc); + + platform_set_drvdata(pdev, priv); + + ret = mfd_add_devices(&pdev->dev, pdev->id, + &priv->cell_mmc, 1, mem, irq); + if (ret) { + clk_disable(priv->clk); + clk_put(priv->clk); + kfree(priv); + } + + return ret; +} + +static int sh_mobile_sdhi_remove(struct platform_device *pdev) +{ + struct sh_mobile_sdhi *priv = platform_get_drvdata(pdev); + + mfd_remove_devices(&pdev->dev); + clk_disable(priv->clk); + clk_put(priv->clk); + kfree(priv); + + return 0; +} + +static struct platform_driver sh_mobile_sdhi_driver = { + .driver = { + .name = "sh_mobile_sdhi", + .owner = THIS_MODULE, + }, + .probe = sh_mobile_sdhi_probe, + .remove = __devexit_p(sh_mobile_sdhi_remove), +}; + +static int __init sh_mobile_sdhi_init(void) +{ + return platform_driver_register(&sh_mobile_sdhi_driver); +} + +static void __exit sh_mobile_sdhi_exit(void) +{ + platform_driver_unregister(&sh_mobile_sdhi_driver); +} + +module_init(sh_mobile_sdhi_init); +module_exit(sh_mobile_sdhi_exit); + +MODULE_DESCRIPTION("SuperH Mobile SDHI driver"); +MODULE_AUTHOR("Magnus Damm"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/mmc/host/Kconfig b/drivers/mmc/host/Kconfig index 432ae8358c8..e04b751680d 100644 --- a/drivers/mmc/host/Kconfig +++ b/drivers/mmc/host/Kconfig @@ -329,7 +329,7 @@ config MMC_SDRICOH_CS config MMC_TMIO tristate "Toshiba Mobile IO Controller (TMIO) MMC/SD function support" - depends on MFD_TMIO || MFD_ASIC3 + depends on MFD_TMIO || MFD_ASIC3 || SUPERH help This provides support for the SD/MMC cell found in TC6393XB, T7L66XB and also HTC ASIC3 |