From 364d4535955f21a8ce13e969aedde946a2d566b8 Mon Sep 17 00:00:00 2001 From: Pantelis Antoniou 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 --- 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 #include #include +#include +#include /* 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