All of lore.kernel.org
 help / color / mirror / Atom feed
* [U-Boot] [PATCH 1/5] doc: fix: Replace SPL_OF_PLATDATA with OF_PLATDATA in examples
@ 2019-08-12  7:22 Lukasz Majewski
  2019-08-12  7:22 ` [U-Boot] [PATCH 2/5] dts: imx28: Remove #include "imx28.dtsi" from imx28-u-boot.dtsi file Lukasz Majewski
                   ` (4 more replies)
  0 siblings, 5 replies; 6+ messages in thread
From: Lukasz Majewski @ 2019-08-12  7:22 UTC (permalink / raw)
  To: u-boot

The of-plat.rst file till this change has been using
#if CONFIG_IS_ENABLED(SPL_OF_PLATDATA) it its examples.

This is at best misleading as SPL_OF_PLATDATA is always defined when we
want to use this SPL tinification feature (also in U-Boot proper).
As a result the OF_PLATDATA SPL specific code is also compiled in when
U-Boot proper is build.

Signed-off-by: Lukasz Majewski <lukma@denx.de>
---

 doc/driver-model/of-plat.rst | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/doc/driver-model/of-plat.rst b/doc/driver-model/of-plat.rst
index 0d3cd8c01e..a38e58e4d2 100644
--- a/doc/driver-model/of-plat.rst
+++ b/doc/driver-model/of-plat.rst
@@ -224,7 +224,7 @@ For example:
     #include <dt-structs.h>
 
     struct mmc_platdata {
-    #if CONFIG_IS_ENABLED(SPL_OF_PLATDATA)
+    #if CONFIG_IS_ENABLED(OF_PLATDATA)
             /* Put this first since driver model will copy the data here */
             struct dtd_mmc dtplat;
     #endif
@@ -237,7 +237,7 @@ For example:
 
     static int mmc_ofdata_to_platdata(struct udevice *dev)
     {
-    #if !CONFIG_IS_ENABLED(SPL_OF_PLATDATA)
+    #if !CONFIG_IS_ENABLED(OF_PLATDATA)
             /* Decode the device tree data */
             struct mmc_platdata *plat = dev_get_platdata(dev);
             const void *blob = gd->fdt_blob;
@@ -253,7 +253,7 @@ For example:
     {
             struct mmc_platdata *plat = dev_get_platdata(dev);
 
-    #if CONFIG_IS_ENABLED(SPL_OF_PLATDATA)
+    #if CONFIG_IS_ENABLED(OF_PLATDATA)
             /* Decode the of-platdata from the C structures */
             struct dtd_mmc *dtplat = &plat->dtplat;
 
@@ -308,7 +308,7 @@ The dt-structs.h file includes the generated file
 (include/generated//dt-structs.h) if CONFIG_SPL_OF_PLATDATA is enabled.
 Otherwise (such as in U-Boot proper) these structs are not available. This
 prevents them being used inadvertently. All usage must be bracketed with
-#if CONFIG_IS_ENABLED(SPL_OF_PLATDATA).
+#if CONFIG_IS_ENABLED(OF_PLATDATA).
 
 The dt-platdata.c file contains the device declarations and is is built in
 spl/dt-platdata.c.
-- 
2.11.0

^ permalink raw reply related	[flat|nested] 6+ messages in thread

* [U-Boot] [PATCH 2/5] dts: imx28: Remove #include "imx28.dtsi" from imx28-u-boot.dtsi file
  2019-08-12  7:22 [U-Boot] [PATCH 1/5] doc: fix: Replace SPL_OF_PLATDATA with OF_PLATDATA in examples Lukasz Majewski
@ 2019-08-12  7:22 ` Lukasz Majewski
  2019-08-12  7:22 ` [U-Boot] [PATCH 3/5] spi: fix: Call mxs_reset_block() during DM/DTS probe Lukasz Majewski
                   ` (3 subsequent siblings)
  4 siblings, 0 replies; 6+ messages in thread
From: Lukasz Majewski @ 2019-08-12  7:22 UTC (permalink / raw)
  To: u-boot

After this change it is possible to use imx28-<board>-u-boot.dtsi with
the imx28-u-boot.dtsi explicitly included without breaking setup from
imx28-<board>.dts file.

The problem is that the imx28.dtsi included in a wrong place overrides the
changes made in imx28-<board>.dts. As a result some devices are "disabled"
in the final DTB.

Signed-off-by: Lukasz Majewski <lukma@denx.de>
---

 arch/arm/dts/imx28-u-boot.dtsi | 1 -
 1 file changed, 1 deletion(-)

diff --git a/arch/arm/dts/imx28-u-boot.dtsi b/arch/arm/dts/imx28-u-boot.dtsi
index d545b402a7..9db72a6be3 100644
--- a/arch/arm/dts/imx28-u-boot.dtsi
+++ b/arch/arm/dts/imx28-u-boot.dtsi
@@ -5,7 +5,6 @@
  *
  * SPDX-License-Identifier:     GPL-2.0+ or X11
  */
-#include "imx28.dtsi"
 
 &gpio0 {
 	gpio-ranges = <&pinctrl 0 0 29>;
-- 
2.11.0

^ permalink raw reply related	[flat|nested] 6+ messages in thread

* [U-Boot] [PATCH 3/5] spi: fix: Call mxs_reset_block() during DM/DTS probe
  2019-08-12  7:22 [U-Boot] [PATCH 1/5] doc: fix: Replace SPL_OF_PLATDATA with OF_PLATDATA in examples Lukasz Majewski
  2019-08-12  7:22 ` [U-Boot] [PATCH 2/5] dts: imx28: Remove #include "imx28.dtsi" from imx28-u-boot.dtsi file Lukasz Majewski
@ 2019-08-12  7:22 ` Lukasz Majewski
  2019-08-12  7:22 ` [U-Boot] [PATCH 4/5] spi: Add support for SPL_OF_PLATDATA to mxs_spi.c driver Lukasz Majewski
                   ` (2 subsequent siblings)
  4 siblings, 0 replies; 6+ messages in thread
From: Lukasz Majewski @ 2019-08-12  7:22 UTC (permalink / raw)
  To: u-boot

Without this change the DM/DTS version of mxs_spi driver doesn't reset the
SPI IP block in probe.
As a result this driver (when used solely on U-Boot proper) relies on reset
performed by mxs spi driver in SPL.

In the use case where eMMC is used in SPL as a boot primary device, the
mxs_reset_block() is not called at all and DM/DTS aware SPI driver in
U-Boot proper is malfunctioning.

Signed-off-by: Lukasz Majewski <lukma@denx.de>
---

 drivers/spi/mxs_spi.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/drivers/spi/mxs_spi.c b/drivers/spi/mxs_spi.c
index 3a9756fbf1..b79a72db2b 100644
--- a/drivers/spi/mxs_spi.c
+++ b/drivers/spi/mxs_spi.c
@@ -436,6 +436,8 @@ static int mxs_spi_probe(struct udevice *bus)
 	priv->dma_channel = plat->dma_id;
 	priv->clk_id = plat->clk_id;
 
+	mxs_reset_block(&priv->regs->hw_ssp_ctrl0_reg);
+
 	ret = mxs_dma_init_channel(priv->dma_channel);
 	if (ret) {
 		printf("%s: DMA init channel error %d\n", __func__, ret);
-- 
2.11.0

^ permalink raw reply related	[flat|nested] 6+ messages in thread

* [U-Boot] [PATCH 4/5] spi: Add support for SPL_OF_PLATDATA to mxs_spi.c driver
  2019-08-12  7:22 [U-Boot] [PATCH 1/5] doc: fix: Replace SPL_OF_PLATDATA with OF_PLATDATA in examples Lukasz Majewski
  2019-08-12  7:22 ` [U-Boot] [PATCH 2/5] dts: imx28: Remove #include "imx28.dtsi" from imx28-u-boot.dtsi file Lukasz Majewski
  2019-08-12  7:22 ` [U-Boot] [PATCH 3/5] spi: fix: Call mxs_reset_block() during DM/DTS probe Lukasz Majewski
@ 2019-08-12  7:22 ` Lukasz Majewski
  2019-08-12  7:22 ` [U-Boot] [PATCH 5/5] mmc: Convert mxsmmc eMMC driver for i.MX2{38} to DM/DTS Lukasz Majewski
  2019-08-13  9:33 ` [U-Boot] [PATCH 1/5] doc: fix: Replace SPL_OF_PLATDATA with OF_PLATDATA in examples Simon Glass
  4 siblings, 0 replies; 6+ messages in thread
From: Lukasz Majewski @ 2019-08-12  7:22 UTC (permalink / raw)
  To: u-boot

After this patch the mxs_spi.c DM/DTS driver can be used at early SPL to
read payload from SPI-NOR memories.

It was necessary to adjust its name to 'fsl_imx_2{38}_spi' to match
requirements for SPL_OF_PLATDATA usage.

Signed-off-by: Lukasz Majewski <lukma@denx.de>
---

 drivers/spi/mxs_spi.c | 34 ++++++++++++++++++++++++++++++++--
 1 file changed, 32 insertions(+), 2 deletions(-)

diff --git a/drivers/spi/mxs_spi.c b/drivers/spi/mxs_spi.c
index b79a72db2b..051263663d 100644
--- a/drivers/spi/mxs_spi.c
+++ b/drivers/spi/mxs_spi.c
@@ -57,7 +57,18 @@ static inline struct mxs_spi_slave *to_mxs_slave(struct spi_slave *slave)
 #else
 #include <dm.h>
 #include <errno.h>
+#include <dt-structs.h>
+
+#ifdef CONFIG_MX28
+#define dtd_fsl_imx_spi dtd_fsl_imx28_spi
+#else /* CONFIG_MX23 */
+#define dtd_fsl_imx_spi dtd_fsl_imx23_spi
+#endif
+
 struct mxs_spi_platdata {
+#if CONFIG_IS_ENABLED(OF_PLATDATA)
+	struct dtd_fsl_imx_spi dtplat;
+#endif
 	s32 frequency;		/* Default clock frequency, -1 for none */
 	fdt_addr_t base;        /* SPI IP block base address */
 	int num_cs;             /* Number of CSes supported */
@@ -430,11 +441,26 @@ static int mxs_spi_probe(struct udevice *bus)
 	int ret;
 
 	debug("%s: probe\n", __func__);
+
+#if CONFIG_IS_ENABLED(OF_PLATDATA)
+	struct dtd_fsl_imx_spi *dtplat = &plat->dtplat;
+	struct phandle_1_arg *p1a = &dtplat->clocks[0];
+
+	priv->regs = (struct mxs_ssp_regs *)dtplat->reg[0];
+	priv->dma_channel = dtplat->dmas[1];
+	priv->clk_id = p1a->arg[0];
+	priv->max_freq = dtplat->spi_max_frequency;
+	plat->num_cs = dtplat->num_cs;
+
+	debug("OF_PLATDATA: regs: 0x%x max freq: %d clkid: %d\n",
+	      (unsigned int)priv->regs, priv->max_freq, priv->clk_id);
+#else
 	priv->regs = (struct mxs_ssp_regs *)plat->base;
 	priv->max_freq = plat->frequency;
 
 	priv->dma_channel = plat->dma_id;
 	priv->clk_id = plat->clk_id;
+#endif
 
 	mxs_reset_block(&priv->regs->hw_ssp_ctrl0_reg);
 
@@ -571,16 +597,20 @@ static int mxs_ofdata_to_platdata(struct udevice *bus)
 
 	return 0;
 }
-#endif
 
 static const struct udevice_id mxs_spi_ids[] = {
 	{ .compatible = "fsl,imx23-spi" },
 	{ .compatible = "fsl,imx28-spi" },
 	{ }
 };
+#endif
 
 U_BOOT_DRIVER(mxs_spi) = {
-	.name	= "mxs_spi",
+#ifdef CONFIG_MX28
+	.name = "fsl_imx28_spi",
+#else /* CONFIG_MX23 */
+	.name = "fsl_imx23_spi",
+#endif
 	.id	= UCLASS_SPI,
 #if CONFIG_IS_ENABLED(OF_CONTROL) && !CONFIG_IS_ENABLED(OF_PLATDATA)
 	.of_match = mxs_spi_ids,
-- 
2.11.0

^ permalink raw reply related	[flat|nested] 6+ messages in thread

* [U-Boot] [PATCH 5/5] mmc: Convert mxsmmc eMMC driver for i.MX2{38} to DM/DTS
  2019-08-12  7:22 [U-Boot] [PATCH 1/5] doc: fix: Replace SPL_OF_PLATDATA with OF_PLATDATA in examples Lukasz Majewski
                   ` (2 preceding siblings ...)
  2019-08-12  7:22 ` [U-Boot] [PATCH 4/5] spi: Add support for SPL_OF_PLATDATA to mxs_spi.c driver Lukasz Majewski
@ 2019-08-12  7:22 ` Lukasz Majewski
  2019-08-13  9:33 ` [U-Boot] [PATCH 1/5] doc: fix: Replace SPL_OF_PLATDATA with OF_PLATDATA in examples Simon Glass
  4 siblings, 0 replies; 6+ messages in thread
From: Lukasz Majewski @ 2019-08-12  7:22 UTC (permalink / raw)
  To: u-boot

This patch converts the mxsmmc driver to support DM/DTS.

Moreover, it is also possible to use it in early SPL with
SPL_OF_PLATDATA enabled.

Signed-off-by: Lukasz Majewski <lukma@denx.de>

---

 drivers/mmc/mxsmmc.c | 439 +++++++++++++++++++++++++++++++++++++++++++--------
 1 file changed, 369 insertions(+), 70 deletions(-)

diff --git a/drivers/mmc/mxsmmc.c b/drivers/mmc/mxsmmc.c
index 92db4ae5a6..a01f81e47e 100644
--- a/drivers/mmc/mxsmmc.c
+++ b/drivers/mmc/mxsmmc.c
@@ -2,6 +2,9 @@
 /*
  * Freescale i.MX28 SSP MMC driver
  *
+ * Copyright (C) 2019 DENX Software Engineering
+ * Lukasz Majewski, DENX Software Engineering, lukma at denx.de
+ *
  * Copyright (C) 2011 Marek Vasut <marek.vasut@gmail.com>
  * on behalf of DENX Software Engineering GmbH
  *
@@ -16,6 +19,7 @@
  * (C) Copyright 2003
  * Kyle Harris, Nexus Technologies, Inc. kharris at nexus-tech.net
  */
+
 #include <common.h>
 #include <malloc.h>
 #include <mmc.h>
@@ -27,19 +31,53 @@
 #include <asm/mach-imx/dma.h>
 #include <bouncebuf.h>
 
+#define	MXSMMC_MAX_TIMEOUT	10000
+#define MXSMMC_SMALL_TRANSFER	512
+
+#if !CONFIG_IS_ENABLED(DM_MMC)
 struct mxsmmc_priv {
 	int			id;
-	struct mxs_ssp_regs	*regs;
-	uint32_t		buswidth;
 	int			(*mmc_is_wp)(int);
 	int			(*mmc_cd)(int);
-	struct mxs_dma_desc	*desc;
 	struct mmc_config	cfg;	/* mmc configuration */
+	struct mxs_dma_desc	*desc;
+	uint32_t		buswidth;
+	struct mxs_ssp_regs	*regs;
 };
+#else /* CONFIG_IS_ENABLED(DM_MMC) */
+#include <dm/device.h>
+#include <dm/read.h>
+#include <dt-structs.h>
+
+#ifdef CONFIG_MX28
+#define dtd_fsl_imx_mmc dtd_fsl_imx28_mmc
+#else /* CONFIG_MX23 */
+#define dtd_fsl_imx_mmc dtd_fsl_imx23_mmc
+#endif
 
-#define	MXSMMC_MAX_TIMEOUT	10000
-#define MXSMMC_SMALL_TRANSFER	512
+struct mxsmmc_platdata {
+#if CONFIG_IS_ENABLED(OF_PLATDATA)
+	struct dtd_fsl_imx_mmc dtplat;
+#endif
+	struct mmc_config cfg;
+	struct mmc mmc;
+	fdt_addr_t base;
+	int non_removable;
+	int buswidth;
+	int dma_id;
+	int clk_id;
+};
 
+struct mxsmmc_priv {
+	int clkid;
+	struct mxs_dma_desc	*desc;
+	u32			buswidth;
+	struct mxs_ssp_regs	*regs;
+	unsigned int            dma_channel;
+};
+#endif
+
+#if !CONFIG_IS_ENABLED(DM_MMC)
 static int mxsmmc_cd(struct mxsmmc_priv *priv)
 {
 	struct mxs_ssp_regs *ssp_regs = priv->regs;
@@ -50,6 +88,131 @@ static int mxsmmc_cd(struct mxsmmc_priv *priv)
 	return !(readl(&ssp_regs->hw_ssp_status) & SSP_STATUS_CARD_DETECT);
 }
 
+static const struct mmc_ops mxsmmc_ops = {
+	.send_cmd	= mxsmmc_send_cmd,
+	.set_ios	= mxsmmc_set_ios,
+	.init		= mxsmmc_init,
+};
+
+static int mxsmmc_set_ios(struct mmc *mmc)
+{
+	struct mxs_ssp_regs *ssp_regs = priv->regs;
+
+	/* Set the clock speed */
+	if (mmc->clock)
+		mxs_set_ssp_busclock(priv->id, mmc->clock / 1000);
+
+	switch (mmc->bus_width) {
+	case 1:
+		priv->buswidth = SSP_CTRL0_BUS_WIDTH_ONE_BIT;
+		break;
+	case 4:
+		priv->buswidth = SSP_CTRL0_BUS_WIDTH_FOUR_BIT;
+		break;
+	case 8:
+		priv->buswidth = SSP_CTRL0_BUS_WIDTH_EIGHT_BIT;
+		break;
+	}
+
+	/* Set the bus width */
+	clrsetbits_le32(&ssp_regs->hw_ssp_ctrl0,
+			SSP_CTRL0_BUS_WIDTH_MASK, priv->buswidth);
+
+	debug("MMC%d: Set %d bits bus width\n",
+	      mmc->block_dev.devnum, mmc->bus_width);
+
+	return 0;
+}
+
+static int mxsmmc_init(struct mmc *mmc)
+{
+	struct mxsmmc_priv *priv = mmc->priv;
+	struct mxs_ssp_regs *ssp_regs = priv->regs;
+
+	/* Reset SSP */
+	mxs_reset_block(&ssp_regs->hw_ssp_ctrl0_reg);
+
+	/* Reconfigure the SSP block for MMC operation */
+	writel(SSP_CTRL1_SSP_MODE_SD_MMC |
+		SSP_CTRL1_WORD_LENGTH_EIGHT_BITS |
+		SSP_CTRL1_DMA_ENABLE |
+		SSP_CTRL1_POLARITY |
+		SSP_CTRL1_RECV_TIMEOUT_IRQ_EN |
+		SSP_CTRL1_DATA_CRC_IRQ_EN |
+		SSP_CTRL1_DATA_TIMEOUT_IRQ_EN |
+		SSP_CTRL1_RESP_TIMEOUT_IRQ_EN |
+		SSP_CTRL1_RESP_ERR_IRQ_EN,
+		&ssp_regs->hw_ssp_ctrl1_set);
+
+	/* Set initial bit clock 400 KHz */
+	mxs_set_ssp_busclock(priv->id, 400);
+
+	/* Send initial 74 clock cycles (185 us @ 400 KHz)*/
+	writel(SSP_CMD0_CONT_CLKING_EN, &ssp_regs->hw_ssp_cmd0_set);
+	udelay(200);
+	writel(SSP_CMD0_CONT_CLKING_EN, &ssp_regs->hw_ssp_cmd0_clr);
+
+	return 0;
+}
+
+int mxsmmc_initialize(bd_t *bis, int id, int (*wp)(int), int (*cd)(int))
+{
+	struct mmc *mmc = NULL;
+	struct mxsmmc_priv *priv = NULL;
+	int ret;
+	const unsigned int mxsmmc_clk_id = mxs_ssp_clock_by_bus(id);
+
+	if (!mxs_ssp_bus_id_valid(id))
+		return -ENODEV;
+
+	priv = malloc(sizeof(struct mxsmmc_priv));
+	if (!priv)
+		return -ENOMEM;
+
+	priv->desc = mxs_dma_desc_alloc();
+	if (!priv->desc) {
+		free(priv);
+		return -ENOMEM;
+	}
+
+	ret = mxs_dma_init_channel(MXS_DMA_CHANNEL_AHB_APBH_SSP0 + id);
+	if (ret)
+		return ret;
+
+	priv->mmc_is_wp = wp;
+	priv->mmc_cd = cd;
+	priv->id = id;
+	priv->regs = mxs_ssp_regs_by_bus(id);
+
+	priv->cfg.name = "MXS MMC";
+	priv->cfg.ops = &mxsmmc_ops;
+
+	priv->cfg.voltages = MMC_VDD_32_33 | MMC_VDD_33_34;
+
+	priv->cfg.host_caps = MMC_MODE_4BIT | MMC_MODE_8BIT |
+			 MMC_MODE_HS_52MHz | MMC_MODE_HS;
+
+	/*
+	 * SSPCLK = 480 * 18 / 29 / 1 = 297.731 MHz
+	 * SSP bit rate = SSPCLK / (CLOCK_DIVIDE * (1 + CLOCK_RATE)),
+	 * CLOCK_DIVIDE has to be an even value from 2 to 254, and
+	 * CLOCK_RATE could be any integer from 0 to 255.
+	 */
+	priv->cfg.f_min = 400000;
+	priv->cfg.f_max = mxc_get_clock(MXC_SSP0_CLK + mxsmmc_clk_id)
+		* 1000 / 2;
+	priv->cfg.b_max = 0x20;
+
+	mmc = mmc_create(&priv->cfg, priv);
+	if (!mmc) {
+		mxs_dma_desc_free(priv->desc);
+		free(priv);
+		return -ENOMEM;
+	}
+	return 0;
+}
+#endif /* CONFIG_IS_ENABLED(DM_MMC) */
+
 static int mxsmmc_send_cmd_pio(struct mxsmmc_priv *priv, struct mmc_data *data)
 {
 	struct mxs_ssp_regs *ssp_regs = priv->regs;
@@ -115,7 +278,11 @@ static int mxsmmc_send_cmd_dma(struct mxsmmc_priv *priv, struct mmc_data *data)
 	priv->desc->cmd.data |= MXS_DMA_DESC_IRQ | MXS_DMA_DESC_DEC_SEM |
 				(data_count << MXS_DMA_DESC_BYTES_OFFSET);
 
+#if !CONFIG_IS_ENABLED(DM_MMC)
 	dmach = MXS_DMA_CHANNEL_AHB_APBH_SSP0 + priv->id;
+#else
+	dmach = priv->dma_channel;
+#endif
 	mxs_dma_desc_append(dmach, priv->desc);
 	if (mxs_dma_go(dmach)) {
 		bounce_buffer_stop(&bbstate);
@@ -127,6 +294,7 @@ static int mxsmmc_send_cmd_dma(struct mxsmmc_priv *priv, struct mmc_data *data)
 	return 0;
 }
 
+#if !CONFIG_IS_ENABLED(DM_MMC)
 /*
  * Sends a command out on the bus.  Takes the mmc pointer,
  * a command pointer, and an optional data pointer.
@@ -136,12 +304,25 @@ mxsmmc_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd, struct mmc_data *data)
 {
 	struct mxsmmc_priv *priv = mmc->priv;
 	struct mxs_ssp_regs *ssp_regs = priv->regs;
+#else
+static int
+mxsmmc_send_cmd(struct udevice *dev, struct mmc_cmd *cmd, struct mmc_data *data)
+{
+	struct mxsmmc_platdata *plat = dev_get_platdata(dev);
+	struct mxsmmc_priv *priv = dev_get_priv(dev);
+	struct mxs_ssp_regs *ssp_regs = priv->regs;
+	struct mmc *mmc = &plat->mmc;
+#endif
 	uint32_t reg;
 	int timeout;
 	uint32_t ctrl0;
 	int ret;
-
-	debug("MMC%d: CMD%d\n", mmc->block_dev.devnum, cmd->cmdidx);
+#if !CONFIG_IS_ENABLED(DM_MMC)
+	int devnum = mmc->block_dev.devnum;
+#else
+	int devnum = mmc_get_blk_desc(mmc)->devnum;
+#endif
+	debug("MMC%d: CMD%d\n", devnum, cmd->cmdidx);
 
 	/* Check bus busy */
 	timeout = MXSMMC_MAX_TIMEOUT;
@@ -156,16 +337,16 @@ mxsmmc_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd, struct mmc_data *data)
 	}
 
 	if (!timeout) {
-		printf("MMC%d: Bus busy timeout!\n", mmc->block_dev.devnum);
+		printf("MMC%d: Bus busy timeout!\n", devnum);
 		return -ETIMEDOUT;
 	}
-
+#if !CONFIG_IS_ENABLED(DM_MMC)
 	/* See if card is present */
 	if (!mxsmmc_cd(priv)) {
-		printf("MMC%d: No card detected!\n", mmc->block_dev.devnum);
+		printf("MMC%d: No card detected!\n", devnum);
 		return -ENOMEDIUM;
 	}
-
+#endif
 	/* Start building CTRL0 contents */
 	ctrl0 = priv->buswidth;
 
@@ -198,13 +379,13 @@ mxsmmc_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd, struct mmc_data *data)
 		/* READ or WRITE */
 		if (data->flags & MMC_DATA_READ) {
 			ctrl0 |= SSP_CTRL0_READ;
+#if !CONFIG_IS_ENABLED(DM_MMC)
 		} else if (priv->mmc_is_wp &&
-			priv->mmc_is_wp(mmc->block_dev.devnum)) {
-			printf("MMC%d: Can not write a locked card!\n",
-				mmc->block_dev.devnum);
+			priv->mmc_is_wp(devnum)) {
+			printf("MMC%d: Can not write a locked card!\n", devnum);
 			return -EOPNOTSUPP;
+#endif
 		}
-
 		ctrl0 |= SSP_CTRL0_DATA_XFER;
 
 		reg = data->blocksize * data->blocks;
@@ -241,22 +422,21 @@ mxsmmc_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd, struct mmc_data *data)
 	}
 
 	if (!timeout) {
-		printf("MMC%d: Command %d busy\n",
-			mmc->block_dev.devnum, cmd->cmdidx);
+		printf("MMC%d: Command %d busy\n", devnum, cmd->cmdidx);
 		return -ETIMEDOUT;
 	}
 
 	/* Check command timeout */
 	if (reg & SSP_STATUS_RESP_TIMEOUT) {
 		printf("MMC%d: Command %d timeout (status 0x%08x)\n",
-			mmc->block_dev.devnum, cmd->cmdidx, reg);
+		       devnum, cmd->cmdidx, reg);
 		return -ETIMEDOUT;
 	}
 
 	/* Check command errors */
 	if (reg & (SSP_STATUS_RESP_CRC_ERR | SSP_STATUS_RESP_ERR)) {
 		printf("MMC%d: Command %d error (status 0x%08x)!\n",
-			mmc->block_dev.devnum, cmd->cmdidx, reg);
+		       devnum, cmd->cmdidx, reg);
 		return -ECOMM;
 	}
 
