All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v5 0/4] Add support for Amlogic Meson MMC driver
@ 2016-02-27 18:01 ` Carlo Caione
  0 siblings, 0 replies; 24+ messages in thread
From: Carlo Caione @ 2016-02-27 18:01 UTC (permalink / raw)
  To: ulf.hansson-QSEj5FYQhm4dnm+yROfE0A,
	robh+dt-DgEjT+Ai2ygdnm+yROfE0A,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	linux-lFZ/pmaqli7XmaaqVzeoHQ, devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-meson-/JYPxA39Uh5TLH3MbocFFw, linux-6IF/jdPJHihWk0Htik3J/w
  Cc: Carlo Caione

From: Carlo Caione <carlo-6IF/jdPJHihWk0Htik3J/w@public.gmane.org>

This patchset adds support for the MMC driver found on the Meson platforms.

Changelog:

v2:
    * fix typo in commit message
    * avoid the bounce buffer (max_segs == 1)

v3:
    * simplify meson_mmc_map_dma() and fix memory leak

v4:
    * code and documentation cleanup
    * removed redundant variables
    * removed useless printing
    * introduced MMC_CAP2_NO_SDIO
    * removed state machine
    * better spinlocks management and positioning

v5:
    * split submission in several patches
    * update mmc->actual_clock
    * fix timeout value
    * add clk_prepare_enable()
    * add 'meson,sd-port' property

Carlo Caione (4):
  mmc: meson: Document Amlogic Meson MMC DT bindings
  mmc: meson: Add driver for the SD/MMC host found on Amlogic Meson SoCs
  ARM: dts: meson8b: Add MMC nodes
  ARM: multi_v7_defconfig: Add Amlogic Meson MMC support

 .../devicetree/bindings/mmc/meson-mmc.txt          |  30 ++
 arch/arm/boot/dts/meson8b-mxq.dts                  |   8 +
 arch/arm/boot/dts/meson8b-odroidc1.dts             |   8 +
 arch/arm/boot/dts/meson8b.dtsi                     |  16 +
 arch/arm/configs/multi_v7_defconfig                |   1 +
 drivers/mmc/host/Kconfig                           |   7 +
 drivers/mmc/host/Makefile                          |   1 +
 drivers/mmc/host/meson-mmc.c                       | 535 +++++++++++++++++++++
 8 files changed, 606 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/mmc/meson-mmc.txt
 create mode 100644 drivers/mmc/host/meson-mmc.c

-- 
1.9.1

--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

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

* [PATCH v5 0/4] Add support for Amlogic Meson MMC driver
@ 2016-02-27 18:01 ` Carlo Caione
  0 siblings, 0 replies; 24+ messages in thread
From: Carlo Caione @ 2016-02-27 18:01 UTC (permalink / raw)
  To: linux-arm-kernel

From: Carlo Caione <carlo@endlessm.com>

This patchset adds support for the MMC driver found on the Meson platforms.

Changelog:

v2:
    * fix typo in commit message
    * avoid the bounce buffer (max_segs == 1)

v3:
    * simplify meson_mmc_map_dma() and fix memory leak

v4:
    * code and documentation cleanup
    * removed redundant variables
    * removed useless printing
    * introduced MMC_CAP2_NO_SDIO
    * removed state machine
    * better spinlocks management and positioning

v5:
    * split submission in several patches
    * update mmc->actual_clock
    * fix timeout value
    * add clk_prepare_enable()
    * add 'meson,sd-port' property

Carlo Caione (4):
  mmc: meson: Document Amlogic Meson MMC DT bindings
  mmc: meson: Add driver for the SD/MMC host found on Amlogic Meson SoCs
  ARM: dts: meson8b: Add MMC nodes
  ARM: multi_v7_defconfig: Add Amlogic Meson MMC support

 .../devicetree/bindings/mmc/meson-mmc.txt          |  30 ++
 arch/arm/boot/dts/meson8b-mxq.dts                  |   8 +
 arch/arm/boot/dts/meson8b-odroidc1.dts             |   8 +
 arch/arm/boot/dts/meson8b.dtsi                     |  16 +
 arch/arm/configs/multi_v7_defconfig                |   1 +
 drivers/mmc/host/Kconfig                           |   7 +
 drivers/mmc/host/Makefile                          |   1 +
 drivers/mmc/host/meson-mmc.c                       | 535 +++++++++++++++++++++
 8 files changed, 606 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/mmc/meson-mmc.txt
 create mode 100644 drivers/mmc/host/meson-mmc.c

-- 
1.9.1

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

* [PATCH v5 1/4] mmc: meson: Document Amlogic Meson MMC DT bindings
  2016-02-27 18:01 ` Carlo Caione
@ 2016-02-27 18:01     ` Carlo Caione
  -1 siblings, 0 replies; 24+ messages in thread
From: Carlo Caione @ 2016-02-27 18:01 UTC (permalink / raw)
  To: ulf.hansson-QSEj5FYQhm4dnm+yROfE0A,
	robh+dt-DgEjT+Ai2ygdnm+yROfE0A,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	linux-lFZ/pmaqli7XmaaqVzeoHQ, devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-meson-/JYPxA39Uh5TLH3MbocFFw, linux-6IF/jdPJHihWk0Htik3J/w
  Cc: Carlo Caione

From: Carlo Caione <carlo-6IF/jdPJHihWk0Htik3J/w@public.gmane.org>

Signed-off-by: Carlo Caione <carlo-6IF/jdPJHihWk0Htik3J/w@public.gmane.org>
---
 .../devicetree/bindings/mmc/meson-mmc.txt          | 30 ++++++++++++++++++++++
 1 file changed, 30 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/mmc/meson-mmc.txt

diff --git a/Documentation/devicetree/bindings/mmc/meson-mmc.txt b/Documentation/devicetree/bindings/mmc/meson-mmc.txt
new file mode 100644
index 0000000..328157e
--- /dev/null
+++ b/Documentation/devicetree/bindings/mmc/meson-mmc.txt
@@ -0,0 +1,30 @@
+* Amlogic Meson MMC controller
+
+The highspeed MMC host controller on Amlogic SoCs provides an interface
+for MMC, SD, SDIO and SDHC types of memory cards.
+
+Supported maximum speeds are the ones of the eMMC standard 4.41 as well
+as the speed of SD standard 2.0.
+
+Required properties:
+ - compatible : "amlogic,meson-mmc"
+ - reg : mmc controller base registers
+ - interrupts : mmc controller interrupt
+ - clocks : phandle to clock provider
+ - pinctrl-names : should contain "sdio_a" or "sdio_b"
+ - pinctrl-0: Should specify pin control groups used for this controller
+
+Optional properties:
+ - meson,sd-port : 0 for port A, 1 for port B
+ - for cd, bus-width and additional generic mmc parameters
+   please refer to mmc.txt within this directory
+
+Examples:
+	mmc0: mmc@c1108c20 {
+		pinctrl-names = "sdio_b";
+		pinctrl-0 = <&mmc0_sd_b_pins>;
+		compatible = "amlogic,meson-mmc";
+		reg = <0xc1108c20 0x20>;
+		interrupts = <0 28 1>;
+		clocks = <&clkc CLKID_CLK81>;
+	};
-- 
1.9.1

--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

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

* [PATCH v5 1/4] mmc: meson: Document Amlogic Meson MMC DT bindings
@ 2016-02-27 18:01     ` Carlo Caione
  0 siblings, 0 replies; 24+ messages in thread
From: Carlo Caione @ 2016-02-27 18:01 UTC (permalink / raw)
  To: linux-arm-kernel

From: Carlo Caione <carlo@endlessm.com>

Signed-off-by: Carlo Caione <carlo@endlessm.com>
---
 .../devicetree/bindings/mmc/meson-mmc.txt          | 30 ++++++++++++++++++++++
 1 file changed, 30 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/mmc/meson-mmc.txt

diff --git a/Documentation/devicetree/bindings/mmc/meson-mmc.txt b/Documentation/devicetree/bindings/mmc/meson-mmc.txt
new file mode 100644
index 0000000..328157e
--- /dev/null
+++ b/Documentation/devicetree/bindings/mmc/meson-mmc.txt
@@ -0,0 +1,30 @@
+* Amlogic Meson MMC controller
+
+The highspeed MMC host controller on Amlogic SoCs provides an interface
+for MMC, SD, SDIO and SDHC types of memory cards.
+
+Supported maximum speeds are the ones of the eMMC standard 4.41 as well
+as the speed of SD standard 2.0.
+
+Required properties:
+ - compatible : "amlogic,meson-mmc"
+ - reg : mmc controller base registers
+ - interrupts : mmc controller interrupt
+ - clocks : phandle to clock provider
+ - pinctrl-names : should contain "sdio_a" or "sdio_b"
+ - pinctrl-0: Should specify pin control groups used for this controller
+
+Optional properties:
+ - meson,sd-port : 0 for port A, 1 for port B
+ - for cd, bus-width and additional generic mmc parameters
+   please refer to mmc.txt within this directory
+
+Examples:
+	mmc0: mmc at c1108c20 {
+		pinctrl-names = "sdio_b";
+		pinctrl-0 = <&mmc0_sd_b_pins>;
+		compatible = "amlogic,meson-mmc";
+		reg = <0xc1108c20 0x20>;
+		interrupts = <0 28 1>;
+		clocks = <&clkc CLKID_CLK81>;
+	};
-- 
1.9.1

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

* [PATCH v5 2/4] mmc: meson: Add driver for the SD/MMC host found on Amlogic Meson SoCs
  2016-02-27 18:01 ` Carlo Caione
