diff options
Diffstat (limited to 'target/linux/ep93xx/patches-2.6.39/004-simone_add_mmc_spi.patch')
-rw-r--r-- | target/linux/ep93xx/patches-2.6.39/004-simone_add_mmc_spi.patch | 179 |
1 files changed, 179 insertions, 0 deletions
diff --git a/target/linux/ep93xx/patches-2.6.39/004-simone_add_mmc_spi.patch b/target/linux/ep93xx/patches-2.6.39/004-simone_add_mmc_spi.patch new file mode 100644 index 0000000000..511d012b86 --- /dev/null +++ b/target/linux/ep93xx/patches-2.6.39/004-simone_add_mmc_spi.patch @@ -0,0 +1,179 @@ +This enables the mmc-over-spi driver for the Sim.One board, based on Mika's +patch, which used a GPIO for chip select in stead of the default SFRMOUT pin. +I've modified it to use the usual SFRMOUT; if you've modified your Sim.One +board to use a GPIO instead, uncomment and modify +// #define MMC_CHIP_SELECT_GPIO EP93XX_GPIO_LINE_EGPIO15 +in the source file. + -martinwguy, 14 May 2010 + +From: Mika Westerberg <mika.westerberg@iki.fi> +Date: Wed, 28 Apr 2010 08:42:46 +0300 +Subject: [PATCH] ep93xx: simone: added board specific SPI support for MMC/SD cards + +This includes setting up EGPIOs 0 and 9 for card detection and chip select +respectively. + +--- a/arch/arm/mach-ep93xx/simone.c ++++ b/arch/arm/mach-ep93xx/simone.c +@@ -18,12 +18,16 @@ + #include <linux/kernel.h> + #include <linux/init.h> + #include <linux/platform_device.h> ++#include <linux/mmc/host.h> + #include <linux/gpio.h> ++#include <linux/spi/spi.h> ++#include <linux/spi/mmc_spi.h> + #include <linux/i2c.h> + #include <linux/i2c-gpio.h> + + #include <mach/hardware.h> + #include <mach/fb.h> ++#include <mach/ep93xx_spi.h> + + #include <asm/mach-types.h> + #include <asm/mach/arch.h> +@@ -38,6 +42,135 @@ static struct ep93xxfb_mach_info __initd + .flags = EP93XXFB_USE_SDCSN0 | EP93XXFB_PCLK_FALLING, + }; + ++/* ++ * GPIO lines used for MMC card detection. ++ */ ++#define MMC_CARD_DETECT_GPIO EP93XX_GPIO_LINE_EGPIO0 ++ ++/* ++ * If you have hacked your Sim.One to use a GPIO as SD card chip select ++ * (SD pin 1), uncomment the following line. ++ * The example, EGPIO15, is on TP17 near the CPU. ++ */ ++// #define MMC_CHIP_SELECT_GPIO EP93XX_GPIO_LINE_EGPIO15 ++ ++/* ++ * MMC SPI chip select GPIO handling. If you are using SFRMOUT (SFRM1) signal, ++ * you can leave these empty and pass NULL as .controller_data. ++ */ ++ ++#ifdef MMC_CHIP_SELECT_GPIO ++static int simone_mmc_spi_setup(struct spi_device *spi) ++{ ++ unsigned int gpio = MMC_CHIP_SELECT_GPIO; ++ int err; ++ ++ err = gpio_request(gpio, spi->modalias); ++ if (err) ++ return err; ++ ++ err = gpio_direction_output(gpio, 1); ++ if (err) { ++ gpio_free(gpio); ++ return err; ++ } ++ ++ return 0; ++} ++ ++static void simone_mmc_spi_cleanup(struct spi_device *spi) ++{ ++ unsigned int gpio = MMC_CHIP_SELECT_GPIO; ++ ++ gpio_set_value(gpio, 1); ++ gpio_direction_input(gpio); ++ gpio_free(gpio); ++} ++ ++static void simone_mmc_spi_cs_control(struct spi_device *spi, int value) ++{ ++ gpio_set_value(MMC_CHIP_SELECT_GPIO, value); ++} ++ ++static struct ep93xx_spi_chip_ops simone_mmc_spi_ops = { ++ .setup = simone_mmc_spi_setup, ++ .cleanup = simone_mmc_spi_cleanup, ++ .cs_control = simone_mmc_spi_cs_control, ++}; ++#endif ++ ++/* ++ * MMC card detection GPIO setup. ++ */ ++static int simone_mmc_spi_init(struct device *dev, ++ irqreturn_t (*irq_handler)(int, void *), void *mmc) ++{ ++ unsigned int gpio = MMC_CARD_DETECT_GPIO; ++ int irq, err; ++ ++ err = gpio_request(gpio, dev_name(dev)); ++ if (err) ++ return err; ++ ++ err = gpio_direction_input(gpio); ++ if (err) ++ goto fail; ++ ++ irq = gpio_to_irq(gpio); ++ if (irq < 0) ++ goto fail; ++ ++ err = request_irq(irq, irq_handler, IRQF_TRIGGER_FALLING, ++ "MMC card detect", mmc); ++ if (err) ++ goto fail; ++ ++ printk(KERN_INFO "%s: using irq %d for MMC card detection\n", ++ dev_name(dev), irq); ++ ++ return 0; ++fail: ++ gpio_free(gpio); ++ return err; ++} ++ ++static void simone_mmc_spi_exit(struct device *dev, void *mmc) ++{ ++ unsigned int gpio = MMC_CARD_DETECT_GPIO; ++ ++ free_irq(gpio_to_irq(gpio), mmc); ++ gpio_free(gpio); ++} ++ ++static struct mmc_spi_platform_data simone_mmc_spi_data = { ++ .init = simone_mmc_spi_init, ++ .exit = simone_mmc_spi_exit, ++ .detect_delay = 500, ++ .ocr_mask = MMC_VDD_32_33 | MMC_VDD_33_34, ++}; ++ ++static struct spi_board_info simone_spi_devices[] __initdata = { ++ { ++ .modalias = "mmc_spi", ++#ifdef MMC_CHIP_SELECT_GPIO ++ .controller_data = &simone_mmc_spi_ops, ++#endif ++ .platform_data = &simone_mmc_spi_data, ++ /* ++ * We use 10 MHz even though the maximum is 3.7 MHz. The driver ++ * will limit it automatically to max. frequency. ++ */ ++ .max_speed_hz = 10 * 1000 * 1000, ++ .bus_num = 0, ++ .chip_select = 0, ++ .mode = SPI_MODE_3, ++ }, ++}; ++ ++static struct ep93xx_spi_info simone_spi_info __initdata = { ++ .num_chipselect = ARRAY_SIZE(simone_spi_devices), ++}; ++ + static struct i2c_gpio_platform_data __initdata simone_i2c_gpio_data = { + .sda_pin = EP93XX_GPIO_LINE_EEDAT, + .sda_is_open_drain = 0, +@@ -61,6 +194,8 @@ static void __init simone_init_machine(v + ep93xx_register_fb(&simone_fb_info); + ep93xx_register_i2c(&simone_i2c_gpio_data, simone_i2c_board_info, + ARRAY_SIZE(simone_i2c_board_info)); ++ ep93xx_register_spi(&simone_spi_info, simone_spi_devices, ++ ARRAY_SIZE(simone_spi_devices)); + ep93xx_register_ac97(); + } + |