@@ -277,15 +457,13 @@ mxsmmc_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd, struct mmc_data *data)
 		ret = mxsmmc_send_cmd_pio(priv, data);
 		if (ret) {
 			printf("MMC%d: Data timeout with command %d "
-				"(status 0x%08x)!\n",
-				mmc->block_dev.devnum, cmd->cmdidx, reg);
+				"(status 0x%08x)!\n", devnum, cmd->cmdidx, reg);
 			return ret;
 		}
 	} else {
 		ret = mxsmmc_send_cmd_dma(priv, data);
 		if (ret) {
-			printf("MMC%d: DMA transfer failed\n",
-				mmc->block_dev.devnum);
+			printf("MMC%d: DMA transfer failed\n", devnum);
 			return ret;
 		}
 	}
@@ -296,21 +474,40 @@ mxsmmc_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd, struct mmc_data *data)
 		(SSP_STATUS_TIMEOUT | SSP_STATUS_DATA_CRC_ERR |
 		SSP_STATUS_FIFO_OVRFLW | SSP_STATUS_FIFO_UNDRFLW)) {
 		printf("MMC%d: Data error with command %d (status 0x%08x)!\n",
-			mmc->block_dev.devnum, cmd->cmdidx, reg);
+		       devnum, cmd->cmdidx, reg);
 		return -ECOMM;
 	}
 
 	return 0;
 }
 