@ 2016-02-27 18:01     ` Carlo Caione
  -1 siblings, 0 replies; 24+ messages in thread
From: Carlo Caione @ 2016-02-27 18:01 UTC (permalink / raw)
  To: ulf.hansson-QSEj5FYQhm4dnm+yROfE0A,
	robh+dt-DgEjT+Ai2ygdnm+yROfE0A,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	linux-lFZ/pmaqli7XmaaqVzeoHQ, devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-meson-/JYPxA39Uh5TLH3MbocFFw, linux-6IF/jdPJHihWk0Htik3J/w
  Cc: Carlo Caione

From: Carlo Caione <carlo-6IF/jdPJHihWk0Htik3J/w@public.gmane.org>

Add a driver for the SD/MMC host found on the Amlogic Meson SoCs. This
is an MMC controller which provides an interface between the application
processor and various memory cards. It supports the SD specification
v2.0 and the eMMC specification v4.41.

Signed-off-by: Carlo Caione <carlo-6IF/jdPJHihWk0Htik3J/w@public.gmane.org>
---

Ulf,
I addressed all your suggestions but the command timeout is still not
implemented. I'm having some trouble trying to figure out how the timeout
registers really work and how to integrate this hw timeout in the driver. This
is not really a problem for the platforms we currently support and the driver
works fairly well already.

---
 drivers/mmc/host/Kconfig     |   7 +
 drivers/mmc/host/Makefile    |   1 +
 drivers/mmc/host/meson-mmc.c | 535 +++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 543 insertions(+)
 create mode 100644 drivers/mmc/host/meson-mmc.c

diff --git a/drivers/mmc/host/Kconfig b/drivers/mmc/host/Kconfig
index 1526b8a..99e0a0d 100644
--- a/drivers/mmc/host/Kconfig
+++ b/drivers/mmc/host/Kconfig
@@ -766,6 +766,13 @@ config MMC_REALTEK_USB
 	  Say Y here to include driver code to support SD/MMC card interface
 	  of Realtek RTS5129/39 series card reader
 
+config MMC_MESON
+	tristate "Amlogic Meson SD/MMC Host Controller support"
+	depends on ARCH_MESON
+	help
+	  This selects support for the SD/MMC Host Controller on
+	  Amlogic Meson SoCs.
+
 config MMC_SUNXI
 	tristate "Allwinner sunxi SD/MMC Host Controller support"
 	depends on ARCH_SUNXI
diff --git a/drivers/mmc/host/Makefile b/drivers/mmc/host/Makefile
index 3595f83..26ddf76 100644
--- a/drivers/mmc/host/Makefile
+++ b/drivers/mmc/host/Makefile
@@ -54,6 +54,7 @@ obj-$(CONFIG_MMC_VUB300)	+= vub300.o
 obj-$(CONFIG_MMC_USHC)		+= ushc.o
 obj-$(CONFIG_MMC_WMT)		+= wmt-sdmmc.o
 obj-$(CONFIG_MMC_MOXART)	+= moxart-mmc.o
+obj-$(CONFIG_MMC_MESON)		+= meson-mmc.o
 obj-$(CONFIG_MMC_SUNXI)		+= sunxi-mmc.o
 obj-$(CONFIG_MMC_USDHI6ROL0)	+= usdhi6rol0.o
 obj-$(CONFIG_MMC_TOSHIBA_PCI)	+= toshsd.o
diff --git a/drivers/mmc/host/meson-mmc.c b/drivers/mmc/host/meson-mmc.c
new file mode 100644
index 0000000..45b13fe
--- /dev/null
+++ b/drivers/mmc/host/meson-mmc.c
@@ -0,0 +1,535 @@
+/*
+ * meson-mmc.c - Meson SDH Controller
+ *
+ * Copyright (C) 2015 Endless Mobile, Inc.
+ * Author: Carlo Caione <carlo-6IF/jdPJHihWk0Htik3J/w@public.gmane.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or (at
+ * your option) any later version.
+ */
+
+#include <linux/clk.h>
+#include <linux/delay.h>
+#include <linux/dma-mapping.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/ioport.h>
+#include <linux/platform_device.h>
+
+#include <linux/mmc/host.h>
+#include <linux/mmc/mmc.h>
+#include <linux/mmc/sdio.h>
+#include <linux/mmc/slot-gpio.h>
+
+#include <linux/of_address.h>
+#include <linux/of_gpio.h>
+#include <linux/of_platform.h>
+
+#define SDIO_ARGU		(0x00)
+#define SDIO_SEND		(0x04)
+#define SDIO_CONF		(0x08)
+#define SDIO_IRQS		(0x0c)
+#define SDIO_IRQC		(0x10)
+#define SDIO_MULT		(0x14)
+#define SDIO_ADDR		(0x18)
+#define SDIO_EXT		(0x1c)
+
+#define REG_IRQS_RESP_CRC7	BIT(5)
+#define REG_IRQS_RD_CRC16	BIT(6)
+#define REG_IRQS_WR_CRC16	BIT(7)
+#define REG_IRQS_CMD_INT	BIT(9)
+
+#define REG_IRQC_ARC_CMD_INT	BIT(4)
+
+#define REG_CONF_CLK_DIV_M	(0x3ff)
+#define REG_CONF_BUS_WIDTH	BIT(20)
+
+#define REG_MULT_PORT_SEL_M	(0x3)
+#define REG_MULT_RD_INDEX_M	(0x0f)
+#define REG_MULT_RD_INDEX_S	(12)
+#define REG_MULT_WR_RD_OUT_IND	BIT(8)
+
+#define REG_SEND_CMD_COMMAND_M	(0xff)
+#define REG_SEND_CMD_RESP_S	(8)
+#define REG_SEND_RESP_NO_CRC7	BIT(16)
+#define REG_SEND_RESP_HAVE_DATA	BIT(17)
+#define REG_SEND_RESP_CRC7_F_8	BIT(18)
+#define REG_SEND_CHECK_BUSY_D0	BIT(19)
+#define REG_SEND_CMD_SEND_DATA	BIT(20)
+#define REG_SEND_REP_PACK_N_M	(0xff)
+#define REG_SEND_REP_PACK_N_S	(24)
+
+#define REG_EXT_DAT_RW_NUM_M	(0x3fff)
+#define REG_EXT_DAT_RW_NUM_S	(16)
+
+#define SDIO_BOUNCE_REQ_SIZE	(128 * 1024)
+
+struct meson_mmc_host {
+	struct mmc_host		*mmc;
+	struct mmc_request	*mrq;
+	struct delayed_work     timeout_work;
+	struct clk		*clk;
+	spinlock_t		lock;
+	void __iomem		*base;
+	long			timeout;
+	int			irq;
+	int			error;
+	unsigned int		port;
+	bool			cmd_is_stop;
+	bool			dying;
+};
+
+static int meson_mmc_clk_set_rate(struct mmc_host *mmc, struct mmc_ios *ios)
+{
+	struct meson_mmc_host *host = mmc_priv(mmc);
+	unsigned long clk_rate;
+	unsigned int clk_ios = ios->clock;
+	unsigned int clk_div;
+	u32 conf_reg;
+
+	clk_rate = clk_get_rate(host->clk);
+	if (clk_rate < 0) {
+		dev_err(mmc_dev(mmc), "cannot get clock rate\n");
+		return -EINVAL;
+	}
+
+	clk_rate >>= 1;
+	clk_div = clk_rate / clk_ios - !(clk_rate % clk_ios);
+
+	conf_reg = readl(host->base + SDIO_CONF);
+	conf_reg &= ~REG_CONF_CLK_DIV_M;
+	conf_reg |= clk_div;
+	writel(conf_reg, host->base + SDIO_CONF);
+
+	host->mmc->actual_clock = clk_rate / ((clk_div + 1) * 2);
+	dev_dbg(mmc_dev(mmc), "clk_ios: %d, clk_div: %d, clk_rate: %ld\n",
+		clk_ios, clk_div, clk_rate);
+
+	return 0;
+}
+
+static void meson_mmc_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
+{
+	struct meson_mmc_host *host = mmc_priv(mmc);
+	u32 reg;
+
+	reg = readl(host->base + SDIO_CONF);
+
+	switch (ios->bus_width) {
+	case MMC_BUS_WIDTH_1:
+		reg &= ~REG_CONF_BUS_WIDTH;
+		break;
+	case MMC_BUS_WIDTH_4:
+		reg |= REG_CONF_BUS_WIDTH;
+		break;
+	case MMC_BUS_WIDTH_8:
+	default:
+		dev_err(mmc_dev(mmc), "meson controller doesn't support 8bit data bus\n");
+		host->error = -EINVAL;
+		return;
+	}
+
+	writel(reg, host->base + SDIO_CONF);
+
+	if (ios->clock && ios->power_mode)
+		host->error = meson_mmc_clk_set_rate(mmc, ios);
+}
+
+static void meson_mmc_start_cmd(struct mmc_host *mmc,
+				struct mmc_command *cmd)
+{
+	struct meson_mmc_host *host = mmc_priv(mmc);
+	unsigned int pack_size;
+	u32 irqc, irqs, mult;
+	u32 send = 0;
+	u32 ext = 0;
+
+	switch (mmc_resp_type(cmd)) {
+	case MMC_RSP_R1:
+	case MMC_RSP_R1B:
+	case MMC_RSP_R3:
+		send |= (45 << REG_SEND_CMD_RESP_S);
+		break;
+	case MMC_RSP_R2:
+		send |= (133 << REG_SEND_CMD_RESP_S);
+		send |= REG_SEND_RESP_CRC7_F_8;
+		break;
+	default:
+		break;
+	}
+
+	if (!(cmd->flags & MMC_RSP_CRC))
+		send |= REG_SEND_RESP_NO_CRC7;
+
+	if (cmd->flags & MMC_RSP_BUSY)
+		send |= REG_SEND_CHECK_BUSY_D0;
+
+	if (cmd->data) {
+		send &= ~(REG_SEND_REP_PACK_N_M << REG_SEND_REP_PACK_N_S);
+		send |= ((cmd->data->blocks - 1) << REG_SEND_REP_PACK_N_S);
+
+		ext &= ~(REG_EXT_DAT_RW_NUM_M << REG_EXT_DAT_RW_NUM_S);
+		if (mmc->ios.bus_width)
+			pack_size = cmd->data->blksz * 8 + (16 - 1) * 4;
+		else
+			pack_size = cmd->data->blksz * 8 + (16 - 1);
+		ext |= (pack_size << REG_EXT_DAT_RW_NUM_S);
+
+		if (cmd->data->flags & MMC_DATA_WRITE)
+			send |= REG_SEND_CMD_SEND_DATA;
+		else
+			send |= REG_SEND_RESP_HAVE_DATA;
+	}
+
+	send &= ~REG_SEND_CMD_COMMAND_M;
+	send |= (0x40 | cmd->opcode);
+
+	irqc = readl(host->base + SDIO_IRQC);
+	irqc |= REG_IRQC_ARC_CMD_INT;
+
+	irqs = readl(host->base + SDIO_IRQS);
+	irqs |= REG_IRQS_CMD_INT;
+
+	mult = readl(host->base + SDIO_MULT);
+	mult &= ~REG_MULT_PORT_SEL_M;
+	mult |= host->port;
+	mult |= (1 << 31);
+	writel(mult, host->base + SDIO_MULT);
+	writel(irqs, host->base + SDIO_IRQS);
+	writel(irqc, host->base + SDIO_IRQC);
+
+	writel(cmd->arg, host->base + SDIO_ARGU);
+	writel(ext, host->base + SDIO_EXT);
+	writel(send, host->base + SDIO_SEND);
+}
+
+static int meson_mmc_map_dma(struct meson_mmc_host *host,
+			     struct mmc_data *data,
+			     unsigned int flags)
+{	u32 dma_len;
+	struct scatterlist *sg = data->sg;
+
+	if (sg->offset & 3 || sg->length & 3) {
+		dev_err(mmc_dev(host->mmc),
+			"unaligned scatterlist: os %x length %d\n",
+			sg->offset, sg->length);
+		return -EINVAL;
+	}
+
+	dma_len = dma_map_sg(mmc_dev(host->mmc), data->sg, data->sg_len,
+			     ((data->flags & MMC_DATA_READ) ?
+			     DMA_FROM_DEVICE : DMA_TO_DEVICE));
+	if (dma_len == 0) {
+		dev_err(mmc_dev(host->mmc), "dma_map_sg failed\n");
+		return -ENOMEM;
+	}
+
+	return 0;
+}
+
+static void meson_mmc_request(struct mmc_host *mmc, struct mmc_request *mrq)
+{
+	struct meson_mmc_host *host = mmc_priv(mmc);
+	struct mmc_command *cmd = mrq->cmd;
+	struct mmc_data *data = mrq->data;
+	unsigned long flags;
+	int ret;
+
+	spin_lock_irqsave(&host->lock, flags);
+
+	if (host->error) {
+		cmd->error = host->error;
+		spin_unlock_irqrestore(&host->lock, flags);
+		mmc_request_done(mmc, mrq);
+		return;
+	}
+
+	if (data) {
+		ret = meson_mmc_map_dma(host, data, data->flags);
+		if (ret < 0) {
+			dev_err(mmc_dev(mmc), "map DMA failed\n");
+			cmd->error = ret;
+			data->error = ret;
+			spin_unlock_irqrestore(&host->lock, flags);
+			mmc_request_done(mmc, mrq);
+			return;
+		}
+		writel(sg_dma_address(data->sg), host->base + SDIO_ADDR);
+	}
+
+	host->mrq = mrq;
+	meson_mmc_start_cmd(mmc, mrq->cmd);
+
+	spin_unlock_irqrestore(&host->lock, flags);
+
+	schedule_delayed_work(&host->timeout_work, host->timeout);
+}
+
+static irqreturn_t meson_mmc_irq(int irq, void *data)
+{
+	struct meson_mmc_host *host = (void *) data;
+	struct mmc_request *mrq = host->mrq;
+	u32 irqs;
+
+	irqs = readl(host->base + SDIO_IRQS);
+	if (mrq && (irqs & REG_IRQS_CMD_INT))
+		return IRQ_WAKE_THREAD;
+
+	return IRQ_HANDLED;
+}
+
+void meson_mmc_read_response(struct meson_mmc_host *host)
+{
+	struct mmc_command *cmd = host->mrq->cmd;
+	u32 mult;
+	int i, resp[4] = { 0 };
+
+	mult = readl(host->base + SDIO_MULT);
+	mult |= REG_MULT_WR_RD_OUT_IND;
+	mult &= ~(REG_MULT_RD_INDEX_M << REG_MULT_RD_INDEX_S);
+	writel(mult, host->base + SDIO_MULT);
+
+	if (cmd->flags & MMC_RSP_136) {
+		for (i = 0; i <= 3; i++)
+			resp[3 - i] = readl(host->base + SDIO_ARGU);
+		cmd->resp[0] = (resp[0] << 8) | ((resp[1] >> 24) & 0xff);
+		cmd->resp[1] = (resp[1] << 8) | ((resp[2] >> 24) & 0xff);
+		cmd->resp[2] = (resp[2] << 8) | ((resp[3] >> 24) & 0xff);
+		cmd->resp[3] = (resp[3] << 8);
+	} else if (cmd->flags & MMC_RSP_PRESENT) {
+		cmd->resp[0] = readl(host->base + SDIO_ARGU);
+	}
+}
+
+static irqreturn_t meson_mmc_irq_thread(int irq, void *irq_data)
+{
+	struct meson_mmc_host *host = (void *) irq_data;
+	struct mmc_data *data;
+	unsigned long flags;
+	struct mmc_request *mrq;
+	u32 irqs, send;
+
+	cancel_delayed_work_sync(&host->timeout_work);
+	spin_lock_irqsave(&host->lock, flags);
+
+	mrq = host->mrq;
+	data = mrq->data;
+
+	if (!mrq) {
+		spin_unlock_irqrestore(&host->lock, flags);
+		return IRQ_HANDLED;
+	}
+
+	if (host->cmd_is_stop)
+		goto out;
+
+	irqs = readl(host->base + SDIO_IRQS);
+	send = readl(host->base + SDIO_SEND);
+
+	mrq->cmd->error = 0;
+
+	if (!data) {
+		if (!((irqs & REG_IRQS_RESP_CRC7) ||
+		      (send & REG_SEND_RESP_NO_CRC7)))
+			mrq->cmd->error = -EILSEQ;
+		else
+			meson_mmc_read_response(host);
+	} else {
+		if (!((irqs & REG_IRQS_RD_CRC16) ||
+		      (irqs & REG_IRQS_WR_CRC16))) {
+			mrq->cmd->error = -EILSEQ;
+		} else {
+			data->bytes_xfered = data->blksz * data->blocks;
+			dma_unmap_sg(mmc_dev(host->mmc), data->sg, data->sg_len,
+				     ((data->flags & MMC_DATA_READ) ?
+				     DMA_FROM_DEVICE : DMA_TO_DEVICE));
+		}
+	}
+
+	if (mrq->stop) {
+		host->cmd_is_stop = true;
+		meson_mmc_start_cmd(host->mmc, mrq->stop);
+		spin_unlock_irqrestore(&host->lock, flags);
+		return IRQ_HANDLED;
+	}
+
+out:
+	host->cmd_is_stop = false;
+	host->mrq = NULL;
+	spin_unlock_irqrestore(&host->lock, flags);
+	mmc_request_done(host->mmc, mrq);
+
+	return IRQ_HANDLED;
+}
+
+static void meson_mmc_timeout(struct work_struct *work)
+{
+	struct meson_mmc_host *host = container_of(work,
+						   struct meson_mmc_host,
+						   timeout_work.work);
+	struct mmc_request *mrq = host->mrq;
+	unsigned long flags;
+	u32 irqc;
+
+	/* Do not run after meson_mmc_remove() */
+	if (host->dying)
+		return;
+
+	spin_lock_irqsave(&host->lock, flags);
+
+	dev_err(mmc_dev(host->mmc), "Timeout on CMD%u\n", mrq->cmd->opcode);
+
+	irqc = readl(host->base + SDIO_IRQC);
+	irqc &= ~REG_IRQC_ARC_CMD_INT;
+	writel(irqc, host->base + SDIO_IRQC);
+
+	mrq->cmd->error = -ETIMEDOUT;
+
+	host->mrq = NULL;
+	spin_unlock_irqrestore(&host->lock, flags);
+
+	mmc_request_done(host->mmc, mrq);
+}
+
+static struct mmc_host_ops meson_mmc_ops = {
+	.request	= meson_mmc_request,
+	.set_ios	= meson_mmc_set_ios,
+	.get_cd		= mmc_gpio_get_cd,
+};
+
+static int meson_mmc_probe(struct platform_device *pdev)
+{
+	struct mmc_host *mmc;
+	struct meson_mmc_host *host;
+	struct pinctrl *pinctrl;
+	struct resource *res;
+	int ret, irq;
+	u32 port;
+
+	mmc = mmc_alloc_host(sizeof(struct meson_mmc_host), &pdev->dev);
+	if (!mmc) {
+		dev_err(&pdev->dev, "mmc alloc host failed\n");
+		return -ENOMEM;
+	}
+
+	host = mmc_priv(mmc);
+	host->mmc = mmc;
+	host->timeout = msecs_to_jiffies(10000);
+	host->port = 0;
+
+	if (!of_property_read_u32(pdev->dev.of_node, "meson,sd-port", &port))
+		host->port = port;
+
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	host->base = devm_ioremap_resource(&pdev->dev, res);
+	if (IS_ERR(host->base)) {
+		ret = PTR_ERR(host->base);
+		goto error_free_host;
+	}
+
+	irq = platform_get_irq(pdev, 0);
+	ret = devm_request_threaded_irq(&pdev->dev, irq, meson_mmc_irq,
+					meson_mmc_irq_thread, 0, "meson_mmc",
+					host);
+	if (ret)
+		goto error_free_host;
+
+	host->clk = devm_clk_get(&pdev->dev, NULL);
+	if (IS_ERR(host->clk)) {
+		ret = PTR_ERR(host->clk);
+		goto error_free_host;
+	}
+
+	ret = clk_prepare_enable(host->clk);
+	if (ret) {
+		dev_err(&pdev->dev, "Enable clk error %d\n", ret);
+		goto error_free_host;
+	}
+
+	/* we do not support scatter lists in hardware */
+	mmc->max_segs = 1;
+	mmc->max_req_size = SDIO_BOUNCE_REQ_SIZE;
+	mmc->max_seg_size = mmc->max_req_size;
+	mmc->max_blk_count = 256;
+	mmc->max_blk_size = mmc->max_req_size / mmc->max_blk_count;
+	mmc->f_min = 300000;
+	mmc->f_max = 50000000;
+	mmc->caps |= MMC_CAP_4_BIT_DATA;
+	mmc->caps |= MMC_CAP_MMC_HIGHSPEED | MMC_CAP_SD_HIGHSPEED;
+	mmc->caps2 |= MMC_CAP2_NO_SDIO;
+	mmc->ocr_avail = MMC_VDD_33_34;
+	mmc->ops = &meson_mmc_ops;
+
+	spin_lock_init(&host->lock);
+
+	INIT_DELAYED_WORK(&host->timeout_work, meson_mmc_timeout);
+
+	pinctrl = devm_pinctrl_get(&pdev->dev);
+	if (IS_ERR(pinctrl)) {
+		ret = PTR_ERR(pinctrl);
+		goto error;
+	}
+
+	ret = mmc_of_parse(mmc);
+	if (ret)
+		goto error;
+
+	platform_set_drvdata(pdev, mmc);
+
+	ret = mmc_add_host(mmc);
+	if (ret)
+		goto error;
+
+	dev_info(&pdev->dev, "base:0x%p irq:%u port:%u\n",
+		 host->base, irq, host->port);
+
+	return 0;
+
+error:
+	clk_disable_unprepare(host->clk);
+error_free_host:
+	mmc_free_host(mmc);
+
+	return ret;
+}
+
+static int meson_mmc_remove(struct platform_device *pdev)
+{
+	struct mmc_host	*mmc = platform_get_drvdata(pdev);
+	struct meson_mmc_host *host = mmc_priv(mmc);
+
+	host->dying = true;
+
+	mmc_remove_host(mmc);
+	cancel_delayed_work_sync(&host->timeout_work);
+	clk_disable_unprepare(host->clk);
+
+	mmc_free_host(mmc);
+
+	return 0;
+}
+
+static const struct of_device_id meson_mmc_of_match[] = {
+	{ .compatible = "amlogic,meson-mmc", },
+	{ /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(of, meson_mmc_of_match);
+
+static struct platform_driver meson_mmc_driver = {
+	.probe   = meson_mmc_probe,
+	.remove  = meson_mmc_remove,
+	.driver  = {
+		.name = "meson-mmc",
+		.of_match_table = of_match_ptr(meson_mmc_of_match),
+	},
+};
+
+module_platform_driver(meson_mmc_driver);
+
+MODULE_DESCRIPTION("Meson Secure Digital Host Driver");
+MODULE_AUTHOR("Carlo Caione <carlo-6IF/jdPJHihWk0Htik3J/w@public.gmane.org>");
+MODULE_LICENSE("GPL");
-- 
1.9.1

--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

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

* [PATCH v5 2/4] mmc: meson: Add driver for the SD/MMC host found on Amlogic Meson SoCs
@ 2016-02-27 18:01     ` Carlo Caione
  0 siblings, 0 replies; 24+ messages in thread
