kernel/0002-omap_hsmmc-Add-reset-g...

139 lines
4.8 KiB
Diff

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