-static int mxsmmc_set_ios(struct mmc *mmc)
+#if CONFIG_IS_ENABLED(DM_MMC)
+/* Base numbers of i.MX2[38] clk for ssp0 IP block */
+#define MXS_SSP_IMX23_CLKID_SSP0 33
+#define MXS_SSP_IMX28_CLKID_SSP0 46
+
+static int mxsmmc_get_cd(struct udevice *dev)
 {
-	struct mxsmmc_priv *priv = mmc->priv;
+	struct mxsmmc_platdata *plat = dev_get_platdata(dev);
+	struct mxsmmc_priv *priv = dev_get_priv(dev);
+	struct mxs_ssp_regs *ssp_regs = priv->regs;
+
+	if (plat->non_removable)
+		return 1;
+
+	return !(readl(&ssp_regs->hw_ssp_status) & SSP_STATUS_CARD_DETECT);
+}
+
+static int mxsmmc_set_ios(struct udevice *dev)
+{
+	struct mxsmmc_platdata *plat = dev_get_platdata(dev);
+	struct mxsmmc_priv *priv = dev_get_priv(dev);
 	struct mxs_ssp_regs *ssp_regs = priv->regs;
+	struct mmc *mmc = &plat->mmc;
 
 	/* Set the clock speed */
 	if (mmc->clock)
-		mxs_set_ssp_busclock(priv->id, mmc->clock / 1000);
+		mxs_set_ssp_busclock(priv->clkid, mmc->clock / 1000);
 
 	switch (mmc->bus_width) {
 	case 1:
@@ -328,15 +525,15 @@ static int mxsmmc_set_ios(struct mmc *mmc)
 	clrsetbits_le32(&ssp_regs->hw_ssp_ctrl0,
 			SSP_CTRL0_BUS_WIDTH_MASK, priv->buswidth);
 
-	debug("MMC%d: Set %d bits bus width\n",
-		mmc->block_dev.devnum, mmc->bus_width);
+	debug("MMC%d: Set %d bits bus width\n", mmc_get_blk_desc(mmc)->devnum,
+	      mmc->bus_width);
 
 	return 0;
 }
 
-static int mxsmmc_init(struct mmc *mmc)
+static int mxsmmc_init(struct udevice *dev)
 {
-	struct mxsmmc_priv *priv = mmc->priv;
+	struct mxsmmc_priv *priv = dev_get_priv(dev);
 	struct mxs_ssp_regs *ssp_regs = priv->regs;
 
 	/* Reset SSP */
@@ -355,7 +552,7 @@ static int mxsmmc_init(struct mmc *mmc)
 		&ssp_regs->hw_ssp_ctrl1_set);
 
 	/* Set initial bit clock 400 KHz */
-	mxs_set_ssp_busclock(priv->id, 400);
+	mxs_set_ssp_busclock(priv->clkid, 400);
 
 	/* Send initial 74 clock cycles (185 us @ 400 KHz)*/
 	writel(SSP_CMD0_CONT_CLKING_EN, &ssp_regs->hw_ssp_cmd0_set);
@@ -365,48 +562,59 @@ static int mxsmmc_init(struct mmc *mmc)
 	return 0;
 }
 