From: Carlo Caione @ 2016-02-27 18:01 UTC (permalink / raw)
  To: linux-arm-kernel

From: Carlo Caione <carlo@endlessm.com>

Add a driver for the SD/MMC host found on the Amlogic Meson SoCs. This
is an MMC controller which provides an interface between the application
processor and various memory cards. It supports the SD specification
v2.0 and the eMMC specification v4.41.

Signed-off-by: Carlo Caione <carlo@endlessm.com>
---

Ulf,
I addressed all your suggestions but the command timeout is still not
implemented. I'm having some trouble trying to figure out how the timeout
registers really work and how to integrate this hw timeout in the driver. This
is not really a problem for the platforms we currently support and the driver
works fairly well already.

---
 drivers/mmc/host/Kconfig     |   7 +
 drivers/mmc/host/Makefile    |   1 +
 drivers/mmc/host/meson-mmc.c | 535 +++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 543 insertions(+)
 create mode 100644 drivers/mmc/host/meson-mmc.c

diff --git a/drivers/mmc/host/Kconfig b/drivers/mmc/host/Kconfig
index 1526b8a..99e0a0d 100644
--- a/drivers/mmc/host/Kconfig
+++ b/drivers/mmc/host/Kconfig
@@ -766,6 +766,13 @@ config MMC_REALTEK_USB
 	  Say Y here to include driver code to support SD/MMC card interface
 	  of Realtek RTS5129/39 series card reader
 
+config MMC_MESON
+	tristate "Amlogic Meson SD/MMC Host Controller support"
+	depends on ARCH_MESON
+	help
+	  This selects support for the SD/MMC Host Controller on
+	  Amlogic Meson SoCs.
+
 config MMC_SUNXI
 	tristate "Allwinner sunxi SD/MMC Host Controller support"
 	depends on ARCH_SUNXI
diff --git a/drivers/mmc/host/Makefile b/drivers/mmc/host/Makefile
index 3595f83..26ddf76 100644
--- a/drivers/mmc/host/Makefile
+++ b/drivers/mmc/host/Makefile
@@ -54,6 +54,7 @@ obj-$(CONFIG_MMC_VUB300)	+= vub300.o
 obj-$(CONFIG_MMC_USHC)		+= ushc.o
 obj-$(CONFIG_MMC_WMT)		+= wmt-sdmmc.o
 obj-$(CONFIG_MMC_MOXART)	+= moxart-mmc.o
+obj-$(CONFIG_MMC_MESON)		+= meson-mmc.o
 obj-$(CONFIG_MMC_SUNXI)		+= sunxi-mmc.o
 obj-$(CONFIG_MMC_USDHI6ROL0)	+= usdhi6rol0.o
 obj-$(CONFIG_MMC_TOSHIBA_PCI)	+= toshsd.o
