mirror of
https://github.com/torvalds/linux.git
synced 2024-11-23 12:42:02 +00:00
Updates for mmci driver:
- Put the device into low power state at system suspend. - Convert to the common mmc DT parser. - Add missing DT bindings needed for ux500. Updates for ARM ux500|u300: - Convert to the common mmc DT bindings. - Remove redundant board file for mmci platform data. -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.4.11 (GNU/Linux) iQIcBAABAgAGBQJTjF3hAAoJEP4mhCVzWIwpXh0QAIbK0n+m4GKOo+MoMeuMzCkr 3Go1mh75/JpkLQiKyWthfKInkVJ5VFMBY9ZgqcP5nfzy/NY8BYk3UTvWFQkANp5Y telmC6uhkzw1b2wxdgytZFdJ9e7LJovJRERhzx3N5xDxuqM8gm/IZECvn8MbaFp8 3lpPgjh42yS28XDdr3zF2e9nAUH/PUDmOwoxa5jrqxZF63KVfe4dhXlhFHZsrpBq y96IOH2te3TyfJ3+RuE53uf4qMSSlNaoG+8LO40k8LG5hHs391sh05s03xoiZVNB LvFbr8icF8jvu6Kbag/v1i3Lrcl1/xLxFr0KNbDoY3n0UvizViHs1v6hKl1ZV0kR J0z4+6tP41oKSnXz70HE4hJK10gtI4h5KZiBnrPXdTmNet5pSpclJ9UtB69ZPmZS pmm90p89gDgTzKhjvdnAM1qBeRjWm4BBI6KPwVxqNfL3U5gt5p6RR01JAqn6r48I AUoDPLJJxOP/YoPQja2VmyHA+dJ1/ax0xB5hQ8K2MEoegi52eYAFk2nl+PgvFdMv 3kcoxqwBtnoUwEuZqpD3Wk9WTBbErexpUxUw3Wd+x3t38sv5FKLdelCt++I3qEZb 5XaUIdppslez/i05BMWPKBdkn3fhWEhlJ7w3aZboczy8c+VbOOjIBIvNROuAIRee R+i5hz/AxYz+wT4PBMnv =09ec -----END PGP SIGNATURE----- Merge tag 'mmc-v3.16-1' of git://git.linaro.org/people/ulf.hansson/mmc into next Pull MMC update from Ulf Hansson: "These patches are mainly updates for the mmci driver and have been tested in linux-next. Some ARM SoC related patches are also included and those have been acked from the corresponding maintainers to go through my mmc tree. Updates for mmci driver: - Put the device into low power state at system suspend. - Convert to the common mmc DT parser. - Add missing DT bindings needed for ux500. Updates for ARM ux500|u300: - Convert to the common mmc DT bindings. - Remove redundant board file for mmci platform data" * tag 'mmc-v3.16-1' of git://git.linaro.org/people/ulf.hansson/mmc: (22 commits) mmc: mmci: Enforce DMA configuration through DT mmc: mmci: Enforce max frequency configuration through DT mmc: mmci: Enforce mmc capabilities through DT mmc: mmci: Enforce DT for signal direction and feedback clock ARM: ux500: Remove redundant board file for mmci platform data ARM: ux500: Add a vmmc regulator through DT for the poped eMMC for href ARM: ux500: Add the mmc capabilities flags to DT mmc: mmci: Enable MMC_CAP_CMD23 mmc: mmci: Mark the DT bindings for highspeed mode as deprecated ARM: u300: Convert to the common mmc DT bindings for highspeed mode ARM: nomadik: Convert to the common mmc DT bindings for highspeed mode ARM: ux500: Convert to the common mmc DT bindings for highspeed mode ARM: ux500: Add mmci signal directions and feeback clock in DT for href mmc: mmci: Use the common mmc DT parser mmc: mmci: Add DT bindings for feedback clock pin mmc: mmci: Add DT bindings for signal direction mmc: mmci: Update DT documentation mmc: mmci: Convert to devm functions mmc: mmci: Convert to the mmc gpio API mmc: mmci: Put the device into low power state at system suspend ...
This commit is contained in:
commit
6c52486ded
@ -4,12 +4,58 @@ The ARM PrimeCell MMCI PL180 and PL181 provides an interface for
|
||||
reading and writing to MultiMedia and SD cards alike.
|
||||
|
||||
This file documents differences between the core properties described
|
||||
by mmc.txt and the properties used by the mmci driver.
|
||||
by mmc.txt and the properties used by the mmci driver. Using "st" as
|
||||
the prefix for a property, indicates support by the ST Micro variant.
|
||||
|
||||
Required properties:
|
||||
- compatible : contains "arm,pl18x", "arm,primecell".
|
||||
- arm,primecell-periphid : contains the PrimeCell Peripheral ID.
|
||||
- vmmc-supply : phandle to the regulator device tree node, mentioned
|
||||
as the VCC/VDD supply in the eMMC/SD specs.
|
||||
|
||||
Optional properties:
|
||||
- mmc-cap-mmc-highspeed : indicates whether MMC is high speed capable
|
||||
- mmc-cap-sd-highspeed : indicates whether SD is high speed capable
|
||||
- arm,primecell-periphid : contains the PrimeCell Peripheral ID, it overrides
|
||||
the ID provided by the HW
|
||||
- vqmmc-supply : phandle to the regulator device tree node, mentioned
|
||||
as the VCCQ/VDD_IO supply in the eMMC/SD specs.
|
||||
- st,sig-dir-dat0 : bus signal direction pin used for DAT[0].
|
||||
- st,sig-dir-dat2 : bus signal direction pin used for DAT[2].
|
||||
- st,sig-dir-dat31 : bus signal direction pin used for DAT[3] and DAT[1].
|
||||
- st,sig-dir-dat74 : bus signal direction pin used for DAT[4] to DAT[7].
|
||||
- st,sig-dir-cmd : cmd signal direction pin used for CMD.
|
||||
- st,sig-pin-fbclk : feedback clock signal pin used.
|
||||
|
||||
Deprecated properties:
|
||||
- mmc-cap-mmc-highspeed : indicates whether MMC is high speed capable.
|
||||
- mmc-cap-sd-highspeed : indicates whether SD is high speed capable.
|
||||
|
||||
Example:
|
||||
|
||||
sdi0_per1@80126000 {
|
||||
compatible = "arm,pl18x", "arm,primecell";
|
||||
reg = <0x80126000 0x1000>;
|
||||
interrupts = <0 60 IRQ_TYPE_LEVEL_HIGH>;
|
||||
|
||||
dmas = <&dma 29 0 0x2>, /* Logical - DevToMem */
|
||||
<&dma 29 0 0x0>; /* Logical - MemToDev */
|
||||
dma-names = "rx", "tx";
|
||||
|
||||
clocks = <&prcc_kclk 1 5>, <&prcc_pclk 1 5>;
|
||||
clock-names = "sdi", "apb_pclk";
|
||||
|
||||
max-frequency = <100000000>;
|
||||
bus-width = <4>;
|
||||
cap-sd-highspeed;
|
||||
cap-mmc-highspeed;
|
||||
cd-gpios = <&gpio2 31 0x4>; // 95
|
||||
st,sig-dir-dat0;
|
||||
st,sig-dir-dat2;
|
||||
st,sig-dir-cmd;
|
||||
st,sig-pin-fbclk;
|
||||
|
||||
vmmc-supply = <&ab8500_ldo_aux3_reg>;
|
||||
vqmmc-supply = <&vmmci>;
|
||||
|
||||
pinctrl-names = "default", "sleep";
|
||||
pinctrl-0 = <&sdi0_default_mode>;
|
||||
pinctrl-1 = <&sdi0_sleep_mode>;
|
||||
};
|
||||
|
@ -38,8 +38,8 @@
|
||||
arm,primecell-periphid = <0x10480180>;
|
||||
max-frequency = <100000000>;
|
||||
bus-width = <4>;
|
||||
mmc-cap-sd-highspeed;
|
||||
mmc-cap-mmc-highspeed;
|
||||
cap-sd-highspeed;
|
||||
cap-mmc-highspeed;
|
||||
vmmc-supply = <&ab8500_ldo_aux3_reg>;
|
||||
|
||||
cd-gpios = <&gpio7 6 0x4>; // 230
|
||||
@ -63,7 +63,7 @@
|
||||
arm,primecell-periphid = <0x10480180>;
|
||||
max-frequency = <100000000>;
|
||||
bus-width = <8>;
|
||||
mmc-cap-mmc-highspeed;
|
||||
cap-mmc-highspeed;
|
||||
vmmc-supply = <&ab8500_ldo_aux2_reg>;
|
||||
|
||||
status = "okay";
|
||||
|
@ -116,8 +116,15 @@
|
||||
arm,primecell-periphid = <0x10480180>;
|
||||
max-frequency = <100000000>;
|
||||
bus-width = <4>;
|
||||
mmc-cap-sd-highspeed;
|
||||
mmc-cap-mmc-highspeed;
|
||||
cap-sd-highspeed;
|
||||
cap-mmc-highspeed;
|
||||
sd-uhs-sdr12;
|
||||
sd-uhs-sdr25;
|
||||
full-pwr-cycle;
|
||||
st,sig-dir-dat0;
|
||||
st,sig-dir-dat2;
|
||||
st,sig-dir-cmd;
|
||||
st,sig-pin-fbclk;
|
||||
vmmc-supply = <&ab8500_ldo_aux3_reg>;
|
||||
vqmmc-supply = <&vmmci>;
|
||||
pinctrl-names = "default", "sleep";
|
||||
@ -132,6 +139,7 @@
|
||||
arm,primecell-periphid = <0x10480180>;
|
||||
max-frequency = <100000000>;
|
||||
bus-width = <4>;
|
||||
non-removable;
|
||||
pinctrl-names = "default", "sleep";
|
||||
pinctrl-0 = <&sdi1_default_mode>;
|
||||
pinctrl-1 = <&sdi1_sleep_mode>;
|
||||
@ -144,7 +152,9 @@
|
||||
arm,primecell-periphid = <0x10480180>;
|
||||
max-frequency = <100000000>;
|
||||
bus-width = <8>;
|
||||
mmc-cap-mmc-highspeed;
|
||||
cap-mmc-highspeed;
|
||||
non-removable;
|
||||
vmmc-supply = <&db8500_vsmps2_reg>;
|
||||
pinctrl-names = "default", "sleep";
|
||||
pinctrl-0 = <&sdi2_default_mode>;
|
||||
pinctrl-1 = <&sdi2_sleep_mode>;
|
||||
@ -157,7 +167,8 @@
|
||||
arm,primecell-periphid = <0x10480180>;
|
||||
max-frequency = <100000000>;
|
||||
bus-width = <8>;
|
||||
mmc-cap-mmc-highspeed;
|
||||
cap-mmc-highspeed;
|
||||
non-removable;
|
||||
vmmc-supply = <&ab8500_ldo_aux2_reg>;
|
||||
pinctrl-names = "default", "sleep";
|
||||
pinctrl-0 = <&sdi4_default_mode>;
|
||||
|
@ -840,8 +840,8 @@
|
||||
interrupts = <22>;
|
||||
max-frequency = <48000000>;
|
||||
bus-width = <4>;
|
||||
mmc-cap-mmc-highspeed;
|
||||
mmc-cap-sd-highspeed;
|
||||
cap-mmc-highspeed;
|
||||
cap-sd-highspeed;
|
||||
cd-gpios = <&gpio3 15 0x1>;
|
||||
cd-inverted;
|
||||
pinctrl-names = "default";
|
||||
|
@ -156,7 +156,7 @@
|
||||
arm,primecell-periphid = <0x10480180>;
|
||||
max-frequency = <100000000>;
|
||||
bus-width = <4>;
|
||||
mmc-cap-mmc-highspeed;
|
||||
cap-mmc-highspeed;
|
||||
vmmc-supply = <&ab8500_ldo_aux3_reg>;
|
||||
vqmmc-supply = <&vmmci>;
|
||||
pinctrl-names = "default", "sleep";
|
||||
@ -195,7 +195,7 @@
|
||||
arm,primecell-periphid = <0x10480180>;
|
||||
max-frequency = <100000000>;
|
||||
bus-width = <8>;
|
||||
mmc-cap-mmc-highspeed;
|
||||
cap-mmc-highspeed;
|
||||
vmmc-supply = <&ab8500_ldo_aux2_reg>;
|
||||
pinctrl-names = "default", "sleep";
|
||||
pinctrl-0 = <&sdi4_default_mode>;
|
||||
|
@ -442,8 +442,8 @@
|
||||
clock-names = "apb_pclk", "mclk";
|
||||
max-frequency = <24000000>;
|
||||
bus-width = <4>; // SD-card slot
|
||||
mmc-cap-mmc-highspeed;
|
||||
mmc-cap-sd-highspeed;
|
||||
cap-mmc-highspeed;
|
||||
cap-sd-highspeed;
|
||||
cd-gpios = <&gpio 12 0x4>;
|
||||
cd-inverted;
|
||||
vmmc-supply = <&ab3100_ldo_g_reg>;
|
||||
|
@ -202,9 +202,6 @@ static struct mmci_platform_data lpc32xx_mmci_data = {
|
||||
.ocr_mask = MMC_VDD_30_31 | MMC_VDD_31_32 |
|
||||
MMC_VDD_32_33 | MMC_VDD_33_34,
|
||||
.ios_handler = mmc_handle_ios,
|
||||
.dma_filter = NULL,
|
||||
/* No DMA for now since AMBA PL080 dmaengine driver only does scatter
|
||||
* gather, and the MMCI driver doesn't do it this way */
|
||||
};
|
||||
|
||||
static struct lpc32xx_slc_platform_data lpc32xx_slc_data = {
|
||||
|
@ -5,8 +5,7 @@
|
||||
obj-y := cpu.o id.o timer.o pm.o
|
||||
obj-$(CONFIG_CACHE_L2X0) += cache-l2x0.o
|
||||
obj-$(CONFIG_UX500_SOC_DB8500) += cpu-db8500.o
|
||||
obj-$(CONFIG_MACH_MOP500) += board-mop500-sdi.o \
|
||||
board-mop500-regulators.o \
|
||||
obj-$(CONFIG_MACH_MOP500) += board-mop500-regulators.o \
|
||||
board-mop500-audio.o
|
||||
obj-$(CONFIG_SMP) += platsmp.o headsmp.o
|
||||
obj-$(CONFIG_HOTPLUG_CPU) += hotplug.o
|
||||
|
@ -1,166 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) ST-Ericsson SA 2010
|
||||
*
|
||||
* Author: Hanumath Prasad <hanumath.prasad@stericsson.com>
|
||||
* License terms: GNU General Public License (GPL) version 2
|
||||
*/
|
||||
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/gpio.h>
|
||||
#include <linux/amba/bus.h>
|
||||
#include <linux/amba/mmci.h>
|
||||
#include <linux/mmc/host.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/platform_data/dma-ste-dma40.h>
|
||||
|
||||
#include <asm/mach-types.h>
|
||||
|
||||
#include "db8500-regs.h"
|
||||
#include "board-mop500.h"
|
||||
#include "ste-dma40-db8500.h"
|
||||
|
||||
/*
|
||||
* v2 has a new version of this block that need to be forced, the number found
|
||||
* in hardware is incorrect
|
||||
*/
|
||||
#define U8500_SDI_V2_PERIPHID 0x10480180
|
||||
|
||||
/*
|
||||
* SDI 0 (MicroSD slot)
|
||||
*/
|
||||
|
||||
#ifdef CONFIG_STE_DMA40
|
||||
struct stedma40_chan_cfg mop500_sdi0_dma_cfg_rx = {
|
||||
.mode = STEDMA40_MODE_LOGICAL,
|
||||
.dir = DMA_DEV_TO_MEM,
|
||||
.dev_type = DB8500_DMA_DEV29_SD_MM0,
|
||||
};
|
||||
|
||||
static struct stedma40_chan_cfg mop500_sdi0_dma_cfg_tx = {
|
||||
.mode = STEDMA40_MODE_LOGICAL,
|
||||
.dir = DMA_MEM_TO_DEV,
|
||||
.dev_type = DB8500_DMA_DEV29_SD_MM0,
|
||||
};
|
||||
#endif
|
||||
|
||||
struct mmci_platform_data mop500_sdi0_data = {
|
||||
.f_max = 100000000,
|
||||
.capabilities = MMC_CAP_4_BIT_DATA |
|
||||
MMC_CAP_SD_HIGHSPEED |
|
||||
MMC_CAP_MMC_HIGHSPEED |
|
||||
MMC_CAP_ERASE |
|
||||
MMC_CAP_UHS_SDR12 |
|
||||
MMC_CAP_UHS_SDR25,
|
||||
.gpio_wp = -1,
|
||||
.sigdir = MCI_ST_FBCLKEN |
|
||||
MCI_ST_CMDDIREN |
|
||||
MCI_ST_DATA0DIREN |
|
||||
MCI_ST_DATA2DIREN,
|
||||
#ifdef CONFIG_STE_DMA40
|
||||
.dma_filter = stedma40_filter,
|
||||
.dma_rx_param = &mop500_sdi0_dma_cfg_rx,
|
||||
.dma_tx_param = &mop500_sdi0_dma_cfg_tx,
|
||||
#endif
|
||||
};
|
||||
|
||||
/*
|
||||
* SDI1 (SDIO WLAN)
|
||||
*/
|
||||
#ifdef CONFIG_STE_DMA40
|
||||
static struct stedma40_chan_cfg sdi1_dma_cfg_rx = {
|
||||
.mode = STEDMA40_MODE_LOGICAL,
|
||||
.dir = DMA_DEV_TO_MEM,
|
||||
.dev_type = DB8500_DMA_DEV32_SD_MM1,
|
||||
};
|
||||
|
||||
static struct stedma40_chan_cfg sdi1_dma_cfg_tx = {
|
||||
.mode = STEDMA40_MODE_LOGICAL,
|
||||
.dir = DMA_MEM_TO_DEV,
|
||||
.dev_type = DB8500_DMA_DEV32_SD_MM1,
|
||||
};
|
||||
#endif
|
||||
|
||||
struct mmci_platform_data mop500_sdi1_data = {
|
||||
.ocr_mask = MMC_VDD_29_30,
|
||||
.f_max = 100000000,
|
||||
.capabilities = MMC_CAP_4_BIT_DATA |
|
||||
MMC_CAP_NONREMOVABLE,
|
||||
.gpio_cd = -1,
|
||||
.gpio_wp = -1,
|
||||
#ifdef CONFIG_STE_DMA40
|
||||
.dma_filter = stedma40_filter,
|
||||
.dma_rx_param = &sdi1_dma_cfg_rx,
|
||||
.dma_tx_param = &sdi1_dma_cfg_tx,
|
||||
#endif
|
||||
};
|
||||
|
||||
/*
|
||||
* SDI 2 (POP eMMC, not on DB8500ed)
|
||||
*/
|
||||
|
||||
#ifdef CONFIG_STE_DMA40
|
||||
struct stedma40_chan_cfg mop500_sdi2_dma_cfg_rx = {
|
||||
.mode = STEDMA40_MODE_LOGICAL,
|
||||
.dir = DMA_DEV_TO_MEM,
|
||||
.dev_type = DB8500_DMA_DEV28_SD_MM2,
|
||||
};
|
||||
|
||||
static struct stedma40_chan_cfg mop500_sdi2_dma_cfg_tx = {
|
||||
.mode = STEDMA40_MODE_LOGICAL,
|
||||
.dir = DMA_MEM_TO_DEV,
|
||||
.dev_type = DB8500_DMA_DEV28_SD_MM2,
|
||||
};
|
||||
#endif
|
||||
|
||||
struct mmci_platform_data mop500_sdi2_data = {
|
||||
.ocr_mask = MMC_VDD_165_195,
|
||||
.f_max = 100000000,
|
||||
.capabilities = MMC_CAP_4_BIT_DATA |
|
||||
MMC_CAP_8_BIT_DATA |
|
||||
MMC_CAP_NONREMOVABLE |
|
||||
MMC_CAP_MMC_HIGHSPEED |
|
||||
MMC_CAP_ERASE |
|
||||
MMC_CAP_CMD23,
|
||||
.gpio_cd = -1,
|
||||
.gpio_wp = -1,
|
||||
#ifdef CONFIG_STE_DMA40
|
||||
.dma_filter = stedma40_filter,
|
||||
.dma_rx_param = &mop500_sdi2_dma_cfg_rx,
|
||||
.dma_tx_param = &mop500_sdi2_dma_cfg_tx,
|
||||
#endif
|
||||
};
|
||||
|
||||
/*
|
||||
* SDI 4 (on-board eMMC)
|
||||
*/
|
||||
|
||||
#ifdef CONFIG_STE_DMA40
|
||||
struct stedma40_chan_cfg mop500_sdi4_dma_cfg_rx = {
|
||||
.mode = STEDMA40_MODE_LOGICAL,
|
||||
.dir = DMA_DEV_TO_MEM,
|
||||
.dev_type = DB8500_DMA_DEV42_SD_MM4,
|
||||
};
|
||||
|
||||
static struct stedma40_chan_cfg mop500_sdi4_dma_cfg_tx = {
|
||||
.mode = STEDMA40_MODE_LOGICAL,
|
||||
.dir = DMA_MEM_TO_DEV,
|
||||
.dev_type = DB8500_DMA_DEV42_SD_MM4,
|
||||
};
|
||||
#endif
|
||||
|
||||
struct mmci_platform_data mop500_sdi4_data = {
|
||||
.f_max = 100000000,
|
||||
.capabilities = MMC_CAP_4_BIT_DATA |
|
||||
MMC_CAP_8_BIT_DATA |
|
||||
MMC_CAP_NONREMOVABLE |
|
||||
MMC_CAP_MMC_HIGHSPEED |
|
||||
MMC_CAP_ERASE |
|
||||
MMC_CAP_CMD23,
|
||||
.gpio_cd = -1,
|
||||
.gpio_wp = -1,
|
||||
#ifdef CONFIG_STE_DMA40
|
||||
.dma_filter = stedma40_filter,
|
||||
.dma_rx_param = &mop500_sdi4_dma_cfg_rx,
|
||||
.dma_tx_param = &mop500_sdi4_dma_cfg_tx,
|
||||
#endif
|
||||
};
|
@ -8,12 +8,7 @@
|
||||
#define __BOARD_MOP500_H
|
||||
|
||||
#include <linux/platform_data/asoc-ux500-msp.h>
|
||||
#include <linux/amba/mmci.h>
|
||||
|
||||
extern struct mmci_platform_data mop500_sdi0_data;
|
||||
extern struct mmci_platform_data mop500_sdi1_data;
|
||||
extern struct mmci_platform_data mop500_sdi2_data;
|
||||
extern struct mmci_platform_data mop500_sdi4_data;
|
||||
extern struct msp_i2s_platform_data msp0_platform_data;
|
||||
extern struct msp_i2s_platform_data msp1_platform_data;
|
||||
extern struct msp_i2s_platform_data msp2_platform_data;
|
||||
|
@ -146,10 +146,6 @@ static struct of_dev_auxdata u8500_auxdata_lookup[] __initdata = {
|
||||
/* Requires call-back bindings. */
|
||||
OF_DEV_AUXDATA("arm,cortex-a9-pmu", 0, "arm-pmu", &db8500_pmu_platdata),
|
||||
/* Requires DMA bindings. */
|
||||
OF_DEV_AUXDATA("arm,pl18x", 0x80126000, "sdi0", &mop500_sdi0_data),
|
||||
OF_DEV_AUXDATA("arm,pl18x", 0x80118000, "sdi1", &mop500_sdi1_data),
|
||||
OF_DEV_AUXDATA("arm,pl18x", 0x80005000, "sdi2", &mop500_sdi2_data),
|
||||
OF_DEV_AUXDATA("arm,pl18x", 0x80114000, "sdi4", &mop500_sdi4_data),
|
||||
OF_DEV_AUXDATA("stericsson,ux500-msp-i2s", 0x80123000,
|
||||
"ux500-msp-i2s.0", &msp0_platform_data),
|
||||
OF_DEV_AUXDATA("stericsson,ux500-msp-i2s", 0x80124000,
|
||||
|
@ -13,6 +13,7 @@
|
||||
#include <linux/init.h>
|
||||
#include <linux/ioport.h>
|
||||
#include <linux/device.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/slab.h>
|
||||
@ -23,6 +24,7 @@
|
||||
#include <linux/mmc/pm.h>
|
||||
#include <linux/mmc/host.h>
|
||||
#include <linux/mmc/card.h>
|
||||
#include <linux/mmc/slot-gpio.h>
|
||||
#include <linux/amba/bus.h>
|
||||
#include <linux/clk.h>
|
||||
#include <linux/scatterlist.h>
|
||||
@ -364,7 +366,6 @@ static void mmci_init_sg(struct mmci_host *host, struct mmc_data *data)
|
||||
#ifdef CONFIG_DMA_ENGINE
|
||||
static void mmci_dma_setup(struct mmci_host *host)
|
||||
{
|
||||
struct mmci_platform_data *plat = host->plat;
|
||||
const char *rxname, *txname;
|
||||
dma_cap_mask_t mask;
|
||||
|
||||
@ -378,25 +379,6 @@ static void mmci_dma_setup(struct mmci_host *host)
|
||||
dma_cap_zero(mask);
|
||||
dma_cap_set(DMA_SLAVE, mask);
|
||||
|
||||
if (plat && plat->dma_filter) {
|
||||
if (!host->dma_rx_channel && plat->dma_rx_param) {
|
||||
host->dma_rx_channel = dma_request_channel(mask,
|
||||
plat->dma_filter,
|
||||
plat->dma_rx_param);
|
||||
/* E.g if no DMA hardware is present */
|
||||
if (!host->dma_rx_channel)
|
||||
dev_err(mmc_dev(host->mmc), "no RX DMA channel\n");
|
||||
}
|
||||
|
||||
if (!host->dma_tx_channel && plat->dma_tx_param) {
|
||||
host->dma_tx_channel = dma_request_channel(mask,
|
||||
plat->dma_filter,
|
||||
plat->dma_tx_param);
|
||||
if (!host->dma_tx_channel)
|
||||
dev_warn(mmc_dev(host->mmc), "no TX DMA channel\n");
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* If only an RX channel is specified, the driver will
|
||||
* attempt to use it bidirectionally, however if it is
|
||||
@ -444,11 +426,9 @@ static void mmci_dma_setup(struct mmci_host *host)
|
||||
*/
|
||||
static inline void mmci_dma_release(struct mmci_host *host)
|
||||
{
|
||||
struct mmci_platform_data *plat = host->plat;
|
||||
|
||||
if (host->dma_rx_channel)
|
||||
dma_release_channel(host->dma_rx_channel);
|
||||
if (host->dma_tx_channel && plat->dma_tx_param)
|
||||
if (host->dma_tx_channel)
|
||||
dma_release_channel(host->dma_tx_channel);
|
||||
host->dma_rx_channel = host->dma_tx_channel = NULL;
|
||||
}
|
||||
@ -1285,7 +1265,7 @@ static void mmci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
|
||||
* indicating signal direction for the signals in
|
||||
* the SD/MMC bus and feedback-clock usage.
|
||||
*/
|
||||
pwr |= host->plat->sigdir;
|
||||
pwr |= host->pwr_reg_add;
|
||||
|
||||
if (ios->bus_width == MMC_BUS_WIDTH_4)
|
||||
pwr &= ~MCI_ST_DATA74DIREN;
|
||||
@ -1326,35 +1306,18 @@ static void mmci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
|
||||
pm_runtime_put_autosuspend(mmc_dev(mmc));
|
||||
}
|
||||
|
||||
static int mmci_get_ro(struct mmc_host *mmc)
|
||||
{
|
||||
struct mmci_host *host = mmc_priv(mmc);
|
||||
|
||||
if (host->gpio_wp == -ENOSYS)
|
||||
return -ENOSYS;
|
||||
|
||||
return gpio_get_value_cansleep(host->gpio_wp);
|
||||
}
|
||||
|
||||
static int mmci_get_cd(struct mmc_host *mmc)
|
||||
{
|
||||
struct mmci_host *host = mmc_priv(mmc);
|
||||
struct mmci_platform_data *plat = host->plat;
|
||||
unsigned int status;
|
||||
unsigned int status = mmc_gpio_get_cd(mmc);
|
||||
|
||||
if (host->gpio_cd == -ENOSYS) {
|
||||
if (status == -ENOSYS) {
|
||||
if (!plat->status)
|
||||
return 1; /* Assume always present */
|
||||
|
||||
status = plat->status(mmc_dev(host->mmc));
|
||||
} else
|
||||
status = !!gpio_get_value_cansleep(host->gpio_cd)
|
||||
^ plat->cd_invert;
|
||||
|
||||
/*
|
||||
* Use positive logic throughout - status is zero for no card,
|
||||
* non-zero for card inserted.
|
||||
*/
|
||||
}
|
||||
return status;
|
||||
}
|
||||
|
||||
@ -1391,70 +1354,44 @@ static int mmci_sig_volt_switch(struct mmc_host *mmc, struct mmc_ios *ios)
|
||||
return ret;
|
||||
}
|
||||
|
||||
static irqreturn_t mmci_cd_irq(int irq, void *dev_id)
|
||||
{
|
||||
struct mmci_host *host = dev_id;
|
||||
|
||||
mmc_detect_change(host->mmc, msecs_to_jiffies(500));
|
||||
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
static struct mmc_host_ops mmci_ops = {
|
||||
.request = mmci_request,
|
||||
.pre_req = mmci_pre_request,
|
||||
.post_req = mmci_post_request,
|
||||
.set_ios = mmci_set_ios,
|
||||
.get_ro = mmci_get_ro,
|
||||
.get_ro = mmc_gpio_get_ro,
|
||||
.get_cd = mmci_get_cd,
|
||||
.start_signal_voltage_switch = mmci_sig_volt_switch,
|
||||
};
|
||||
|
||||
#ifdef CONFIG_OF
|
||||
static void mmci_dt_populate_generic_pdata(struct device_node *np,
|
||||
struct mmci_platform_data *pdata)
|
||||
static int mmci_of_parse(struct device_node *np, struct mmc_host *mmc)
|
||||
{
|
||||
int bus_width = 0;
|
||||
struct mmci_host *host = mmc_priv(mmc);
|
||||
int ret = mmc_of_parse(mmc);
|
||||
|
||||
pdata->gpio_wp = of_get_named_gpio(np, "wp-gpios", 0);
|
||||
pdata->gpio_cd = of_get_named_gpio(np, "cd-gpios", 0);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
if (of_get_property(np, "cd-inverted", NULL))
|
||||
pdata->cd_invert = true;
|
||||
else
|
||||
pdata->cd_invert = false;
|
||||
|
||||
of_property_read_u32(np, "max-frequency", &pdata->f_max);
|
||||
if (!pdata->f_max)
|
||||
pr_warn("%s has no 'max-frequency' property\n", np->full_name);
|
||||
if (of_get_property(np, "st,sig-dir-dat0", NULL))
|
||||
host->pwr_reg_add |= MCI_ST_DATA0DIREN;
|
||||
if (of_get_property(np, "st,sig-dir-dat2", NULL))
|
||||
host->pwr_reg_add |= MCI_ST_DATA2DIREN;
|
||||
if (of_get_property(np, "st,sig-dir-dat31", NULL))
|
||||
host->pwr_reg_add |= MCI_ST_DATA31DIREN;
|
||||
if (of_get_property(np, "st,sig-dir-dat74", NULL))
|
||||
host->pwr_reg_add |= MCI_ST_DATA74DIREN;
|
||||
if (of_get_property(np, "st,sig-dir-cmd", NULL))
|
||||
host->pwr_reg_add |= MCI_ST_CMDDIREN;
|
||||
if (of_get_property(np, "st,sig-pin-fbclk", NULL))
|
||||
host->pwr_reg_add |= MCI_ST_FBCLKEN;
|
||||
|
||||
if (of_get_property(np, "mmc-cap-mmc-highspeed", NULL))
|
||||
pdata->capabilities |= MMC_CAP_MMC_HIGHSPEED;
|
||||
mmc->caps |= MMC_CAP_MMC_HIGHSPEED;
|
||||
if (of_get_property(np, "mmc-cap-sd-highspeed", NULL))
|
||||
pdata->capabilities |= MMC_CAP_SD_HIGHSPEED;
|
||||
mmc->caps |= MMC_CAP_SD_HIGHSPEED;
|
||||
|
||||
of_property_read_u32(np, "bus-width", &bus_width);
|
||||
switch (bus_width) {
|
||||
case 0 :
|
||||
/* No bus-width supplied. */
|
||||
break;
|
||||
case 4 :
|
||||
pdata->capabilities |= MMC_CAP_4_BIT_DATA;
|
||||
break;
|
||||
case 8 :
|
||||
pdata->capabilities |= MMC_CAP_8_BIT_DATA;
|
||||
break;
|
||||
default :
|
||||
pr_warn("%s: Unsupported bus width\n", np->full_name);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
#else
|
||||
static void mmci_dt_populate_generic_pdata(struct device_node *np,
|
||||
struct mmci_platform_data *pdata)
|
||||
{
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
static int mmci_probe(struct amba_device *dev,
|
||||
const struct amba_id *id)
|
||||
@ -1478,26 +1415,17 @@ static int mmci_probe(struct amba_device *dev,
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
if (np)
|
||||
mmci_dt_populate_generic_pdata(np, plat);
|
||||
|
||||
ret = amba_request_regions(dev, DRIVER_NAME);
|
||||
if (ret)
|
||||
goto out;
|
||||
|
||||
mmc = mmc_alloc_host(sizeof(struct mmci_host), &dev->dev);
|
||||
if (!mmc) {
|
||||
ret = -ENOMEM;
|
||||
goto rel_regions;
|
||||
}
|
||||
if (!mmc)
|
||||
return -ENOMEM;
|
||||
|
||||
ret = mmci_of_parse(np, mmc);
|
||||
if (ret)
|
||||
goto host_free;
|
||||
|
||||
host = mmc_priv(mmc);
|
||||
host->mmc = mmc;
|
||||
|
||||
host->gpio_wp = -ENOSYS;
|
||||
host->gpio_cd = -ENOSYS;
|
||||
host->gpio_cd_irq = -1;
|
||||
|
||||
host->hw_designer = amba_manf(dev);
|
||||
host->hw_revision = amba_rev(dev);
|
||||
dev_dbg(mmc_dev(mmc), "designer ID = 0x%02x\n", host->hw_designer);
|
||||
@ -1529,10 +1457,11 @@ static int mmci_probe(struct amba_device *dev,
|
||||
dev_dbg(mmc_dev(mmc), "eventual mclk rate: %u Hz\n",
|
||||
host->mclk);
|
||||
}
|
||||
|
||||
host->phybase = dev->res.start;
|
||||
host->base = ioremap(dev->res.start, resource_size(&dev->res));
|
||||
if (!host->base) {
|
||||
ret = -ENOMEM;
|
||||
host->base = devm_ioremap_resource(&dev->dev, &dev->res);
|
||||
if (IS_ERR(host->base)) {
|
||||
ret = PTR_ERR(host->base);
|
||||
goto clk_disable;
|
||||
}
|
||||
|
||||
@ -1546,15 +1475,13 @@ static int mmci_probe(struct amba_device *dev,
|
||||
else
|
||||
mmc->f_min = DIV_ROUND_UP(host->mclk, 512);
|
||||
/*
|
||||
* If the platform data supplies a maximum operating
|
||||
* frequency, this takes precedence. Else, we fall back
|
||||
* to using the module parameter, which has a (low)
|
||||
* default value in case it is not specified. Either
|
||||
* value must not exceed the clock rate into the block,
|
||||
* of course.
|
||||
* If no maximum operating frequency is supplied, fall back to use
|
||||
* the module parameter, which has a (low) default value in case it
|
||||
* is not specified. Either value must not exceed the clock rate into
|
||||
* the block, of course.
|
||||
*/
|
||||
if (plat->f_max)
|
||||
mmc->f_max = min(host->mclk, plat->f_max);
|
||||
if (mmc->f_max)
|
||||
mmc->f_max = min(host->mclk, mmc->f_max);
|
||||
else
|
||||
mmc->f_max = min(host->mclk, fmax);
|
||||
dev_dbg(mmc_dev(mmc), "clocking block at %u Hz\n", mmc->f_max);
|
||||
@ -1566,8 +1493,15 @@ static int mmci_probe(struct amba_device *dev,
|
||||
else if (plat->ocr_mask)
|
||||
dev_warn(mmc_dev(mmc), "Platform OCR mask is ignored\n");
|
||||
|
||||
mmc->caps = plat->capabilities;
|
||||
mmc->caps2 = plat->capabilities2;
|
||||
/* DT takes precedence over platform data. */
|
||||
if (!np) {
|
||||
if (!plat->cd_invert)
|
||||
mmc->caps2 |= MMC_CAP2_CD_ACTIVE_HIGH;
|
||||
mmc->caps2 |= MMC_CAP2_RO_ACTIVE_HIGH;
|
||||
}
|
||||
|
||||
/* We support these capabilities. */
|
||||
mmc->caps |= MMC_CAP_CMD23;
|
||||
|
||||
if (variant->busy_detect) {
|
||||
mmci_ops.card_busy = mmci_card_busy;
|
||||
@ -1579,7 +1513,7 @@ static int mmci_probe(struct amba_device *dev,
|
||||
mmc->ops = &mmci_ops;
|
||||
|
||||
/* We support these PM capabilities. */
|
||||
mmc->pm_caps = MMC_PM_KEEP_POWER;
|
||||
mmc->pm_caps |= MMC_PM_KEEP_POWER;
|
||||
|
||||
/*
|
||||
* We can do SGIO
|
||||
@ -1616,62 +1550,30 @@ static int mmci_probe(struct amba_device *dev,
|
||||
writel(0, host->base + MMCIMASK1);
|
||||
writel(0xfff, host->base + MMCICLEAR);
|
||||
|
||||
if (plat->gpio_cd == -EPROBE_DEFER) {
|
||||
ret = -EPROBE_DEFER;
|
||||
goto err_gpio_cd;
|
||||
/* If DT, cd/wp gpios must be supplied through it. */
|
||||
if (!np && gpio_is_valid(plat->gpio_cd)) {
|
||||
ret = mmc_gpio_request_cd(mmc, plat->gpio_cd, 0);
|
||||
if (ret)
|
||||
goto clk_disable;
|
||||
}
|
||||
if (gpio_is_valid(plat->gpio_cd)) {
|
||||
ret = gpio_request(plat->gpio_cd, DRIVER_NAME " (cd)");
|
||||
if (ret == 0)
|
||||
ret = gpio_direction_input(plat->gpio_cd);
|
||||
if (ret == 0)
|
||||
host->gpio_cd = plat->gpio_cd;
|
||||
else if (ret != -ENOSYS)
|
||||
goto err_gpio_cd;
|
||||
|
||||
/*
|
||||
* A gpio pin that will detect cards when inserted and removed
|
||||
* will most likely want to trigger on the edges if it is
|
||||
* 0 when ejected and 1 when inserted (or mutatis mutandis
|
||||
* for the inverted case) so we request triggers on both
|
||||
* edges.
|
||||
*/
|
||||
ret = request_any_context_irq(gpio_to_irq(plat->gpio_cd),
|
||||
mmci_cd_irq,
|
||||
IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING,
|
||||
DRIVER_NAME " (cd)", host);
|
||||
if (ret >= 0)
|
||||
host->gpio_cd_irq = gpio_to_irq(plat->gpio_cd);
|
||||
}
|
||||
if (plat->gpio_wp == -EPROBE_DEFER) {
|
||||
ret = -EPROBE_DEFER;
|
||||
goto err_gpio_wp;
|
||||
}
|
||||
if (gpio_is_valid(plat->gpio_wp)) {
|
||||
ret = gpio_request(plat->gpio_wp, DRIVER_NAME " (wp)");
|
||||
if (ret == 0)
|
||||
ret = gpio_direction_input(plat->gpio_wp);
|
||||
if (ret == 0)
|
||||
host->gpio_wp = plat->gpio_wp;
|
||||
else if (ret != -ENOSYS)
|
||||
goto err_gpio_wp;
|
||||
if (!np && gpio_is_valid(plat->gpio_wp)) {
|
||||
ret = mmc_gpio_request_ro(mmc, plat->gpio_wp);
|
||||
if (ret)
|
||||
goto clk_disable;
|
||||
}
|
||||
|
||||
if ((host->plat->status || host->gpio_cd != -ENOSYS)
|
||||
&& host->gpio_cd_irq < 0)
|
||||
mmc->caps |= MMC_CAP_NEEDS_POLL;
|
||||
|
||||
ret = request_irq(dev->irq[0], mmci_irq, IRQF_SHARED, DRIVER_NAME " (cmd)", host);
|
||||
ret = devm_request_irq(&dev->dev, dev->irq[0], mmci_irq, IRQF_SHARED,
|
||||
DRIVER_NAME " (cmd)", host);
|
||||
if (ret)
|
||||
goto unmap;
|
||||
goto clk_disable;
|
||||
|
||||
if (!dev->irq[1])
|
||||
host->singleirq = true;
|
||||
else {
|
||||
ret = request_irq(dev->irq[1], mmci_pio_irq, IRQF_SHARED,
|
||||
DRIVER_NAME " (pio)", host);
|
||||
ret = devm_request_irq(&dev->dev, dev->irq[1], mmci_pio_irq,
|
||||
IRQF_SHARED, DRIVER_NAME " (pio)", host);
|
||||
if (ret)
|
||||
goto irq0_free;
|
||||
goto clk_disable;
|
||||
}
|
||||
|
||||
writel(MCI_IRQENABLE, host->base + MMCIMASK0);
|
||||
@ -1693,25 +1595,10 @@ static int mmci_probe(struct amba_device *dev,
|
||||
|
||||
return 0;
|
||||
|
||||
irq0_free:
|
||||
free_irq(dev->irq[0], host);
|
||||
unmap:
|
||||
if (host->gpio_wp != -ENOSYS)
|
||||
gpio_free(host->gpio_wp);
|
||||
err_gpio_wp:
|
||||
if (host->gpio_cd_irq >= 0)
|
||||
free_irq(host->gpio_cd_irq, host);
|
||||
if (host->gpio_cd != -ENOSYS)
|
||||
gpio_free(host->gpio_cd);
|
||||
err_gpio_cd:
|
||||
iounmap(host->base);
|
||||
clk_disable:
|
||||
clk_disable_unprepare(host->clk);
|
||||
host_free:
|
||||
mmc_free_host(mmc);
|
||||
rel_regions:
|
||||
amba_release_regions(dev);
|
||||
out:
|
||||
return ret;
|
||||
}
|
||||
|
||||
@ -1737,92 +1624,46 @@ static int mmci_remove(struct amba_device *dev)
|
||||
writel(0, host->base + MMCIDATACTRL);
|
||||
|
||||
mmci_dma_release(host);
|
||||
free_irq(dev->irq[0], host);
|
||||
if (!host->singleirq)
|
||||
free_irq(dev->irq[1], host);
|
||||
|
||||
if (host->gpio_wp != -ENOSYS)
|
||||
gpio_free(host->gpio_wp);
|
||||
if (host->gpio_cd_irq >= 0)
|
||||
free_irq(host->gpio_cd_irq, host);
|
||||
if (host->gpio_cd != -ENOSYS)
|
||||
gpio_free(host->gpio_cd);
|
||||
|
||||
iounmap(host->base);
|
||||
clk_disable_unprepare(host->clk);
|
||||
|
||||
mmc_free_host(mmc);
|
||||
|
||||
amba_release_regions(dev);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_SUSPEND
|
||||
static int mmci_suspend(struct device *dev)
|
||||
{
|
||||
struct amba_device *adev = to_amba_device(dev);
|
||||
struct mmc_host *mmc = amba_get_drvdata(adev);
|
||||
|
||||
if (mmc) {
|
||||
struct mmci_host *host = mmc_priv(mmc);
|
||||
pm_runtime_get_sync(dev);
|
||||
writel(0, host->base + MMCIMASK0);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int mmci_resume(struct device *dev)
|
||||
{
|
||||
struct amba_device *adev = to_amba_device(dev);
|
||||
struct mmc_host *mmc = amba_get_drvdata(adev);
|
||||
|
||||
if (mmc) {
|
||||
struct mmci_host *host = mmc_priv(mmc);
|
||||
writel(MCI_IRQENABLE, host->base + MMCIMASK0);
|
||||
pm_runtime_put(dev);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_PM_RUNTIME
|
||||
#ifdef CONFIG_PM
|
||||
static void mmci_save(struct mmci_host *host)
|
||||
{
|
||||
unsigned long flags;
|
||||
|
||||
if (host->variant->pwrreg_nopower) {
|
||||
spin_lock_irqsave(&host->lock, flags);
|
||||
spin_lock_irqsave(&host->lock, flags);
|
||||
|
||||
writel(0, host->base + MMCIMASK0);
|
||||
writel(0, host->base + MMCIMASK0);
|
||||
if (host->variant->pwrreg_nopower) {
|
||||
writel(0, host->base + MMCIDATACTRL);
|
||||
writel(0, host->base + MMCIPOWER);
|
||||
writel(0, host->base + MMCICLOCK);
|
||||
mmci_reg_delay(host);
|
||||
|
||||
spin_unlock_irqrestore(&host->lock, flags);
|
||||
}
|
||||
mmci_reg_delay(host);
|
||||
|
||||
spin_unlock_irqrestore(&host->lock, flags);
|
||||
}
|
||||
|
||||
static void mmci_restore(struct mmci_host *host)
|
||||
{
|
||||
unsigned long flags;
|
||||
|
||||
if (host->variant->pwrreg_nopower) {
|
||||
spin_lock_irqsave(&host->lock, flags);
|
||||
spin_lock_irqsave(&host->lock, flags);
|
||||
|
||||
if (host->variant->pwrreg_nopower) {
|
||||
writel(host->clk_reg, host->base + MMCICLOCK);
|
||||
writel(host->datactrl_reg, host->base + MMCIDATACTRL);
|
||||
writel(host->pwr_reg, host->base + MMCIPOWER);
|
||||
writel(MCI_IRQENABLE, host->base + MMCIMASK0);
|
||||
mmci_reg_delay(host);
|
||||
|
||||
spin_unlock_irqrestore(&host->lock, flags);
|
||||
}
|
||||
writel(MCI_IRQENABLE, host->base + MMCIMASK0);
|
||||
mmci_reg_delay(host);
|
||||
|
||||
spin_unlock_irqrestore(&host->lock, flags);
|
||||
}
|
||||
|
||||
static int mmci_runtime_suspend(struct device *dev)
|
||||
@ -1857,8 +1698,9 @@ static int mmci_runtime_resume(struct device *dev)
|
||||
#endif
|
||||
|
||||
static const struct dev_pm_ops mmci_dev_pm_ops = {
|
||||
SET_SYSTEM_SLEEP_PM_OPS(mmci_suspend, mmci_resume)
|
||||
SET_RUNTIME_PM_OPS(mmci_runtime_suspend, mmci_runtime_resume, NULL)
|
||||
SET_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend,
|
||||
pm_runtime_force_resume)
|
||||
SET_PM_RUNTIME_PM_OPS(mmci_runtime_suspend, mmci_runtime_resume, NULL)
|
||||
};
|
||||
|
||||
static struct amba_id mmci_ids[] = {
|
||||
|
@ -13,6 +13,16 @@
|
||||
#define MCI_PWR_ON 0x03
|
||||
#define MCI_OD (1 << 6)
|
||||
#define MCI_ROD (1 << 7)
|
||||
/*
|
||||
* The ST Micro version does not have ROD and reuse the voltage registers for
|
||||
* direction settings.
|
||||
*/
|
||||
#define MCI_ST_DATA2DIREN (1 << 2)
|
||||
#define MCI_ST_CMDDIREN (1 << 3)
|
||||
#define MCI_ST_DATA0DIREN (1 << 4)
|
||||
#define MCI_ST_DATA31DIREN (1 << 5)
|
||||
#define MCI_ST_FBCLKEN (1 << 7)
|
||||
#define MCI_ST_DATA74DIREN (1 << 8)
|
||||
|
||||
#define MMCICLOCK 0x004
|
||||
#define MCI_CLK_ENABLE (1 << 8)
|
||||
@ -176,9 +186,6 @@ struct mmci_host {
|
||||
struct mmc_data *data;
|
||||
struct mmc_host *mmc;
|
||||
struct clk *clk;
|
||||
int gpio_cd;
|
||||
int gpio_wp;
|
||||
int gpio_cd_irq;
|
||||
bool singleirq;
|
||||
|
||||
spinlock_t lock;
|
||||
@ -186,6 +193,7 @@ struct mmci_host {
|
||||
unsigned int mclk;
|
||||
unsigned int cclk;
|
||||
u32 pwr_reg;
|
||||
u32 pwr_reg_add;
|
||||
u32 clk_reg;
|
||||
u32 datactrl_reg;
|
||||
u32 busy_status;
|
||||
|
@ -6,28 +6,9 @@
|
||||
|
||||
#include <linux/mmc/host.h>
|
||||
|
||||
|
||||
/*
|
||||
* These defines is places here due to access is needed from machine
|
||||
* configuration files. The ST Micro version does not have ROD and
|
||||
* reuse the voltage registers for direction settings.
|
||||
*/
|
||||
#define MCI_ST_DATA2DIREN (1 << 2)
|
||||
#define MCI_ST_CMDDIREN (1 << 3)
|
||||
#define MCI_ST_DATA0DIREN (1 << 4)
|
||||
#define MCI_ST_DATA31DIREN (1 << 5)
|
||||
#define MCI_ST_FBCLKEN (1 << 7)
|
||||
#define MCI_ST_DATA74DIREN (1 << 8)
|
||||
|
||||
/* Just some dummy forwarding */
|
||||
struct dma_chan;
|
||||
|
||||
/**
|
||||
* struct mmci_platform_data - platform configuration for the MMCI
|
||||
* (also known as PL180) block.
|
||||
* @f_max: the maximum operational frequency for this host in this
|
||||
* platform configuration. When this is specified it takes precedence
|
||||
* over the module parameter for the same frequency.
|
||||
* @ocr_mask: available voltages on the 4 pins from the block, this
|
||||
* is ignored if a regulator is used, see the MMC_VDD_* masks in
|
||||
* mmc/host.h
|
||||
@ -42,37 +23,14 @@ struct dma_chan;
|
||||
* @gpio_wp: read this GPIO pin to see if the card is write protected
|
||||
* @gpio_cd: read this GPIO pin to detect card insertion
|
||||
* @cd_invert: true if the gpio_cd pin value is active low
|
||||
* @capabilities: the capabilities of the block as implemented in
|
||||
* this platform, signify anything MMC_CAP_* from mmc/host.h
|
||||
* @capabilities2: more capabilities, MMC_CAP2_* from mmc/host.h
|
||||
* @sigdir: a bit field indicating for what bits in the MMC bus the host
|
||||
* should enable signal direction indication.
|
||||
* @dma_filter: function used to select an appropriate RX and TX
|
||||
* DMA channel to be used for DMA, if and only if you're deploying the
|
||||
* generic DMA engine
|
||||
* @dma_rx_param: parameter passed to the DMA allocation
|
||||
* filter in order to select an appropriate RX channel. If
|
||||
* there is a bidirectional RX+TX channel, then just specify
|
||||
* this and leave dma_tx_param set to NULL
|
||||
* @dma_tx_param: parameter passed to the DMA allocation
|
||||
* filter in order to select an appropriate TX channel. If this
|
||||
* is NULL the driver will attempt to use the RX channel as a
|
||||
* bidirectional channel
|
||||
*/
|
||||
struct mmci_platform_data {
|
||||
unsigned int f_max;
|
||||
unsigned int ocr_mask;
|
||||
int (*ios_handler)(struct device *, struct mmc_ios *);
|
||||
unsigned int (*status)(struct device *);
|
||||
int gpio_wp;
|
||||
int gpio_cd;
|
||||
bool cd_invert;
|
||||
unsigned long capabilities;
|
||||
unsigned long capabilities2;
|
||||
u32 sigdir;
|
||||
bool (*dma_filter)(struct dma_chan *chan, void *filter_param);
|
||||
void *dma_rx_param;
|
||||
void *dma_tx_param;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
Loading…
Reference in New Issue
Block a user