summaryrefslogtreecommitdiffstats
path: root/0002-omap_hsmmc-Add-reset-gpio.patch
diff options
context:
space:
mode:
authorPeter Robinson <pbrobinson@gmail.com>2013-09-04 02:43:18 +0100
committerPeter Robinson <pbrobinson@gmail.com>2013-09-04 02:43:18 +0100
commitbad69a54fc999f7ed3871b472a31c1a760ed1e81 (patch)
tree16a0df217b495c859746080ca7f3cc4e1ff26366 /0002-omap_hsmmc-Add-reset-gpio.patch
parent7ad7e4c4014b96bb176b000b8be71063cf5fc60f (diff)
downloadkernel-bad69a54fc999f7ed3871b472a31c1a760ed1e81.tar.gz
kernel-bad69a54fc999f7ed3871b472a31c1a760ed1e81.tar.xz
kernel-bad69a54fc999f7ed3871b472a31c1a760ed1e81.zip
Add patch set to fix MMC on AM33xx, Add basic support for BeagleBone Black
Diffstat (limited to '0002-omap_hsmmc-Add-reset-gpio.patch')
-rw-r--r--0002-omap_hsmmc-Add-reset-gpio.patch138
1 files changed, 138 insertions, 0 deletions
diff --git a/0002-omap_hsmmc-Add-reset-gpio.patch b/0002-omap_hsmmc-Add-reset-gpio.patch
new file mode 100644
index 000000000..ea686e78e
--- /dev/null
+++ b/0002-omap_hsmmc-Add-reset-gpio.patch
@@ -0,0 +1,138 @@
+From 364d4535955f21a8ce13e969aedde946a2d566b8 Mon Sep 17 00:00:00 2001
+From: Pantelis Antoniou <panto@antoniou-consulting.com>
+Date: Fri, 30 Nov 2012 12:18:16 +0200
+Subject: [PATCH 2/2] omap_hsmmc: Add reset gpio
+
+Add a gpio property for controlling reset of the mmc device.
+eMMC on the beaglebone black requires it.
+
+Signed-off-by: Pantelis Antoniou <panto@antoniou-consulting.com>
+---
+ drivers/mmc/host/omap_hsmmc.c | 40 +++++++++++++++++++++++++++++++++-
+ include/linux/platform_data/mmc-omap.h | 3 +++
+ 2 files changed, 42 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/mmc/host/omap_hsmmc.c b/drivers/mmc/host/omap_hsmmc.c
+index 8ab4a93..1fe7469 100644
+--- a/drivers/mmc/host/omap_hsmmc.c
++++ b/drivers/mmc/host/omap_hsmmc.c
+@@ -40,6 +40,8 @@
+ #include <linux/pinctrl/consumer.h>
+ #include <linux/pm_runtime.h>
+ #include <linux/platform_data/mmc-omap.h>
++#include <linux/pinctrl/consumer.h>
++#include <linux/err.h>
+
+ /* OMAP HSMMC Host Controller Registers */
+ #define OMAP_HSMMC_SYSSTATUS 0x0014
+@@ -396,6 +398,7 @@ static inline int omap_hsmmc_have_reg(void)
+ static int omap_hsmmc_gpio_init(struct omap_mmc_platform_data *pdata)
+ {
+ int ret;
++ unsigned long flags;
+
+ if (gpio_is_valid(pdata->slots[0].switch_pin)) {
+ if (pdata->slots[0].cover)
+@@ -425,6 +428,24 @@ static int omap_hsmmc_gpio_init(struct omap_mmc_platform_data *pdata)
+ } else
+ pdata->slots[0].gpio_wp = -EINVAL;
+
++ if (gpio_is_valid(pdata->slots[0].gpio_reset)) {
++ flags = pdata->slots[0].gpio_reset_active_low ?
++ GPIOF_OUT_INIT_LOW : GPIOF_OUT_INIT_HIGH;
++ ret = gpio_request_one(pdata->slots[0].gpio_reset, flags,
++ "mmc_reset");
++ if (ret)
++ goto err_free_wp;
++
++ /* hold reset */
++ udelay(pdata->slots[0].gpio_reset_hold_us);
++
++ gpio_set_value(pdata->slots[0].gpio_reset,
++ !pdata->slots[0].gpio_reset_active_low);
++
++ } else
++ pdata->slots[0].gpio_reset = -EINVAL;
++
++
+ return 0;
+
+ err_free_wp:
+@@ -438,6 +459,8 @@ err_free_sp:
+
+ static void omap_hsmmc_gpio_free(struct omap_mmc_platform_data *pdata)
+ {
++ if (gpio_is_valid(pdata->slots[0].gpio_reset))
++ gpio_free(pdata->slots[0].gpio_reset);
+ if (gpio_is_valid(pdata->slots[0].gpio_wp))
+ gpio_free(pdata->slots[0].gpio_wp);
+ if (gpio_is_valid(pdata->slots[0].switch_pin))
+@@ -792,7 +815,7 @@ omap_hsmmc_start_command(struct omap_hsmmc_host *host, struct mmc_command *cmd,
+ * ac, bc, adtc, bcr. Only commands ending an open ended transfer need
+ * a val of 0x3, rest 0x0.
+ */
+- if (cmd == host->mrq->stop)
++ if (host->mrq && cmd == host->mrq->stop)
+ cmdtype = 0x3;
+
+ cmdreg = (cmd->opcode << 24) | (resptype << 16) | (cmdtype << 22);
+@@ -835,6 +858,8 @@ static void omap_hsmmc_request_done(struct omap_hsmmc_host *host, struct mmc_req
+ int completed;
+ unsigned long flags;
+
++ BUG_ON(mrq == NULL);
++
+ spin_lock_irqsave(&host->irq_lock, flags);
+
+ host->req_flags &= ~RQF_REQ_IN_PROGRESS;
+@@ -1775,6 +1800,7 @@ static struct omap_mmc_platform_data *of_get_hsmmc_pdata(struct device *dev)
+ struct device_node *np = dev->of_node;
+ u32 bus_width, max_freq;
+ int cd_gpio, wp_gpio;
++ enum of_gpio_flags reset_flags;
+
+ cd_gpio = of_get_named_gpio(np, "cd-gpios", 0);
+ wp_gpio = of_get_named_gpio(np, "wp-gpios", 0);
+@@ -1792,6 +1818,14 @@ static struct omap_mmc_platform_data *of_get_hsmmc_pdata(struct device *dev)
+ pdata->nr_slots = 1;
+ pdata->slots[0].switch_pin = cd_gpio;
+ pdata->slots[0].gpio_wp = wp_gpio;
++ reset_flags = 0;
++ pdata->slots[0].gpio_reset = of_get_named_gpio_flags(np,
++ "reset-gpios", 0, &reset_flags);
++ pdata->slots[0].gpio_reset_active_low =
++ (reset_flags & OF_GPIO_ACTIVE_LOW) != 0;
++ pdata->slots[0].gpio_reset_hold_us = 100; /* default */
++ of_property_read_u32(np, "reset-gpio-hold-us",
++ &pdata->slots[0].gpio_reset_hold_us);
+
+ if (of_find_property(np, "ti,non-removable", NULL)) {
+ pdata->slots[0].nonremovable = true;
+@@ -1858,6 +1892,10 @@ static int omap_hsmmc_probe(struct platform_device *pdev)
+ return -ENXIO;
+ }
+
++ pinctrl = devm_pinctrl_get_select_default(&pdev->dev);
++ if (IS_ERR(pinctrl))
++ dev_warn(&pdev->dev, "unable to select pin group\n");
++
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ irq = platform_get_irq(pdev, 0);
+ if (res == NULL || irq < 0)
+diff --git a/include/linux/platform_data/mmc-omap.h b/include/linux/platform_data/mmc-omap.h
+index 2bf1b30..d548994 100644
+--- a/include/linux/platform_data/mmc-omap.h
++++ b/include/linux/platform_data/mmc-omap.h
+@@ -115,6 +115,9 @@ struct omap_mmc_platform_data {
+
+ int switch_pin; /* gpio (card detect) */
+ int gpio_wp; /* gpio (write protect) */
++ int gpio_reset; /* gpio (reset) */
++ int gpio_reset_active_low; /* 1 if reset is active low */
++ u32 gpio_reset_hold_us; /* time to hold in us */
+
+ int (*set_bus_mode)(struct device *dev, int slot, int bus_mode);
+ int (*set_power)(struct device *dev, int slot,
+--
+1.8.2.1
+