diff --git a/drivers/mmc/host/meson-mmc.c b/drivers/mmc/host/meson-mmc.c
new file mode 100644
index 0000000..45b13fe
--- /dev/null
+++ b/drivers/mmc/host/meson-mmc.c
@@ -0,0 +1,535 @@
+/*
+ * meson-mmc.c - Meson SDH Controller
+ *
+ * Copyright (C) 2015 Endless Mobile, Inc.
+ * Author: Carlo Caione <carlo@endlessm.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or (at
+ * your option) any later version.
+ */
+
+#include <linux/clk.h>
+#include <linux/delay.h>
+#include <linux/dma-mapping.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/ioport.h>
+#include <linux/platform_device.h>
+
+#include <linux/mmc/host.h>
+#include <linux/mmc/mmc.h>
+#include <linux/mmc/sdio.h>
+#include <linux/mmc/slot-gpio.h>
+
+#include <linux/of_address.h>
+#include <linux/of_gpio.h>
+#include <linux/of_platform.h>
+
+#define SDIO_ARGU		(0x00)
+#define SDIO_SEND		(0x04)
+#define SDIO_CONF		(0x08)
+#define SDIO_IRQS		(0x0c)
+#define SDIO_IRQC		(0x10)
+#define SDIO_MULT		(0x14)
+#define SDIO_ADDR		(0x18)
+#define SDIO_EXT		(0x1c)
+
+#define REG_IRQS_RESP_CRC7	BIT(5)
+#define REG_IRQS_RD_CRC16	BIT(6)
+#define REG_IRQS_WR_CRC16	BIT(7)
+#define REG_IRQS_CMD_INT	BIT(9)
+
+#define REG_IRQC_ARC_CMD_INT	BIT(4)
+
+#define REG_CONF_CLK_DIV_M	(0x3ff)
+#define REG_CONF_BUS_WIDTH	BIT(20)
+
+#define REG_MULT_PORT_SEL_M	(0x3)
+#define REG_MULT_RD_INDEX_M	(0x0f)
+#define REG_MULT_RD_INDEX_S	(12)
+#define REG_MULT_WR_RD_OUT_IND	BIT(8)
+
+#define REG_SEND_CMD_COMMAND_M	(0xff)
+#define REG_SEND_CMD_RESP_S	(8)
+#define REG_SEND_RESP_NO_CRC7	BIT(16)
+#define REG_SEND_RESP_HAVE_DATA	BIT(17)
+#define REG_SEND_RESP_CRC7_F_8	BIT(18)
+#define REG_SEND_CHECK_BUSY_D0	BIT(19)
+#define REG_SEND_CMD_SEND_DATA	BIT(20)
+#define REG_SEND_REP_PACK_N_M	(0xff)
+#define REG_SEND_REP_PACK_N_S	(24)
+
+#define REG_EXT_DAT_RW_NUM_M	(0x3fff)
+#define REG_EXT_DAT_RW_NUM_S	(16)
+
+#define SDIO_BOUNCE_REQ_SIZE	(128 * 1024)
+
+struct meson_mmc_host {
+	struct mmc_host		*mmc;
+	struct mmc_request	*mrq;
+	struct delayed_work     timeout_work;
+	struct clk		*clk;
+	spinlock_t		lock;
+	void __iomem		*base;
+	long			timeout;
+	int			irq;
+	int			error;
+	unsigned int		port;
+	bool			cmd_is_stop;
+	bool			dying;
+};
+
+static int meson_mmc_clk_set_rate(struct mmc_host *mmc, struct mmc_ios *ios)
+{
+	struct meson_mmc_host *host = mmc_priv(mmc);
+	unsigned long clk_rate;
+	unsigned int clk_ios = ios->clock;
+	unsigned int clk_div;
+	u32 conf_reg;
+
+	clk_rate = clk_get_rate(host->clk);
+	if (clk_rate < 0) {
+		dev_err(mmc_dev(mmc), "cannot get clock rate\n");
+		return -EINVAL;
+	}
+
+	clk_rate >>= 1;
+	clk_div = clk_rate / clk_ios - !(clk_rate % clk_ios);
+
+	conf_reg = readl(host->base + SDIO_CONF);
+	conf_reg &= ~REG_CONF_CLK_DIV_M;
+	conf_reg |= clk_div;
+	writel(conf_reg, host->base + SDIO_CONF);
+
+	host->mmc->actual_clock = clk_rate / ((clk_div + 1) * 2);
+	dev_dbg(mmc_dev(mmc), "clk_ios: %d, clk_div: %d, clk_rate: %ld\n",
+		clk_ios, clk_div, clk_rate);
+
+	return 0;
+}
+
+static void meson_mmc_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
+{
+	struct meson_mmc_host *host = mmc_priv(mmc);
+	u32 reg;
+
+	reg = readl(host->base + SDIO_CONF);
+
+	switch (ios->bus_width) {
+	case MMC_BUS_WIDTH_1:
+		reg &= ~REG_CONF_BUS_WIDTH;
+		break;
+	case MMC_BUS_WIDTH_4:
+		reg |= REG_CONF_BUS_WIDTH;
+		break;
+	case MMC_BUS_WIDTH_8:
+	default:
+		dev_err(mmc_dev(mmc), "meson controller doesn't support 8bit data bus\n");
+		host->error = -EINVAL;
+		return;
+	}
+
+	writel(reg, host->base + SDIO_CONF);
+
+	if (ios->clock && ios->power_mode)
+		host->error = meson_mmc_clk_set_rate(mmc, ios);
+}
+
+static void meson_mmc_start_cmd(struct mmc_host *mmc,
+				struct mmc_command *cmd)
+{
+	struct meson_mmc_host *host = mmc_priv(mmc);
+	unsigned int pack_size;
+	u32 irqc, irqs, mult;
+	u32 send = 0;
+	u32 ext = 0;
+
+	switch (mmc_resp_type(cmd)) {
+	case MMC_RSP_R1:
+	case MMC_RSP_R1B:
+	case MMC_RSP_R3:
+		send |= (45 << REG_SEND_CMD_RESP_S);
+		break;
+	case MMC_RSP_R2:
+		send |= (133 << REG_SEND_CMD_RESP_S);
+		send |= REG_SEND_RESP_CRC7_F_8;
+		break;
+	default:
+		break;
+	}
+
+	if (!(cmd->flags & MMC_RSP_CRC))
+		send |= REG_SEND_RESP_NO_CRC7;
+
+	if (cmd->flags & MMC_RSP_BUSY)
+		send |= REG_SEND_CHECK_BUSY_D0;
+
+	if (cmd->data) {
+		send &= ~(REG_SEND_REP_PACK_N_M << REG_SEND_REP_PACK_N_S);
+		send |= ((cmd->data->blocks - 1) << REG_SEND_REP_PACK_N_S);
+
+		ext &= ~(REG_EXT_DAT_RW_NUM_M << REG_EXT_DAT_RW_NUM_S);
+		if (mmc->ios.bus_width)
+			pack_size = cmd->data->blksz * 8 + (16 - 1) * 4;
+		else
+			pack_size = cmd->data->blksz * 8 + (16 - 1);
+		ext |= (pack_size << REG_EXT_DAT_RW_NUM_S);
+
+		if (cmd->data->flags & MMC_DATA_WRITE)
+			send |= REG_SEND_CMD_SEND_DATA;
+		else
+			send |= REG_SEND_RESP_HAVE_DATA;
+	}
+
+	send &= ~REG_SEND_CMD_COMMAND_M;
+	send |= (0x40 | cmd->opcode);
+
+	irqc = readl(host->base + SDIO_IRQC);
+	irqc |= REG_IRQC_ARC_CMD_INT;
+
+	irqs = readl(host->base + SDIO_IRQS);
+	irqs |= REG_IRQS_CMD_INT;
+
+	mult = readl(host->base + SDIO_MULT);
+	mult &= ~REG_MULT_PORT_SEL_M;
+	mult |= host->port;
+	mult |= (1 << 31);
+	writel(mult, host->base + SDIO_MULT);
+	writel(irqs, host->base + SDIO_IRQS);
+	writel(irqc, host->base + SDIO_IRQC);
+
+	writel(cmd->arg, host->base + SDIO_ARGU);
+	writel(ext, host->base + SDIO_EXT);
+	writel(send, host->base + SDIO_SEND);
+}
+
+static int meson_mmc_map_dma(struct meson_mmc_host *host,
+			     struct mmc_data *data,
+			     unsigned int flags)
+{	u32 dma_len;
+	struct scatterlist *sg = data->sg;
+
+	if (sg->offset & 3 || sg->length & 3) {
+		dev_err(mmc_dev(host->mmc),
+			"unaligned scatterlist: os %x length %d\n",
+			sg->offset, sg->length);
+		return -EINVAL;
+	}
+
+	dma_len = dma_map_sg(mmc_dev(host->mmc), data->sg, data->sg_len,
+			     ((data->flags & MMC_DATA_READ) ?
+			     DMA_FROM_DEVICE : DMA_TO_DEVICE));
+	if (dma_len == 0) {
+		dev_err(mmc_dev(host->mmc), "dma_map_sg failed\n");
+		return -ENOMEM;
+	}
+
+	return 0;
+}
+
+static void meson_mmc_request(struct mmc_host *mmc, struct mmc_request *mrq)
+{
+	struct meson_mmc_host *host = mmc_priv(mmc);
+	struct mmc_command *cmd = mrq->cmd;
+	struct mmc_data *data = mrq->data;
+	unsigned long flags;
+	int ret;
+
+	spin_lock_irqsave(&host->lock, flags);
+
+	if (host->error) {
+		cmd->error = host->error;
+		spin_unlock_irqrestore(&host->lock, flags);
+		mmc_request_done(mmc, mrq);
+		return;
+	}
+
+	if (data) {
+		ret = meson_mmc_map_dma(host, data, data->flags);
+		if (ret < 0) {
+			dev_err(mmc_dev(mmc), "map DMA failed\n");
+			cmd->error = ret;
+			data->error = ret;
+			spin_unlock_irqrestore(&host->lock, flags);
+			mmc_request_done(mmc, mrq);
+			return;
+		}
+		writel(sg_dma_address(data->sg), host->base + SDIO_ADDR);
+	}
+
+	host->mrq = mrq;
+	meson_mmc_start_cmd(mmc, mrq->cmd);
+
+	spin_unlock_irqrestore(&host->lock, flags);
+
+	schedule_delayed_work(&host->timeout_work, host->timeout);
+}
+
+static irqreturn_t meson_mmc_irq(int irq, void *data)
+{
+	struct meson_mmc_host *host = (void *) data;
+	struct mmc_request *mrq = host->mrq;
+	u32 irqs;
+
+	irqs = readl(host->base + SDIO_IRQS);
+	if (mrq && (irqs & REG_IRQS_CMD_INT))
+		return IRQ_WAKE_THREAD;
+
+	return IRQ_HANDLED;
+}
+
+void meson_mmc_read_response(struct meson_mmc_host *host)
+{
+	struct mmc_command *cmd = host->mrq->cmd;
+	u32 mult;
+	int i, resp[4] = { 0 };
+
+	mult = readl(host->base + SDIO_MULT);
+	mult |= REG_MULT_WR_RD_OUT_IND;
+	mult &= ~(REG_MULT_RD_INDEX_M << REG_MULT_RD_INDEX_S);
+	writel(mult, host->base + SDIO_MULT);
+
+	if (cmd->flags & MMC_RSP_136) {
+		for (i = 0; i <= 3; i++)
+			resp[3 - i] = readl(host->base + SDIO_ARGU);
+		cmd->resp[0] = (resp[0] << 8) | ((resp[1] >> 24) & 0xff);
+		cmd->resp[1] = (resp[1] << 8) | ((resp[2] >> 24) & 0xff);
+		cmd->resp[2] = (resp[2] << 8) | ((resp[3] >> 24) & 0xff);
+		cmd->resp[3] = (resp[3] << 8);
+	} else if (cmd->flags & MMC_RSP_PRESENT) {
+		cmd->resp[0] = readl(host->base + SDIO_ARGU);
+	}
+}
+
+static irqreturn_t meson_mmc_irq_thread(int irq, void *irq_data)
+{
+	struct meson_mmc_host *host = (void *) irq_data;
+	struct mmc_data *data;
+	unsigned long flags;
+	struct mmc_request *mrq;
+	u32 irqs, send;
+
+	cancel_delayed_work_sync(&host->timeout_work);
+	spin_lock_irqsave(&host->lock, flags);
+
+	mrq = host->mrq;
+	data = mrq->data;
+
+	if (!mrq) {
+		spin_unlock_irqrestore(&host->lock, flags);
+		return IRQ_HANDLED;
+	}
+
+	if (host->cmd_is_stop)
+		goto out;
+
+	irqs = readl(host->base + SDIO_IRQS);
+	send = readl(host->base + SDIO_SEND);
+
+	mrq->cmd->error = 0;
+
+	if (!data) {
+		if (!((irqs & REG_IRQS_RESP_CRC7) ||
+		      (send & REG_SEND_RESP_NO_CRC7)))
+			mrq->cmd->error = -EILSEQ;
+		else
+			meson_mmc_read_response(host);
+	} else {
+		if (!((irqs & REG_IRQS_RD_CRC16) ||
+		      (irqs & REG_IRQS_WR_CRC16))) {
+			mrq->cmd->error = -EILSEQ;
+		} else {
+			data->bytes_xfered = data->blksz * data->blocks;
+			dma_unmap_sg(mmc_dev(host->mmc), data->sg, data->sg_len,
+				     ((data->flags & MMC_DATA_READ) ?
+				     DMA_FROM_DEVICE : DMA_TO_DEVICE));
+		}
+	}
+
+	if (mrq->stop) {
+		host->cmd_is_stop = true;
+		meson_mmc_start_cmd(host->mmc, mrq->stop);
+		spin_unlock_irqrestore(&host->lock, flags);
+		return IRQ_HANDLED;
+	}
+
+out:
+	host->cmd_is_stop = false;
+	host->mrq = NULL;
+	spin_unlock_irqrestore(&host->lock, flags);
+	mmc_request_done(host->mmc, mrq);
+
+	return IRQ_HANDLED;
+}
+
+static void meson_mmc_timeout(struct work_struct *work)
+{
+	struct meson_mmc_host *host = container_of(work,
+						   struct meson_mmc_host,
+						   timeout_work.work);
+	struct mmc_request *mrq = host->mrq;
+	unsigned long flags;
+	u32 irqc;
+
+	/* Do not run after meson_mmc_remove() */
+	if (host->dying)
+		return;
+
+	spin_lock_irqsave(&host->lock, flags);
+
+	dev_err(mmc_dev(host->mmc), "Timeout on CMD%u\n", mrq->cmd->opcode);
+
+	irqc = readl(host->base + SDIO_IRQC);
+	irqc &= ~REG_IRQC_ARC_CMD_INT;
+	writel(irqc, host->base + SDIO_IRQC);
+
+	mrq->cmd->error = -ETIMEDOUT;
+
+	host->mrq = NULL;
+	spin_unlock_irqrestore(&host->lock, flags);
+
+	mmc_request_done(host->mmc, mrq);
+}
+
+static struct mmc_host_ops meson_mmc_ops = {
+	.request	= meson_mmc_request,
+	.set_ios	= meson_mmc_set_ios,
+	.get_cd		= mmc_gpio_get_cd,
+};
+
+static int meson_mmc_probe(struct platform_device *pdev)
+{
+	struct mmc_host *mmc;
+	struct meson_mmc_host *host;
+	struct pinctrl *pinctrl;
+	struct resource *res;
+	int ret, irq;
+	u32 port;
+
+	mmc = mmc_alloc_host(sizeof(struct meson_mmc_host), &pdev->dev);
+	if (!mmc) {
+		dev_err(&pdev->dev, "mmc alloc host failed\n");
+		return -ENOMEM;
+	}
+
+	host = mmc_priv(mmc);
+	host->mmc = mmc;
+	host->timeout = msecs_to_jiffies(10000);
+	host->port = 0;
+
+	if (!of_property_read_u32(pdev->dev.of_node, "meson,sd-port", &port))
+		host->port = port;
+
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	host->base = devm_ioremap_resource(&pdev->dev, res);
+	if (IS_ERR(host->base)) {
+		ret = PTR_ERR(host->base);
+		goto error_free_host;
+	}
+
+	irq = platform_get_irq(pdev, 0);
+	ret = devm_request_threaded_irq(&pdev->dev, irq, meson_mmc_irq,
+					meson_mmc_irq_thread, 0, "meson_mmc",
+					host);
+	if (ret)
+		goto error_free_host;
+
+	host->clk = devm_clk_get(&pdev->dev, NULL);
+	if (IS_ERR(host->clk)) {
+		ret = PTR_ERR(host->clk);
+		goto error_free_host;
+	}
+
+	ret = clk_prepare_enable(host->clk);
+	if (ret) {
+		dev_err(&pdev->dev, "Enable clk error %d\n", ret);
+		goto error_free_host;
+	}
+
+	/* we do not support scatter lists in hardware */
+	mmc->max_segs = 1;
+	mmc->max_req_size = SDIO_BOUNCE_REQ_SIZE;
+	mmc->max_seg_size = mmc->max_req_size;
+	mmc->max_blk_count = 256;
+	mmc->max_blk_size = mmc->max_req_size / mmc->max_blk_count;
+	mmc->f_min = 300000;
+	mmc->f_max = 50000000;
+	mmc->caps |= MMC_CAP_4_BIT_DATA;
+	mmc->caps |= MMC_CAP_MMC_HIGHSPEED | MMC_CAP_SD_HIGHSPEED;
+	mmc->caps2 |= MMC_CAP2_NO_SDIO;
+	mmc->ocr_avail = MMC_VDD_33_34;
+	mmc->ops = &meson_mmc_ops;
+
+	spin_lock_init(&host->lock);
+
+	INIT_DELAYED_WORK(&host->timeout_work, meson_mmc_timeout);
+
+	pinctrl = devm_pinctrl_get(&pdev->dev);
+	if (IS_ERR(pinctrl)) {
+		ret = PTR_ERR(pinctrl);
+		goto error;
+	}
+
+	ret = mmc_of_parse(mmc);
+	if (ret)
+		goto error;
+
+	platform_set_drvdata(pdev, mmc);
+
+	ret = mmc_add_host(mmc);
+	if (ret)
+		goto error;
+
+	dev_info(&pdev->dev, "base:0x%p irq:%u port:%u\n",
+		 host->base, irq, host->port);
+
+	return 0;
+
+error:
+	clk_disable_unprepare(host->clk);
+error_free_host:
+	mmc_free_host(mmc);
+
+	return ret;
+}
+
+static int meson_mmc_remove(struct platform_device *pdev)
+{
+	struct mmc_host	*mmc = platform_get_drvdata(pdev);
+	struct meson_mmc_host *host = mmc_priv(mmc);
+
+	host->dying = true;
+
+	mmc_remove_host(mmc);
+	cancel_delayed_work_sync(&host->timeout_work);
+	clk_disable_unprepare(host->clk);
+
+	mmc_free_host(mmc);
+
+	return 0;
+}
+
+static const struct of_device_id meson_mmc_of_match[] = {
+	{ .compatible = "amlogic,meson-mmc", },
+	{ /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(of, meson_mmc_of_match);
+
+static struct platform_driver meson_mmc_driver = {
+	.probe   = meson_mmc_probe,
+	.remove  = meson_mmc_remove,
+	.driver  = {
+		.name = "meson-mmc",
+		.of_match_table = of_match_ptr(meson_mmc_of_match),
+	},
+};
+
+module_platform_driver(meson_mmc_driver);
+
+MODULE_DESCRIPTION("Meson Secure Digital Host Driver");
+MODULE_AUTHOR("Carlo Caione <carlo@endlessm.com>");
+MODULE_LICENSE("GPL");
-- 
1.9.1

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

* [PATCH v5 3/4] ARM: dts: meson8b: Add MMC nodes
  2016-02-27 18:01 ` Carlo Caione
@ 2016-02-27 18:01     ` Carlo Caione
  -1 siblings, 0 replies; 24+ messages in thread
From: Carlo Caione @ 2016-02-27 18:01 UTC (permalink / raw)
  To: ulf.hansson-QSEj5FYQhm4dnm+yROfE0A,
	robh+dt-DgEjT+Ai2ygdnm+yROfE0A,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	linux-lFZ/pmaqli7XmaaqVzeoHQ, devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-meson-/JYPxA39Uh5TLH3MbocFFw, linux-6IF/jdPJHihWk0Htik3J/w
  Cc: Carlo Caione

From: Carlo Caione <carlo-6IF/jdPJHihWk0Htik3J/w@public.gmane.org>

Enable the MMC for the Meson8b platforms.

Signed-off-by: Carlo Caione <carlo-6IF/jdPJHihWk0Htik3J/w@public.gmane.org>
---
 arch/arm/boot/dts/meson8b-mxq.dts      |  8 ++++++++
 arch/arm/boot/dts/meson8b-odroidc1.dts |  8 ++++++++
 arch/arm/boot/dts/meson8b.dtsi         | 16 ++++++++++++++++
 3 files changed, 32 insertions(+)

diff --git a/arch/arm/boot/dts/meson8b-mxq.dts b/arch/arm/boot/dts/meson8b-mxq.dts
index c7fdaea..5c533a6 100644
--- a/arch/arm/boot/dts/meson8b-mxq.dts
+++ b/arch/arm/boot/dts/meson8b-mxq.dts
@@ -60,6 +60,14 @@
 	};
 };
 
+&mmc0 {
+	status = "okay";
+	pinctrl-names = "sdio_b";
+	pinctrl-0 = <&mmc0_sd_b_pins>;
+	meson,sd-port = <1>;
+	broken-cd;
+};
+
 &uart_AO {
 	status = "okay";
 	pinctrl-0 = <&uart_ao_a_pins>;
diff --git a/arch/arm/boot/dts/meson8b-odroidc1.dts b/arch/arm/boot/dts/meson8b-odroidc1.dts
index e50f1a1..a060c84 100644
--- a/arch/arm/boot/dts/meson8b-odroidc1.dts
+++ b/arch/arm/boot/dts/meson8b-odroidc1.dts
@@ -71,6 +71,14 @@
 	};
 };
 
+&mmc0 {
+	status = "okay";
+	pinctrl-names = "sdio_b";
+	pinctrl-0 = <&mmc0_sd_b_pins>;
+	meson,sd-port = <1>;
+	broken-cd;
+};
+
 &uart_AO {
 	status = "okay";
 	pinctrl-0 = <&uart_ao_a_pins>;
diff --git a/arch/arm/boot/dts/meson8b.dtsi b/arch/arm/boot/dts/meson8b.dtsi
index 8bad557..25d795c 100644
--- a/arch/arm/boot/dts/meson8b.dtsi
+++ b/arch/arm/boot/dts/meson8b.dtsi
@@ -187,6 +187,22 @@
 					function = "uart_ao";
 				};
 			};
+
+			mmc0_sd_b_pins: mmc0_sd_b {
+				mux {
+					groups = "sd_d1_b", "sd_d0_b", "sd_clk_b", "sd_cmd_b",
+						 "sd_d3_b", "sd_d2_b";
+					function = "sd_b";
+				};
+			};
+		};
+
+		mmc0: mmc@c1108c20 {
+			compatible = "amlogic,meson-mmc";
+			reg = <0xc1108c20 0x20>;
+			interrupts = <0 28 1>;
+			clocks = <&clkc CLKID_CLK81>;
+			status = "disabled";
 		};
 	};
 }; /* end of / */
-- 
1.9.1

--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

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

