summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--arch/Kconfig1
-rw-r--r--arch/arm/Kconfig11
-rw-r--r--arch/arm/dts/dra7-evm.dts6
-rw-r--r--arch/arm/dts/dra72-evm.dts6
-rw-r--r--arch/arm/dts/k2e-evm.dts3
-rw-r--r--arch/arm/dts/k2g-evm.dts69
-rw-r--r--arch/arm/dts/k2g.dtsi61
-rw-r--r--arch/arm/dts/k2hk-evm.dts3
-rw-r--r--arch/arm/dts/k2l-evm.dts3
-rw-r--r--arch/arm/dts/keystone.dtsi3
-rw-r--r--arch/arm/mach-rockchip/Kconfig27
-rw-r--r--arch/powerpc/include/asm/arch-mpc85xx/gpio.h6
-rw-r--r--arch/x86/cpu/ivybridge/lpc.c6
-rw-r--r--board/evb_rk3036/evb_rk3036/MAINTAINERS6
-rw-r--r--board/kylin/kylin_rk3036/MAINTAINERS6
-rw-r--r--cmd/sf.c2
-rw-r--r--common/env_sf.c8
-rw-r--r--common/fb_mmc.c2
-rw-r--r--common/spl/spl_mmc.c6
-rw-r--r--configs/dragonboard410c_defconfig2
-rw-r--r--configs/k2e_evm_defconfig2
-rw-r--r--configs/k2g_evm_defconfig4
-rw-r--r--configs/k2hk_evm_defconfig2
-rw-r--r--configs/k2l_evm_defconfig2
-rw-r--r--configs/sandbox_defconfig4
-rw-r--r--drivers/core/device.c11
-rw-r--r--drivers/dfu/dfu_mmc.c11
-rw-r--r--drivers/gpio/mpc85xx_gpio.c37
-rw-r--r--drivers/misc/cros_ec_sandbox.c11
-rw-r--r--drivers/mmc/Kconfig11
-rw-r--r--drivers/mmc/Makefile3
-rw-r--r--drivers/mmc/dw_mmc.c33
-rw-r--r--drivers/mmc/mmc-uclass.c146
-rw-r--r--drivers/mmc/mmc.c371
-rw-r--r--drivers/mmc/mmc_boot.c131
-rw-r--r--drivers/mmc/mmc_legacy.c91
-rw-r--r--drivers/mmc/mmc_private.h47
-rw-r--r--drivers/mmc/msm_sdhci.c35
-rw-r--r--drivers/mmc/rockchip_dw_mmc.c14
-rw-r--r--drivers/mmc/sandbox_mmc.c17
-rw-r--r--drivers/mmc/sdhci.c147
-rw-r--r--drivers/spi/cadence_qspi.c3
-rw-r--r--drivers/spi/cadence_qspi.h2
-rw-r--r--drivers/spi/cadence_qspi_apb.c15
-rw-r--r--drivers/spi/davinci_spi.c329
-rw-r--r--drivers/spi/spi-uclass.c10
-rw-r--r--include/configs/k2g_evm.h6
-rw-r--r--include/configs/rk3036_common.h1
-rw-r--r--include/configs/rk3288_common.h1
-rw-r--r--include/configs/ti_armv7_keystone2.h4
-rw-r--r--include/dm/device.h13
-rw-r--r--include/dm/uclass-id.h4
-rw-r--r--include/dwmmc.h73
-rw-r--r--include/fdtdec.h8
-rw-r--r--include/mmc.h66
-rw-r--r--include/sdhci.h80
-rw-r--r--lib/fdtdec.c19
-rw-r--r--tools/patman/patchstream.py38
58 files changed, 1445 insertions, 594 deletions
diff --git a/arch/Kconfig b/arch/Kconfig
index 566f044..c43787c 100644
--- a/arch/Kconfig
+++ b/arch/Kconfig
@@ -63,6 +63,7 @@ config SANDBOX
select DM_I2C
select DM_SPI
select DM_GPIO
+ select DM_MMC
config SH
bool "SuperH architecture"
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index 3237a74..585b408 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -842,7 +842,18 @@ config ARCH_ROCKCHIP
select SPL
select OF_CONTROL
select CPU_V7
+ select BLK
select DM
+ select SPL_DM
+ select SYS_MALLOC_F
+ select SPL_SYS_MALLOC_SIMPLE
+ select DM_GPIO
+ select DM_I2C
+ select DM_MMC
+ select DM_MMC_OPS
+ select DM_SERIAL
+ select DM_SPI
+ select DM_SPI_FLASH
config TARGET_THUNDERX_88XX
bool "Support ThunderX 88xx"
diff --git a/arch/arm/dts/dra7-evm.dts b/arch/arm/dts/dra7-evm.dts
index 08ef04e..429b9ed 100644
--- a/arch/arm/dts/dra7-evm.dts
+++ b/arch/arm/dts/dra7-evm.dts
@@ -491,15 +491,13 @@
pinctrl-names = "default";
pinctrl-0 = <&qspi1_pins>;
- spi-max-frequency = <48000000>;
+ spi-max-frequency = <64000000>;
m25p80@0 {
compatible = "s25fl256s1","spi-flash";
- spi-max-frequency = <48000000>;
+ spi-max-frequency = <64000000>;
reg = <0>;
spi-tx-bus-width = <1>;
spi-rx-bus-width = <4>;
- spi-cpol;
- spi-cpha;
#address-cells = <1>;
#size-cells = <1>;
diff --git a/arch/arm/dts/dra72-evm.dts b/arch/arm/dts/dra72-evm.dts
index 205103e..ced2f11 100644
--- a/arch/arm/dts/dra72-evm.dts
+++ b/arch/arm/dts/dra72-evm.dts
@@ -603,15 +603,13 @@
pinctrl-names = "default";
pinctrl-0 = <&qspi1_pins>;
- spi-max-frequency = <48000000>;
+ spi-max-frequency = <64000000>;
m25p80@0 {
compatible = "s25fl256s1","spi-flash";
- spi-max-frequency = <48000000>;
+ spi-max-frequency = <64000000>;
reg = <0>;
spi-tx-bus-width = <1>;
spi-rx-bus-width = <4>;
- spi-cpol;
- spi-cpha;
#address-cells = <1>;
#size-cells = <1>;
diff --git a/arch/arm/dts/k2e-evm.dts b/arch/arm/dts/k2e-evm.dts
index 50c83c2..e2c3fb4 100644
--- a/arch/arm/dts/k2e-evm.dts
+++ b/arch/arm/dts/k2e-evm.dts
@@ -119,10 +119,11 @@
};
&spi0 {
+ status = "okay";
nor_flash: n25q128a11@0 {
#address-cells = <1>;
#size-cells = <1>;
- compatible = "Micron,n25q128a11";
+ compatible = "Micron,n25q128a11", "spi-flash";
spi-max-frequency = <54000000>;
m25p,fast-read;
reg = <0>;
diff --git a/arch/arm/dts/k2g-evm.dts b/arch/arm/dts/k2g-evm.dts
index 0ca36ef..e95efd4 100644
--- a/arch/arm/dts/k2g-evm.dts
+++ b/arch/arm/dts/k2g-evm.dts
@@ -31,3 +31,72 @@
&gbe0 {
phy-handle = <&ethphy0>;
};
+
+&spi1 {
+ status = "okay";
+
+ spi_nor: flash@0 {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ compatible = "spi-flash";
+ spi-max-frequency = <50000000>;
+ m25p,fast-read;
+ reg = <0>;
+
+ partition@0 {
+ label = "u-boot-spl";
+ reg = <0x0 0x80000>;
+ read-only;
+ };
+
+ partition@1 {
+ label = "misc";
+ reg = <0x80000 0xf80000>;
+ };
+ };
+};
+
+&qspi {
+ status = "okay";
+
+ flash0: m25p80@0 {
+ compatible = "s25fl512s","spi-flash";
+ reg = <0>;
+ spi-tx-bus-width = <1>;
+ spi-rx-bus-width = <4>;
+ spi-max-frequency = <96000000>;
+ #address-cells = <1>;
+ #size-cells = <1>;
+ tshsl-ns = <392>;
+ tsd2d-ns = <392>;
+ tchsh-ns = <100>;
+ tslch-ns = <100>;
+ block-size = <18>;
+
+
+ partition@0 {
+ label = "QSPI.u-boot-spl-os";
+ reg = <0x00000000 0x00100000>;
+ };
+ partition@1 {
+ label = "QSPI.u-boot-env";
+ reg = <0x00100000 0x00040000>;
+ };
+ partition@2 {
+ label = "QSPI.skern";
+ reg = <0x00140000 0x0040000>;
+ };
+ partition@3 {
+ label = "QSPI.pmmc-firmware";
+ reg = <0x00180000 0x0040000>;
+ };
+ partition@4 {
+ label = "QSPI.kernel";
+ reg = <0x001C0000 0x0800000>;
+ };
+ partition@5 {
+ label = "QSPI.file-system";
+ reg = <0x009C0000 0x3640000>;
+ };
+ };
+};
diff --git a/arch/arm/dts/k2g.dtsi b/arch/arm/dts/k2g.dtsi
index a3ed444..00cd492 100644
--- a/arch/arm/dts/k2g.dtsi
+++ b/arch/arm/dts/k2g.dtsi
@@ -19,6 +19,11 @@
aliases {
serial0 = &uart0;
+ spi0 = &spi0;
+ spi1 = &spi1;
+ spi2 = &spi2;
+ spi3 = &spi3;
+ spi4 = &qspi;
};
memory {
@@ -80,6 +85,19 @@
bus_freq = <2500000>;
};
+ qspi: qspi@2940000 {
+ compatible = "cadence,qspi";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <0x02940000 0x1000>,
+ <0x24000000 0x4000000>;
+ interrupts = <GIC_SPI 198 IRQ_TYPE_EDGE_RISING>;
+ num-cs = <4>;
+ fifo-depth = <256>;
+ sram-size = <256>;
+ status = "disabled";
+ };
+
#include "k2g-netcp.dtsi"
pmmc: pmmc@2900000 {
@@ -88,5 +106,48 @@
ti,lpsc_module = <1>;
};
+ spi0: spi@21805400 {
+ compatible = "ti,keystone-spi", "ti,dm6441-spi";
+ reg = <0x21805400 0x200>;
+ num-cs = <4>;
+ ti,davinci-spi-intr-line = <0>;
+ interrupts = <GIC_SPI 64 IRQ_TYPE_EDGE_RISING>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ status = "disabled";
+ };
+
+ spi1: spi@21805800 {
+ compatible = "ti,keystone-spi", "ti,dm6441-spi";
+ reg = <0x21805800 0x200>;
+ num-cs = <4>;
+ ti,davinci-spi-intr-line = <0>;
+ interrupts = <GIC_SPI 66 IRQ_TYPE_EDGE_RISING>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ status = "disabled";
+ };
+
+ spi2: spi@21805c00 {
+ compatible = "ti,keystone-spi", "ti,dm6441-spi";
+ reg = <0x21805C00 0x200>;
+ num-cs = <4>;
+ ti,davinci-spi-intr-line = <0>;
+ interrupts = <GIC_SPI 68 IRQ_TYPE_EDGE_RISING>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ status = "disabled";
+ };
+
+ spi3: spi@21806000 {
+ compatible = "ti,keystone-spi", "ti,dm6441-spi";
+ reg = <0x21806000 0x200>;
+ num-cs = <4>;
+ ti,davinci-spi-intr-line = <0>;
+ interrupts = <GIC_SPI 70 IRQ_TYPE_EDGE_RISING>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ status = "disabled";
+ };
};
};
diff --git a/arch/arm/dts/k2hk-evm.dts b/arch/arm/dts/k2hk-evm.dts
index 660ebf5..c5cad2c 100644
--- a/arch/arm/dts/k2hk-evm.dts
+++ b/arch/arm/dts/k2hk-evm.dts
@@ -147,10 +147,11 @@
};
&spi0 {
+ status = "okay";
nor_flash: n25q128a11@0 {
#address-cells = <1>;
#size-cells = <1>;
- compatible = "Micron,n25q128a11";
+ compatible = "Micron,n25q128a11", "spi-flash";
spi-max-frequency = <54000000>;
m25p,fast-read;
reg = <0>;
diff --git a/arch/arm/dts/k2l-evm.dts b/arch/arm/dts/k2l-evm.dts
index 9a69a6b..da0661b 100644
--- a/arch/arm/dts/k2l-evm.dts
+++ b/arch/arm/dts/k2l-evm.dts
@@ -96,10 +96,11 @@
};
&spi0 {
+ status ="okay";
nor_flash: n25q128a11@0 {
#address-cells = <1>;
#size-cells = <1>;
- compatible = "Micron,n25q128a11";
+ compatible = "Micron,n25q128a11", "spi-flash";
spi-max-frequency = <54000000>;
m25p,fast-read;
reg = <0>;
diff --git a/arch/arm/dts/keystone.dtsi b/arch/arm/dts/keystone.dtsi
index f39b969..be97f3f 100644
--- a/arch/arm/dts/keystone.dtsi
+++ b/arch/arm/dts/keystone.dtsi
@@ -19,6 +19,9 @@
aliases {
serial0 = &uart0;
+ spi0 = &spi0;
+ spi1 = &spi1;
+ spi2 = &spi2;
};
chosen {
diff --git a/arch/arm/mach-rockchip/Kconfig b/arch/arm/mach-rockchip/Kconfig
index 2a8afac..c49cc19 100644
--- a/arch/arm/mach-rockchip/Kconfig
+++ b/arch/arm/mach-rockchip/Kconfig
@@ -17,33 +17,6 @@ config ROCKCHIP_RK3036
and video codec support. Peripherals include Gigabit Ethernet,
USB2 host and OTG, SDIO, I2S, UART, SPI, I2C and PWMs.
-config SYS_MALLOC_F
- default y
-
-config SPL_SYS_MALLOC_SIMPLE
- default y
-
-config SPL_DM
- default y
-
-config DM_SERIAL
- default y
-
-config DM_SPI
- default y
-
-config DM_SPI_FLASH
- default y
-
-config DM_I2C
- default y
-
-config DM_GPIO
- default y
-
-config BLK
- default y
-
source "arch/arm/mach-rockchip/rk3288/Kconfig"
source "arch/arm/mach-rockchip/rk3036/Kconfig"
endif
diff --git a/arch/powerpc/include/asm/arch-mpc85xx/gpio.h b/arch/powerpc/include/asm/arch-mpc85xx/gpio.h
index 41b6677..76faa22 100644
--- a/arch/powerpc/include/asm/arch-mpc85xx/gpio.h
+++ b/arch/powerpc/include/asm/arch-mpc85xx/gpio.h
@@ -18,4 +18,10 @@
#include <asm/mpc85xx_gpio.h>
#endif
+struct mpc85xx_gpio_plat {
+ ulong addr;
+ unsigned long size;
+ uint ngpios;
+};
+
#endif
diff --git a/arch/x86/cpu/ivybridge/lpc.c b/arch/x86/cpu/ivybridge/lpc.c
index ff1faa5..4e0be2a 100644
--- a/arch/x86/cpu/ivybridge/lpc.c
+++ b/arch/x86/cpu/ivybridge/lpc.c
@@ -424,8 +424,6 @@ static void set_spi_speed(void)
static int lpc_init_extra(struct udevice *dev)
{
struct udevice *pch = dev->parent;
- const void *blob = gd->fdt_blob;
- int node;
debug("pch: lpc_init\n");
dm_pci_write_bar32(pch, 0, 0);
@@ -434,10 +432,6 @@ static int lpc_init_extra(struct udevice *dev)
dm_pci_write_bar32(pch, 3, 0x800);
dm_pci_write_bar32(pch, 4, 0x900);
- node = fdtdec_next_compatible(blob, 0, COMPAT_INTEL_PCH);
- if (node < 0)
- return -ENOENT;
-
/* Set the value for PCI command register. */
dm_pci_write_config16(pch, PCI_COMMAND, 0x000f);
diff --git a/board/evb_rk3036/evb_rk3036/MAINTAINERS b/board/evb_rk3036/evb_rk3036/MAINTAINERS
index e69de29..152d31c 100644
--- a/board/evb_rk3036/evb_rk3036/MAINTAINERS
+++ b/board/evb_rk3036/evb_rk3036/MAINTAINERS
@@ -0,0 +1,6 @@
+EVB-RK3036
+M: huang lin <hl@rock-chips.com>
+S: Maintained
+F: board/evb/evb-rk3036
+F: include/configs/evb-rk3036.h
+F: configs/evb-rk3036_defconfig
diff --git a/board/kylin/kylin_rk3036/MAINTAINERS b/board/kylin/kylin_rk3036/MAINTAINERS
index e69de29..f8ee834 100644
--- a/board/kylin/kylin_rk3036/MAINTAINERS
+++ b/board/kylin/kylin_rk3036/MAINTAINERS
@@ -0,0 +1,6 @@
+KYLIN-RK3036
+M: huang lin <hl@rock-chips.com>
+S: Maintained
+F: board/kylin/kylin-rk3036
+F: include/configs/kylin-rk3036.h
+F: configs/kylin-rk3036_defconfig
diff --git a/cmd/sf.c b/cmd/sf.c
index 42862d9..286906c 100644
--- a/cmd/sf.c
+++ b/cmd/sf.c
@@ -88,6 +88,8 @@ static int do_spi_flash_probe(int argc, char * const argv[])
#ifdef CONFIG_DM_SPI_FLASH
struct udevice *new, *bus_dev;
int ret;
+ /* In DM mode defaults will be taken from DT */
+ speed = 0, mode = 0;
#else
struct spi_flash *new;
#endif
diff --git a/common/env_sf.c b/common/env_sf.c
index 273098c..c53200f 100644
--- a/common/env_sf.c
+++ b/common/env_sf.c
@@ -55,9 +55,9 @@ int saveenv(void)
#ifdef CONFIG_DM_SPI_FLASH
struct udevice *new;
+ /* speed and mode will be read from DT */
ret = spi_flash_probe_bus_cs(CONFIG_ENV_SPI_BUS, CONFIG_ENV_SPI_CS,
- CONFIG_ENV_SPI_MAX_HZ,
- CONFIG_ENV_SPI_MODE, &new);
+ 0, 0, &new);
if (ret) {
set_default_env("!spi_flash_probe_bus_cs() failed");
return 1;
@@ -245,9 +245,9 @@ int saveenv(void)
#ifdef CONFIG_DM_SPI_FLASH
struct udevice *new;
+ /* speed and mode will be read from DT */
ret = spi_flash_probe_bus_cs(CONFIG_ENV_SPI_BUS, CONFIG_ENV_SPI_CS,
- CONFIG_ENV_SPI_MAX_HZ,
- CONFIG_ENV_SPI_MODE, &new);
+ 0, 0, &new);
if (ret) {
set_default_env("!spi_flash_probe_bus_cs() failed");
return 1;
diff --git a/common/fb_mmc.c b/common/fb_mmc.c
index c739651..8d0524d 100644
--- a/common/fb_mmc.c
+++ b/common/fb_mmc.c
@@ -191,7 +191,7 @@ void fb_mmc_erase(const char *cmd)
printf("Erasing blocks " LBAFU " to " LBAFU " due to alignment\n",
blks_start, blks_start + blks_size);
- blks = dev_desc->block_erase(dev_desc, blks_start, blks_size);
+ blks = blk_derase(dev_desc, blks_start, blks_size);
if (blks != blks_size) {
error("failed erasing from device %d", dev_desc->devnum);
fastboot_fail("failed erasing from device");
diff --git a/common/spl/spl_mmc.c b/common/spl/spl_mmc.c
index c44f1b5..6b3e9e4 100644
--- a/common/spl/spl_mmc.c
+++ b/common/spl/spl_mmc.c
@@ -184,7 +184,7 @@ static int mmc_load_image_raw_os(struct mmc *mmc)
unsigned long count;
int ret;
- count = mmc->block_dev.block_read(&mmc->block_dev,
+ count = blk_dread(mmc_get_blk_desc(mmc),
CONFIG_SYS_MMCSD_RAW_MODE_ARGS_SECTOR,
CONFIG_SYS_MMCSD_RAW_MODE_ARGS_SECTORS,
(void *) CONFIG_SYS_SPL_ARGS_ADDR);
@@ -225,13 +225,13 @@ int spl_mmc_do_fs_boot(struct mmc *mmc)
#ifdef CONFIG_SPL_FAT_SUPPORT
if (!spl_start_uboot()) {
- err = spl_load_image_fat_os(&mmc->block_dev,
+ err = spl_load_image_fat_os(mmc_get_blk_desc(mmc),
CONFIG_SYS_MMCSD_FS_BOOT_PARTITION);
if (!err)
return err;
}
#ifdef CONFIG_SPL_FS_LOAD_PAYLOAD_NAME
- err = spl_load_image_fat(&mmc->block_dev,
+ err = spl_load_image_fat(mmc_get_blk_desc(mmc),
CONFIG_SYS_MMCSD_FS_BOOT_PARTITION,
CONFIG_SPL_FS_LOAD_PAYLOAD_NAME);
if (!err)
diff --git a/configs/dragonboard410c_defconfig b/configs/dragonboard410c_defconfig
index 37c5ea77..ad2e8b8 100644
--- a/configs/dragonboard410c_defconfig
+++ b/configs/dragonboard410c_defconfig
@@ -18,6 +18,7 @@ CONFIG_CMD_EXT2=y
CONFIG_CMD_EXT4=y
CONFIG_CMD_FAT=y
CONFIG_CMD_FS_GENERIC=y
+CONFIG_BLK=y
CONFIG_CLK=y
CONFIG_MSM_GPIO=y
CONFIG_PM8916_GPIO=y
@@ -25,6 +26,7 @@ CONFIG_LED=y
CONFIG_LED_GPIO=y
CONFIG_SYSRESET=y
CONFIG_DM_MMC=y
+CONFIG_DM_MMC_OPS=y
CONFIG_MSM_SDHCI=y
CONFIG_DM_PMIC=y
CONFIG_PMIC_PM8916=y
diff --git a/configs/k2e_evm_defconfig b/configs/k2e_evm_defconfig
index 9fcdfe9..65561b1 100644
--- a/configs/k2e_evm_defconfig
+++ b/configs/k2e_evm_defconfig
@@ -28,6 +28,8 @@ CONFIG_CMD_FS_GENERIC=y
CONFIG_OF_CONTROL=y
CONFIG_DM=y
CONFIG_TI_AEMIF=y
+CONFIG_DM_SPI=y
+CONFIG_DM_SPI_FLASH=y
CONFIG_SPI_FLASH=y
CONFIG_SPI_FLASH_STMICRO=y
CONFIG_DM_ETH=y
diff --git a/configs/k2g_evm_defconfig b/configs/k2g_evm_defconfig
index 8efa58c..5d44e8d 100644
--- a/configs/k2g_evm_defconfig
+++ b/configs/k2g_evm_defconfig
@@ -27,6 +27,8 @@ CONFIG_CMD_FAT=y
CONFIG_CMD_FS_GENERIC=y
CONFIG_OF_CONTROL=y
CONFIG_DM=y
+CONFIG_DM_SPI=y
+CONFIG_DM_SPI_FLASH=y
CONFIG_SPI_FLASH=y
CONFIG_SPI_FLASH_STMICRO=y
CONFIG_DM_ETH=y
@@ -35,3 +37,5 @@ CONFIG_SYS_NS16550=y
CONFIG_USB=y
CONFIG_USB_XHCI_HCD=y
CONFIG_USB_XHCI_DWC3=y
+CONFIG_SPI_FLASH_SPANSION=y
+CONFIG_SPI_FLASH_BAR=y
diff --git a/configs/k2hk_evm_defconfig b/configs/k2hk_evm_defconfig
index 278eaf3..8623e1c 100644
--- a/configs/k2hk_evm_defconfig
+++ b/configs/k2hk_evm_defconfig
@@ -28,6 +28,8 @@ CONFIG_CMD_FS_GENERIC=y
CONFIG_OF_CONTROL=y
CONFIG_DM=y
CONFIG_TI_AEMIF=y
+CONFIG_DM_SPI=y
+CONFIG_DM_SPI_FLASH=y
CONFIG_SPI_FLASH=y
CONFIG_SPI_FLASH_STMICRO=y
CONFIG_DM_ETH=y
diff --git a/configs/k2l_evm_defconfig b/configs/k2l_evm_defconfig
index 8417e0a..9aa429c 100644
--- a/configs/k2l_evm_defconfig
+++ b/configs/k2l_evm_defconfig
@@ -28,6 +28,8 @@ CONFIG_CMD_FS_GENERIC=y
CONFIG_OF_CONTROL=y
CONFIG_DM=y
CONFIG_TI_AEMIF=y
+CONFIG_DM_SPI=y
+CONFIG_DM_SPI_FLASH=y
CONFIG_SPI_FLASH=y
CONFIG_SPI_FLASH_STMICRO=y
CONFIG_DM_ETH=y
diff --git a/configs/sandbox_defconfig b/configs/sandbox_defconfig
index 94253a6..6a1874a 100644
--- a/configs/sandbox_defconfig
+++ b/configs/sandbox_defconfig
@@ -1,5 +1,4 @@
CONFIG_SYS_MALLOC_F_LEN=0x2000
-CONFIG_BLK=y
CONFIG_MMC=y
CONFIG_PCI=y
CONFIG_DEFAULT_DEVICE_TREE="sandbox"
@@ -71,6 +70,7 @@ CONFIG_DEVRES=y
CONFIG_DEBUG_DEVRES=y
CONFIG_ADC=y
CONFIG_ADC_SANDBOX=y
+CONFIG_BLK=y
CONFIG_CLK=y
CONFIG_CPU=y
CONFIG_DM_DEMO=y
@@ -101,7 +101,7 @@ CONFIG_CROS_EC_SPI=y
CONFIG_PWRSEQ=y
CONFIG_SPL_PWRSEQ=y
CONFIG_SYSRESET=y
-CONFIG_DM_MMC=y
+CONFIG_DM_MMC_OPS=y
CONFIG_SANDBOX_MMC=y
CONFIG_SPI_FLASH_SANDBOX=y
CONFIG_SPI_FLASH=y
diff --git a/drivers/core/device.c b/drivers/core/device.c
index eb75b17..f7fb0cc 100644
--- a/drivers/core/device.c
+++ b/drivers/core/device.c
@@ -10,6 +10,7 @@
*/
#include <common.h>
+#include <asm/io.h>
#include <fdtdec.h>
#include <fdt_support.h>
#include <malloc.h>
@@ -697,6 +698,16 @@ void *dev_get_addr_ptr(struct udevice *dev)
return (void *)(uintptr_t)dev_get_addr_index(dev, 0);
}
+void *dev_map_physmem(struct udevice *dev, unsigned long size)
+{
+ fdt_addr_t addr = dev_get_addr(dev);
+
+ if (addr == FDT_ADDR_T_NONE)
+ return NULL;
+
+ return map_physmem(addr, size, MAP_NOCACHE);
+}
+
bool device_has_children(struct udevice *dev)
{
return !list_empty(&dev->child_head);
diff --git a/drivers/dfu/dfu_mmc.c b/drivers/dfu/dfu_mmc.c
index 78724e4..926ccbd 100644
--- a/drivers/dfu/dfu_mmc.c
+++ b/drivers/dfu/dfu_mmc.c
@@ -49,7 +49,7 @@ static int mmc_block_op(enum dfu_op op, struct dfu_entity *dfu,
}
if (dfu->data.mmc.hw_partition >= 0) {
- part_num_bkp = mmc->block_dev.hwpart;
+ part_num_bkp = mmc_get_blk_desc(mmc)->hwpart;
ret = blk_select_hwpart_devnum(IF_TYPE_MMC,
dfu->data.mmc.dev_num,
dfu->data.mmc.hw_partition);
@@ -62,12 +62,11 @@ static int mmc_block_op(enum dfu_op op, struct dfu_entity *dfu,
dfu->data.mmc.dev_num, blk_start, blk_count, buf);
switch (op) {
case DFU_OP_READ:
- n = mmc->block_dev.block_read(&mmc->block_dev, blk_start,
- blk_count, buf);
+ n = blk_dread(mmc_get_blk_desc(mmc), blk_start, blk_count, buf);
break;
case DFU_OP_WRITE:
- n = mmc->block_dev.block_write(&mmc->block_dev, blk_start,
- blk_count, buf);
+ n = blk_dwrite(mmc_get_blk_desc(mmc), blk_start, blk_count,
+ buf);
break;
default:
error("Operation not supported\n");
@@ -356,7 +355,7 @@ int dfu_fill_entity_mmc(struct dfu_entity *dfu, char *devstr, char *s)
} else if (!strcmp(entity_type, "part")) {
disk_partition_t partinfo;
- struct blk_desc *blk_dev = &mmc->block_dev;
+ struct blk_desc *blk_dev = mmc_get_blk_desc(mmc);
int mmcdev = second_arg;
int mmcpart = third_arg;
diff --git a/drivers/gpio/mpc85xx_gpio.c b/drivers/gpio/mpc85xx_gpio.c
index 04773e2..3754a82 100644
--- a/drivers/gpio/mpc85xx_gpio.c
+++ b/drivers/gpio/mpc85xx_gpio.c
@@ -163,23 +163,41 @@ static int mpc85xx_gpio_get_function(struct udevice *dev, unsigned gpio)
return dir ? GPIOF_OUTPUT : GPIOF_INPUT;
}
+#if CONFIG_IS_ENABLED(OF_CONTROL)
static int mpc85xx_gpio_ofdata_to_platdata(struct udevice *dev) {
- struct mpc85xx_gpio_data *data = dev_get_priv(dev);
+ struct mpc85xx_gpio_plat *plat = dev_get_platdata(dev);
fdt_addr_t addr;
fdt_size_t size;
addr = fdtdec_get_addr_size_auto_noparent(gd->fdt_blob, dev->of_offset,
"reg", 0, &size);
- data->addr = addr;
- data->base = map_sysmem(CONFIG_SYS_IMMR + addr, size);
+ plat->addr = addr;
+ plat->size = size;
+ plat->ngpios = fdtdec_get_int(gd->fdt_blob, dev->of_offset,
+ "ngpios", 32);
- if (!data->base)
+ return 0;
+}
+#endif
+
+static int mpc85xx_gpio_platdata_to_priv(struct udevice *dev)
+{
+ struct mpc85xx_gpio_data *priv = dev_get_priv(dev);
+ struct mpc85xx_gpio_plat *plat = dev_get_platdata(dev);
+ unsigned long size = plat->size;
+
+ if (size == 0)
+ size = 0x100;
+
+ priv->addr = plat->addr;
+ priv->base = map_sysmem(CONFIG_SYS_IMMR + plat->addr, size);
+
+ if (!priv->base)
return -ENOMEM;
- data->gpio_count = fdtdec_get_int(gd->fdt_blob, dev->of_offset,
- "ngpios", 32);
- data->dat_shadow = 0;
+ priv->gpio_count = plat->ngpios;
+ priv->dat_shadow = 0;
return 0;
}
@@ -190,6 +208,8 @@ static int mpc85xx_gpio_probe(struct udevice *dev)
struct mpc85xx_gpio_data *data = dev_get_priv(dev);
char name[32], *str;
+ mpc85xx_gpio_platdata_to_priv(dev);
+
snprintf(name, sizeof(name), "MPC@%lx_", data->addr);
str = strdup(name);
@@ -221,8 +241,11 @@ U_BOOT_DRIVER(gpio_mpc85xx) = {
.name = "gpio_mpc85xx",
.id = UCLASS_GPIO,
.ops = &gpio_mpc85xx_ops,
+#if CONFIG_IS_ENABLED(OF_CONTROL)
.ofdata_to_platdata = mpc85xx_gpio_ofdata_to_platdata,
+ .platdata_auto_alloc_size = sizeof(struct mpc85xx_gpio_plat),
.of_match = mpc85xx_gpio_ids,
+#endif
.probe = mpc85xx_gpio_probe,
.priv_auto_alloc_size = sizeof(struct mpc85xx_gpio_data),
};
diff --git a/drivers/misc/cros_ec_sandbox.c b/drivers/misc/cros_ec_sandbox.c
index 98f19a6..c4fbca0 100644
--- a/drivers/misc/cros_ec_sandbox.c
+++ b/drivers/misc/cros_ec_sandbox.c
@@ -517,6 +517,7 @@ int cros_ec_probe(struct udevice *dev)
struct ec_state *ec = dev->priv;
struct cros_ec_dev *cdev = dev->uclass_priv;
const void *blob = gd->fdt_blob;
+ struct udevice *keyb_dev;
int node;
int err;
@@ -525,7 +526,15 @@ int cros_ec_probe(struct udevice *dev)
if (err)
return err;
- node = fdtdec_next_compatible(blob, 0, COMPAT_GOOGLE_CROS_EC_KEYB);
+ node = -1;
+ for (device_find_first_child(dev, &keyb_dev);
+ keyb_dev;
+ device_find_next_child(&keyb_dev)) {
+ if (device_get_uclass_id(keyb_dev) == UCLASS_KEYBOARD) {
+ node = keyb_dev->of_offset;
+ break;
+ }
+ }
if (node < 0) {
debug("%s: No cros_ec keyboard found\n", __func__);
} else if (keyscan_read_fdt_matrix(ec, blob, node)) {
diff --git a/drivers/mmc/Kconfig b/drivers/mmc/Kconfig
index c80efc3..79cf18f 100644
--- a/drivers/mmc/Kconfig
+++ b/drivers/mmc/Kconfig
@@ -16,9 +16,18 @@ config DM_MMC
appear as block devices in U-Boot and can support filesystems such
as EXT4 and FAT.
+config DM_MMC_OPS
+ bool "Support MMC controller operations using Driver Model"
+ depends on DM_MMC
+ help
+ Driver model provides a means of supporting device operations. This
+ option moves MMC operations under the control of driver model. The
+ option will be removed as soon as all DM_MMC drivers use it, as it
+ will the only supported behaviour.
+
config MSM_SDHCI
bool "Qualcomm SDHCI controller"
- depends on DM_MMC
+ depends on DM_MMC && BLK && DM_MMC_OPS
help
Enables support for SDHCI 2.0 controller present on some Qualcomm
Snapdragon devices. This device is compatible with eMMC v4.5 and
diff --git a/drivers/mmc/Makefile b/drivers/mmc/Makefile
index 3da4817..b44a12e 100644
--- a/drivers/mmc/Makefile
+++ b/drivers/mmc/Makefile
@@ -25,6 +25,9 @@ obj-$(CONFIG_FSL_ESDHC) += fsl_esdhc.o
obj-$(CONFIG_FTSDC010) += ftsdc010_mci.o
obj-$(CONFIG_FTSDC021) += ftsdc021_sdhci.o
obj-$(CONFIG_GENERIC_MMC) += mmc.o
+ifdef CONFIG_SUPPORT_EMMC_BOOT
+obj-$(CONFIG_GENERIC_MMC) += mmc_boot.o
+endif
obj-$(CONFIG_GENERIC_ATMEL_MCI) += gen_atmel_mci.o
obj-$(CONFIG_KONA_SDHCI) += kona_sdhci.o
obj-$(CONFIG_MMC_SPI) += mmc_spi.o
diff --git a/drivers/mmc/dw_mmc.c b/drivers/mmc/dw_mmc.c
index af6e04a..2cf7bae 100644
--- a/drivers/mmc/dw_mmc.c
+++ b/drivers/mmc/dw_mmc.c
@@ -181,9 +181,16 @@ static int dwmci_set_transfer_mode(struct dwmci_host *host,
return mode;
}
+#ifdef CONFIG_DM_MMC_OPS
+int dwmci_send_cmd(struct udevice *dev, struct mmc_cmd *cmd,
+ struct mmc_data *data)
+{
+ struct mmc *mmc = mmc_get_mmc_dev(dev);
+#else
static int dwmci_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd,
struct mmc_data *data)
{
+#endif
struct dwmci_host *host = mmc->priv;
ALLOC_CACHE_ALIGN_BUFFER(struct dwmci_idmac, cur_idmac,
data ? DIV_ROUND_UP(data->blocks, 8) : 0);
@@ -373,8 +380,14 @@ static int dwmci_setup_bus(struct dwmci_host *host, u32 freq)
return 0;
}
+#ifdef CONFIG_DM_MMC_OPS
+int dwmci_set_ios(struct udevice *dev)
+{
+ struct mmc *mmc = mmc_get_mmc_dev(dev);
+#else
static void dwmci_set_ios(struct mmc *mmc)
{
+#endif
struct dwmci_host *host = (struct dwmci_host *)mmc->priv;
u32 ctype, regs;
@@ -405,6 +418,9 @@ static void dwmci_set_ios(struct mmc *mmc)
if (host->clksel)
host->clksel(host);
+#ifdef CONFIG_DM_MMC_OPS
+ return 0;
+#endif
}
static int dwmci_init(struct mmc *mmc)
@@ -448,17 +464,34 @@ static int dwmci_init(struct mmc *mmc)
return 0;
}
+#ifdef CONFIG_DM_MMC_OPS
+int dwmci_probe(struct udevice *dev)
+{
+ struct mmc *mmc = mmc_get_mmc_dev(dev);
+
+ return dwmci_init(mmc);
+}
+
+const struct dm_mmc_ops dm_dwmci_ops = {
+ .send_cmd = dwmci_send_cmd,
+ .set_ios = dwmci_set_ios,
+};
+
+#else
static const struct mmc_ops dwmci_ops = {
.send_cmd = dwmci_send_cmd,
.set_ios = dwmci_set_ios,
.init = dwmci_init,
};
+#endif
void dwmci_setup_cfg(struct mmc_config *cfg, const char *name, int buswidth,
uint caps, u32 max_clk, u32 min_clk)
{
cfg->name = name;
+#ifndef CONFIG_DM_MMC_OPS
cfg->ops = &dwmci_ops;
+#endif
cfg->f_min = min_clk;
cfg->f_max = max_clk;
diff --git a/drivers/mmc/mmc-uclass.c b/drivers/mmc/mmc-uclass.c
index 1b967d9..38ced41 100644
--- a/drivers/mmc/mmc-uclass.c
+++ b/drivers/mmc/mmc-uclass.c
@@ -8,8 +8,76 @@
#include <common.h>
#include <mmc.h>
#include <dm.h>
+#include <dm/device-internal.h>
#include <dm/lists.h>
#include <dm/root.h>
+#include "mmc_private.h"
+
+#ifdef CONFIG_DM_MMC_OPS
+int dm_mmc_send_cmd(struct udevice *dev, struct mmc_cmd *cmd,
+ struct mmc_data *data)
+{
+ struct mmc *mmc = mmc_get_mmc_dev(dev);
+ struct dm_mmc_ops *ops = mmc_get_ops(dev);
+ int ret;
+
+ mmmc_trace_before_send(mmc, cmd);
+ if (ops->send_cmd)
+ ret = ops->send_cmd(dev, cmd, data);
+ else
+ ret = -ENOSYS;
+ mmmc_trace_after_send(mmc, cmd, ret);
+
+ return ret;
+}
+
+int mmc_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd, struct mmc_data *data)
+{
+ return dm_mmc_send_cmd(mmc->dev, cmd, data);
+}
+
+int dm_mmc_set_ios(struct udevice *dev)
+{
+ struct dm_mmc_ops *ops = mmc_get_ops(dev);
+
+ if (!ops->set_ios)
+ return -ENOSYS;
+ return ops->set_ios(dev);
+}
+
+int mmc_set_ios(struct mmc *mmc)
+{
+ return dm_mmc_set_ios(mmc->dev);
+}
+
+int dm_mmc_get_wp(struct udevice *dev)
+{
+ struct dm_mmc_ops *ops = mmc_get_ops(dev);
+
+ if (!ops->get_wp)
+ return -ENOSYS;
+ return ops->get_wp(dev);
+}
+
+int mmc_getwp(struct mmc *mmc)
+{
+ return dm_mmc_get_wp(mmc->dev);
+}
+
+int dm_mmc_get_cd(struct udevice *dev)
+{
+ struct dm_mmc_ops *ops = mmc_get_ops(dev);
+
+ if (!ops->get_cd)
+ return -ENOSYS;
+ return ops->get_cd(dev);
+}
+
+int mmc_getcd(struct mmc *mmc)
+{
+ return dm_mmc_get_cd(mmc->dev);
+}
+#endif
struct mmc *mmc_get_mmc_dev(struct udevice *dev)
{
@@ -125,6 +193,84 @@ void print_mmc_devices(char separator)
#else
void print_mmc_devices(char separator) { }
#endif
+
+int mmc_bind(struct udevice *dev, struct mmc *mmc, const struct mmc_config *cfg)
+{
+ struct blk_desc *bdesc;
+ struct udevice *bdev;
+ int ret;
+
+ ret = blk_create_devicef(dev, "mmc_blk", "blk", IF_TYPE_MMC, -1, 512,
+ 0, &bdev);
+ if (ret) {
+ debug("Cannot create block device\n");
+ return ret;
+ }
+ bdesc = dev_get_uclass_platdata(bdev);
+ mmc->cfg = cfg;
+ mmc->priv = dev;
+
+ /* the following chunk was from mmc_register() */
+
+ /* Setup dsr related values */
+ mmc->dsr_imp = 0;
+ mmc->dsr = 0xffffffff;
+ /* Setup the universal parts of the block interface just once */
+ bdesc->removable = 1;
+
+ /* setup initial part type */
+ bdesc->part_type = cfg->part_type;
+ mmc->dev = dev;
+
+ return 0;
+}
+
+int mmc_unbind(struct udevice *dev)
+{
+ struct udevice *bdev;
+
+ device_find_first_child(dev, &bdev);
+ if (bdev) {
+ device_remove(bdev);
+ device_unbind(bdev);
+ }
+
+ return 0;
+}
+
+static int mmc_select_hwpart(struct udevice *bdev, int hwpart)
+{
+ struct udevice *mmc_dev = dev_get_parent(bdev);
+ struct mmc *mmc = mmc_get_mmc_dev(mmc_dev);
+ struct blk_desc *desc = dev_get_uclass_platdata(bdev);
+ int ret;
+
+ if (desc->hwpart == hwpart)
+ return 0;
+
+ if (mmc->part_config == MMCPART_NOAVAILABLE)
+ return -EMEDIUMTYPE;
+
+ ret = mmc_switch_part(mmc, hwpart);
+ if (ret)
+ return ret;
+
+ return 0;
+}
+
+static const struct blk_ops mmc_blk_ops = {
+ .read = mmc_bread,
+#ifndef CONFIG_SPL_BUILD
+ .write = mmc_bwrite,
+#endif
+ .select_hwpart = mmc_select_hwpart,
+};
+
+U_BOOT_DRIVER(mmc_blk) = {
+ .name = "mmc_blk",
+ .id = UCLASS_BLK,
+ .ops = &mmc_blk_ops,
+};
#endif /* CONFIG_BLK */
U_BOOT_DRIVER(mmc) = {
diff --git a/drivers/mmc/mmc.c b/drivers/mmc/mmc.c
index aabfc71..f8e5f7a 100644
--- a/drivers/mmc/mmc.c
+++ b/drivers/mmc/mmc.c
@@ -21,6 +21,7 @@
#include <div64.h>
#include "mmc_private.h"
+#ifndef CONFIG_DM_MMC_OPS
__weak int board_mmc_getwp(struct mmc *mmc)
{
return -1;
@@ -46,18 +47,20 @@ __weak int board_mmc_getcd(struct mmc *mmc)
{
return -1;
}
+#endif
-int mmc_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd, struct mmc_data *data)
+#ifdef CONFIG_MMC_TRACE
+void mmmc_trace_before_send(struct mmc *mmc, struct mmc_cmd *cmd)
{
- int ret;
+ printf("CMD_SEND:%d\n", cmd->cmdidx);
+ printf("\t\tARG\t\t\t 0x%08X\n", cmd->cmdarg);
+}
-#ifdef CONFIG_MMC_TRACE
+void mmmc_trace_after_send(struct mmc *mmc, struct mmc_cmd *cmd, int ret)
+{
int i;
u8 *ptr;
- printf("CMD_SEND:%d\n", cmd->cmdidx);
- printf("\t\tARG\t\t\t 0x%08X\n", cmd->cmdarg);
- ret = mmc->cfg->ops->send_cmd(mmc, cmd, data);
if (ret) {
printf("\t\tRET\t\t\t %d\n", ret);
} else {
@@ -103,19 +106,34 @@ int mmc_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd, struct mmc_data *data)
break;
}
}
-#else
- ret = mmc->cfg->ops->send_cmd(mmc, cmd, data);
+}
+
+void mmc_trace_state(struct mmc *mmc, struct mmc_cmd *cmd)
+{
+ int status;
+
+ status = (cmd->response[0] & MMC_STATUS_CURR_STATE) >> 9;
+ printf("CURR STATE:%d\n", status);
+}
#endif
+
+#ifndef CONFIG_DM_MMC_OPS
+int mmc_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd, struct mmc_data *data)
+{
+ int ret;
+
+ mmmc_trace_before_send(mmc, cmd);
+ ret = mmc->cfg->ops->send_cmd(mmc, cmd, data);
+ mmmc_trace_after_send(mmc, cmd, ret);
+
return ret;
}
+#endif
int mmc_send_status(struct mmc *mmc, int timeout)
{
struct mmc_cmd cmd;
int err, retries = 5;
-#ifdef CONFIG_MMC_TRACE
- int status;
-#endif
cmd.cmdidx = MMC_CMD_SEND_STATUS;
cmd.resp_type = MMC_RSP_R1;
@@ -145,10 +163,7 @@ int mmc_send_status(struct mmc *mmc, int timeout)
udelay(1000);
}
-#ifdef CONFIG_MMC_TRACE
- status = (cmd.response[0] & MMC_STATUS_CURR_STATE) >> 9;
- printf("CURR STATE:%d\n", status);
-#endif
+ mmc_trace_state(mmc, &cmd);
if (timeout <= 0) {
#if !defined(CONFIG_SPL_BUILD) || defined(CONFIG_SPL_LIBCOMMON_SUPPORT)
printf("Timeout waiting card ready\n");
@@ -215,11 +230,10 @@ static int mmc_read_blocks(struct mmc *mmc, void *dst, lbaint_t start,
}
#ifdef CONFIG_BLK
-static ulong mmc_bread(struct udevice *dev, lbaint_t start, lbaint_t blkcnt,
- void *dst)
+ulong mmc_bread(struct udevice *dev, lbaint_t start, lbaint_t blkcnt, void *dst)
#else
-static ulong mmc_bread(struct blk_desc *block_dev, lbaint_t start,
- lbaint_t blkcnt, void *dst)
+ulong mmc_bread(struct blk_desc *block_dev, lbaint_t start, lbaint_t blkcnt,
+ void *dst)
#endif
{
#ifdef CONFIG_BLK
@@ -464,8 +478,7 @@ static int mmc_send_ext_csd(struct mmc *mmc, u8 *ext_csd)
return err;
}
-
-static int mmc_switch(struct mmc *mmc, u8 set, u8 index, u8 value)
+int mmc_switch(struct mmc *mmc, u8 set, u8 index, u8 value)
{
struct mmc_cmd cmd;
int timeout = 1000;
@@ -566,7 +579,7 @@ static int mmc_set_capacity(struct mmc *mmc, int part_num)
return 0;
}
-static int mmc_switch_part(struct mmc *mmc, unsigned int part_num)
+int mmc_switch_part(struct mmc *mmc, unsigned int part_num)
{
int ret;
@@ -586,49 +599,6 @@ static int mmc_switch_part(struct mmc *mmc, unsigned int part_num)
return ret;
}
-#ifdef CONFIG_BLK
-static int mmc_select_hwpart(struct udevice *bdev, int hwpart)
-{
- struct udevice *mmc_dev = dev_get_parent(bdev);
- struct mmc *mmc = mmc_get_mmc_dev(mmc_dev);
- struct blk_desc *desc = dev_get_uclass_platdata(bdev);
- int ret;
-
- if (desc->hwpart == hwpart)
- return 0;
-
- if (mmc->part_config == MMCPART_NOAVAILABLE)
- return -EMEDIUMTYPE;
-
- ret = mmc_switch_part(mmc, hwpart);
- if (ret)
- return ret;
-
- return 0;
-}
-#else
-static int mmc_select_hwpartp(struct blk_desc *desc, int hwpart)
-{
- struct mmc *mmc = find_mmc_device(desc->devnum);
- int ret;
-
- if (!mmc)
- return -ENODEV;
-
- if (mmc->block_dev.hwpart == hwpart)
- return 0;
-
- if (mmc->part_config == MMCPART_NOAVAILABLE)
- return -EMEDIUMTYPE;
-
- ret = mmc_switch_part(mmc, hwpart);
- if (ret)
- return ret;
-
- return 0;
-}
-#endif
-
int mmc_hwpart_config(struct mmc *mmc,
const struct mmc_hwpart_conf *conf,
enum mmc_hwpart_conf_mode mode)
@@ -823,6 +793,7 @@ int mmc_hwpart_config(struct mmc *mmc,
return 0;
}
+#ifndef CONFIG_DM_MMC_OPS
int mmc_getcd(struct mmc *mmc)
{
int cd;
@@ -838,6 +809,7 @@ int mmc_getcd(struct mmc *mmc)
return cd;
}
+#endif
static int sd_switch(struct mmc *mmc, int mode, int group, u8 value, u8 *resp)
{
@@ -1001,11 +973,13 @@ static const u8 multipliers[] = {
80,
};
+#ifndef CONFIG_DM_MMC_OPS
static void mmc_set_ios(struct mmc *mmc)
{
if (mmc->cfg->ops->set_ios)
mmc->cfg->ops->set_ios(mmc);
}
+#endif
void mmc_set_clock(struct mmc *mmc, uint clock)
{
@@ -1532,115 +1506,6 @@ static int mmc_send_if_cond(struct mmc *mmc)
return 0;
}
-#ifdef CONFIG_BLK
-int mmc_bind(struct udevice *dev, struct mmc *mmc, const struct mmc_config *cfg)
-{
- struct blk_desc *bdesc;
- struct udevice *bdev;
- int ret;
-
- ret = blk_create_devicef(dev, "mmc_blk", "blk", IF_TYPE_MMC, -1, 512,
- 0, &bdev);
- if (ret) {
- debug("Cannot create block device\n");
- return ret;
- }
- bdesc = dev_get_uclass_platdata(bdev);
- mmc->cfg = cfg;
- mmc->priv = dev;
-
- /* the following chunk was from mmc_register() */
-
- /* Setup dsr related values */
- mmc->dsr_imp = 0;
- mmc->dsr = 0xffffffff;
- /* Setup the universal parts of the block interface just once */
- bdesc->removable = 1;
-
- /* setup initial part type */
- bdesc->part_type = cfg->part_type;
- mmc->dev = dev;
-
- return 0;
-}
-
-int mmc_unbind(struct udevice *dev)
-{
- struct udevice *bdev;
-
- device_find_first_child(dev, &bdev);
- if (bdev) {
- device_remove(bdev);
- device_unbind(bdev);
- }
-
- return 0;
-}
-
-#else
-struct mmc *mmc_create(const struct mmc_config *cfg, void *priv)
-{
- struct blk_desc *bdesc;
- struct mmc *mmc;
-
- /* quick validation */
- if (cfg == NULL || cfg->ops == NULL || cfg->ops->send_cmd == NULL ||
- cfg->f_min == 0 || cfg->f_max == 0 || cfg->b_max == 0)
- return NULL;
-
- mmc = calloc(1, sizeof(*mmc));
- if (mmc == NULL)
- return NULL;
-
- mmc->cfg = cfg;
- mmc->priv = priv;
-
- /* the following chunk was mmc_register() */
-
- /* Setup dsr related values */
- mmc->dsr_imp = 0;
- mmc->dsr = 0xffffffff;
- /* Setup the universal parts of the block interface just once */
- bdesc = mmc_get_blk_desc(mmc);
- bdesc->if_type = IF_TYPE_MMC;
- bdesc->removable = 1;
- bdesc->devnum = mmc_get_next_devnum();
- bdesc->block_read = mmc_bread;
- bdesc->block_write = mmc_bwrite;
- bdesc->block_erase = mmc_berase;
-
- /* setup initial part type */
- bdesc->part_type = mmc->cfg->part_type;
- mmc_list_add(mmc);
-
- return mmc;
-}
-
-void mmc_destroy(struct mmc *mmc)
-{
- /* only freeing memory for now */
- free(mmc);
-}
-#endif
-
-#ifndef CONFIG_BLK
-static int mmc_get_dev(int dev, struct blk_desc **descp)
-{
- struct mmc *mmc = find_mmc_device(dev);
- int ret;
-
- if (!mmc)
- return -ENODEV;
- ret = mmc_init(mmc);
- if (ret)
- return ret;
-
- *descp = &mmc->block_dev;
-
- return 0;
-}
-#endif
-
/* board-specific MMC power initializations. */
__weak void board_mmc_power_init(void)
{
@@ -1648,10 +1513,15 @@ __weak void board_mmc_power_init(void)
int mmc_start_init(struct mmc *mmc)
{
+ bool no_card;
int err;
/* we pretend there's no card when init is NULL */
- if (mmc_getcd(mmc) == 0 || mmc->cfg->ops->init == NULL) {
+ no_card = mmc_getcd(mmc) == 0;
+#ifndef CONFIG_DM_MMC_OPS
+ no_card = no_card || (mmc->cfg->ops->init == NULL);
+#endif
+ if (no_card) {
mmc->has_init = 0;
#if !defined(CONFIG_SPL_BUILD) || defined(CONFIG_SPL_LIBCOMMON_SUPPORT)
printf("MMC: no card present\n");
@@ -1667,12 +1537,14 @@ int mmc_start_init(struct mmc *mmc)
#endif
board_mmc_power_init();
+#ifdef CONFIG_DM_MMC_OPS
+ /* The device has already been probed ready for use */
+#else
/* made sure it's not NULL earlier */
err = mmc->cfg->ops->init(mmc);
-
if (err)
return err;
-
+#endif
mmc->ddr_mode = 0;
mmc_set_bus_width(mmc, 1);
mmc_set_clock(mmc, 1);
@@ -1839,148 +1711,3 @@ int mmc_initialize(bd_t *bis)
mmc_do_preinit();
return 0;
}
-
-#ifdef CONFIG_SUPPORT_EMMC_BOOT
-/*
- * This function changes the size of boot partition and the size of rpmb
- * partition present on EMMC devices.
- *
- * Input Parameters:
- * struct *mmc: pointer for the mmc device strcuture
- * bootsize: size of boot partition
- * rpmbsize: size of rpmb partition
- *
- * Returns 0 on success.
- */
-
-int mmc_boot_partition_size_change(struct mmc *mmc, unsigned long bootsize,
- unsigned long rpmbsize)
-{
- int err;
- struct mmc_cmd cmd;
-
- /* Only use this command for raw EMMC moviNAND. Enter backdoor mode */
- cmd.cmdidx = MMC_CMD_RES_MAN;
- cmd.resp_type = MMC_RSP_R1b;
- cmd.cmdarg = MMC_CMD62_ARG1;
-
- err = mmc_send_cmd(mmc, &cmd, NULL);
- if (err) {
- debug("mmc_boot_partition_size_change: Error1 = %d\n", err);
- return err;
- }
-
- /* Boot partition changing mode */
- cmd.cmdidx = MMC_CMD_RES_MAN;
- cmd.resp_type = MMC_RSP_R1b;
- cmd.cmdarg = MMC_CMD62_ARG2;
-
- err = mmc_send_cmd(mmc, &cmd, NULL);
- if (err) {
- debug("mmc_boot_partition_size_change: Error2 = %d\n", err);
- return err;
- }
- /* boot partition size is multiple of 128KB */
- bootsize = (bootsize * 1024) / 128;
-
- /* Arg: boot partition size */
- cmd.cmdidx = MMC_CMD_RES_MAN;
- cmd.resp_type = MMC_RSP_R1b;
- cmd.cmdarg = bootsize;
-
- err = mmc_send_cmd(mmc, &cmd, NULL);
- if (err) {
- debug("mmc_boot_partition_size_change: Error3 = %d\n", err);
- return err;
- }
- /* RPMB partition size is multiple of 128KB */
- rpmbsize = (rpmbsize * 1024) / 128;
- /* Arg: RPMB partition size */
- cmd.cmdidx = MMC_CMD_RES_MAN;
- cmd.resp_type = MMC_RSP_R1b;
- cmd.cmdarg = rpmbsize;
-
- err = mmc_send_cmd(mmc, &cmd, NULL);
- if (err) {
- debug("mmc_boot_partition_size_change: Error4 = %d\n", err);
- return err;
- }
- return 0;
-}
-
-/*
- * Modify EXT_CSD[177] which is BOOT_BUS_WIDTH
- * based on the passed in values for BOOT_BUS_WIDTH, RESET_BOOT_BUS_WIDTH
- * and BOOT_MODE.
- *
- * Returns 0 on success.
- */
-int mmc_set_boot_bus_width(struct mmc *mmc, u8 width, u8 reset, u8 mode)
-{
- int err;
-
- err = mmc_switch(mmc, EXT_CSD_CMD_SET_NORMAL, EXT_CSD_BOOT_BUS_WIDTH,
- EXT_CSD_BOOT_BUS_WIDTH_MODE(mode) |
- EXT_CSD_BOOT_BUS_WIDTH_RESET(reset) |
- EXT_CSD_BOOT_BUS_WIDTH_WIDTH(width));
-
- if (err)
- return err;
- return 0;
-}
-
-/*
- * Modify EXT_CSD[179] which is PARTITION_CONFIG (formerly BOOT_CONFIG)
- * based on the passed in values for BOOT_ACK, BOOT_PARTITION_ENABLE and
- * PARTITION_ACCESS.
- *
- * Returns 0 on success.
- */
-int mmc_set_part_conf(struct mmc *mmc, u8 ack, u8 part_num, u8 access)
-{
- int err;
-
- err = mmc_switch(mmc, EXT_CSD_CMD_SET_NORMAL, EXT_CSD_PART_CONF,
- EXT_CSD_BOOT_ACK(ack) |
- EXT_CSD_BOOT_PART_NUM(part_num) |
- EXT_CSD_PARTITION_ACCESS(access));
-
- if (err)
- return err;
- return 0;
-}
-
-/*
- * Modify EXT_CSD[162] which is RST_n_FUNCTION based on the given value
- * for enable. Note that this is a write-once field for non-zero values.
- *
- * Returns 0 on success.
- */
-int mmc_set_rst_n_function(struct mmc *mmc, u8 enable)
-{
- return mmc_switch(mmc, EXT_CSD_CMD_SET_NORMAL, EXT_CSD_RST_N_FUNCTION,
- enable);
-}
-#endif
-
-#ifdef CONFIG_BLK
-static const struct blk_ops mmc_blk_ops = {
- .read = mmc_bread,
- .write = mmc_bwrite,
- .select_hwpart = mmc_select_hwpart,
-};
-
-U_BOOT_DRIVER(mmc_blk) = {
- .name = "mmc_blk",
- .id = UCLASS_BLK,
- .ops = &mmc_blk_ops,
-};
-#else
-U_BOOT_LEGACY_BLK(mmc) = {
- .if_typename = "mmc",
- .if_type = IF_TYPE_MMC,
- .max_devs = -1,
- .get_dev = mmc_get_dev,
- .select_hwpart = mmc_select_hwpartp,
-};
-#endif
diff --git a/drivers/mmc/mmc_boot.c b/drivers/mmc/mmc_boot.c
new file mode 100644
index 0000000..756a982
--- /dev/null
+++ b/drivers/mmc/mmc_boot.c
@@ -0,0 +1,131 @@
+/*
+ * Copyright (C) 2016 Google, Inc
+ * Written by Amar <amarendra.xt@samsung.com>
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+#include <common.h>
+#include <mmc.h>
+#include "mmc_private.h"
+
+/*
+ * This function changes the size of boot partition and the size of rpmb
+ * partition present on EMMC devices.
+ *
+ * Input Parameters:
+ * struct *mmc: pointer for the mmc device strcuture
+ * bootsize: size of boot partition
+ * rpmbsize: size of rpmb partition
+ *
+ * Returns 0 on success.
+ */
+
+int mmc_boot_partition_size_change(struct mmc *mmc, unsigned long bootsize,
+ unsigned long rpmbsize)
+{
+ int err;
+ struct mmc_cmd cmd;
+
+ /* Only use this command for raw EMMC moviNAND. Enter backdoor mode */
+ cmd.cmdidx = MMC_CMD_RES_MAN;
+ cmd.resp_type = MMC_RSP_R1b;
+ cmd.cmdarg = MMC_CMD62_ARG1;
+
+ err = mmc_send_cmd(mmc, &cmd, NULL);
+ if (err) {
+ debug("mmc_boot_partition_size_change: Error1 = %d\n", err);
+ return err;
+ }
+
+ /* Boot partition changing mode */
+ cmd.cmdidx = MMC_CMD_RES_MAN;
+ cmd.resp_type = MMC_RSP_R1b;
+ cmd.cmdarg = MMC_CMD62_ARG2;
+
+ err = mmc_send_cmd(mmc, &cmd, NULL);
+ if (err) {
+ debug("mmc_boot_partition_size_change: Error2 = %d\n", err);
+ return err;
+ }
+ /* boot partition size is multiple of 128KB */
+ bootsize = (bootsize * 1024) / 128;
+
+ /* Arg: boot partition size */
+ cmd.cmdidx = MMC_CMD_RES_MAN;
+ cmd.resp_type = MMC_RSP_R1b;
+ cmd.cmdarg = bootsize;
+
+ err = mmc_send_cmd(mmc, &cmd, NULL);
+ if (err) {
+ debug("mmc_boot_partition_size_change: Error3 = %d\n", err);
+ return err;
+ }
+ /* RPMB partition size is multiple of 128KB */
+ rpmbsize = (rpmbsize * 1024) / 128;
+ /* Arg: RPMB partition size */
+ cmd.cmdidx = MMC_CMD_RES_MAN;
+ cmd.resp_type = MMC_RSP_R1b;
+ cmd.cmdarg = rpmbsize;
+
+ err = mmc_send_cmd(mmc, &cmd, NULL);
+ if (err) {
+ debug("mmc_boot_partition_size_change: Error4 = %d\n", err);
+ return err;
+ }
+ return 0;
+}
+
+/*
+ * Modify EXT_CSD[177] which is BOOT_BUS_WIDTH
+ * based on the passed in values for BOOT_BUS_WIDTH, RESET_BOOT_BUS_WIDTH
+ * and BOOT_MODE.
+ *
+ * Returns 0 on success.
+ */
+int mmc_set_boot_bus_width(struct mmc *mmc, u8 width, u8 reset, u8 mode)
+{
+ int err;
+
+ err = mmc_switch(mmc, EXT_CSD_CMD_SET_NORMAL, EXT_CSD_BOOT_BUS_WIDTH,
+ EXT_CSD_BOOT_BUS_WIDTH_MODE(mode) |
+ EXT_CSD_BOOT_BUS_WIDTH_RESET(reset) |
+ EXT_CSD_BOOT_BUS_WIDTH_WIDTH(width));
+
+ if (err)
+ return err;
+ return 0;
+}
+
+/*
+ * Modify EXT_CSD[179] which is PARTITION_CONFIG (formerly BOOT_CONFIG)
+ * based on the passed in values for BOOT_ACK, BOOT_PARTITION_ENABLE and
+ * PARTITION_ACCESS.
+ *
+ * Returns 0 on success.
+ */
+int mmc_set_part_conf(struct mmc *mmc, u8 ack, u8 part_num, u8 access)
+{
+ int err;
+
+ err = mmc_switch(mmc, EXT_CSD_CMD_SET_NORMAL, EXT_CSD_PART_CONF,
+ EXT_CSD_BOOT_ACK(ack) |
+ EXT_CSD_BOOT_PART_NUM(part_num) |
+ EXT_CSD_PARTITION_ACCESS(access));
+
+ if (err)
+ return err;
+ return 0;
+}
+
+/*
+ * Modify EXT_CSD[162] which is RST_n_FUNCTION based on the given value
+ * for enable. Note that this is a write-once field for non-zero values.
+ *
+ * Returns 0 on success.
+ */
+int mmc_set_rst_n_function(struct mmc *mmc, u8 enable)
+{
+ return mmc_switch(mmc, EXT_CSD_CMD_SET_NORMAL, EXT_CSD_RST_N_FUNCTION,
+ enable);
+}
diff --git a/drivers/mmc/mmc_legacy.c b/drivers/mmc/mmc_legacy.c
index 3ec649f..040728b 100644
--- a/drivers/mmc/mmc_legacy.c
+++ b/drivers/mmc/mmc_legacy.c
@@ -6,7 +6,9 @@
*/
#include <common.h>
+#include <malloc.h>
#include <mmc.h>
+#include "mmc_private.h"
static struct list_head mmc_devices;
static int cur_dev_num = -1;
@@ -106,3 +108,92 @@ void print_mmc_devices(char separator)
#else
void print_mmc_devices(char separator) { }
#endif
+
+struct mmc *mmc_create(const struct mmc_config *cfg, void *priv)
+{
+ struct blk_desc *bdesc;
+ struct mmc *mmc;
+
+ /* quick validation */
+ if (cfg == NULL || cfg->ops == NULL || cfg->ops->send_cmd == NULL ||
+ cfg->f_min == 0 || cfg->f_max == 0 || cfg->b_max == 0)
+ return NULL;
+
+ mmc = calloc(1, sizeof(*mmc));
+ if (mmc == NULL)
+ return NULL;
+
+ mmc->cfg = cfg;
+ mmc->priv = priv;
+
+ /* the following chunk was mmc_register() */
+
+ /* Setup dsr related values */
+ mmc->dsr_imp = 0;
+ mmc->dsr = 0xffffffff;
+ /* Setup the universal parts of the block interface just once */
+ bdesc = mmc_get_blk_desc(mmc);
+ bdesc->if_type = IF_TYPE_MMC;
+ bdesc->removable = 1;
+ bdesc->devnum = mmc_get_next_devnum();
+ bdesc->block_read = mmc_bread;
+ bdesc->block_write = mmc_bwrite;
+ bdesc->block_erase = mmc_berase;
+
+ /* setup initial part type */
+ bdesc->part_type = mmc->cfg->part_type;
+ mmc_list_add(mmc);
+
+ return mmc;
+}
+
+void mmc_destroy(struct mmc *mmc)
+{
+ /* only freeing memory for now */
+ free(mmc);
+}
+
+static int mmc_select_hwpartp(struct blk_desc *desc, int hwpart)
+{
+ struct mmc *mmc = find_mmc_device(desc->devnum);
+ int ret;
+
+ if (!mmc)
+ return -ENODEV;
+
+ if (mmc->block_dev.hwpart == hwpart)
+ return 0;
+
+ if (mmc->part_config == MMCPART_NOAVAILABLE)
+ return -EMEDIUMTYPE;
+
+ ret = mmc_switch_part(mmc, hwpart);
+ if (ret)
+ return ret;
+
+ return 0;
+}
+
+static int mmc_get_dev(int dev, struct blk_desc **descp)
+{
+ struct mmc *mmc = find_mmc_device(dev);
+ int ret;
+
+ if (!mmc)
+ return -ENODEV;
+ ret = mmc_init(mmc);
+ if (ret)
+ return ret;
+
+ *descp = &mmc->block_dev;
+
+ return 0;
+}
+
+U_BOOT_LEGACY_BLK(mmc) = {
+ .if_typename = "mmc",
+ .if_type = IF_TYPE_MMC,
+ .max_devs = -1,
+ .get_dev = mmc_get_dev,
+ .select_hwpart = mmc_select_hwpartp,
+};
diff --git a/drivers/mmc/mmc_private.h b/drivers/mmc/mmc_private.h
index 9f0d5c2..49ec022 100644
--- a/drivers/mmc/mmc_private.h
+++ b/drivers/mmc/mmc_private.h
@@ -20,6 +20,14 @@ extern int mmc_set_blocklen(struct mmc *mmc, int len);
void mmc_adapter_card_type_ident(void);
#endif
+#ifdef CONFIG_BLK
+ulong mmc_bread(struct udevice *dev, lbaint_t start, lbaint_t blkcnt,
+ void *dst);
+#else
+ulong mmc_bread(struct blk_desc *block_dev, lbaint_t start, lbaint_t blkcnt,
+ void *dst);
+#endif
+
#ifndef CONFIG_SPL_BUILD
unsigned long mmc_berase(struct blk_desc *block_dev, lbaint_t start,
@@ -65,6 +73,25 @@ static inline ulong mmc_bwrite(struct blk_desc *block_dev, lbaint_t start,
#endif /* CONFIG_SPL_BUILD */
+#ifdef CONFIG_MMC_TRACE
+void mmmc_trace_before_send(struct mmc *mmc, struct mmc_cmd *cmd);
+void mmmc_trace_after_send(struct mmc *mmc, struct mmc_cmd *cmd, int ret);
+void mmc_trace_state(struct mmc *mmc, struct mmc_cmd *cmd);
+#else
+static inline void mmmc_trace_before_send(struct mmc *mmc, struct mmc_cmd *cmd)
+{
+}
+
+static inline void mmmc_trace_after_send(struct mmc *mmc, struct mmc_cmd *cmd,
+ int ret)
+{
+}
+
+static inline void mmc_trace_state(struct mmc *mmc, struct mmc_cmd *cmd)
+{
+}
+#endif
+
/**
* mmc_get_next_devnum() - Get the next available MMC device number
*
@@ -89,4 +116,24 @@ void mmc_list_init(void);
*/
void mmc_list_add(struct mmc *mmc);
+/**
+ * mmc_switch_part() - Switch to a new MMC hardware partition
+ *
+ * @mmc: MMC device
+ * @part_num: Hardware partition number
+ * @return 0 if OK, -ve on error
+ */
+int mmc_switch_part(struct mmc *mmc, unsigned int part_num);
+
+/**
+ * mmc_switch() - Issue and MMC switch mode command
+ *
+ * @mmc: MMC device
+ * @set: Unused
+ * @index: Cmdarg index
+ * @value: Cmdarg value
+ * @return 0 if OK, -ve on error
+ */
+int mmc_switch(struct mmc *mmc, u8 set, u8 index, u8 value);
+
#endif /* _MMC_PRIVATE_H_ */
diff --git a/drivers/mmc/msm_sdhci.c b/drivers/mmc/msm_sdhci.c
index 96dcdbe..70a8d96 100644
--- a/drivers/mmc/msm_sdhci.c
+++ b/drivers/mmc/msm_sdhci.c
@@ -36,6 +36,11 @@
/* Non standard (?) SDHCI register */
#define SDHCI_VENDOR_SPEC_CAPABILITIES0 0x11c
+struct msm_sdhc_plat {
+ struct mmc_config cfg;
+ struct mmc mmc;
+};
+
struct msm_sdhc {
struct sdhci_host host;
void *base;
@@ -81,9 +86,12 @@ static int msm_sdc_clk_init(struct udevice *dev)
static int msm_sdc_probe(struct udevice *dev)
{
+ struct mmc_uclass_priv *upriv = dev_get_uclass_priv(dev);
+ struct msm_sdhc_plat *plat = dev_get_platdata(dev);
struct msm_sdhc *prv = dev_get_priv(dev);
struct sdhci_host *host = &prv->host;
u32 core_version, core_minor, core_major;
+ u32 caps;
int ret;
host->quirks = SDHCI_QUIRK_WAIT_SEND_CMD | SDHCI_QUIRK_BROKEN_R1B;
@@ -127,7 +135,7 @@ static int msm_sdc_probe(struct udevice *dev)
* controller versions and must be explicitly enabled.
*/
if (core_major >= 1 && core_minor != 0x11 && core_minor != 0x12) {
- u32 caps = readl(host->ioaddr + SDHCI_CAPABILITIES);
+ caps = readl(host->ioaddr + SDHCI_CAPABILITIES);
caps |= SDHCI_CAN_VDD_300 | SDHCI_CAN_DO_8BIT;
writel(caps, host->ioaddr + SDHCI_VENDOR_SPEC_CAPABILITIES0);
}
@@ -135,13 +143,17 @@ static int msm_sdc_probe(struct udevice *dev)
/* Set host controller version */
host->version = sdhci_readw(host, SDHCI_HOST_VERSION);
- /* automatically detect max and min speed */
- ret = add_sdhci(host, 0, 0);
+ caps = sdhci_readl(host, SDHCI_CAPABILITIES);
+ ret = sdhci_setup_cfg(&plat->cfg, dev->name, host->bus_width,
+ caps, 0, 0, host->version, host->quirks, 0);
+ host->mmc = &plat->mmc;
if (ret)
return ret;
+ host->mmc->priv = &prv->host;
host->mmc->dev = dev;
+ upriv->mmc = host->mmc;
- return 0;
+ return sdhci_probe(dev);
}
static int msm_sdc_remove(struct udevice *dev)
@@ -176,6 +188,18 @@ static int msm_ofdata_to_platdata(struct udevice *dev)
return 0;
}
+static int msm_sdc_bind(struct udevice *dev)
+{
+ struct msm_sdhc_plat *plat = dev_get_platdata(dev);
+ int ret;
+
+ ret = sdhci_bind(dev, &plat->mmc, &plat->cfg);
+ if (ret)
+ return ret;
+
+ return 0;
+}
+
static const struct udevice_id msm_mmc_ids[] = {
{ .compatible = "qcom,sdhci-msm-v4" },
{ }
@@ -186,7 +210,10 @@ U_BOOT_DRIVER(msm_sdc_drv) = {
.id = UCLASS_MMC,
.of_match = msm_mmc_ids,
.ofdata_to_platdata = msm_ofdata_to_platdata,
+ .ops = &sdhci_ops,
+ .bind = msm_sdc_bind,
.probe = msm_sdc_probe,
.remove = msm_sdc_remove,
.priv_auto_alloc_size = sizeof(struct msm_sdhc),
+ .platdata_auto_alloc_size = sizeof(struct msm_sdhc_plat),
};
diff --git a/drivers/mmc/rockchip_dw_mmc.c b/drivers/mmc/rockchip_dw_mmc.c
index d41d60c..691a515 100644
--- a/drivers/mmc/rockchip_dw_mmc.c
+++ b/drivers/mmc/rockchip_dw_mmc.c
@@ -66,9 +66,7 @@ static int rockchip_dwmmc_ofdata_to_platdata(struct udevice *dev)
static int rockchip_dwmmc_probe(struct udevice *dev)
{
-#ifdef CONFIG_BLK
struct rockchip_mmc_plat *plat = dev_get_platdata(dev);
-#endif
struct mmc_uclass_priv *upriv = dev_get_uclass_priv(dev);
struct rockchip_dwmmc_priv *priv = dev_get_priv(dev);
struct dwmci_host *host = &priv->host;
@@ -106,33 +104,24 @@ static int rockchip_dwmmc_probe(struct udevice *dev)
return ret;
}
#endif
-#ifdef CONFIG_BLK
dwmci_setup_cfg(&plat->cfg, dev->name, host->buswidth, host->caps,
minmax[1], minmax[0]);
host->mmc = &plat->mmc;
-#else
- ret = add_dwmci(host, minmax[1], minmax[0]);
- if (ret)
- return ret;
-
-#endif
host->mmc->priv = &priv->host;
host->mmc->dev = dev;
upriv->mmc = host->mmc;
- return 0;
+ return dwmci_probe(dev);
}
static int rockchip_dwmmc_bind(struct udevice *dev)
{
-#ifdef CONFIG_BLK
struct rockchip_mmc_plat *plat = dev_get_platdata(dev);
int ret;
ret = dwmci_bind(dev, &plat->mmc, &plat->cfg);
if (ret)
return ret;
-#endif
return 0;
}
@@ -147,6 +136,7 @@ U_BOOT_DRIVER(rockchip_dwmmc_drv) = {
.id = UCLASS_MMC,
.of_match = rockchip_dwmmc_ids,
.ofdata_to_platdata = rockchip_dwmmc_ofdata_to_platdata,
+ .ops = &dm_dwmci_ops,
.bind = rockchip_dwmmc_bind,
.probe = rockchip_dwmmc_probe,
.priv_auto_alloc_size = sizeof(struct rockchip_dwmmc_priv),
diff --git a/drivers/mmc/sandbox_mmc.c b/drivers/mmc/sandbox_mmc.c
index 7da059c..5f1333b 100644
--- a/drivers/mmc/sandbox_mmc.c
+++ b/drivers/mmc/sandbox_mmc.c
@@ -25,7 +25,7 @@ struct sandbox_mmc_plat {
* This emulate an SD card version 2. Single-block reads result in zero data.
* Multiple-block reads return a test string.
*/
-static int sandbox_mmc_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd,
+static int sandbox_mmc_send_cmd(struct udevice *dev, struct mmc_cmd *cmd,
struct mmc_data *data)
{
switch (cmd->cmdidx) {
@@ -85,25 +85,20 @@ static int sandbox_mmc_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd,
return 0;
}
-static void sandbox_mmc_set_ios(struct mmc *mmc)
-{
-}
-
-static int sandbox_mmc_init(struct mmc *mmc)
+static int sandbox_mmc_set_ios(struct udevice *dev)
{
return 0;
}
-static int sandbox_mmc_getcd(struct mmc *mmc)
+static int sandbox_mmc_get_cd(struct udevice *dev)
{
return 1;
}
-static const struct mmc_ops sandbox_mmc_ops = {
+static const struct dm_mmc_ops sandbox_mmc_ops = {
.send_cmd = sandbox_mmc_send_cmd,
.set_ios = sandbox_mmc_set_ios,
- .init = sandbox_mmc_init,
- .getcd = sandbox_mmc_getcd,
+ .get_cd = sandbox_mmc_get_cd,
};
int sandbox_mmc_probe(struct udevice *dev)
@@ -120,7 +115,6 @@ int sandbox_mmc_bind(struct udevice *dev)
int ret;
cfg->name = dev->name;
- cfg->ops = &sandbox_mmc_ops;
cfg->host_caps = MMC_MODE_HS_52MHz | MMC_MODE_HS | MMC_MODE_8BIT;
cfg->voltages = MMC_VDD_165_195 | MMC_VDD_32_33 | MMC_VDD_33_34;
cfg->f_min = 1000000;
@@ -150,6 +144,7 @@ U_BOOT_DRIVER(mmc_sandbox) = {
.name = "mmc_sandbox",
.id = UCLASS_MMC,
.of_match = sandbox_mmc_ids,
+ .ops = &sandbox_mmc_ops,
.bind = sandbox_mmc_bind,
.unbind = sandbox_mmc_unbind,
.probe = sandbox_mmc_probe,
diff --git a/drivers/mmc/sdhci.c b/drivers/mmc/sdhci.c
index 604f18d..de8d8ea 100644
--- a/drivers/mmc/sdhci.c
+++ b/drivers/mmc/sdhci.c
@@ -9,6 +9,7 @@
*/
#include <common.h>
+#include <errno.h>
#include <malloc.h>
#include <mmc.h>
#include <sdhci.h>
@@ -129,9 +130,17 @@ static int sdhci_transfer_data(struct sdhci_host *host, struct mmc_data *data,
#define CONFIG_SDHCI_CMD_DEFAULT_TIMEOUT 100
#define SDHCI_READ_STATUS_TIMEOUT 1000
+#ifdef CONFIG_DM_MMC_OPS
+static int sdhci_send_command(struct udevice *dev, struct mmc_cmd *cmd,
+ struct mmc_data *data)
+{
+ struct mmc *mmc = mmc_get_mmc_dev(dev);
+
+#else
static int sdhci_send_command(struct mmc *mmc, struct mmc_cmd *cmd,
- struct mmc_data *data)
+ struct mmc_data *data)
{
+#endif
struct sdhci_host *host = mmc->priv;
unsigned int stat = 0;
int ret = 0;
@@ -389,8 +398,14 @@ static void sdhci_set_power(struct sdhci_host *host, unsigned short power)
sdhci_writeb(host, pwr, SDHCI_POWER_CONTROL);
}
+#ifdef CONFIG_DM_MMC_OPS
+static int sdhci_set_ios(struct udevice *dev)
+{
+ struct mmc *mmc = mmc_get_mmc_dev(dev);
+#else
static void sdhci_set_ios(struct mmc *mmc)
{
+#endif
u32 ctrl;
struct sdhci_host *host = mmc->priv;
@@ -426,6 +441,9 @@ static void sdhci_set_ios(struct mmc *mmc)
ctrl &= ~SDHCI_CTRL_HISPD;
sdhci_writeb(host, ctrl, SDHCI_HOST_CONTROL);
+#ifdef CONFIG_DM_MMC_OPS
+ return 0;
+#endif
}
static int sdhci_init(struct mmc *mmc)
@@ -472,80 +490,110 @@ static int sdhci_init(struct mmc *mmc)
return 0;
}
+#ifdef CONFIG_DM_MMC_OPS
+int sdhci_probe(struct udevice *dev)
+{
+ struct mmc *mmc = mmc_get_mmc_dev(dev);
+
+ return sdhci_init(mmc);
+}
+const struct dm_mmc_ops sdhci_ops = {
+ .send_cmd = sdhci_send_command,
+ .set_ios = sdhci_set_ios,
+};
+#else
static const struct mmc_ops sdhci_ops = {
.send_cmd = sdhci_send_command,
.set_ios = sdhci_set_ios,
.init = sdhci_init,
};
+#endif
-int add_sdhci(struct sdhci_host *host, u32 max_clk, u32 min_clk)
+int sdhci_setup_cfg(struct mmc_config *cfg, const char *name, int buswidth,
+ uint caps, u32 max_clk, u32 min_clk, uint version,
+ uint quirks, uint host_caps)
{
- unsigned int caps;
-
- host->cfg.name = host->name;
- host->cfg.ops = &sdhci_ops;
-
- caps = sdhci_readl(host, SDHCI_CAPABILITIES);
-#ifdef CONFIG_MMC_SDMA
- if (!(caps & SDHCI_CAN_DO_SDMA)) {
- printf("%s: Your controller doesn't support SDMA!!\n",
- __func__);
- return -1;
- }
+ cfg->name = name;
+#ifndef CONFIG_DM_MMC_OPS
+ cfg->ops = &sdhci_ops;
#endif
-
if (max_clk)
- host->cfg.f_max = max_clk;
+ cfg->f_max = max_clk;
else {
- if (SDHCI_GET_VERSION(host) >= SDHCI_SPEC_300)
- host->cfg.f_max = (caps & SDHCI_CLOCK_V3_BASE_MASK)
- >> SDHCI_CLOCK_BASE_SHIFT;
+ if (version >= SDHCI_SPEC_300)
+ cfg->f_max = (caps & SDHCI_CLOCK_V3_BASE_MASK) >>
+ SDHCI_CLOCK_BASE_SHIFT;
else
- host->cfg.f_max = (caps & SDHCI_CLOCK_BASE_MASK)
- >> SDHCI_CLOCK_BASE_SHIFT;
- host->cfg.f_max *= 1000000;
- }
- if (host->cfg.f_max == 0) {
- printf("%s: Hardware doesn't specify base clock frequency\n",
- __func__);
- return -1;
+ cfg->f_max = (caps & SDHCI_CLOCK_BASE_MASK) >>
+ SDHCI_CLOCK_BASE_SHIFT;
+ cfg->f_max *= 1000000;
}
+ if (cfg->f_max == 0)
+ return -EINVAL;
if (min_clk)
- host->cfg.f_min = min_clk;
+ cfg->f_min = min_clk;
else {
- if (SDHCI_GET_VERSION(host) >= SDHCI_SPEC_300)
- host->cfg.f_min = host->cfg.f_max /
- SDHCI_MAX_DIV_SPEC_300;
+ if (version >= SDHCI_SPEC_300)
+ cfg->f_min = cfg->f_max / SDHCI_MAX_DIV_SPEC_300;
else
- host->cfg.f_min = host->cfg.f_max /
- SDHCI_MAX_DIV_SPEC_200;
+ cfg->f_min = cfg->f_max / SDHCI_MAX_DIV_SPEC_200;
}
-
- host->cfg.voltages = 0;
+ cfg->voltages = 0;
if (caps & SDHCI_CAN_VDD_330)
- host->cfg.voltages |= MMC_VDD_32_33 | MMC_VDD_33_34;
+ cfg->voltages |= MMC_VDD_32_33 | MMC_VDD_33_34;
if (caps & SDHCI_CAN_VDD_300)
- host->cfg.voltages |= MMC_VDD_29_30 | MMC_VDD_30_31;
+ cfg->voltages |= MMC_VDD_29_30 | MMC_VDD_30_31;
if (caps & SDHCI_CAN_VDD_180)
- host->cfg.voltages |= MMC_VDD_165_195;
+ cfg->voltages |= MMC_VDD_165_195;
- if (host->quirks & SDHCI_QUIRK_BROKEN_VOLTAGE)
- host->cfg.voltages |= host->voltages;
-
- host->cfg.host_caps = MMC_MODE_HS | MMC_MODE_HS_52MHz | MMC_MODE_4BIT;
- if (SDHCI_GET_VERSION(host) >= SDHCI_SPEC_300) {
+ cfg->host_caps = MMC_MODE_HS | MMC_MODE_HS_52MHz | MMC_MODE_4BIT;
+ if (version >= SDHCI_SPEC_300) {
if (caps & SDHCI_CAN_DO_8BIT)
- host->cfg.host_caps |= MMC_MODE_8BIT;
+ cfg->host_caps |= MMC_MODE_8BIT;
}
- if (host->quirks & SDHCI_QUIRK_NO_HISPD_BIT)
- host->cfg.host_caps &= ~(MMC_MODE_HS | MMC_MODE_HS_52MHz);
+ if (quirks & SDHCI_QUIRK_NO_HISPD_BIT)
+ cfg->host_caps &= ~(MMC_MODE_HS | MMC_MODE_HS_52MHz);
- if (host->host_caps)
- host->cfg.host_caps |= host->host_caps;
+ if (host_caps)
+ cfg->host_caps |= host_caps;
- host->cfg.b_max = CONFIG_SYS_MMC_MAX_BLK_COUNT;
+
+ cfg->b_max = CONFIG_SYS_MMC_MAX_BLK_COUNT;
+
+ return 0;
+}
+
+#ifdef CONFIG_BLK
+int sdhci_bind(struct udevice *dev, struct mmc *mmc, struct mmc_config *cfg)
+{
+ return mmc_bind(dev, mmc, cfg);
+}
+#else
+int add_sdhci(struct sdhci_host *host, u32 max_clk, u32 min_clk)
+{
+ unsigned int caps;
+
+ caps = sdhci_readl(host, SDHCI_CAPABILITIES);
+#ifdef CONFIG_MMC_SDMA
+ if (!(caps & SDHCI_CAN_DO_SDMA)) {
+ printf("%s: Your controller doesn't support SDMA!!\n",
+ __func__);
+ return -1;
+ }
+#endif
+
+ if (sdhci_setup_cfg(&host->cfg, host->name, host->bus_width, caps,
+ max_clk, min_clk, SDHCI_GET_VERSION(host),
+ host->quirks, host->host_caps)) {
+ printf("%s: Hardware doesn't specify base clock frequency\n",
+ __func__);
+ return -EINVAL;
+ }
+
+ if (host->quirks & SDHCI_QUIRK_BROKEN_VOLTAGE)
+ host->cfg.voltages |= host->voltages;
sdhci_reset(host, SDHCI_RESET_ALL);
@@ -557,3 +605,4 @@ int add_sdhci(struct sdhci_host *host, u32 max_clk, u32 min_clk)
return 0;
}
+#endif
diff --git a/drivers/spi/cadence_qspi.c b/drivers/spi/cadence_qspi.c
index 4f7fd52..a5244ff 100644
--- a/drivers/spi/cadence_qspi.c
+++ b/drivers/spi/cadence_qspi.c
@@ -191,6 +191,7 @@ static int cadence_spi_xfer(struct udevice *dev, unsigned int bitlen,
struct udevice *bus = dev->parent;
struct cadence_spi_platdata *plat = bus->platdata;
struct cadence_spi_priv *priv = dev_get_priv(bus);
+ struct dm_spi_slave_platdata *dm_plat = dev_get_parent_platdata(dev);
void *base = priv->regbase;
u8 *cmd_buf = priv->cmd_buf;
size_t data_bytes;
@@ -250,7 +251,7 @@ static int cadence_spi_xfer(struct udevice *dev, unsigned int bitlen,
break;
case CQSPI_INDIRECT_READ:
err = cadence_qspi_apb_indirect_read_setup(plat,
- priv->cmd_len, cmd_buf);
+ priv->cmd_len, dm_plat->mode_rx, cmd_buf);
if (!err) {
err = cadence_qspi_apb_indirect_read_execute
(plat, data_bytes, din);
diff --git a/drivers/spi/cadence_qspi.h b/drivers/spi/cadence_qspi.h
index 2912e36..a849f7b 100644
--- a/drivers/spi/cadence_qspi.h
+++ b/drivers/spi/cadence_qspi.h
@@ -53,7 +53,7 @@ int cadence_qspi_apb_command_write(void *reg_base_addr,
unsigned int txlen, const u8 *txbuf);
int cadence_qspi_apb_indirect_read_setup(struct cadence_spi_platdata *plat,
- unsigned int cmdlen, const u8 *cmdbuf);
+ unsigned int cmdlen, unsigned int rx_width, const u8 *cmdbuf);
int cadence_qspi_apb_indirect_read_execute(struct cadence_spi_platdata *plat,
unsigned int rxlen, u8 *rxbuf);
int cadence_qspi_apb_indirect_write_setup(struct cadence_spi_platdata *plat,
diff --git a/drivers/spi/cadence_qspi_apb.c b/drivers/spi/cadence_qspi_apb.c
index a71531d..1a35d55 100644
--- a/drivers/spi/cadence_qspi_apb.c
+++ b/drivers/spi/cadence_qspi_apb.c
@@ -29,6 +29,7 @@
#include <asm/io.h>
#include <asm/errno.h>
#include <wait_bit.h>
+#include <spi.h>
#include "cadence_qspi.h"
#define CQSPI_REG_POLL_US (1) /* 1us */
@@ -45,7 +46,6 @@
#define CQSPI_INST_TYPE_QUAD (2)
#define CQSPI_STIG_DATA_LEN_MAX (8)
-#define CQSPI_INDIRECTTRIGGER_ADDR_MASK (0xFFFFF)
#define CQSPI_DUMMY_CLKS_PER_BYTE (8)
#define CQSPI_DUMMY_BYTES_MAX (4)
@@ -549,7 +549,7 @@ int cadence_qspi_apb_command_write(void *reg_base, unsigned int cmdlen,
/* Opcode + Address (3/4 bytes) + dummy bytes (0-4 bytes) */
int cadence_qspi_apb_indirect_read_setup(struct cadence_spi_platdata *plat,
- unsigned int cmdlen, const u8 *cmdbuf)
+ unsigned int cmdlen, unsigned int rx_width, const u8 *cmdbuf)
{
unsigned int reg;
unsigned int rd_reg;
@@ -573,16 +573,15 @@ int cadence_qspi_apb_indirect_read_setup(struct cadence_spi_platdata *plat,
addr_bytes = cmdlen - 1;
/* Setup the indirect trigger address */
- writel(((u32)plat->ahbbase & CQSPI_INDIRECTTRIGGER_ADDR_MASK),
+ writel((u32)plat->ahbbase,
plat->regbase + CQSPI_REG_INDIRECTTRIGGER);
/* Configure the opcode */
rd_reg = cmdbuf[0] << CQSPI_REG_RD_INSTR_OPCODE_LSB;
-#if (CONFIG_SPI_FLASH_QUAD == 1)
- /* Instruction and address at DQ0, data at DQ0-3. */
- rd_reg |= CQSPI_INST_TYPE_QUAD << CQSPI_REG_RD_INSTR_TYPE_DATA_LSB;
-#endif
+ if (rx_width & SPI_RX_QUAD)
+ /* Instruction and address at DQ0, data at DQ0-3. */
+ rd_reg |= CQSPI_INST_TYPE_QUAD << CQSPI_REG_RD_INSTR_TYPE_DATA_LSB;
/* Get address */
addr_value = cadence_qspi_apb_cmd2addr(&cmdbuf[1], addr_bytes);
@@ -714,7 +713,7 @@ int cadence_qspi_apb_indirect_write_setup(struct cadence_spi_platdata *plat,
return -EINVAL;
}
/* Setup the indirect trigger address */
- writel(((u32)plat->ahbbase & CQSPI_INDIRECTTRIGGER_ADDR_MASK),
+ writel((u32)plat->ahbbase,
plat->regbase + CQSPI_REG_INDIRECTTRIGGER);
/* Configure the opcode */
diff --git a/drivers/spi/davinci_spi.c b/drivers/spi/davinci_spi.c
index 0bd4f88..20aa99a 100644
--- a/drivers/spi/davinci_spi.c
+++ b/drivers/spi/davinci_spi.c
@@ -14,6 +14,7 @@
#include <malloc.h>
#include <asm/io.h>
#include <asm/arch/hardware.h>
+#include <dm.h>
/* SPIGCR0 */
#define SPIGCR0_SPIENA_MASK 0x1
@@ -51,6 +52,7 @@
/* SPIDEF */
#define SPIDEF_CSDEF0_MASK BIT(0)
+#ifndef CONFIG_DM_SPI
#define SPI0_BUS 0
#define SPI0_BASE CONFIG_SYS_SPI_BASE
/*
@@ -83,6 +85,9 @@
#define SPI2_NUM_CS CONFIG_SYS_SPI2_NUM_CS
#define SPI2_BASE CONFIG_SYS_SPI2_BASE
#endif
+#endif
+
+DECLARE_GLOBAL_DATA_PTR;
/* davinci spi register set */
struct davinci_spi_regs {
@@ -114,16 +119,17 @@ struct davinci_spi_regs {
/* davinci spi slave */
struct davinci_spi_slave {
+#ifndef CONFIG_DM_SPI
struct spi_slave slave;
+#endif
struct davinci_spi_regs *regs;
- unsigned int freq;
+ unsigned int freq; /* current SPI bus frequency */
+ unsigned int mode; /* current SPI mode used */
+ u8 num_cs; /* total no. of CS available */
+ u8 cur_cs; /* CS of current slave */
+ bool half_duplex; /* true, if master is half-duplex only */
};
-static inline struct davinci_spi_slave *to_davinci_spi(struct spi_slave *slave)
-{
- return container_of(slave, struct davinci_spi_slave, slave);
-}
-
/*
* This functions needs to act like a macro to avoid pipeline reloads in the
* loops below. Use always_inline. This gains us about 160KiB/s and the bloat
@@ -144,15 +150,14 @@ static inline u32 davinci_spi_xfer_data(struct davinci_spi_slave *ds, u32 data)
return buf_reg_val;
}
-static int davinci_spi_read(struct spi_slave *slave, unsigned int len,
+static int davinci_spi_read(struct davinci_spi_slave *ds, unsigned int len,
u8 *rxp, unsigned long flags)
{
- struct davinci_spi_slave *ds = to_davinci_spi(slave);
unsigned int data1_reg_val;
/* enable CS hold, CS[n] and clear the data bits */
data1_reg_val = ((1 << SPIDAT1_CSHOLD_SHIFT) |
- (slave->cs << SPIDAT1_CSNR_SHIFT));
+ (ds->cur_cs << SPIDAT1_CSNR_SHIFT));
/* wait till TXFULL is deasserted */
while (readl(&ds->regs->buf) & SPIBUF_TXFULL_MASK)
@@ -175,15 +180,14 @@ static int davinci_spi_read(struct spi_slave *slave, unsigned int len,
return 0;
}
-static int davinci_spi_write(struct spi_slave *slave, unsigned int len,
+static int davinci_spi_write(struct davinci_spi_slave *ds, unsigned int len,
const u8 *txp, unsigned long flags)
{
- struct davinci_spi_slave *ds = to_davinci_spi(slave);
unsigned int data1_reg_val;
/* enable CS hold and clear the data bits */
data1_reg_val = ((1 << SPIDAT1_CSHOLD_SHIFT) |
- (slave->cs << SPIDAT1_CSNR_SHIFT));
+ (ds->cur_cs << SPIDAT1_CSNR_SHIFT));
/* wait till TXFULL is deasserted */
while (readl(&ds->regs->buf) & SPIBUF_TXFULL_MASK)
@@ -209,16 +213,15 @@ static int davinci_spi_write(struct spi_slave *slave, unsigned int len,
return 0;
}
-#ifndef CONFIG_SPI_HALF_DUPLEX
-static int davinci_spi_read_write(struct spi_slave *slave, unsigned int len,
- u8 *rxp, const u8 *txp, unsigned long flags)
+static int davinci_spi_read_write(struct davinci_spi_slave *ds, unsigned
+ int len, u8 *rxp, const u8 *txp,
+ unsigned long flags)
{
- struct davinci_spi_slave *ds = to_davinci_spi(slave);
unsigned int data1_reg_val;
/* enable CS hold and clear the data bits */
data1_reg_val = ((1 << SPIDAT1_CSHOLD_SHIFT) |
- (slave->cs << SPIDAT1_CSNR_SHIFT));
+ (ds->cur_cs << SPIDAT1_CSNR_SHIFT));
/* wait till TXFULL is deasserted */
while (readl(&ds->regs->buf) & SPIBUF_TXFULL_MASK)
@@ -237,7 +240,115 @@ static int davinci_spi_read_write(struct spi_slave *slave, unsigned int len,
return 0;
}
-#endif
+
+
+static int __davinci_spi_claim_bus(struct davinci_spi_slave *ds, int cs)
+{
+ unsigned int mode = 0, scalar;
+
+ /* Enable the SPI hardware */
+ writel(SPIGCR0_SPIRST_MASK, &ds->regs->gcr0);
+ udelay(1000);
+ writel(SPIGCR0_SPIENA_MASK, &ds->regs->gcr0);
+
+ /* Set master mode, powered up and not activated */
+ writel(SPIGCR1_MASTER_MASK | SPIGCR1_CLKMOD_MASK, &ds->regs->gcr1);
+
+ /* CS, CLK, SIMO and SOMI are functional pins */
+ writel(((1 << cs) | SPIPC0_CLKFUN_MASK |
+ SPIPC0_DOFUN_MASK | SPIPC0_DIFUN_MASK), &ds->regs->pc0);
+
+ /* setup format */
+ scalar = ((CONFIG_SYS_SPI_CLK / ds->freq) - 1) & 0xFF;
+
+ /*
+ * Use following format:
+ * character length = 8,
+ * MSB shifted out first
+ */
+ if (ds->mode & SPI_CPOL)
+ mode |= SPI_CPOL;
+ if (!(ds->mode & SPI_CPHA))
+ mode |= SPI_CPHA;
+ writel(8 | (scalar << SPIFMT_PRESCALE_SHIFT) |
+ (mode << SPIFMT_PHASE_SHIFT), &ds->regs->fmt0);
+
+ /*
+ * Including a minor delay. No science here. Should be good even with
+ * no delay
+ */
+ writel((50 << SPI_C2TDELAY_SHIFT) |
+ (50 << SPI_T2CDELAY_SHIFT), &ds->regs->delay);
+
+ /* default chip select register */
+ writel(SPIDEF_CSDEF0_MASK, &ds->regs->def);
+
+ /* no interrupts */
+ writel(0, &ds->regs->int0);
+ writel(0, &ds->regs->lvl);
+
+ /* enable SPI */
+ writel((readl(&ds->regs->gcr1) | SPIGCR1_SPIENA_MASK), &ds->regs->gcr1);
+
+ return 0;
+}
+
+static int __davinci_spi_release_bus(struct davinci_spi_slave *ds)
+{
+ /* Disable the SPI hardware */
+ writel(SPIGCR0_SPIRST_MASK, &ds->regs->gcr0);
+
+ return 0;
+}
+
+static int __davinci_spi_xfer(struct davinci_spi_slave *ds,
+ unsigned int bitlen, const void *dout, void *din,
+ unsigned long flags)
+{
+ unsigned int len;
+
+ if (bitlen == 0)
+ /* Finish any previously submitted transfers */
+ goto out;
+
+ /*
+ * It's not clear how non-8-bit-aligned transfers are supposed to be
+ * represented as a stream of bytes...this is a limitation of
+ * the current SPI interface - here we terminate on receiving such a
+ * transfer request.
+ */
+ if (bitlen % 8) {
+ /* Errors always terminate an ongoing transfer */
+ flags |= SPI_XFER_END;
+ goto out;
+ }
+
+ len = bitlen / 8;
+
+ if (!dout)
+ return davinci_spi_read(ds, len, din, flags);
+ if (!din)
+ return davinci_spi_write(ds, len, dout, flags);
+ if (!ds->half_duplex)
+ return davinci_spi_read_write(ds, len, din, dout, flags);
+
+ printf("SPI full duplex not supported\n");
+ flags |= SPI_XFER_END;
+
+out:
+ if (flags & SPI_XFER_END) {
+ u8 dummy = 0;
+ davinci_spi_write(ds, 1, &dummy, flags);
+ }
+ return 0;
+}
+
+#ifndef CONFIG_DM_SPI
+
+static inline struct davinci_spi_slave *to_davinci_spi(struct spi_slave *slave)
+{
+ return container_of(slave, struct davinci_spi_slave, slave);
+}
int spi_cs_is_valid(unsigned int bus, unsigned int cs)
{
@@ -313,6 +424,7 @@ struct spi_slave *spi_setup_slave(unsigned int bus, unsigned int cs,
}
ds->freq = max_hz;
+ ds->mode = mode;
return &ds->slave;
}
@@ -324,104 +436,143 @@ void spi_free_slave(struct spi_slave *slave)
free(ds);
}
+int spi_xfer(struct spi_slave *slave, unsigned int bitlen,
+ const void *dout, void *din, unsigned long flags)
+{
+ struct davinci_spi_slave *ds = to_davinci_spi(slave);
+
+ ds->cur_cs = slave->cs;
+
+ return __davinci_spi_xfer(ds, bitlen, dout, din, flags);
+}
+
int spi_claim_bus(struct spi_slave *slave)
{
struct davinci_spi_slave *ds = to_davinci_spi(slave);
- unsigned int scalar;
- /* Enable the SPI hardware */
- writel(SPIGCR0_SPIRST_MASK, &ds->regs->gcr0);
- udelay(1000);
- writel(SPIGCR0_SPIENA_MASK, &ds->regs->gcr0);
+#ifdef CONFIG_SPI_HALF_DUPLEX
+ ds->half_duplex = true;
+#else
+ ds->half_duplex = false;
+#endif
+ return __davinci_spi_claim_bus(ds, ds->slave.cs);
+}
- /* Set master mode, powered up and not activated */
- writel(SPIGCR1_MASTER_MASK | SPIGCR1_CLKMOD_MASK, &ds->regs->gcr1);
+void spi_release_bus(struct spi_slave *slave)
+{
+ struct davinci_spi_slave *ds = to_davinci_spi(slave);
- /* CS, CLK, SIMO and SOMI are functional pins */
- writel(((1 << slave->cs) | SPIPC0_CLKFUN_MASK |
- SPIPC0_DOFUN_MASK | SPIPC0_DIFUN_MASK), &ds->regs->pc0);
+ __davinci_spi_release_bus(ds);
+}
- /* setup format */
- scalar = ((CONFIG_SYS_SPI_CLK / ds->freq) - 1) & 0xFF;
+#else
+static int davinci_spi_set_speed(struct udevice *bus, uint max_hz)
+{
+ struct davinci_spi_slave *ds = dev_get_priv(bus);
- /*
- * Use following format:
- * character length = 8,
- * clock signal delayed by half clk cycle,
- * clock low in idle state - Mode 0,
- * MSB shifted out first
- */
- writel(8 | (scalar << SPIFMT_PRESCALE_SHIFT) |
- (1 << SPIFMT_PHASE_SHIFT), &ds->regs->fmt0);
+ debug("%s speed %u\n", __func__, max_hz);
+ if (max_hz > CONFIG_SYS_SPI_CLK / 2)
+ return -EINVAL;
- /*
- * Including a minor delay. No science here. Should be good even with
- * no delay
- */
- writel((50 << SPI_C2TDELAY_SHIFT) |
- (50 << SPI_T2CDELAY_SHIFT), &ds->regs->delay);
+ ds->freq = max_hz;
- /* default chip select register */
- writel(SPIDEF_CSDEF0_MASK, &ds->regs->def);
+ return 0;
+}
- /* no interrupts */
- writel(0, &ds->regs->int0);
- writel(0, &ds->regs->lvl);
+static int davinci_spi_set_mode(struct udevice *bus, uint mode)
+{
+ struct davinci_spi_slave *ds = dev_get_priv(bus);
- /* enable SPI */
- writel((readl(&ds->regs->gcr1) | SPIGCR1_SPIENA_MASK), &ds->regs->gcr1);
+ debug("%s mode %u\n", __func__, mode);
+ ds->mode = mode;
return 0;
}
-void spi_release_bus(struct spi_slave *slave)
+static int davinci_spi_claim_bus(struct udevice *dev)
{
- struct davinci_spi_slave *ds = to_davinci_spi(slave);
+ struct dm_spi_slave_platdata *slave_plat =
+ dev_get_parent_platdata(dev);
+ struct udevice *bus = dev->parent;
+ struct davinci_spi_slave *ds = dev_get_priv(bus);
+
+ if (slave_plat->cs >= ds->num_cs) {
+ printf("Invalid SPI chipselect\n");
+ return -EINVAL;
+ }
+ ds->half_duplex = slave_plat->mode & SPI_PREAMBLE;
- /* Disable the SPI hardware */
- writel(SPIGCR0_SPIRST_MASK, &ds->regs->gcr0);
+ return __davinci_spi_claim_bus(ds, slave_plat->cs);
}
-int spi_xfer(struct spi_slave *slave, unsigned int bitlen,
- const void *dout, void *din, unsigned long flags)
+static int davinci_spi_release_bus(struct udevice *dev)
{
- unsigned int len;
+ struct davinci_spi_slave *ds = dev_get_priv(dev->parent);
- if (bitlen == 0)
- /* Finish any previously submitted transfers */
- goto out;
+ return __davinci_spi_release_bus(ds);
+}
- /*
- * It's not clear how non-8-bit-aligned transfers are supposed to be
- * represented as a stream of bytes...this is a limitation of
- * the current SPI interface - here we terminate on receiving such a
- * transfer request.
- */
- if (bitlen % 8) {
- /* Errors always terminate an ongoing transfer */
- flags |= SPI_XFER_END;
- goto out;
+static int davinci_spi_xfer(struct udevice *dev, unsigned int bitlen,
+ const void *dout, void *din,
+ unsigned long flags)
+{
+ struct dm_spi_slave_platdata *slave =
+ dev_get_parent_platdata(dev);
+ struct udevice *bus = dev->parent;
+ struct davinci_spi_slave *ds = dev_get_priv(bus);
+
+ if (slave->cs >= ds->num_cs) {
+ printf("Invalid SPI chipselect\n");
+ return -EINVAL;
}
+ ds->cur_cs = slave->cs;
- len = bitlen / 8;
+ return __davinci_spi_xfer(ds, bitlen, dout, din, flags);
+}
- if (!dout)
- return davinci_spi_read(slave, len, din, flags);
- else if (!din)
- return davinci_spi_write(slave, len, dout, flags);
-#ifndef CONFIG_SPI_HALF_DUPLEX
- else
- return davinci_spi_read_write(slave, len, din, dout, flags);
-#else
- printf("SPI full duplex transaction requested with "
- "CONFIG_SPI_HALF_DUPLEX defined.\n");
- flags |= SPI_XFER_END;
-#endif
+static int davinci_spi_probe(struct udevice *bus)
+{
+ /* Nothing to do */
+ return 0;
+}
-out:
- if (flags & SPI_XFER_END) {
- u8 dummy = 0;
- davinci_spi_write(slave, 1, &dummy, flags);
+static int davinci_ofdata_to_platadata(struct udevice *bus)
+{
+ struct davinci_spi_slave *ds = dev_get_priv(bus);
+ const void *blob = gd->fdt_blob;
+ int node = bus->of_offset;
+
+ ds->regs = dev_map_physmem(bus, sizeof(struct davinci_spi_regs));
+ if (!ds->regs) {
+ printf("%s: could not map device address\n", __func__);
+ return -EINVAL;
}
+ ds->num_cs = fdtdec_get_int(blob, node, "num-cs", 4);
+
return 0;
}
+
+static const struct dm_spi_ops davinci_spi_ops = {
+ .claim_bus = davinci_spi_claim_bus,
+ .release_bus = davinci_spi_release_bus,
+ .xfer = davinci_spi_xfer,
+ .set_speed = davinci_spi_set_speed,
+ .set_mode = davinci_spi_set_mode,
+};
+
+static const struct udevice_id davinci_spi_ids[] = {
+ { .compatible = "ti,keystone-spi" },
+ { .compatible = "ti,dm6441-spi" },
+ { }
+};
+
+U_BOOT_DRIVER(davinci_spi) = {
+ .name = "davinci_spi",
+ .id = UCLASS_SPI,
+ .of_match = davinci_spi_ids,
+ .ops = &davinci_spi_ops,
+ .ofdata_to_platdata = davinci_ofdata_to_platadata,
+ .priv_auto_alloc_size = sizeof(struct davinci_spi_slave),
+ .probe = davinci_spi_probe,
+};
+#endif
diff --git a/drivers/spi/spi-uclass.c b/drivers/spi/spi-uclass.c
index 84b6786..8003f9b 100644
--- a/drivers/spi/spi-uclass.c
+++ b/drivers/spi/spi-uclass.c
@@ -278,6 +278,7 @@ int spi_get_bus_and_cs(int busnum, int cs, int speed, int mode,
struct udevice **busp, struct spi_slave **devp)
{
struct udevice *bus, *dev;
+ struct dm_spi_slave_platdata *plat;
bool created = false;
int ret;
@@ -294,8 +295,6 @@ int spi_get_bus_and_cs(int busnum, int cs, int speed, int mode,
* SPI flash chip - we will bind to the correct driver.
*/
if (ret == -ENODEV && drv_name) {
- struct dm_spi_slave_platdata *plat;
-
debug("%s: Binding new device '%s', busnum=%d, cs=%d, driver=%s\n",
__func__, dev_name, busnum, cs, drv_name);
ret = device_bind_driver(bus, drv_name, dev_name, &dev);
@@ -322,6 +321,11 @@ int spi_get_bus_and_cs(int busnum, int cs, int speed, int mode,
slave->dev = dev;
}
+ plat = dev_get_parent_platdata(dev);
+ if (!speed) {
+ speed = plat->max_hz;
+ mode = plat->mode;
+ }
ret = spi_set_speed_mode(bus, speed, mode);
if (ret)
goto err;
@@ -333,7 +337,7 @@ int spi_get_bus_and_cs(int busnum, int cs, int speed, int mode,
return 0;
err:
- debug("%s: Error path, credted=%d, device '%s'\n", __func__,
+ debug("%s: Error path, created=%d, device '%s'\n", __func__,
created, dev->name);
if (created) {
device_remove(dev);
diff --git a/include/configs/k2g_evm.h b/include/configs/k2g_evm.h
index f8bba67..71b0037 100644
--- a/include/configs/k2g_evm.h
+++ b/include/configs/k2g_evm.h
@@ -73,4 +73,10 @@
#define CONFIG_SF_DEFAULT_BUS 1
#define CONFIG_SF_DEFAULT_CS 0
+#ifndef CONFIG_SPL_BUILD
+#define CONFIG_CADENCE_QSPI
+#define CONFIG_CQSPI_REF_CLK 384000000
+#define CONFIG_CQSPI_DECODER 0x0
+#endif
+
#endif /* __CONFIG_K2G_EVM_H */
diff --git a/include/configs/rk3036_common.h b/include/configs/rk3036_common.h
index 1bdcf9d..ae4b101 100644
--- a/include/configs/rk3036_common.h
+++ b/include/configs/rk3036_common.h
@@ -45,7 +45,6 @@
/* MMC/SD IP block */
#define CONFIG_MMC
#define CONFIG_GENERIC_MMC
-#define CONFIG_SDHCI
#define CONFIG_DWMMC
#define CONFIG_BOUNCE_BUFFER
diff --git a/include/configs/rk3288_common.h b/include/configs/rk3288_common.h
index 9d50d83..8adc26f 100644
--- a/include/configs/rk3288_common.h
+++ b/include/configs/rk3288_common.h
@@ -51,7 +51,6 @@
/* MMC/SD IP block */
#define CONFIG_MMC
#define CONFIG_GENERIC_MMC
-#define CONFIG_SDHCI
#define CONFIG_DWMMC
#define CONFIG_BOUNCE_BUFFER
diff --git a/include/configs/ti_armv7_keystone2.h b/include/configs/ti_armv7_keystone2.h
index 2ee26c4..4aa262e 100644
--- a/include/configs/ti_armv7_keystone2.h
+++ b/include/configs/ti_armv7_keystone2.h
@@ -89,6 +89,10 @@
#define CONFIG_SYS_SPI2
#define CONFIG_SYS_SPI2_BASE KS2_SPI2_BASE
#define CONFIG_SYS_SPI2_NUM_CS 4
+#ifdef CONFIG_SPL_BUILD
+#undef CONFIG_DM_SPI
+#undef CONFIG_DM_SPI_FLASH
+#endif
/* Network Configuration */
#define CONFIG_PHYLIB
diff --git a/include/dm/device.h b/include/dm/device.h
index f03bcd3..1bfcf3b 100644
--- a/include/dm/device.h
+++ b/include/dm/device.h
@@ -467,6 +467,19 @@ fdt_addr_t dev_get_addr(struct udevice *dev);
void *dev_get_addr_ptr(struct udevice *dev);
/**
+ * dev_map_physmem() - Read device address from reg property of the
+ * device node and map the address into CPU address
+ * space.
+ *
+ * @dev: Pointer to device
+ * @size: size of the memory to map
+ *
+ * @return mapped address, or NULL if the device does not have reg
+ * property.
+ */
+void *dev_map_physmem(struct udevice *dev, unsigned long size);
+
+/**
* dev_get_addr_index() - Get the indexed reg property of a device
*
* @dev: Pointer to a device
diff --git a/include/dm/uclass-id.h b/include/dm/uclass-id.h
index b768660..c5cdfc7 100644
--- a/include/dm/uclass-id.h
+++ b/include/dm/uclass-id.h
@@ -33,7 +33,6 @@ enum uclass_id {
UCLASS_CROS_EC, /* Chrome OS EC */
UCLASS_DISPLAY, /* Display (e.g. DisplayPort, HDMI) */
UCLASS_DMA, /* Direct Memory Access */
- UCLASS_RAM, /* RAM controller */
UCLASS_ETH, /* Ethernet device */
UCLASS_GPIO, /* Bank of general-purpose I/O pins */
UCLASS_I2C, /* I2C bus */
@@ -56,11 +55,12 @@ enum uclass_id {
UCLASS_PCH, /* x86 platform controller hub */
UCLASS_PCI, /* PCI bus */
UCLASS_PCI_GENERIC, /* Generic PCI bus device */
- UCLASS_PINCTRL, /* Pinctrl (pin muxing/configuration) device */
UCLASS_PINCONFIG, /* Pin configuration node device */
+ UCLASS_PINCTRL, /* Pinctrl (pin muxing/configuration) device */
UCLASS_PMIC, /* PMIC I/O device */
UCLASS_PWM, /* Pulse-width modulator */
UCLASS_PWRSEQ, /* Power sequence device */
+ UCLASS_RAM, /* RAM controller */
UCLASS_REGULATOR, /* Regulator device */
UCLASS_REMOTEPROC, /* Remote Processor device */
UCLASS_RESET, /* Reset controller device */
diff --git a/include/dwmmc.h b/include/dwmmc.h
index 335af51..6aebe96 100644
--- a/include/dwmmc.h
+++ b/include/dwmmc.h
@@ -224,9 +224,82 @@ static inline u8 dwmci_readb(struct dwmci_host *host, int reg)
return readb(host->ioaddr + reg);
}
+#ifdef CONFIG_BLK
+/**
+ * dwmci_setup_cfg() - Set up the configuration for DWMMC
+ *
+ * This is used to set up a DWMMC device when you are using CONFIG_BLK.
+ *
+ * This should be called from your MMC driver's probe() method once you have
+ * the information required.
+ *
+ * Generally your driver will have a platform data structure which holds both
+ * the configuration (struct mmc_config) and the MMC device info (struct mmc).
+ * For example:
+ *
+ * struct rockchip_mmc_plat {
+ * struct mmc_config cfg;
+ * struct mmc mmc;
+ * };
+ *
+ * ...
+ *
+ * Inside U_BOOT_DRIVER():
+ * .platdata_auto_alloc_size = sizeof(struct rockchip_mmc_plat),
+ *
+ * To access platform data:
+ * struct rockchip_mmc_plat *plat = dev_get_platdata(dev);
+ *
+ * See rockchip_dw_mmc.c for an example.
+ *
+ * @cfg: Configuration structure to fill in (generally &plat->mmc)
+ * @name: Device name (normally dev->name)
+ * @buswidth: Bus width (in bits, such as 4 or 8)
+ * @caps: Host capabilities (MMC_MODE_...)
+ * @max_clk: Maximum supported clock speed in HZ (e.g. 400000)
+ * @min_clk: Minimum supported clock speed in HZ (e.g. 150000000)
+ */
void dwmci_setup_cfg(struct mmc_config *cfg, const char *name, int buswidth,
uint caps, u32 max_clk, u32 min_clk);
+
+/**
+ * dwmci_bind() - Set up a new MMC block device
+ *
+ * This is used to set up a DWMMC block device when you are using CONFIG_BLK.
+ * It should be called from your driver's bind() method.
+ *
+ * See rockchip_dw_mmc.c for an example.
+ *
+ * @dev: Device to set up
+ * @mmc: Pointer to mmc structure (normally &plat->mmc)
+ * @cfg: Empty configuration structure (generally &plat->cfg). This is
+ * normally all zeroes at this point. The only purpose of passing
+ * this in is to set mmc->cfg to it.
+ * @return 0 if OK, -ve if the block device could not be created
+ */
int dwmci_bind(struct udevice *dev, struct mmc *mmc, struct mmc_config *cfg);
+#else
+/**
+ * add_dwmci() - Add a new DWMMC interface
+ *
+ * This is used when you are not using CONFIG_BLK. Convert your driver over!
+ *
+ * @host: DWMMC host structure
+ * @max_clk: Maximum supported clock speed in HZ (e.g. 400000)
+ * @min_clk: Minimum supported clock speed in HZ (e.g. 150000000)
+ * @return 0 if OK, -ve on error
+ */
int add_dwmci(struct dwmci_host *host, u32 max_clk, u32 min_clk);
+#endif /* !CONFIG_BLK */
+
+#ifdef CONFIG_DM_MMC_OPS
+/* Export the operations to drivers */
+int dwmci_send_cmd(struct udevice *dev, struct mmc_cmd *cmd,
+ struct mmc_data *data);
+int dwmci_set_ios(struct udevice *dev);
+int dwmci_probe(struct udevice *dev);
+extern const struct dm_mmc_ops dm_dwmci_ops;
+#endif
+
#endif /* __DWMMC_HW_H */
diff --git a/include/fdtdec.h b/include/fdtdec.h
index 05d70c4..151c590 100644
--- a/include/fdtdec.h
+++ b/include/fdtdec.h
@@ -134,13 +134,10 @@ enum fdt_compat_id {
COMPAT_SAMSUNG_S3C2440_I2C, /* Exynos I2C Controller */
COMPAT_SAMSUNG_EXYNOS5_SOUND, /* Exynos Sound */
COMPAT_WOLFSON_WM8994_CODEC, /* Wolfson WM8994 Sound Codec */
- COMPAT_GOOGLE_CROS_EC_KEYB, /* Google CROS_EC Keyboard */
COMPAT_SAMSUNG_EXYNOS_USB_PHY, /* Exynos phy controller for usb2.0 */
COMPAT_SAMSUNG_EXYNOS5_USB3_PHY,/* Exynos phy controller for usb3.0 */
COMPAT_SAMSUNG_EXYNOS_TMU, /* Exynos TMU */
- COMPAT_SAMSUNG_EXYNOS_FIMD, /* Exynos Display controller */
COMPAT_SAMSUNG_EXYNOS_MIPI_DSI, /* Exynos mipi dsi */
- COMPAT_SAMSUNG_EXYNOS5_DP, /* Exynos Display port controller */
COMPAT_SAMSUNG_EXYNOS_DWMMC, /* Exynos DWMMC controller */
COMPAT_SAMSUNG_EXYNOS_MMC, /* Exynos MMC controller */
COMPAT_MAXIM_MAX77686_PMIC, /* MAX77686 PMIC */
@@ -149,14 +146,9 @@ enum fdt_compat_id {
COMPAT_SAMSUNG_EXYNOS5_I2C, /* Exynos5 High Speed I2C Controller */
COMPAT_SAMSUNG_EXYNOS_SYSMMU, /* Exynos sysmmu */
COMPAT_INTEL_MICROCODE, /* Intel microcode update */
- COMPAT_INTEL_PANTHERPOINT_AHCI, /* Intel Pantherpoint AHCI */
- COMPAT_INTEL_MODEL_206AX, /* Intel Model 206AX CPU */
- COMPAT_INTEL_GMA, /* Intel Graphics Media Accelerator */
COMPAT_AMS_AS3722, /* AMS AS3722 PMIC */
- COMPAT_INTEL_ICH_SPI, /* Intel ICH7/9 SPI controller */
COMPAT_INTEL_QRK_MRC, /* Intel Quark MRC */
COMPAT_SOCIONEXT_XHCI, /* Socionext UniPhier xHCI */
- COMPAT_INTEL_PCH, /* Intel PCH */
COMPAT_ALTERA_SOCFPGA_DWMAC, /* SoCFPGA Ethernet controller */
COMPAT_ALTERA_SOCFPGA_DWMMC, /* SoCFPGA DWMMC controller */
COMPAT_ALTERA_SOCFPGA_DWC2USB, /* SoCFPGA DWC2 USB controller */
diff --git a/include/mmc.h b/include/mmc.h
index f383925..8f309f1 100644
--- a/include/mmc.h
+++ b/include/mmc.h
@@ -323,6 +323,58 @@ struct mmc_data {
/* forward decl. */
struct mmc;
+#ifdef CONFIG_DM_MMC_OPS
+struct dm_mmc_ops {
+ /**
+ * send_cmd() - Send a command to the MMC device
+ *
+ * @dev: Device to receive the command
+ * @cmd: Command to send
+ * @data: Additional data to send/receive
+ * @return 0 if OK, -ve on error
+ */
+ int (*send_cmd)(struct udevice *dev, struct mmc_cmd *cmd,
+ struct mmc_data *data);
+
+ /**
+ * set_ios() - Set the I/O speed/width for an MMC device
+ *
+ * @dev: Device to update
+ * @return 0 if OK, -ve on error
+ */
+ int (*set_ios)(struct udevice *dev);
+
+ /**
+ * get_cd() - See whether a card is present
+ *
+ * @dev: Device to check
+ * @return 0 if not present, 1 if present, -ve on error
+ */
+ int (*get_cd)(struct udevice *dev);
+
+ /**
+ * get_wp() - See whether a card has write-protect enabled
+ *
+ * @dev: Device to check
+ * @return 0 if write-enabled, 1 if write-protected, -ve on error
+ */
+ int (*get_wp)(struct udevice *dev);
+};
+
+#define mmc_get_ops(dev) ((struct dm_mmc_ops *)(dev)->driver->ops)
+
+int dm_mmc_send_cmd(struct udevice *dev, struct mmc_cmd *cmd,
+ struct mmc_data *data);
+int dm_mmc_set_ios(struct udevice *dev);
+int dm_mmc_get_cd(struct udevice *dev);
+int dm_mmc_get_wp(struct udevice *dev);
+
+/* Transition functions for compatibility */
+int mmc_set_ios(struct mmc *mmc);
+int mmc_getcd(struct mmc *mmc);
+int mmc_getwp(struct mmc *mmc);
+
+#else
struct mmc_ops {
int (*send_cmd)(struct mmc *mmc,
struct mmc_cmd *cmd, struct mmc_data *data);
@@ -331,10 +383,13 @@ struct mmc_ops {
int (*getcd)(struct mmc *mmc);
int (*getwp)(struct mmc *mmc);
};
+#endif
struct mmc_config {
const char *name;
+#ifndef CONFIG_DM_MMC_OPS
const struct mmc_ops *ops;
+#endif
uint host_caps;
uint voltages;
uint f_min;
@@ -343,7 +398,12 @@ struct mmc_config {
unsigned char part_type;
};
-/* TODO struct mmc should be in mmc_private but it's hard to fix right now */
+/*
+ * With CONFIG_DM_MMC enabled, struct mmc can be accessed from the MMC device
+ * with mmc_get_mmc_dev().
+ *
+ * TODO struct mmc should be in mmc_private but it's hard to fix right now
+ */
struct mmc {
#ifndef CONFIG_BLK
struct list_head link;
@@ -446,10 +506,14 @@ void print_mmc_devices(char separator);
int get_mmc_num(void);
int mmc_hwpart_config(struct mmc *mmc, const struct mmc_hwpart_conf *conf,
enum mmc_hwpart_conf_mode mode);
+
+#ifndef CONFIG_DM_MMC_OPS
int mmc_getcd(struct mmc *mmc);
int board_mmc_getcd(struct mmc *mmc);
int mmc_getwp(struct mmc *mmc);
int board_mmc_getwp(struct mmc *mmc);
+#endif
+
int mmc_set_dsr(struct mmc *mmc, u16 val);
/* Function to change the size of boot partition and rpmb partitions */
int mmc_boot_partition_size_change(struct mmc *mmc, unsigned long bootsize,
diff --git a/include/sdhci.h b/include/sdhci.h
index e0f6667..c4d3b55 100644
--- a/include/sdhci.h
+++ b/include/sdhci.h
@@ -338,5 +338,85 @@ static inline u8 sdhci_readb(struct sdhci_host *host, int reg)
}
#endif
+#ifdef CONFIG_BLK
+/**
+ * sdhci_setup_cfg() - Set up the configuration for DWMMC
+ *
+ * This is used to set up an SDHCI device when you are using CONFIG_BLK.
+ *
+ * This should be called from your MMC driver's probe() method once you have
+ * the information required.
+ *
+ * Generally your driver will have a platform data structure which holds both
+ * the configuration (struct mmc_config) and the MMC device info (struct mmc).
+ * For example:
+ *
+ * struct msm_sdhc_plat {
+ * struct mmc_config cfg;
+ * struct mmc mmc;
+ * };
+ *
+ * ...
+ *
+ * Inside U_BOOT_DRIVER():
+ * .platdata_auto_alloc_size = sizeof(struct msm_sdhc_plat),
+ *
+ * To access platform data:
+ * struct msm_sdhc_plat *plat = dev_get_platdata(dev);
+ *
+ * See msm_sdhci.c for an example.
+ *
+ * @cfg: Configuration structure to fill in (generally &plat->mmc)
+ * @name: Device name (normally dev->name)
+ * @buswidth: Bus width (in bits, such as 4 or 8)
+ * @caps: Host capabilities (MMC_MODE_...)
+ * @max_clk: Maximum supported clock speed in HZ (0 for default)
+ * @min_clk: Minimum supported clock speed in HZ (0 for default)
+ * @version: Host controller version (generally read from the
+ * SDHCI_HOST_VERSION register)
+ * @quirks: Quick flags (SDHCI_QUIRK_...)
+ * @host_caps: Additional host capabilities (0 if none)
+ */
+int sdhci_setup_cfg(struct mmc_config *cfg, const char *name, int buswidth,
+ uint caps, u32 max_clk, u32 min_clk, uint version,
+ uint quirks, uint host_caps);
+
+/**
+ * sdhci_bind() - Set up a new MMC block device
+ *
+ * This is used to set up an SDHCI block device when you are using CONFIG_BLK.
+ * It should be called from your driver's bind() method.
+ *
+ * See msm_sdhci.c for an example.
+ *
+ * @dev: Device to set up
+ * @mmc: Pointer to mmc structure (normally &plat->mmc)
+ * @cfg: Empty configuration structure (generally &plat->cfg). This is
+ * normally all zeroes at this point. The only purpose of passing
+ * this in is to set mmc->cfg to it.
+ * @return 0 if OK, -ve if the block device could not be created
+ */
+int sdhci_bind(struct udevice *dev, struct mmc *mmc, struct mmc_config *cfg);
+#else
+
+/**
+ * add_sdhci() - Add a new SDHCI interface
+ *
+ * This is used when you are not using CONFIG_BLK. Convert your driver over!
+ *
+ * @host: SDHCI host structure
+ * @max_clk: Maximum supported clock speed in HZ (0 for default)
+ * @min_clk: Minimum supported clock speed in HZ (0 for default)
+ * @return 0 if OK, -ve on error
+ */
int add_sdhci(struct sdhci_host *host, u32 max_clk, u32 min_clk);
+#endif /* !CONFIG_BLK */
+
+#ifdef CONFIG_DM_MMC_OPS
+/* Export the operations to drivers */
+int sdhci_probe(struct udevice *dev);
+extern const struct dm_mmc_ops sdhci_ops;
+#else
+#endif
+
#endif /* __SDHCI_HW_H */
diff --git a/lib/fdtdec.c b/lib/fdtdec.c
index 0534c0b..c2bcbde 100644
--- a/lib/fdtdec.c
+++ b/lib/fdtdec.c
@@ -19,6 +19,11 @@ DECLARE_GLOBAL_DATA_PTR;
* Here are the type we know about. One day we might allow drivers to
* register. For now we just put them here. The COMPAT macro allows us to
* turn this into a sparse list later, and keeps the ID with the name.
+ *
+ * NOTE: This list is basically a TODO list for things that need to be
+ * converted to driver model. So don't add new things here unless there is a
+ * good reason why driver-model conversion is infeasible. Examples include
+ * things which are used before driver model is available.
*/
#define COMPAT(id, name) name
static const char * const compat_names[COMPAT_COUNT] = {
@@ -39,13 +44,10 @@ static const char * const compat_names[COMPAT_COUNT] = {
COMPAT(SAMSUNG_S3C2440_I2C, "samsung,s3c2440-i2c"),
COMPAT(SAMSUNG_EXYNOS5_SOUND, "samsung,exynos-sound"),
COMPAT(WOLFSON_WM8994_CODEC, "wolfson,wm8994-codec"),
- COMPAT(GOOGLE_CROS_EC_KEYB, "google,cros-ec-keyb"),
COMPAT(SAMSUNG_EXYNOS_USB_PHY, "samsung,exynos-usb-phy"),
COMPAT(SAMSUNG_EXYNOS5_USB3_PHY, "samsung,exynos5250-usb3-phy"),
COMPAT(SAMSUNG_EXYNOS_TMU, "samsung,exynos-tmu"),
- COMPAT(SAMSUNG_EXYNOS_FIMD, "samsung,exynos-fimd"),
COMPAT(SAMSUNG_EXYNOS_MIPI_DSI, "samsung,exynos-mipi-dsi"),
- COMPAT(SAMSUNG_EXYNOS5_DP, "samsung,exynos5-dp"),
COMPAT(SAMSUNG_EXYNOS_DWMMC, "samsung,exynos-dwmmc"),
COMPAT(SAMSUNG_EXYNOS_MMC, "samsung,exynos-mmc"),
COMPAT(MAXIM_MAX77686_PMIC, "maxim,max77686"),
@@ -54,20 +56,15 @@ static const char * const compat_names[COMPAT_COUNT] = {
COMPAT(SAMSUNG_EXYNOS5_I2C, "samsung,exynos5-hsi2c"),
COMPAT(SAMSUNG_EXYNOS_SYSMMU, "samsung,sysmmu-v3.3"),
COMPAT(INTEL_MICROCODE, "intel,microcode"),
- COMPAT(INTEL_PANTHERPOINT_AHCI, "intel,pantherpoint-ahci"),
- COMPAT(INTEL_MODEL_206AX, "intel,model-206ax"),
- COMPAT(INTEL_GMA, "intel,gma"),
COMPAT(AMS_AS3722, "ams,as3722"),
- COMPAT(INTEL_ICH_SPI, "intel,ich-spi"),
COMPAT(INTEL_QRK_MRC, "intel,quark-mrc"),
COMPAT(SOCIONEXT_XHCI, "socionext,uniphier-xhci"),
- COMPAT(COMPAT_INTEL_PCH, "intel,bd82x6x"),
COMPAT(ALTERA_SOCFPGA_DWMAC, "altr,socfpga-stmmac"),
COMPAT(ALTERA_SOCFPGA_DWMMC, "altr,socfpga-dw-mshc"),
COMPAT(ALTERA_SOCFPGA_DWC2USB, "snps,dwc2"),
- COMPAT(COMPAT_INTEL_BAYTRAIL_FSP, "intel,baytrail-fsp"),
- COMPAT(COMPAT_INTEL_BAYTRAIL_FSP_MDP, "intel,baytrail-fsp-mdp"),
- COMPAT(COMPAT_INTEL_IVYBRIDGE_FSP, "intel,ivybridge-fsp"),
+ COMPAT(INTEL_BAYTRAIL_FSP, "intel,baytrail-fsp"),
+ COMPAT(INTEL_BAYTRAIL_FSP_MDP, "intel,baytrail-fsp-mdp"),
+ COMPAT(INTEL_IVYBRIDGE_FSP, "intel,ivybridge-fsp"),
};
const char *fdtdec_get_compatible(enum fdt_compat_id id)
diff --git a/tools/patman/patchstream.py b/tools/patman/patchstream.py
index 27d031e..69d5cfb 100644
--- a/tools/patman/patchstream.py
+++ b/tools/patman/patchstream.py
@@ -112,6 +112,14 @@ class PatchStream:
if self.commit and self.is_log:
self.series.AddCommit(self.commit)
self.commit = None
+ # If 'END' is missing in a 'Cover-letter' section, and that section
+ # happens to show up at the very end of the commit message, this is
+ # the chance for us to fix it up.
+ if self.in_section == 'cover' and self.is_log:
+ self.series.cover = self.section
+ self.in_section = None
+ self.skip_blank = True
+ self.section = []
def ProcessLine(self, line):
"""Process a single line of a patch file or commit log
@@ -150,6 +158,7 @@ class PatchStream:
# Handle state transition and skipping blank lines
series_tag_match = re_series_tag.match(line)
commit_tag_match = re_commit_tag.match(line)
+ cover_match = re_cover.match(line)
cover_cc_match = re_cover_cc.match(line)
signoff_match = re_signoff.match(line)
tag_match = None
@@ -168,6 +177,33 @@ class PatchStream:
elif commit_match:
self.state = STATE_MSG_HEADER
+ # If a tag is detected, or a new commit starts
+ if series_tag_match or commit_tag_match or \
+ cover_match or cover_cc_match or signoff_match or \
+ self.state == STATE_MSG_HEADER:
+ # but we are already in a section, this means 'END' is missing
+ # for that section, fix it up.
+ if self.in_section:
+ self.warn.append("Missing 'END' in section '%s'" % self.in_section)
+ if self.in_section == 'cover':
+ self.series.cover = self.section
+ elif self.in_section == 'notes':
+ if self.is_log:
+ self.series.notes += self.section
+ elif self.in_section == 'commit-notes':
+ if self.is_log:
+ self.commit.notes += self.section
+ else:
+ self.warn.append("Unknown section '%s'" % self.in_section)
+ self.in_section = None
+ self.skip_blank = True
+ self.section = []
+ # but we are already in a change list, that means a blank line
+ # is missing, fix it up.
+ if self.in_change:
+ self.warn.append("Missing 'blank line' in section 'Series-changes'")
+ self.in_change = 0
+
# If we are in a section, keep collecting lines until we see END
if self.in_section:
if line == 'END':
@@ -203,7 +239,7 @@ class PatchStream:
self.skip_blank = False
# Detect the start of a cover letter section
- elif re_cover.match(line):
+ elif cover_match:
self.in_section = 'cover'
self.skip_blank = False