-static const struct mmc_ops mxsmmc_ops = {
-	.send_cmd	= mxsmmc_send_cmd,
-	.set_ios	= mxsmmc_set_ios,
-	.init		= mxsmmc_init,
-};
-
-int mxsmmc_initialize(bd_t *bis, int id, int (*wp)(int), int (*cd)(int))
+static int mxsmmc_probe(struct udevice *dev)
 {
-	struct mmc *mmc = NULL;
-	struct mxsmmc_priv *priv = NULL;
-	int ret;
-	const unsigned int mxsmmc_clk_id = mxs_ssp_clock_by_bus(id);
-
-	if (!mxs_ssp_bus_id_valid(id))
-		return -ENODEV;
+	struct mmc_uclass_priv *upriv = dev_get_uclass_priv(dev);
+	struct mxsmmc_platdata *plat = dev_get_platdata(dev);
+	struct mxsmmc_priv *priv = dev_get_priv(dev);
+	struct blk_desc *bdesc;
+	struct mmc *mmc;
+	int ret, clkid;
+
+	debug("%s: probe\n", __func__);
+
+#if CONFIG_IS_ENABLED(OF_PLATDATA)
+	struct dtd_fsl_imx_mmc *dtplat = &plat->dtplat;
+	struct phandle_1_arg *p1a = &dtplat->clocks[0];
+
+	priv->buswidth = dtplat->bus_width;
+	priv->regs = (struct mxs_ssp_regs *)dtplat->reg[0];
+	priv->dma_channel = dtplat->dmas[1];
+	clkid = p1a->arg[0];
+	plat->non_removable = dtplat->non_removable;
+
+	debug("OF_PLATDATA: regs: 0x%p bw: %d clkid: %d non_removable: %d\n",
+	      priv->regs, priv->buswidth, clkid, plat->non_removable);
+#else
+	priv->regs = (struct mxs_ssp_regs *)plat->base;
+	priv->dma_channel = plat->dma_id;
+	clkid = plat->clk_id;
+#endif
 
-	priv = malloc(sizeof(struct mxsmmc_priv));
-	if (!priv)
-		return -ENOMEM;
+#ifdef CONFIG_MX28
+	priv->clkid = clkid - MXS_SSP_IMX28_CLKID_SSP0;
+#else /* CONFIG_MX23 */
+	priv->clkid = clkid - MXS_SSP_IMX23_CLKID_SSP0;
+#endif
+	mmc = &plat->mmc;
+	mmc->cfg = &plat->cfg;
+	mmc->dev = dev;
 
 	priv->desc = mxs_dma_desc_alloc();
 	if (!priv->desc) {
-		free(priv);
+		printf("%s: Cannot allocate DMA descriptor\n", __func__);
 		return -ENOMEM;
 	}
 
-	ret = mxs_dma_init_channel(MXS_DMA_CHANNEL_AHB_APBH_SSP0 + id);
+	ret = mxs_dma_init_channel(priv->dma_channel);
 	if (ret)
 		return ret;
 
-	priv->mmc_is_wp = wp;
-	priv->mmc_cd = cd;
-	priv->id = id;
-	priv->regs = mxs_ssp_regs_by_bus(id);
-
-	priv->cfg.name = "MXS MMC";
-	priv->cfg.ops = &mxsmmc_ops;
-
-	priv->cfg.voltages = MMC_VDD_32_33 | MMC_VDD_33_34;
+	plat->cfg.name = "MXS MMC";
+	plat->cfg.voltages = MMC_VDD_32_33 | MMC_VDD_33_34;
 
-	priv->cfg.host_caps = MMC_MODE_4BIT | MMC_MODE_8BIT |
-			 MMC_MODE_HS_52MHz | MMC_MODE_HS;
+	plat->cfg.host_caps = MMC_MODE_4BIT | MMC_MODE_8BIT |
+		MMC_MODE_HS_52MHz | MMC_MODE_HS;
 
 	/*
 	 * SSPCLK = 480 * 18 / 29 / 1 = 297.731 MHz
@@ -414,15 +622,106 @@ int mxsmmc_initialize(bd_t *bis, int id, int (*wp)(int), int (*cd)(int))
 	 * CLOCK_DIVIDE has to be an even value from 2 to 254, and
 	 * CLOCK_RATE could be any integer from 0 to 255.
 	 */
-	priv->cfg.f_min = 400000;
-	priv->cfg.f_max = mxc_get_clock(MXC_SSP0_CLK + mxsmmc_clk_id) * 1000 / 2;
-	priv->cfg.b_max = 0x20;
+	plat->cfg.f_min = 400000;
+	plat->cfg.f_max = mxc_get_clock(MXC_SSP0_CLK + priv->clkid) * 1000 / 2;
+	plat->cfg.b_max = 0x20;
 
-	mmc = mmc_create(&priv->cfg, priv);
-	if (mmc == NULL) {
-		mxs_dma_desc_free(priv->desc);
-		free(priv);
-		return -ENOMEM;
+	bdesc = mmc_get_blk_desc(mmc);
+	if (!bdesc) {
+		printf("%s: No block device descriptor!\n", __func__);
+		return -ENODEV;
 	}
+
+	if (plat->non_removable)
+		bdesc->removable = 0;
+
+	ret = mxsmmc_init(dev);
+	if (ret)
+		printf("%s: MMC%d init error %d\n", __func__,
+		       bdesc->devnum, ret);
+
+	/* Set the initial clock speed */
+	mmc_set_clock(mmc, 400000, MMC_CLK_ENABLE);
+
+	upriv->mmc = mmc;
+
+	return 0;
+};
+
+#if CONFIG_IS_ENABLED(BLK)
+static int mxsmmc_bind(struct udevice *dev)
+{
+	struct mxsmmc_platdata *plat = dev_get_platdata(dev);
+
+	return mmc_bind(dev, &plat->mmc, &plat->cfg);
+}
+#endif
+
+static const struct dm_mmc_ops mxsmmc_ops = {
+	.get_cd		= mxsmmc_get_cd,
+	.send_cmd	= mxsmmc_send_cmd,
+	.set_ios	= mxsmmc_set_ios,
+};
+
+#if CONFIG_IS_ENABLED(OF_CONTROL) && !CONFIG_IS_ENABLED(OF_PLATDATA)
+static int mxsmmc_ofdata_to_platdata(struct udevice *bus)
+{
+	struct mxsmmc_platdata *plat = bus->platdata;
+	u32 prop[2];
+	int ret;
+
+	plat->base = dev_read_addr(bus);
+	plat->buswidth =
+		dev_read_u32_default(bus, "bus-width", 1);
+	plat->non_removable = dev_read_bool(bus, "non-removable");
+
+	ret = dev_read_u32_array(bus, "dmas", prop, ARRAY_SIZE(prop));
+	if (ret) {
+		printf("%s: Reading 'dmas' property failed!\n", __func__);
+		return ret;
+	}
+	plat->dma_id = prop[1];
+
+	ret = dev_read_u32_array(bus, "clocks", prop, ARRAY_SIZE(prop));
+	if (ret) {
+		printf("%s: Reading 'clocks' property failed!\n", __func__);
+		return ret;
+	}
+	plat->clk_id = prop[1];
+
+	debug("%s: base=0x%x, bus_width=%d %s dma_id=%d clk_id=%d\n",
+	      __func__, (uint)plat->base, plat->buswidth,
+	      plat->non_removable ? "non-removable" : NULL,
+	      plat->dma_id, plat->clk_id);
+
 	return 0;
 }
+
+static const struct udevice_id mxsmmc_ids[] = {
+	{ .compatible = "fsl,imx23-mmc", },
+	{ .compatible = "fsl,imx28-mmc", },
+	{ /* sentinel */ }
+};
+#endif
+
+U_BOOT_DRIVER(mxsmmc) = {
+#ifdef CONFIG_MX28
+	.name = "fsl_imx28_mmc",
+#else /* CONFIG_MX23 */
+	.name = "fsl_imx23_mmc",
+#endif
+	.id	= UCLASS_MMC,
+#if CONFIG_IS_ENABLED(OF_CONTROL) && !CONFIG_IS_ENABLED(OF_PLATDATA)
+	.of_match = mxsmmc_ids,
+	.ofdata_to_platdata = mxsmmc_ofdata_to_platdata,
+#endif
+	.ops	= &mxsmmc_ops,
+#if CONFIG_IS_ENABLED(BLK)
+	.bind	= mxsmmc_bind,
+#endif
+	.probe	= mxsmmc_probe,
+	.priv_auto_alloc_size = sizeof(struct mxsmmc_priv),
+	.platdata_auto_alloc_size = sizeof(struct mxsmmc_platdata),
+};
+
+#endif /* CONFIG_DM_MMC */
-- 
2.11.0

^ permalink raw reply related	[flat|nested] 6+ messages in thread

* [U-Boot] [PATCH 1/5] doc: fix: Replace SPL_OF_PLATDATA with OF_PLATDATA in examples
  2019-08-12  7:22 [U-Boot] [PATCH 1/5] doc: fix: Replace SPL_OF_PLATDATA with OF_PLATDATA in examples Lukasz Majewski
                   ` (3 preceding siblings ...)
  2019-08-12  7:22 ` [U-Boot] [PATCH 5/5] mmc: Convert mxsmmc eMMC driver for i.MX2{38} to DM/DTS Lukasz Majewski
@ 2019-08-13  9:33 ` Simon Glass
  4 siblings, 0 replies; 6+ messages in thread
From: Simon Glass @ 2019-08-13  9:33 UTC (permalink / raw)
  To: u-boot

On Mon, 12 Aug 2019 at 01:23, Lukasz Majewski <lukma@denx.de> wrote:
>
> The of-plat.rst file till this change has been using
> #if CONFIG_IS_ENABLED(SPL_OF_PLATDATA) it its examples.
>
> This is at best misleading as SPL_OF_PLATDATA is always defined when we
> want to use this SPL tinification feature (also in U-Boot proper).
> As a result the OF_PLATDATA SPL specific code is also compiled in when
> U-Boot proper is build.
>
> Signed-off-by: Lukasz Majewski <lukma@denx.de>
> ---
>
>  doc/driver-model/of-plat.rst | 8 ++++----
>  1 file changed, 4 insertions(+), 4 deletions(-)

Reviewed-by: Simon Glass <sjg@chromium.org>

^ permalink raw reply	[flat|nested] 6+ messages in thread

end of thread, other threads:[~2019-08-13  9:33 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2019-08-12  7:22 [U-Boot] [PATCH 1/5] doc: fix: Replace SPL_OF_PLATDATA with OF_PLATDATA in examples Lukasz Majewski
2019-08-12  7:22 ` [U-Boot] [PATCH 2/5] dts: imx28: Remove #include "imx28.dtsi" from imx28-u-boot.dtsi file Lukasz Majewski
2019-08-12  7:22 ` [U-Boot] [PATCH 3/5] spi: fix: Call mxs_reset_block() during DM/DTS probe Lukasz Majewski
2019-08-12  7:22 ` [U-Boot] [PATCH 4/5] spi: Add support for SPL_OF_PLATDATA to mxs_spi.c driver Lukasz Majewski
2019-08-12  7:22 ` [U-Boot] [PATCH 5/5] mmc: Convert mxsmmc eMMC driver for i.MX2{38} to DM/DTS Lukasz Majewski
2019-08-13  9:33 ` [U-Boot] [PATCH 1/5] doc: fix: Replace SPL_OF_PLATDATA with OF_PLATDATA in examples Simon Glass

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.