* [PATCH v5 3/4] ARM: dts: meson8b: Add MMC nodes
@ 2016-02-27 18:01     ` Carlo Caione
  0 siblings, 0 replies; 24+ messages in thread
From: Carlo Caione @ 2016-02-27 18:01 UTC (permalink / raw)
  To: linux-arm-kernel

From: Carlo Caione <carlo@endlessm.com>

Enable the MMC for the Meson8b platforms.

Signed-off-by: Carlo Caione <carlo@endlessm.com>
---
 arch/arm/boot/dts/meson8b-mxq.dts      |  8 ++++++++
 arch/arm/boot/dts/meson8b-odroidc1.dts |  8 ++++++++
 arch/arm/boot/dts/meson8b.dtsi         | 16 ++++++++++++++++
 3 files changed, 32 insertions(+)

diff --git a/arch/arm/boot/dts/meson8b-mxq.dts b/arch/arm/boot/dts/meson8b-mxq.dts
index c7fdaea..5c533a6 100644
--- a/arch/arm/boot/dts/meson8b-mxq.dts
+++ b/arch/arm/boot/dts/meson8b-mxq.dts
@@ -60,6 +60,14 @@
 	};
 };
 
+&mmc0 {
+	status = "okay";
+	pinctrl-names = "sdio_b";
+	pinctrl-0 = <&mmc0_sd_b_pins>;
+	meson,sd-port = <1>;
+	broken-cd;
+};
+
 &uart_AO {
 	status = "okay";
 	pinctrl-0 = <&uart_ao_a_pins>;
diff --git a/arch/arm/boot/dts/meson8b-odroidc1.dts b/arch/arm/boot/dts/meson8b-odroidc1.dts
index e50f1a1..a060c84 100644
--- a/arch/arm/boot/dts/meson8b-odroidc1.dts
+++ b/arch/arm/boot/dts/meson8b-odroidc1.dts
@@ -71,6 +71,14 @@
 	};
 };
 
+&mmc0 {
+	status = "okay";
+	pinctrl-names = "sdio_b";
+	pinctrl-0 = <&mmc0_sd_b_pins>;
+	meson,sd-port = <1>;
+	broken-cd;
+};
+
 &uart_AO {
 	status = "okay";
 	pinctrl-0 = <&uart_ao_a_pins>;
diff --git a/arch/arm/boot/dts/meson8b.dtsi b/arch/arm/boot/dts/meson8b.dtsi
index 8bad557..25d795c 100644
--- a/arch/arm/boot/dts/meson8b.dtsi
+++ b/arch/arm/boot/dts/meson8b.dtsi
@@ -187,6 +187,22 @@
 					function = "uart_ao";
 				};
 			};
+
+			mmc0_sd_b_pins: mmc0_sd_b {
+				mux {
+					groups = "sd_d1_b", "sd_d0_b", "sd_clk_b", "sd_cmd_b",
+						 "sd_d3_b", "sd_d2_b";
+					function = "sd_b";
+				};
+			};
+		};
+
+		mmc0: mmc at c1108c20 {
+			compatible = "amlogic,meson-mmc";
+			reg = <0xc1108c20 0x20>;
+			interrupts = <0 28 1>;
+			clocks = <&clkc CLKID_CLK81>;
+			status = "disabled";
 		};
 	};
 }; /* end of / */
-- 
1.9.1

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

* [PATCH v5 4/4] ARM: multi_v7_defconfig: Add Amlogic Meson MMC support
  2016-02-27 18:01 ` Carlo Caione
@ 2016-02-27 18:01     ` Carlo Caione
  -1 siblings, 0 replies; 24+ messages in thread
From: Carlo Caione @ 2016-02-27 18:01 UTC (permalink / raw)
  To: ulf.hansson-QSEj5FYQhm4dnm+yROfE0A,
	robh+dt-DgEjT+Ai2ygdnm+yROfE0A,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	linux-lFZ/pmaqli7XmaaqVzeoHQ, devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-meson-/JYPxA39Uh5TLH3MbocFFw, linux-6IF/jdPJHihWk0Htik3J/w
  Cc: Carlo Caione

From: Carlo Caione <carlo-6IF/jdPJHihWk0Htik3J/w@public.gmane.org>

Signed-off-by: Carlo Caione <carlo-6IF/jdPJHihWk0Htik3J/w@public.gmane.org>
---
 arch/arm/configs/multi_v7_defconfig | 1 +
 1 file changed, 1 insertion(+)

diff --git a/arch/arm/configs/multi_v7_defconfig b/arch/arm/configs/multi_v7_defconfig
index 314f6be..113b234 100644
--- a/arch/arm/configs/multi_v7_defconfig
+++ b/arch/arm/configs/multi_v7_defconfig
@@ -633,6 +633,7 @@ CONFIG_MMC_DW_IDMAC=y
 CONFIG_MMC_DW_PLTFM=y
 CONFIG_MMC_DW_EXYNOS=y
 CONFIG_MMC_DW_ROCKCHIP=y
+CONFIG_MMC_MESON=y
 CONFIG_MMC_SH_MMCIF=y
 CONFIG_MMC_SUNXI=y
 CONFIG_NEW_LEDS=y
-- 
1.9.1

--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

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

* [PATCH v5 4/4] ARM: multi_v7_defconfig: Add Amlogic Meson MMC support
@ 2016-02-27 18:01     ` Carlo Caione
  0 siblings, 0 replies; 24+ messages in thread
From: Carlo Caione @ 2016-02-27 18:01 UTC (permalink / raw)
  To: linux-arm-kernel

From: Carlo Caione <carlo@endlessm.com>

Signed-off-by: Carlo Caione <carlo@endlessm.com>
---
 arch/arm/configs/multi_v7_defconfig | 1 +
 1 file changed, 1 insertion(+)

diff --git a/arch/arm/configs/multi_v7_defconfig b/arch/arm/configs/multi_v7_defconfig
index 314f6be..113b234 100644
--- a/arch/arm/configs/multi_v7_defconfig
+++ b/arch/arm/configs/multi_v7_defconfig
@@ -633,6 +633,7 @@ CONFIG_MMC_DW_IDMAC=y
 CONFIG_MMC_DW_PLTFM=y
 CONFIG_MMC_DW_EXYNOS=y
 CONFIG_MMC_DW_ROCKCHIP=y
+CONFIG_MMC_MESON=y
 CONFIG_MMC_SH_MMCIF=y
 CONFIG_MMC_SUNXI=y
 CONFIG_NEW_LEDS=y
-- 
1.9.1

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

* Re: [PATCH v5 2/4] mmc: meson: Add driver for the SD/MMC host found on Amlogic Meson SoCs
  2016-02-27 18:01     ` Carlo Caione
@ 2016-03-02  2:14         ` Andreas Färber
  -1 siblings, 0 replies; 24+ messages in thread
From: Andreas Färber @ 2016-03-02  2:14 UTC (permalink / raw)
  To: Carlo Caione, linux-meson-/JYPxA39Uh5TLH3MbocFFw
  Cc: ulf.hansson-QSEj5FYQhm4dnm+yROfE0A,
	robh+dt-DgEjT+Ai2ygdnm+yROfE0A,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	linux-lFZ/pmaqli7XmaaqVzeoHQ, devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-6IF/jdPJHihWk0Htik3J/w, Carlo Caione

Hi Carlo,

Am 27.02.2016 um 19:01 schrieb Carlo Caione:
> Add a driver for the SD/MMC host found on the Amlogic Meson SoCs. This
> is an MMC controller which provides an interface between the application
> processor and various memory cards. It supports the SD specification
> v2.0 and the eMMC specification v4.41.
> 
> Signed-off-by: Carlo Caione <carlo-6IF/jdPJHihWk0Htik3J/w@public.gmane.org>

Enabling this driver on top of my v2 arm64 gxbb series, I get:

  CC      drivers/mmc/host/meson-mmc.o
drivers/mmc/host/meson-mmc.c: In function 'meson_mmc_probe':
drivers/mmc/host/meson-mmc.c:471:12: error: implicit declaration of
function 'devm_pinctrl_get' [-Werror=implicit-function-declaration]
  pinctrl = devm_pinctrl_get(&pdev->dev);
            ^
drivers/mmc/host/meson-mmc.c:471:10: warning: assignment makes pointer
from integer without a cast [-Wint-conversion]
  pinctrl = devm_pinctrl_get(&pdev->dev);
          ^
cc1: some warnings being treated as errors
scripts/Makefile.build:258: recipe for target
'drivers/mmc/host/meson-mmc.o' failed
make[3]: *** [drivers/mmc/host/meson-mmc.o] Error 1
scripts/Makefile.build:407: recipe for target 'drivers/mmc/host' failed
make[2]: *** [drivers/mmc/host] Error 2
scripts/Makefile.build:407: recipe for target 'drivers/mmc' failed
make[1]: *** [drivers/mmc] Error 2
Makefile:959: recipe for target 'drivers' failed
make: *** [drivers] Error 2

Either this is missing a Kconfig dependency on PINCTRL, or should be
using #ifdef CONFIG_PINCTRL or some other guard.

For gxbb we could just ignore this in the hopes that Nicolas will have a
working pinctrl driver soon, but it might reappear for COMPILE_TEST.

Regards,
Andreas

-- 
SUSE Linux GmbH, Maxfeldstr. 5, 90409 Nürnberg, Germany
GF: Felix Imendörffer, Jane Smithard, Graham Norton; HRB 21284 (AG Nürnberg)
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

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

* [PATCH v5 2/4] mmc: meson: Add driver for the SD/MMC host found on Amlogic Meson SoCs
@ 2016-03-02  2:14         ` Andreas Färber
  0 siblings, 0 replies; 24+ messages in thread
From: Andreas Färber @ 2016-03-02  2:14 UTC (permalink / raw)
  To: linux-arm-kernel

Hi Carlo,

Am 27.02.2016 um 19:01 schrieb Carlo Caione:
> Add a driver for the SD/MMC host found on the Amlogic Meson SoCs. This
> is an MMC controller which provides an interface between the application
> processor and various memory cards. It supports the SD specification
> v2.0 and the eMMC specification v4.41.
> 
> Signed-off-by: Carlo Caione <carlo@endlessm.com>

Enabling this driver on top of my v2 arm64 gxbb series, I get:

  CC      drivers/mmc/host/meson-mmc.o
drivers/mmc/host/meson-mmc.c: In function 'meson_mmc_probe':
drivers/mmc/host/meson-mmc.c:471:12: error: implicit declaration of
function 'devm_pinctrl_get' [-Werror=implicit-function-declaration]
  pinctrl = devm_pinctrl_get(&pdev->dev);
            ^
drivers/mmc/host/meson-mmc.c:471:10: warning: assignment makes pointer
from integer without a cast [-Wint-conversion]
  pinctrl = devm_pinctrl_get(&pdev->dev);
          ^
cc1: some warnings being treated as errors
scripts/Makefile.build:258: recipe for target
'drivers/mmc/host/meson-mmc.o' failed
make[3]: *** [drivers/mmc/host/meson-mmc.o] Error 1
scripts/Makefile.build:407: recipe for target 'drivers/mmc/host' failed
make[2]: *** [drivers/mmc/host] Error 2
scripts/Makefile.build:407: recipe for target 'drivers/mmc' failed
make[1]: *** [drivers/mmc] Error 2
Makefile:959: recipe for target 'drivers' failed
make: *** [drivers] Error 2

Either this is missing a Kconfig dependency on PINCTRL, or should be
using #ifdef CONFIG_PINCTRL or some other guard.

For gxbb we could just ignore this in the hopes that Nicolas will have a
working pinctrl driver soon, but it might reappear for COMPILE_TEST.

Regards,
Andreas

-- 
SUSE Linux GmbH, Maxfeldstr. 5, 90409 N?rnberg, Germany
GF: Felix Imend?rffer, Jane Smithard, Graham Norton; HRB 21284 (AG N?rnberg)

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

* Re: [PATCH v5 2/4] mmc: meson: Add driver for the SD/MMC host found on Amlogic Meson SoCs
  2016-03-02  2:14         ` Andreas Färber
@ 2016-03-02  8:11             ` Carlo Caione
  -1 siblings, 0 replies; 24+ messages in thread
From: Carlo Caione @ 2016-03-02  8:11 UTC (permalink / raw)
  To: Andreas Färber
  Cc: Carlo Caione, linux-meson, Ulf Hansson,
	robh+dt-DgEjT+Ai2ygdnm+yROfE0A, linux-arm-kernel,
	Russell King - ARM Linux, devicetree,
	linux-6IF/jdPJHihWk0Htik3J/w, Carlo Caione

On Wed, Mar 2, 2016 at 3:14 AM, Andreas Färber <afaerber-l3A5Bk7waGM@public.gmane.org> wrote:
> Hi Carlo,
>
> Am 27.02.2016 um 19:01 schrieb Carlo Caione:
>> Add a driver for the SD/MMC host found on the Amlogic Meson SoCs. This
>> is an MMC controller which provides an interface between the application
>> processor and various memory cards. It supports the SD specification
>> v2.0 and the eMMC specification v4.41.
>>
>> Signed-off-by: Carlo Caione <carlo-6IF/jdPJHihWk0Htik3J/w@public.gmane.org>
>
> Enabling this driver on top of my v2 arm64 gxbb series, I get:
>
>   CC      drivers/mmc/host/meson-mmc.o
> drivers/mmc/host/meson-mmc.c: In function 'meson_mmc_probe':
> drivers/mmc/host/meson-mmc.c:471:12: error: implicit declaration of
> function 'devm_pinctrl_get' [-Werror=implicit-function-declaration]
>   pinctrl = devm_pinctrl_get(&pdev->dev);
>             ^
> drivers/mmc/host/meson-mmc.c:471:10: warning: assignment makes pointer
> from integer without a cast [-Wint-conversion]
>   pinctrl = devm_pinctrl_get(&pdev->dev);
>           ^
> cc1: some warnings being treated as errors
> scripts/Makefile.build:258: recipe for target
> 'drivers/mmc/host/meson-mmc.o' failed
> make[3]: *** [drivers/mmc/host/meson-mmc.o] Error 1
> scripts/Makefile.build:407: recipe for target 'drivers/mmc/host' failed
> make[2]: *** [drivers/mmc/host] Error 2
> scripts/Makefile.build:407: recipe for target 'drivers/mmc' failed
> make[1]: *** [drivers/mmc] Error 2
> Makefile:959: recipe for target 'drivers' failed
> make: *** [drivers] Error 2
>
> Either this is missing a Kconfig dependency on PINCTRL, or should be
> using #ifdef CONFIG_PINCTRL or some other guard.

I think that we can actually drop the whole devm_pinctrl_get().
I'll wait for some comments from Ulf before submitting a fix.

> For gxbb we could just ignore this in the hopes that Nicolas will have a
> working pinctrl driver soon, but it might reappear for COMPILE_TEST.

AFAIR from a discussion with Amlogic it seems that they totally
changed the SD controller in the S905 so probably we will need a new
driver for the gxbb. At this point I also wonder if it's not worthy it
already to change the compatible for this driver to something more
specific for Meson8 / Meson8b.
Probably we will have some more news when the documentation will be available.

Thank you for testing this,

-- 
Carlo Caione
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

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

* [PATCH v5 2/4] mmc: meson: Add driver for the SD/MMC host found on Amlogic Meson SoCs
@ 2016-03-02  8:11             ` Carlo Caione
  0 siblings, 0 replies; 24+ messages in thread
From: Carlo Caione @ 2016-03-02  8:11 UTC (permalink / raw)
  To: linux-arm-kernel

On Wed, Mar 2, 2016 at 3:14 AM, Andreas F?rber <afaerber@suse.de> wrote:
> Hi Carlo,
>
> Am 27.02.2016 um 19:01 schrieb Carlo Caione:
>> Add a driver for the SD/MMC host found on the Amlogic Meson SoCs. This
>> is an MMC controller which provides an interface between the application
>> processor and various memory cards. It supports the SD specification
>> v2.0 and the eMMC specification v4.41.
>>
>> Signed-off-by: Carlo Caione <carlo@endlessm.com>
>
> Enabling this driver on top of my v2 arm64 gxbb series, I get:
>
>   CC      drivers/mmc/host/meson-mmc.o
> drivers/mmc/host/meson-mmc.c: In function 'meson_mmc_probe':
> drivers/mmc/host/meson-mmc.c:471:12: error: implicit declaration of
> function 'devm_pinctrl_get' [-Werror=implicit-function-declaration]
>   pinctrl = devm_pinctrl_get(&pdev->dev);
>             ^
> drivers/mmc/host/meson-mmc.c:471:10: warning: assignment makes pointer
> from integer without a cast [-Wint-conversion]
>   pinctrl = devm_pinctrl_get(&pdev->dev);
>           ^
> cc1: some warnings being treated as errors
> scripts/Makefile.build:258: recipe for target
> 'drivers/mmc/host/meson-mmc.o' failed
> make[3]: *** [drivers/mmc/host/meson-mmc.o] Error 1
> scripts/Makefile.build:407: recipe for target 'drivers/mmc/host' failed
> make[2]: *** [drivers/mmc/host] Error 2
> scripts/Makefile.build:407: recipe for target 'drivers/mmc' failed
> make[1]: *** [drivers/mmc] Error 2
> Makefile:959: recipe for target 'drivers' failed
> make: *** [drivers] Error 2
>
> Either this is missing a Kconfig dependency on PINCTRL, or should be
> using #ifdef CONFIG_PINCTRL or some other guard.

I think that we can actually drop the whole devm_pinctrl_get().
I'll wait for some comments from Ulf before submitting a fix.

> For gxbb we could just ignore this in the hopes that Nicolas will have a
> working pinctrl driver soon, but it might reappear for COMPILE_TEST.

AFAIR from a discussion with Amlogic it seems that they totally
changed the SD controller in the S905 so probably we will need a new
driver for the gxbb. At this point I also wonder if it's not worthy it
already to change the compatible for this driver to something more
specific for Meson8 / Meson8b.
Probably we will have some more news when the documentation will be available.

Thank you for testing this,

-- 
Carlo Caione

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

* Re: [PATCH v5 1/4] mmc: meson: Document Amlogic Meson MMC DT bindings
  2016-02-27 18:01     ` Carlo Caione
@ 2016-03-03 22:17         ` Rob Herring
  -1 siblings, 0 replies; 24+ messages in thread
From: Rob Herring @ 2016-03-03 22:17 UTC (permalink / raw)
  To: Carlo Caione
  Cc: ulf.hansson-QSEj5FYQhm4dnm+yROfE0A,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	linux-lFZ/pmaqli7XmaaqVzeoHQ, devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-meson-/JYPxA39Uh5TLH3MbocFFw, linux-6IF/jdPJHihWk0Htik3J/w,
	Carlo Caione

On Sat, Feb 27, 2016 at 07:01:45PM +0100, Carlo Caione wrote:
> From: Carlo Caione <carlo-6IF/jdPJHihWk0Htik3J/w@public.gmane.org>
> 
> Signed-off-by: Carlo Caione <carlo-6IF/jdPJHihWk0Htik3J/w@public.gmane.org>
> ---
>  .../devicetree/bindings/mmc/meson-mmc.txt          | 30 ++++++++++++++++++++++
>  1 file changed, 30 insertions(+)
>  create mode 100644 Documentation/devicetree/bindings/mmc/meson-mmc.txt
> 
> diff --git a/Documentation/devicetree/bindings/mmc/meson-mmc.txt b/Documentation/devicetree/bindings/mmc/meson-mmc.txt
> new file mode 100644
> index 0000000..328157e
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/mmc/meson-mmc.txt
> @@ -0,0 +1,30 @@
> +* Amlogic Meson MMC controller
> +
> +The highspeed MMC host controller on Amlogic SoCs provides an interface
> +for MMC, SD, SDIO and SDHC types of memory cards.
> +
> +Supported maximum speeds are the ones of the eMMC standard 4.41 as well
> +as the speed of SD standard 2.0.
> +
> +Required properties:
> + - compatible : "amlogic,meson-mmc"
> + - reg : mmc controller base registers
> + - interrupts : mmc controller interrupt
> + - clocks : phandle to clock provider
> + - pinctrl-names : should contain "sdio_a" or "sdio_b"
> + - pinctrl-0: Should specify pin control groups used for this controller
> +
> +Optional properties:
> + - meson,sd-port : 0 for port A, 1 for port B

This is different than the pinctrl-names? It needs a better description 
including what is the default if absent.

> + - for cd, bus-width and additional generic mmc parameters
> +   please refer to mmc.txt within this directory
> +
> +Examples:
> +	mmc0: mmc@c1108c20 {
> +		pinctrl-names = "sdio_b";
> +		pinctrl-0 = <&mmc0_sd_b_pins>;
> +		compatible = "amlogic,meson-mmc";
> +		reg = <0xc1108c20 0x20>;
> +		interrupts = <0 28 1>;
> +		clocks = <&clkc CLKID_CLK81>;
> +	};
> -- 
> 1.9.1
> 
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

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

* [PATCH v5 1/4] mmc: meson: Document Amlogic Meson MMC DT bindings
@ 2016-03-03 22:17         ` Rob Herring
  0 siblings, 0 replies; 24+ messages in thread
From: Rob Herring @ 2016-03-03 22:17 UTC (permalink / raw)
  To: linux-arm-kernel

On Sat, Feb 27, 2016 at 07:01:45PM +0100, Carlo Caione wrote:
> From: Carlo Caione <carlo@endlessm.com>
> 
> Signed-off-by: Carlo Caione <carlo@endlessm.com>
> ---
>  .../devicetree/bindings/mmc/meson-mmc.txt          | 30 ++++++++++++++++++++++
>  1 file changed, 30 insertions(+)
>  create mode 100644 Documentation/devicetree/bindings/mmc/meson-mmc.txt
> 
> diff --git a/Documentation/devicetree/bindings/mmc/meson-mmc.txt b/Documentation/devicetree/bindings/mmc/meson-mmc.txt
> new file mode 100644
> index 0000000..328157e
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/mmc/meson-mmc.txt
> @@ -0,0 +1,30 @@
> +* Amlogic Meson MMC controller
> +
> +The highspeed MMC host controller on Amlogic SoCs provides an interface
> +for MMC, SD, SDIO and SDHC types of memory cards.
> +
> +Supported maximum speeds are the ones of the eMMC standard 4.41 as well
> +as the speed of SD standard 2.0.
> +
> +Required properties:
> + - compatible : "amlogic,meson-mmc"
> + - reg : mmc controller base registers
> + - interrupts : mmc controller interrupt
> + - clocks : phandle to clock provider
> + - pinctrl-names : should contain "sdio_a" or "sdio_b"
> + - pinctrl-0: Should specify pin control groups used for this controller
> +
> +Optional properties:
> + - meson,sd-port : 0 for port A, 1 for port B

This is different than the pinctrl-names? It needs a better description 
including what is the default if absent.

> + - for cd, bus-width and additional generic mmc parameters
> +   please refer to mmc.txt within this directory
> +
> +Examples:
> +	mmc0: mmc at c1108c20 {
> +		pinctrl-names = "sdio_b";
> +		pinctrl-0 = <&mmc0_sd_b_pins>;
> +		compatible = "amlogic,meson-mmc";
> +		reg = <0xc1108c20 0x20>;
> +		interrupts = <0 28 1>;
> +		clocks = <&clkc CLKID_CLK81>;
> +	};
> -- 
> 1.9.1
> 

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

* Re: [PATCH v5 1/4] mmc: meson: Document Amlogic Meson MMC DT bindings
  2016-03-03 22:17         ` Rob Herring
@ 2016-03-04  8:11           ` Carlo Caione
  -1 siblings, 0 replies; 24+ messages in thread
From: Carlo Caione @ 2016-03-04  8:11 UTC (permalink / raw)
  To: Rob Herring
  Cc: Carlo Caione, Ulf Hansson, linux-arm-kernel,
	Russell King - ARM Linux, devicetree, linux-meson,
	linux-6IF/jdPJHihWk0Htik3J/w, Carlo Caione

On Thu, Mar 3, 2016 at 11:17 PM, Rob Herring <robh-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org> wrote:
> On Sat, Feb 27, 2016 at 07:01:45PM +0100, Carlo Caione wrote:
>> From: Carlo Caione <carlo-6IF/jdPJHihWk0Htik3J/w@public.gmane.org>
>>
>> Signed-off-by: Carlo Caione <carlo-6IF/jdPJHihWk0Htik3J/w@public.gmane.org>
>> ---
>>  .../devicetree/bindings/mmc/meson-mmc.txt          | 30 ++++++++++++++++++++++
>>  1 file changed, 30 insertions(+)
>>  create mode 100644 Documentation/devicetree/bindings/mmc/meson-mmc.txt
>>
>> diff --git a/Documentation/devicetree/bindings/mmc/meson-mmc.txt b/Documentation/devicetree/bindings/mmc/meson-mmc.txt
>> new file mode 100644
>> index 0000000..328157e
>> --- /dev/null
>> +++ b/Documentation/devicetree/bindings/mmc/meson-mmc.txt
>> @@ -0,0 +1,30 @@
>> +* Amlogic Meson MMC controller
>> +
>> +The highspeed MMC host controller on Amlogic SoCs provides an interface
>> +for MMC, SD, SDIO and SDHC types of memory cards.
>> +
>> +Supported maximum speeds are the ones of the eMMC standard 4.41 as well
>> +as the speed of SD standard 2.0.
>> +
>> +Required properties:
>> + - compatible : "amlogic,meson-mmc"
>> + - reg : mmc controller base registers
>> + - interrupts : mmc controller interrupt
>> + - clocks : phandle to clock provider
>> + - pinctrl-names : should contain "sdio_a" or "sdio_b"
>> + - pinctrl-0: Should specify pin control groups used for this controller
>> +
>> +Optional properties:
>> + - meson,sd-port : 0 for port A, 1 for port B
>
> This is different than the pinctrl-names? It needs a better description
> including what is the default if absent.
>

This was already discussed here
http://www.spinics.net/lists/linux-mmc/msg34407.html.
In the previous version (V4) I used pinctrl-names to select the
correct port but discussing with Ulf we decided to switch back to have
a new property in the DTS.
About what this value is, it is a bit up to our interpretation. We use
this value to setup the SDIO_PORT_SEL register and in the register
description in the documentation I read only "SDIO port selection. 0:
SDIO A; 1: SDIO B".
So I'm assuming this is somehow related to the muxing / pin controller
configuration but probably it's better to stay on the safe side and
just have a new property to setup this value.

I'll add the new default value in the next version.

-- 
Carlo Caione
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

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

* [PATCH v5 1/4] mmc: meson: Document Amlogic Meson MMC DT bindings
@ 2016-03-04  8:11           ` Carlo Caione
  0 siblings, 0 replies; 24+ messages in thread
From: Carlo Caione @ 2016-03-04  8:11 UTC (permalink / raw)
  To: linux-arm-kernel

On Thu, Mar 3, 2016 at 11:17 PM, Rob Herring <robh@kernel.org> wrote:
> On Sat, Feb 27, 2016 at 07:01:45PM +0100, Carlo Caione wrote:
>> From: Carlo Caione <carlo@endlessm.com>
>>
>> Signed-off-by: Carlo Caione <carlo@endlessm.com>
>> ---
>>  .../devicetree/bindings/mmc/meson-mmc.txt          | 30 ++++++++++++++++++++++
>>  1 file changed, 30 insertions(+)
>>  create mode 100644 Documentation/devicetree/bindings/mmc/meson-mmc.txt
>>
>> diff --git a/Documentation/devicetree/bindings/mmc/meson-mmc.txt b/Documentation/devicetree/bindings/mmc/meson-mmc.txt
>> new file mode 100644
>> index 0000000..328157e
>> --- /dev/null
>> +++ b/Documentation/devicetree/bindings/mmc/meson-mmc.txt
>> @@ -0,0 +1,30 @@
>> +* Amlogic Meson MMC controller
>> +
>> +The highspeed MMC host controller on Amlogic SoCs provides an interface
>> +for MMC, SD, SDIO and SDHC types of memory cards.
>> +
>> +Supported maximum speeds are the ones of the eMMC standard 4.41 as well
>> +as the speed of SD standard 2.0.
>> +
>> +Required properties:
>> + - compatible : "amlogic,meson-mmc"
>> + - reg : mmc controller base registers
>> + - interrupts : mmc controller interrupt
>> + - clocks : phandle to clock provider
>> + - pinctrl-names : should contain "sdio_a" or "sdio_b"
>> + - pinctrl-0: Should specify pin control groups used for this controller
>> +
>> +Optional properties:
>> + - meson,sd-port : 0 for port A, 1 for port B
>
> This is different than the pinctrl-names? It needs a better description
> including what is the default if absent.
>

This was already discussed here
http://www.spinics.net/lists/linux-mmc/msg34407.html.
In the previous version (V4) I used pinctrl-names to select the
correct port but discussing with Ulf we decided to switch back to have
a new property in the DTS.
About what this value is, it is a bit up to our interpretation. We use
this value to setup the SDIO_PORT_SEL register and in the register
description in the documentation I read only "SDIO port selection. 0:
SDIO A; 1: SDIO B".
So I'm assuming this is somehow related to the muxing / pin controller
configuration but probably it's better to stay on the safe side and
just have a new property to setup this value.

I'll add the new default value in the next version.

-- 
Carlo Caione

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

* Re: [PATCH v5 2/4] mmc: meson: Add driver for the SD/MMC host found on Amlogic Meson SoCs
  2016-02-27 18:01     ` Carlo Caione
@ 2016-04-18 13:47         ` Ulf Hansson
  -1 siblings, 0 replies; 24+ messages in thread
From: Ulf Hansson @ 2016-04-18 13:47 UTC (permalink / raw)
  To: Carlo Caione
  Cc: Rob Herring, linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	Russell King - ARM Linux, devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-meson-/JYPxA39Uh5TLH3MbocFFw, linux-6IF/jdPJHihWk0Htik3J/w,
	Carlo Caione

On 27 February 2016 at 19:01, Carlo Caione <carlo-KA+7E9HrN00dnm+yROfE0A@public.gmane.org> wrote:
> From: Carlo Caione <carlo-6IF/jdPJHihWk0Htik3J/w@public.gmane.org>
>
> Add a driver for the SD/MMC host found on the Amlogic Meson SoCs. This
> is an MMC controller which provides an interface between the application
> processor and various memory cards. It supports the SD specification
> v2.0 and the eMMC specification v4.41.
>
> Signed-off-by: Carlo Caione <carlo-6IF/jdPJHihWk0Htik3J/w@public.gmane.org>

Sorry for the delay.

Apparently this slipped through my mmc mail filters, as I think you
forgotten to post this to linux-mmc.

[...]

> +static void meson_mmc_request(struct mmc_host *mmc, struct mmc_request *mrq)
> +{
> +       struct meson_mmc_host *host = mmc_priv(mmc);
> +       struct mmc_command *cmd = mrq->cmd;
> +       struct mmc_data *data = mrq->data;
> +       unsigned long flags;
> +       int ret;
> +
> +       spin_lock_irqsave(&host->lock, flags);

I would advise you to re-visit the deployment of the locking in this
driver. It doesn't seem correct.

For example, keeping IRQ disabled while mapping DMA buffers isn't a
good idea, as it may cause the IRQs to be disabled for quite a while.

> +
> +       if (host->error) {
> +               cmd->error = host->error;
> +               spin_unlock_irqrestore(&host->lock, flags);
> +               mmc_request_done(mmc, mrq);
> +               return;
> +       }
> +
> +       if (data) {
> +               ret = meson_mmc_map_dma(host, data, data->flags);
> +               if (ret < 0) {
> +                       dev_err(mmc_dev(mmc), "map DMA failed\n");
> +                       cmd->error = ret;
> +                       data->error = ret;
> +                       spin_unlock_irqrestore(&host->lock, flags);
> +                       mmc_request_done(mmc, mrq);
> +                       return;
> +               }
> +               writel(sg_dma_address(data->sg), host->base + SDIO_ADDR);
> +       }
> +
> +       host->mrq = mrq;
> +       meson_mmc_start_cmd(mmc, mrq->cmd);
> +
> +       spin_unlock_irqrestore(&host->lock, flags);
> +
> +       schedule_delayed_work(&host->timeout_work, host->timeout);
> +}
> +
> +static irqreturn_t meson_mmc_irq(int irq, void *data)
> +{
> +       struct meson_mmc_host *host = (void *) data;
> +       struct mmc_request *mrq = host->mrq;
> +       u32 irqs;
> +
> +       irqs = readl(host->base + SDIO_IRQS);
> +       if (mrq && (irqs & REG_IRQS_CMD_INT))
> +               return IRQ_WAKE_THREAD;

As you don't use the IRQF_ONESHOT flag, this hard IRQ handler may be
invoked while the threaded handler runs.

Although, I don't see any protection of the host->mrq pointer etc,
don't you need that?

> +
> +       return IRQ_HANDLED;
> +}
> +
> +void meson_mmc_read_response(struct meson_mmc_host *host)
> +{
> +       struct mmc_command *cmd = host->mrq->cmd;
> +       u32 mult;
> +       int i, resp[4] = { 0 };
> +
> +       mult = readl(host->base + SDIO_MULT);
> +       mult |= REG_MULT_WR_RD_OUT_IND;
> +       mult &= ~(REG_MULT_RD_INDEX_M << REG_MULT_RD_INDEX_S);
> +       writel(mult, host->base + SDIO_MULT);
> +
> +       if (cmd->flags & MMC_RSP_136) {
> +               for (i = 0; i <= 3; i++)
> +                       resp[3 - i] = readl(host->base + SDIO_ARGU);
> +               cmd->resp[0] = (resp[0] << 8) | ((resp[1] >> 24) & 0xff);
> +               cmd->resp[1] = (resp[1] << 8) | ((resp[2] >> 24) & 0xff);
> +               cmd->resp[2] = (resp[2] << 8) | ((resp[3] >> 24) & 0xff);
> +               cmd->resp[3] = (resp[3] << 8);
> +       } else if (cmd->flags & MMC_RSP_PRESENT) {
> +               cmd->resp[0] = readl(host->base + SDIO_ARGU);
> +       }
> +}
> +
> +static irqreturn_t meson_mmc_irq_thread(int irq, void *irq_data)
> +{
> +       struct meson_mmc_host *host = (void *) irq_data;
> +       struct mmc_data *data;
> +       unsigned long flags;
> +       struct mmc_request *mrq;
> +       u32 irqs, send;
> +
> +       cancel_delayed_work_sync(&host->timeout_work);
> +       spin_lock_irqsave(&host->lock, flags);

You are disabling IRQs during the entire execution of this threaded
IRQ handler, that's not a good behaviour as it may be disabled for
quite a while.

Although, perhaps you do this to avoid needing to protect host->mrq in
the hard IRQ handler!?

> +
> +       mrq = host->mrq;
> +       data = mrq->data;
> +
> +       if (!mrq) {
> +               spin_unlock_irqrestore(&host->lock, flags);
> +               return IRQ_HANDLED;
> +       }
> +
> +       if (host->cmd_is_stop)
> +               goto out;
> +
> +       irqs = readl(host->base + SDIO_IRQS);
> +       send = readl(host->base + SDIO_SEND);
> +
> +       mrq->cmd->error = 0;
> +
> +       if (!data) {
> +               if (!((irqs & REG_IRQS_RESP_CRC7) ||
> +                     (send & REG_SEND_RESP_NO_CRC7)))
> +                       mrq->cmd->error = -EILSEQ;
> +               else
> +                       meson_mmc_read_response(host);
> +       } else {
> +               if (!((irqs & REG_IRQS_RD_CRC16) ||
> +                     (irqs & REG_IRQS_WR_CRC16))) {
> +                       mrq->cmd->error = -EILSEQ;
> +               } else {
> +                       data->bytes_xfered = data->blksz * data->blocks;
> +                       dma_unmap_sg(mmc_dev(host->mmc), data->sg, data->sg_len,
> +                                    ((data->flags & MMC_DATA_READ) ?
> +                                    DMA_FROM_DEVICE : DMA_TO_DEVICE));
> +               }
> +       }
> +
> +       if (mrq->stop) {
> +               host->cmd_is_stop = true;
> +               meson_mmc_start_cmd(host->mmc, mrq->stop);
> +               spin_unlock_irqrestore(&host->lock, flags);
> +               return IRQ_HANDLED;
> +       }
> +
> +out:
> +       host->cmd_is_stop = false;
> +       host->mrq = NULL;
> +       spin_unlock_irqrestore(&host->lock, flags);
> +       mmc_request_done(host->mmc, mrq);
> +
> +       return IRQ_HANDLED;
> +}
> +

[...]

> +static int meson_mmc_probe(struct platform_device *pdev)
> +{
> +       struct mmc_host *mmc;
> +       struct meson_mmc_host *host;
> +       struct pinctrl *pinctrl;
> +       struct resource *res;
> +       int ret, irq;
> +       u32 port;
> +
> +       mmc = mmc_alloc_host(sizeof(struct meson_mmc_host), &pdev->dev);
> +       if (!mmc) {
> +               dev_err(&pdev->dev, "mmc alloc host failed\n");
> +               return -ENOMEM;
> +       }
> +
> +       host = mmc_priv(mmc);
> +       host->mmc = mmc;
> +       host->timeout = msecs_to_jiffies(10000);
> +       host->port = 0;
> +
> +       if (!of_property_read_u32(pdev->dev.of_node, "meson,sd-port", &port))
> +               host->port = port;
> +
> +
> +       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> +       host->base = devm_ioremap_resource(&pdev->dev, res);
> +       if (IS_ERR(host->base)) {
> +               ret = PTR_ERR(host->base);
> +               goto error_free_host;
> +       }
> +
> +       irq = platform_get_irq(pdev, 0);
> +       ret = devm_request_threaded_irq(&pdev->dev, irq, meson_mmc_irq,
> +                                       meson_mmc_irq_thread, 0, "meson_mmc",

Is the IRQs level or edge triggered? In other words, will the hard IRQ
handler miss IRQs if you use IRQF_ONESHOT?

> +                                       host);
> +       if (ret)
> +               goto error_free_host;
> +
> +       host->clk = devm_clk_get(&pdev->dev, NULL);
> +       if (IS_ERR(host->clk)) {
> +               ret = PTR_ERR(host->clk);
> +               goto error_free_host;
> +       }
> +
> +       ret = clk_prepare_enable(host->clk);
> +       if (ret) {
> +               dev_err(&pdev->dev, "Enable clk error %d\n", ret);
> +               goto error_free_host;
> +       }
> +
> +       /* we do not support scatter lists in hardware */
> +       mmc->max_segs = 1;
> +       mmc->max_req_size = SDIO_BOUNCE_REQ_SIZE;
> +       mmc->max_seg_size = mmc->max_req_size;
> +       mmc->max_blk_count = 256;
> +       mmc->max_blk_size = mmc->max_req_size / mmc->max_blk_count;
> +       mmc->f_min = 300000;
> +       mmc->f_max = 50000000;
> +       mmc->caps |= MMC_CAP_4_BIT_DATA;
> +       mmc->caps |= MMC_CAP_MMC_HIGHSPEED | MMC_CAP_SD_HIGHSPEED;
> +       mmc->caps2 |= MMC_CAP2_NO_SDIO;
> +       mmc->ocr_avail = MMC_VDD_33_34;
> +       mmc->ops = &meson_mmc_ops;
> +
> +       spin_lock_init(&host->lock);
> +
> +       INIT_DELAYED_WORK(&host->timeout_work, meson_mmc_timeout);
> +
> +       pinctrl = devm_pinctrl_get(&pdev->dev);
> +       if (IS_ERR(pinctrl)) {
> +               ret = PTR_ERR(pinctrl);
> +               goto error;
> +       }
> +
> +       ret = mmc_of_parse(mmc);
> +       if (ret)
> +               goto error;
> +
> +       platform_set_drvdata(pdev, mmc);
> +
> +       ret = mmc_add_host(mmc);
> +       if (ret)
> +               goto error;
> +
> +       dev_info(&pdev->dev, "base:0x%p irq:%u port:%u\n",
> +                host->base, irq, host->port);
> +
> +       return 0;
> +
> +error:
> +       clk_disable_unprepare(host->clk);
> +error_free_host:
> +       mmc_free_host(mmc);
> +
> +       return ret;
> +}
> +

[...]

Kind regards
Uffe
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

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

* [PATCH v5 2/4] mmc: meson: Add driver for the SD/MMC host found on Amlogic Meson SoCs
@ 2016-04-18 13:47         ` Ulf Hansson
  0 siblings, 0 replies; 24+ messages in thread
From: Ulf Hansson @ 2016-04-18 13:47 UTC (permalink / raw)
  To: linux-arm-kernel

On 27 February 2016 at 19:01, Carlo Caione <carlo@caione.org> wrote:
> From: Carlo Caione <carlo@endlessm.com>
>
> Add a driver for the SD/MMC host found on the Amlogic Meson SoCs. This
> is an MMC controller which provides an interface between the application
> processor and various memory cards. It supports the SD specification
> v2.0 and the eMMC specification v4.41.
>
> Signed-off-by: Carlo Caione <carlo@endlessm.com>

Sorry for the delay.

Apparently this slipped through my mmc mail filters, as I think you
forgotten to post this to linux-mmc.

[...]

> +static void meson_mmc_request(struct mmc_host *mmc, struct mmc_request *mrq)
> +{
> +       struct meson_mmc_host *host = mmc_priv(mmc);
> +       struct mmc_command *cmd = mrq->cmd;
> +       struct mmc_data *data = mrq->data;
> +       unsigned long flags;
> +       int ret;
> +
> +       spin_lock_irqsave(&host->lock, flags);

I would advise you to re-visit the deployment of the locking in this
driver. It doesn't seem correct.

For example, keeping IRQ disabled while mapping DMA buffers isn't a
good idea, as it may cause the IRQs to be disabled for quite a while.

> +
> +       if (host->error) {
> +               cmd->error = host->error;
> +               spin_unlock_irqrestore(&host->lock, flags);
> +               mmc_request_done(mmc, mrq);
> +               return;
> +       }
> +
> +       if (data) {
> +               ret = meson_mmc_map_dma(host, data, data->flags);
> +               if (ret < 0) {
> +                       dev_err(mmc_dev(mmc), "map DMA failed\n");
> +                       cmd->error = ret;
> +                       data->error = ret;
> +                       spin_unlock_irqrestore(&host->lock, flags);
> +                       mmc_request_done(mmc, mrq);
> +                       return;
> +               }
> +               writel(sg_dma_address(data->sg), host->base + SDIO_ADDR);
> +       }
> +
> +       host->mrq = mrq;
> +       meson_mmc_start_cmd(mmc, mrq->cmd);
> +
> +       spin_unlock_irqrestore(&host->lock, flags);
> +
> +       schedule_delayed_work(&host->timeout_work, host->timeout);
> +}
> +
> +static irqreturn_t meson_mmc_irq(int irq, void *data)
> +{
> +       struct meson_mmc_host *host = (void *) data;
> +       struct mmc_request *mrq = host->mrq;
> +       u32 irqs;
> +
> +       irqs = readl(host->base + SDIO_IRQS);
> +       if (mrq && (irqs & REG_IRQS_CMD_INT))
> +               return IRQ_WAKE_THREAD;

As you don't use the IRQF_ONESHOT flag, this hard IRQ handler may be
invoked while the threaded handler runs.

Although, I don't see any protection of the host->mrq pointer etc,
don't you need that?

> +
> +       return IRQ_HANDLED;
> +}
> +
> +void meson_mmc_read_response(struct meson_mmc_host *host)
> +{
> +       struct mmc_command *cmd = host->mrq->cmd;
> +       u32 mult;
> +       int i, resp[4] = { 0 };
> +
> +       mult = readl(host->base + SDIO_MULT);
> +       mult |= REG_MULT_WR_RD_OUT_IND;
> +       mult &= ~(REG_MULT_RD_INDEX_M << REG_MULT_RD_INDEX_S);
> +       writel(mult, host->base + SDIO_MULT);
> +
> +       if (cmd->flags & MMC_RSP_136) {
> +               for (i = 0; i <= 3; i++)
> +                       resp[3 - i] = readl(host->base + SDIO_ARGU);
> +               cmd->resp[0] = (resp[0] << 8) | ((resp[1] >> 24) & 0xff);
> +               cmd->resp[1] = (resp[1] << 8) | ((resp[2] >> 24) & 0xff);
> +               cmd->resp[2] = (resp[2] << 8) | ((resp[3] >> 24) & 0xff);
> +               cmd->resp[3] = (resp[3] << 8);
> +       } else if (cmd->flags & MMC_RSP_PRESENT) {
> +               cmd->resp[0] = readl(host->base + SDIO_ARGU);
> +       }
> +}
> +
> +static irqreturn_t meson_mmc_irq_thread(int irq, void *irq_data)
> +{
> +       struct meson_mmc_host *host = (void *) irq_data;
> +       struct mmc_data *data;
> +       unsigned long flags;
> +       struct mmc_request *mrq;
> +       u32 irqs, send;
> +
> +       cancel_delayed_work_sync(&host->timeout_work);
> +       spin_lock_irqsave(&host->lock, flags);

You are disabling IRQs during the entire execution of this threaded
IRQ handler, that's not a good behaviour as it may be disabled for
quite a while.

Although, perhaps you do this to avoid needing to protect host->mrq in
the hard IRQ handler!?

> +
> +       mrq = host->mrq;
> +       data = mrq->data;
> +
> +       if (!mrq) {
> +               spin_unlock_irqrestore(&host->lock, flags);
> +               return IRQ_HANDLED;
> +       }
> +
> +       if (host->cmd_is_stop)
> +               goto out;
> +
> +       irqs = readl(host->base + SDIO_IRQS);
> +       send = readl(host->base + SDIO_SEND);
> +
> +       mrq->cmd->error = 0;
> +
> +       if (!data) {
> +               if (!((irqs & REG_IRQS_RESP_CRC7) ||
> +                     (send & REG_SEND_RESP_NO_CRC7)))
> +                       mrq->cmd->error = -EILSEQ;
> +               else
> +                       meson_mmc_read_response(host);
> +       } else {
> +               if (!((irqs & REG_IRQS_RD_CRC16) ||
> +                     (irqs & REG_IRQS_WR_CRC16))) {
> +                       mrq->cmd->error = -EILSEQ;
> +               } else {
> +                       data->bytes_xfered = data->blksz * data->blocks;
> +                       dma_unmap_sg(mmc_dev(host->mmc), data->sg, data->sg_len,
> +                                    ((data->flags & MMC_DATA_READ) ?
> +                                    DMA_FROM_DEVICE : DMA_TO_DEVICE));
> +               }
> +       }
> +
> +       if (mrq->stop) {
> +               host->cmd_is_stop = true;
> +               meson_mmc_start_cmd(host->mmc, mrq->stop);
> +               spin_unlock_irqrestore(&host->lock, flags);
> +               return IRQ_HANDLED;
> +       }
> +
> +out:
> +       host->cmd_is_stop = false;
> +       host->mrq = NULL;
> +       spin_unlock_irqrestore(&host->lock, flags);
> +       mmc_request_done(host->mmc, mrq);
> +
> +       return IRQ_HANDLED;
> +}
> +

[...]

> +static int meson_mmc_probe(struct platform_device *pdev)
> +{
> +       struct mmc_host *mmc;
> +       struct meson_mmc_host *host;
> +       struct pinctrl *pinctrl;
> +       struct resource *res;
> +       int ret, irq;
> +       u32 port;
> +
> +       mmc = mmc_alloc_host(sizeof(struct meson_mmc_host), &pdev->dev);
> +       if (!mmc) {
> +               dev_err(&pdev->dev, "mmc alloc host failed\n");
> +               return -ENOMEM;
> +       }
> +
> +       host = mmc_priv(mmc);
> +       host->mmc = mmc;
> +       host->timeout = msecs_to_jiffies(10000);
> +       host->port = 0;
> +
> +       if (!of_property_read_u32(pdev->dev.of_node, "meson,sd-port", &port))
> +               host->port = port;
> +
> +
> +       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> +       host->base = devm_ioremap_resource(&pdev->dev, res);
> +       if (IS_ERR(host->base)) {
> +               ret = PTR_ERR(host->base);
> +               goto error_free_host;
> +       }
> +
> +       irq = platform_get_irq(pdev, 0);
> +       ret = devm_request_threaded_irq(&pdev->dev, irq, meson_mmc_irq,
> +                                       meson_mmc_irq_thread, 0, "meson_mmc",

Is the IRQs level or edge triggered? In other words, will the hard IRQ
handler miss IRQs if you use IRQF_ONESHOT?

> +                                       host);
> +       if (ret)
> +               goto error_free_host;
> +
> +       host->clk = devm_clk_get(&pdev->dev, NULL);
> +       if (IS_ERR(host->clk)) {
> +               ret = PTR_ERR(host->clk);
> +               goto error_free_host;
> +       }
> +
> +       ret = clk_prepare_enable(host->clk);
> +       if (ret) {
> +               dev_err(&pdev->dev, "Enable clk error %d\n", ret);
> +               goto error_free_host;
> +       }
> +
> +       /* we do not support scatter lists in hardware */
> +       mmc->max_segs = 1;
> +       mmc->max_req_size = SDIO_BOUNCE_REQ_SIZE;
> +       mmc->max_seg_size = mmc->max_req_size;
> +       mmc->max_blk_count = 256;
> +       mmc->max_blk_size = mmc->max_req_size / mmc->max_blk_count;
> +       mmc->f_min = 300000;
> +       mmc->f_max = 50000000;
> +       mmc->caps |= MMC_CAP_4_BIT_DATA;
> +       mmc->caps |= MMC_CAP_MMC_HIGHSPEED | MMC_CAP_SD_HIGHSPEED;
> +       mmc->caps2 |= MMC_CAP2_NO_SDIO;
> +       mmc->ocr_avail = MMC_VDD_33_34;
> +       mmc->ops = &meson_mmc_ops;
> +
> +       spin_lock_init(&host->lock);
> +
> +       INIT_DELAYED_WORK(&host->timeout_work, meson_mmc_timeout);
> +
> +       pinctrl = devm_pinctrl_get(&pdev->dev);
> +       if (IS_ERR(pinctrl)) {
> +               ret = PTR_ERR(pinctrl);
> +               goto error;
> +       }
> +
> +       ret = mmc_of_parse(mmc);
> +       if (ret)
> +               goto error;
> +
> +       platform_set_drvdata(pdev, mmc);
> +
> +       ret = mmc_add_host(mmc);
> +       if (ret)
> +               goto error;
> +
> +       dev_info(&pdev->dev, "base:0x%p irq:%u port:%u\n",
> +                host->base, irq, host->port);
> +
> +       return 0;
> +
> +error:
> +       clk_disable_unprepare(host->clk);
> +error_free_host:
> +       mmc_free_host(mmc);
> +
> +       return ret;
> +}
> +

[...]

Kind regards
Uffe

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

* Re: [PATCH v5 3/4] ARM: dts: meson8b: Add MMC nodes
  2016-02-27 18:01     ` Carlo Caione
@ 2016-05-11 17:57         ` Kevin Hilman
  -1 siblings, 0 replies; 24+ messages in thread
From: Kevin Hilman @ 2016-05-11 17:57 UTC (permalink / raw)
  To: Carlo Caione
  Cc: ulf.hansson-QSEj5FYQhm4dnm+yROfE0A,
	robh+dt-DgEjT+Ai2ygdnm+yROfE0A,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	linux-lFZ/pmaqli7XmaaqVzeoHQ, devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-meson-/JYPxA39Uh5TLH3MbocFFw, linux-6IF/jdPJHihWk0Htik3J/w,
	Carlo Caione

Hi Carlo,

Carlo Caione <carlo-KA+7E9HrN00dnm+yROfE0A@public.gmane.org> writes:

> From: Carlo Caione <carlo-6IF/jdPJHihWk0Htik3J/w@public.gmane.org>
>
> Enable the MMC for the Meson8b platforms.
>
> Signed-off-by: Carlo Caione <carlo-6IF/jdPJHihWk0Htik3J/w@public.gmane.org>

[...]

> diff --git a/arch/arm/boot/dts/meson8b.dtsi b/arch/arm/boot/dts/meson8b.dtsi
> index 8bad557..25d795c 100644
> --- a/arch/arm/boot/dts/meson8b.dtsi
> +++ b/arch/arm/boot/dts/meson8b.dtsi
> @@ -187,6 +187,22 @@
>  					function = "uart_ao";
>  				};
>  			};
> +
> +			mmc0_sd_b_pins: mmc0_sd_b {
> +				mux {
> +					groups = "sd_d1_b", "sd_d0_b", "sd_clk_b", "sd_cmd_b",
> +						 "sd_d3_b", "sd_d2_b";
> +					function = "sd_b";
> +				};
> +			};

These pins are added under pinctrl_aobus, but in the pinctrl driver,
they're under cbus.  If I move this into the pinctrl_cbus node, I get it
to work on my odroid-c1, and am able to mount/use an MMC rootfs.

Kevin
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

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

* [PATCH v5 3/4] ARM: dts: meson8b: Add MMC nodes
@ 2016-05-11 17:57         ` Kevin Hilman
  0 siblings, 0 replies; 24+ messages in thread
From: Kevin Hilman @ 2016-05-11 17:57 UTC (permalink / raw)
  To: linux-arm-kernel

Hi Carlo,

Carlo Caione <carlo@caione.org> writes:

> From: Carlo Caione <carlo@endlessm.com>
>
> Enable the MMC for the Meson8b platforms.
>
> Signed-off-by: Carlo Caione <carlo@endlessm.com>

[...]

> diff --git a/arch/arm/boot/dts/meson8b.dtsi b/arch/arm/boot/dts/meson8b.dtsi
> index 8bad557..25d795c 100644
> --- a/arch/arm/boot/dts/meson8b.dtsi
> +++ b/arch/arm/boot/dts/meson8b.dtsi
> @@ -187,6 +187,22 @@
>  					function = "uart_ao";
>  				};
>  			};
> +
> +			mmc0_sd_b_pins: mmc0_sd_b {
> +				mux {
> +					groups = "sd_d1_b", "sd_d0_b", "sd_clk_b", "sd_cmd_b",
> +						 "sd_d3_b", "sd_d2_b";
> +					function = "sd_b";
> +				};
> +			};

These pins are added under pinctrl_aobus, but in the pinctrl driver,
they're under cbus.  If I move this into the pinctrl_cbus node, I get it
to work on my odroid-c1, and am able to mount/use an MMC rootfs.

Kevin

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

* Re: [PATCH v5 3/4] ARM: dts: meson8b: Add MMC nodes
  2016-05-11 17:57         ` Kevin Hilman
@ 2016-05-11 18:05             ` Carlo Caione
  -1 siblings, 0 replies; 24+ messages in thread
From: Carlo Caione @ 2016-05-11 18:05 UTC (permalink / raw)
  To: Kevin Hilman
  Cc: Carlo Caione, Ulf Hansson, robh+dt-DgEjT+Ai2ygdnm+yROfE0A,
	linux-arm-kernel, Russell King - ARM Linux, devicetree,
	linux-meson, linux-6IF/jdPJHihWk0Htik3J/w, Carlo Caione

On Wed, May 11, 2016 at 7:57 PM, Kevin Hilman <khilman-rdvid1DuHRBWk0Htik3J/w@public.gmane.org> wrote:
> Hi Carlo,
>
> Carlo Caione <carlo-KA+7E9HrN00dnm+yROfE0A@public.gmane.org> writes:
>
>> From: Carlo Caione <carlo-6IF/jdPJHihWk0Htik3J/w@public.gmane.org>
>>
>> Enable the MMC for the Meson8b platforms.
>>
>> Signed-off-by: Carlo Caione <carlo-6IF/jdPJHihWk0Htik3J/w@public.gmane.org>
>
> [...]
>
>> diff --git a/arch/arm/boot/dts/meson8b.dtsi b/arch/arm/boot/dts/meson8b.dtsi
>> index 8bad557..25d795c 100644
>> --- a/arch/arm/boot/dts/meson8b.dtsi
>> +++ b/arch/arm/boot/dts/meson8b.dtsi
>> @@ -187,6 +187,22 @@
>>                                       function = "uart_ao";
>>                               };
>>                       };
>> +
>> +                     mmc0_sd_b_pins: mmc0_sd_b {
>> +                             mux {
>> +                                     groups = "sd_d1_b", "sd_d0_b", "sd_clk_b", "sd_cmd_b",
>> +                                              "sd_d3_b", "sd_d2_b";
>> +                                     function = "sd_b";
>> +                             };
>> +                     };
>
> These pins are added under pinctrl_aobus, but in the pinctrl driver,
> they're under cbus.  If I move this into the pinctrl_cbus node, I get it
> to work on my odroid-c1, and am able to mount/use an MMC rootfs.

Ouch, thank you for pointing this out, I'll fix it in v6.

thanks,

-- 
Carlo Caione
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

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

* [PATCH v5 3/4] ARM: dts: meson8b: Add MMC nodes
@ 2016-05-11 18:05             ` Carlo Caione
  0 siblings, 0 replies; 24+ messages in thread
From: Carlo Caione @ 2016-05-11 18:05 UTC (permalink / raw)
  To: linux-arm-kernel

On Wed, May 11, 2016 at 7:57 PM, Kevin Hilman <khilman@baylibre.com> wrote:
> Hi Carlo,
>
> Carlo Caione <carlo@caione.org> writes:
>
>> From: Carlo Caione <carlo@endlessm.com>
>>
>> Enable the MMC for the Meson8b platforms.
>>
>> Signed-off-by: Carlo Caione <carlo@endlessm.com>
>
> [...]
>
>> diff --git a/arch/arm/boot/dts/meson8b.dtsi b/arch/arm/boot/dts/meson8b.dtsi
>> index 8bad557..25d795c 100644
>> --- a/arch/arm/boot/dts/meson8b.dtsi
>> +++ b/arch/arm/boot/dts/meson8b.dtsi
>> @@ -187,6 +187,22 @@
>>                                       function = "uart_ao";
>>                               };
>>                       };
>> +
>> +                     mmc0_sd_b_pins: mmc0_sd_b {
>> +                             mux {
>> +                                     groups = "sd_d1_b", "sd_d0_b", "sd_clk_b", "sd_cmd_b",
>> +                                              "sd_d3_b", "sd_d2_b";
>> +                                     function = "sd_b";
>> +                             };
>> +                     };
>
> These pins are added under pinctrl_aobus, but in the pinctrl driver,
> they're under cbus.  If I move this into the pinctrl_cbus node, I get it
> to work on my odroid-c1, and am able to mount/use an MMC rootfs.

Ouch, thank you for pointing this out, I'll fix it in v6.

thanks,

-- 
Carlo Caione

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

end of thread, other threads:[~2016-05-11 18:05 UTC | newest]

Thread overview: 24+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2016-02-27 18:01 [PATCH v5 0/4] Add support for Amlogic Meson MMC driver Carlo Caione
2016-02-27 18:01 ` Carlo Caione
     [not found] ` <1456596108-1406-1-git-send-email-carlo-KA+7E9HrN00dnm+yROfE0A@public.gmane.org>
2016-02-27 18:01   ` [PATCH v5 1/4] mmc: meson: Document Amlogic Meson MMC DT bindings Carlo Caione
2016-02-27 18:01     ` Carlo Caione
     [not found]     ` <1456596108-1406-2-git-send-email-carlo-KA+7E9HrN00dnm+yROfE0A@public.gmane.org>
2016-03-03 22:17       ` Rob Herring
2016-03-03 22:17         ` Rob Herring
2016-03-04  8:11         ` Carlo Caione
2016-03-04  8:11           ` Carlo Caione
2016-02-27 18:01   ` [PATCH v5 2/4] mmc: meson: Add driver for the SD/MMC host found on Amlogic Meson SoCs Carlo Caione
2016-02-27 18:01     ` Carlo Caione
     [not found]     ` <1456596108-1406-3-git-send-email-carlo-KA+7E9HrN00dnm+yROfE0A@public.gmane.org>
2016-03-02  2:14       ` Andreas Färber
2016-03-02  2:14         ` Andreas Färber
     [not found]         ` <56D64C9A.3030004-l3A5Bk7waGM@public.gmane.org>
2016-03-02  8:11           ` Carlo Caione
2016-03-02  8:11             ` Carlo Caione
2016-04-18 13:47       ` Ulf Hansson
2016-04-18 13:47         ` Ulf Hansson
2016-02-27 18:01   ` [PATCH v5 3/4] ARM: dts: meson8b: Add MMC nodes Carlo Caione
2016-02-27 18:01     ` Carlo Caione
     [not found]     ` <1456596108-1406-4-git-send-email-carlo-KA+7E9HrN00dnm+yROfE0A@public.gmane.org>
2016-05-11 17:57       ` Kevin Hilman
2016-05-11 17:57         ` Kevin Hilman
     [not found]         ` <m24ma47a0n.fsf-rdvid1DuHRBWk0Htik3J/w@public.gmane.org>
2016-05-11 18:05           ` Carlo Caione
2016-05-11 18:05             ` Carlo Caione
2016-02-27 18:01   ` [PATCH v5 4/4] ARM: multi_v7_defconfig: Add Amlogic Meson MMC support Carlo Caione
2016-02-27 18:01     ` Carlo Caione

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.