Skip to content
Browse files

3.7: more capebus patches to make mmc/sdio capes works

Signed-off-by: Koen Kooi <koen@dominion.thruhere.net>
  • Loading branch information...
1 parent 23e7a5b commit fba444affcc67369f0f3add95db09f01a8b18953 @koenkooi koenkooi committed Nov 30, 2012
View
2 configs/beaglebone
@@ -3258,7 +3258,7 @@ CONFIG_DMA_VIRTUAL_CHANNELS=y
#
# DMA Clients
#
-CONFIG_NET_DMA=y
+# CONFIG_NET_DMA is not set
CONFIG_ASYNC_TX_DMA=y
CONFIG_DMATEST=m
# CONFIG_AUXDISPLAY is not set
View
68 patches/capebus/0027-Allow-more-than-one-instance-of-generic-devices.patch
@@ -0,0 +1,68 @@
+From 0710d0f2c13165dd901680538f0e67dc5230a863 Mon Sep 17 00:00:00 2001
+From: Pantelis Antoniou <panto@antoniou-consulting.com>
+Date: Fri, 30 Nov 2012 12:23:29 +0200
+Subject: [PATCH 27/30] Allow more than one instance of generic devices
+
+Generate unique name to allow more than one instance of devices.
+---
+ drivers/capebus/capebus-driver.c | 19 ++++++++++++++++++-
+ include/linux/capebus.h | 7 ++++---
+ 2 files changed, 22 insertions(+), 4 deletions(-)
+
+diff --git a/drivers/capebus/capebus-driver.c b/drivers/capebus/capebus-driver.c
+index 82b1d1b..a299c77 100644
+--- a/drivers/capebus/capebus-driver.c
++++ b/drivers/capebus/capebus-driver.c
+@@ -441,13 +441,30 @@ capebus_of_platform_compatible_device_create(struct cape_dev *dev,
+ {
+ struct device_node *node;
+ struct platform_device *pdev;
++ char *name, *buf;
+
+ node = capebus_of_compatible_device_property_match(dev, matches, prop,
+ prop_value);
+ if (node == NULL)
+ return ERR_PTR(-ENXIO);
+
+- pdev = of_platform_device_create(node, pdev_name, dev->bus->dev.parent);
++ /* create system-wide unique name */
++ buf = kasprintf(GFP_KERNEL, "%d:%d-%s.%d",
++ dev->bus->busno, dev->slot->slotno,
++ pdev_name, dev->slot->next_pdevid++);
++ if (buf == NULL)
++ return ERR_PTR(-ENOMEM);
++
++ name = devm_kzalloc(&dev->dev, strlen(buf) + 1, GFP_KERNEL);
++ kfree(buf);
++
++ if (name == NULL)
++ return ERR_PTR(-ENOMEM);
++
++ /* safe */
++ strcpy(name, buf);
++
++ pdev = of_platform_device_create(node, name, &dev->dev);
+
+ /* release the reference to the node */
+ of_node_put(node);
+diff --git a/include/linux/capebus.h b/include/linux/capebus.h
+index 7524401..2f8ab7b 100644
+--- a/include/linux/capebus.h
++++ b/include/linux/capebus.h
+@@ -43,9 +43,10 @@ struct cape_slot;
+
+ struct cape_slot {
+ struct list_head node;
+- struct cape_bus *bus; /* the bus this slot is on */
+- int slotno; /* index of this slot */
+- struct cape_dev *dev; /* the device (if found) */
++ struct cape_bus *bus; /* the bus this slot is on */
++ int slotno; /* index of this slot */
++ struct cape_dev *dev; /* the device (if found) */
++ unsigned int next_pdevid; /* next assigned pdev_id */
+ };
+
+ struct cape_driver {
+--
+1.7.7.6
+
View
56 patches/capebus/0028-Mark-the-device-as-PRIVATE.patch
@@ -0,0 +1,56 @@
+From 6dd94627f7deb07ea03874cf0f7bc1e0afcaa2ba Mon Sep 17 00:00:00 2001
+From: Pantelis Antoniou <panto@antoniou-consulting.com>
+Date: Fri, 30 Nov 2012 12:23:31 +0200
+Subject: [PATCH 28/30] Mark the device as PRIVATE
+
+Turns out if you enable CONFIG_NET_DMA the ip stack will try
+to grab all the available non-private DMA channels sometime late in the
+boot sequence.
+
+That's bad enough, what is worse is that it brindly iterates over
+any possible channel; if the driver returns ENODEV on any of the
+channels dmaengine will remove the device from the list of available
+dma devices.
+
+Very crazy bug.
+---
+ drivers/dma/edma.c | 8 ++++++--
+ 1 files changed, 6 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/dma/edma.c b/drivers/dma/edma.c
+index 47ba7bf..75ab2d5 100644
+--- a/drivers/dma/edma.c
++++ b/drivers/dma/edma.c
+@@ -394,8 +394,11 @@ static int edma_alloc_chan_resources(struct dma_chan *chan)
+ a_ch_num = edma_alloc_channel(echan->ch_num, edma_callback,
+ chan, EVENTQ_DEFAULT);
+
++ /* NOTE: DO NOT RETURN ENODEV */
++ /* It causes dmaengine to remove the device from it's list */
++
+ if (a_ch_num < 0) {
+- ret = -ENODEV;
++ ret = -EINVAL;
+ goto err_no_chan;
+ }
+
+@@ -403,7 +406,7 @@ static int edma_alloc_chan_resources(struct dma_chan *chan)
+ dev_err(dev, "failed to allocate requested channel %u:%u\n",
+ EDMA_CTLR(echan->ch_num),
+ EDMA_CHAN_SLOT(echan->ch_num));
+- ret = -ENODEV;
++ ret = -EINVAL;
+ goto err_wrong_chan;
+ }
+
+@@ -564,6 +567,7 @@ static int __devinit edma_probe(struct platform_device *pdev)
+
+ dma_cap_zero(ecc->dma_slave.cap_mask);
+ dma_cap_set(DMA_SLAVE, ecc->dma_slave.cap_mask);
++ dma_cap_set(DMA_PRIVATE, ecc->dma_slave.cap_mask);
+
+ edma_dma_init(ecc, &ecc->dma_slave, &pdev->dev);
+
+--
+1.7.7.6
+
View
452 patches/capebus/0029-DT-overlay.patch
@@ -0,0 +1,452 @@
+From 13eead03e6880732e63ac4ccbebda38acfce8ee0 Mon Sep 17 00:00:00 2001
+From: Pantelis Antoniou <panto@antoniou-consulting.com>
+Date: Fri, 30 Nov 2012 12:23:32 +0200
+Subject: [PATCH 29/30] DT overlay
+
+For things like uarts and mmc hosts you need to overlay DT.
+---
+ drivers/capebus/boards/capebus-bone-generic.c | 6 +
+ drivers/capebus/boards/capebus-bone-pdevs.c | 389 +++++++++++++++++++++++++
+ 2 files changed, 395 insertions(+), 0 deletions(-)
+
+diff --git a/drivers/capebus/boards/capebus-bone-generic.c b/drivers/capebus/boards/capebus-bone-generic.c
+index b1b79eb..8c2c6cc 100644
+--- a/drivers/capebus/boards/capebus-bone-generic.c
++++ b/drivers/capebus/boards/capebus-bone-generic.c
+@@ -141,6 +141,12 @@ static const struct bone_capebus_generic_device_data gendevs[] = {
+ { .compatible = "spi-dt", }, { },
+ },
+ .units = 0, /* no limit */
++ }, {
++ .name = "dt-overlay",
++ .of_match = (const struct of_device_id []) {
++ { .compatible = "dt-overlay", }, { },
++ },
++ .units = 0, /* no limit */
+ }
+ };
+
+diff --git a/drivers/capebus/boards/capebus-bone-pdevs.c b/drivers/capebus/boards/capebus-bone-pdevs.c
+index f32134a..f97100b 100644
+--- a/drivers/capebus/boards/capebus-bone-pdevs.c
++++ b/drivers/capebus/boards/capebus-bone-pdevs.c
+@@ -22,6 +22,7 @@
+ #include <linux/module.h>
+ #include <linux/kernel.h>
+ #include <linux/string.h>
++#include <linux/ctype.h>
+ #include <linux/timer.h>
+ #include <linux/errno.h>
+ #include <linux/init.h>
+@@ -38,6 +39,7 @@
+ #include <linux/clk.h>
+ #include <asm/barrier.h>
+ #include <linux/i2c.h>
++#include <linux/of.h>
+ #include <linux/of_i2c.h>
+ #include <linux/spi/spi.h>
+
+@@ -246,6 +248,390 @@ static struct platform_driver spi_dt_driver = {
+ },
+ };
+
++/*******************************************************************/
++
++static int of_is_printable_string(const void *data, int len)
++{
++ const char *s = data;
++ const char *ss, *se;
++
++ /* zero length is not */
++ if (len == 0)
++ return 0;
++
++ /* must terminate with zero */
++ if (s[len - 1] != '\0')
++ return 0;
++
++ se = s + len;
++
++ while (s < se) {
++ ss = s;
++ while (s < se && *s && isprint(*s))
++ s++;
++
++ /* not zero, or not done yet */
++ if (*s != '\0' || s == ss)
++ return 0;
++
++ s++;
++ }
++
++ return 1;
++}
++
++static char *of_dump_prop(struct property *prop)
++{
++ const void *data = prop->value;
++ int len = prop->length;
++ int i, tbuflen;
++ const char *p = data;
++ const char *s;
++ char *buf, *bufp, *bufe;
++
++ /* play it safe */
++ buf = kmalloc(PAGE_SIZE + len * 8, GFP_KERNEL);
++ if (buf == NULL)
++ return NULL;
++ bufp = buf;
++ bufe = buf + PAGE_SIZE + len * 8;
++
++#undef append_sprintf
++#define append_sprintf(format, ...) \
++ do { \
++ tbuflen = snprintf(NULL, 0, format, ## __VA_ARGS__); \
++ if (bufp + tbuflen + 1 >= bufe) \
++ goto err_out; \
++ snprintf(bufp, tbuflen + 1, format, ## __VA_ARGS__); \
++ bufp += tbuflen; \
++ } while(0)
++
++ if (len == 0) {
++ /* nothing; just terminate */
++ *buf = '\0';
++ return buf;
++ }
++
++ append_sprintf(" = ");
++
++ if (of_is_printable_string(data, len)) {
++ s = data;
++ do {
++ append_sprintf("\"%s\"", s);
++ s += strlen(s) + 1;
++ if (s < (const char *)data + len)
++ append_sprintf(", ");
++ } while (s < (const char *)data + len);
++
++ } else if ((len % 4) == 0) {
++ append_sprintf("<");
++ for (i = 0; i < len; i += 4)
++ append_sprintf("0x%08x%s",
++ be32_to_cpu(*(uint32_t *)(p + i)),
++ i < (len - 4) ? " " : "");
++ append_sprintf(">");
++ } else {
++ append_sprintf("[");
++ for (i = 0; i < len; i++)
++ append_sprintf("%02x%s", *(p + i),
++ i < len - 1 ? " " : "");
++ append_sprintf("]");
++ }
++
++ return buf;
++err_out:
++ kfree(buf);
++ return NULL;
++#undef append_sprintf
++}
++
++static void of_dump_tree(struct device *dev, int level,
++ struct device_node *node)
++{
++ struct device_node *child;
++ struct property *prop;
++ static const char *leveltab = "\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t";
++ int maxlevel = strlen(leveltab);
++ const char *thislevel;
++ const char *nextlevel;
++ char *propstr;
++
++ thislevel = leveltab + maxlevel - level;
++ if (thislevel < leveltab)
++ thislevel = leveltab;
++ nextlevel = thislevel - 1;
++ if (nextlevel < leveltab)
++ nextlevel = leveltab;
++
++ dev_info(dev, "%s%s {\n", thislevel, node->name);
++
++ for_each_property_of_node(node, prop) {
++
++ if (strcmp(prop->name, "name") == 0)
++ continue;
++
++ propstr = of_dump_prop(prop);
++ dev_info(dev, "%s%s%s;\n", nextlevel, prop->name,
++ propstr ? propstr : "*ERROR*");
++ kfree(propstr);
++ }
++
++ for_each_child_of_node(node, child)
++ of_dump_tree(dev, level + 1, child);
++
++ dev_info(dev, "%s};", thislevel);
++}
++
++struct dt_fragment {
++ struct list_head node;
++ struct device_node *target_node;
++ int status_changed : 1;
++ int status_new : 1;
++
++ struct device_node *saved_tree;
++};
++
++struct dt_overlay_priv {
++ struct list_head frag_list;
++};
++
++static const struct of_device_id of_dt_overlay_match[] = {
++ { .compatible = "dt-overlay", },
++ {},
++};
++
++#define for_each_property_of_node_safe(dn, pp, ppn) \
++ for (pp = dn->properties, ppn = pp ? pp->next : NULL; pp != NULL; pp = ppn, ppn = pp->next)
++
++static void of_overlay_node(struct device *dev, struct device_node *target, struct device_node *overlay)
++{
++ struct device_node *child;
++ struct device_node **childp;
++ struct property *prop, *propn;
++ struct property **propp;
++ char *propstr;
++ int found;
++
++ dev_info(dev, "Overlaying target %p with overlay %p\n", target, overlay);
++
++ while ((prop = overlay->properties) != NULL) {
++ /* remove head prop */
++ overlay->properties = prop->next;
++ prop->next = NULL;
++
++ found = 0;
++ propp = &target->properties;
++ while (*propp) {
++
++ /* found? */
++ if (of_prop_cmp((*propp)->name, prop->name) == 0) {
++ found = 1;
++ break;
++ }
++
++ propp = &(*propp)->next;
++ }
++
++ if (found) {
++ propn = (*propp)->next;
++ prop->next = propn;
++ /* propn is now dead */
++
++ }
++
++ *propp = prop;
++
++ propstr = of_dump_prop(prop);
++ dev_info(dev, "%c %s%s;\n", found ? 'U' : 'I', prop->name, propstr);
++ kfree(propstr);
++ }
++
++ /* remove each child */
++ while ((child = overlay->child) != NULL) {
++ overlay->child = child->sibling;
++ child->sibling = NULL;
++
++ found = 0;
++ childp = &target->child;
++ while (*childp) {
++
++ /* found? */
++ if ((*childp)->name && of_node_cmp((*childp)->name, child->name) == 0) {
++ found = 1;
++ break;
++ }
++
++ childp = &(*childp)->sibling;
++ }
++
++ if (found) {
++ dev_info(dev, "overlaying node '%s'\n", child->name);
++ of_overlay_node(dev, (*childp), child);
++ } else {
++ *childp = child;
++ child->parent = target;
++
++ dev_info(dev, "inserted node '%s'\n", child->name);
++ }
++ }
++}
++
++static int __devinit dt_overlay_probe(struct platform_device *pdev)
++{
++ struct dt_overlay_priv *priv = NULL;
++ struct dt_fragment *frag;
++ int ret = -EINVAL;
++ struct device_node *target_node, *node, *tnode;
++ u32 val;
++ int prev_status, new_status;
++ struct platform_device *target_pdev, *parent_pdev;
++ struct list_head *lh, *lhp;
++ unsigned long flags;
++
++ frag = NULL;
++ target_node = NULL;
++ ret = 0;
++
++ if (pdev->dev.of_node == NULL) {
++ dev_err(&pdev->dev, "Only support OF case\n");
++ return -ENOMEM;
++ }
++
++ priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);
++ if (priv == NULL) {
++ dev_err(&pdev->dev, "Failed to allocate priv\n");
++ return -ENOMEM;
++ }
++ INIT_LIST_HEAD(&priv->frag_list);
++
++ frag = NULL;
++ target_node = NULL;
++ ret = 0;
++
++ /* iterate over fragment children */
++ for_each_child_of_node(pdev->dev.of_node, node) {
++
++ frag = NULL;
++ target_node = NULL;
++
++ frag = devm_kzalloc(&pdev->dev, sizeof(*frag), GFP_KERNEL);
++ if (frag == NULL) {
++ dev_err(&pdev->dev, "Failed to allocate frag\n");
++ ret = -ENOMEM;
++ goto err_fail;
++ }
++
++ ret = of_property_read_u32(node, "target", &val);
++ if (ret != 0) {
++ dev_err(&pdev->dev, "Failed to find target property\n");
++ goto err_fail;
++ }
++
++ target_node = of_find_node_by_phandle(val);
++ if (target_node == NULL) {
++ dev_err(&pdev->dev, "Failed to find target node\n");
++ ret = -EINVAL;
++ goto err_fail;
++ }
++
++ frag->target_node = target_node;
++
++ prev_status = of_device_is_available(target_node);
++
++ tnode = of_get_child_by_name(node, "content");
++
++ dev_info(&pdev->dev, "overlay %p (before)\n", tnode);
++ of_dump_tree(&pdev->dev, 1, tnode);
++ dev_info(&pdev->dev, "\n");
++
++ dev_info(&pdev->dev, "target %p (before)\n", target_node);
++ of_dump_tree(&pdev->dev, 1, target_node);
++ dev_info(&pdev->dev, "\n");
++
++ write_lock_irqsave(&devtree_lock, flags);
++ of_overlay_node(&pdev->dev, target_node, tnode);
++ write_unlock_irqrestore(&devtree_lock, flags);
++
++ dev_info(&pdev->dev, "target %p (after)\n", target_node);
++ of_dump_tree(&pdev->dev, 1, target_node);
++ dev_info(&pdev->dev, "\n");
++
++ of_node_put(tnode);
++
++ new_status = of_device_is_available(target_node);
++
++ dev_info(&pdev->dev, "target prev %d new %d\n",
++ prev_status, new_status);
++
++ if (prev_status != new_status) {
++
++ if (new_status) {
++ parent_pdev = of_find_device_by_node(target_node->parent);
++
++ target_pdev = of_platform_device_create(target_node, NULL,
++ parent_pdev ? &parent_pdev->dev : NULL);
++ if (target_pdev == NULL) {
++ dev_info(&pdev->dev, "failed to enable platform_device\n");
++ platform_device_put(parent_pdev);
++ goto err_fail;
++ }
++ } else {
++ target_pdev = of_find_device_by_node(target_node);
++ if (target_pdev != NULL) {
++ dev_info(&pdev->dev, "Cannot find platform_device yet\n");
++ ret = -ENODEV;
++ goto err_fail;
++ }
++ platform_device_unregister(target_pdev);
++ platform_device_put(target_pdev);
++ }
++
++ frag->status_changed = 1;
++ frag->status_new = new_status;
++
++ }
++
++ list_add_tail(&frag->node, &priv->frag_list);
++ }
++
++ dev_info(&pdev->dev, "Completed.\n");
++
++ platform_set_drvdata(pdev, priv);
++
++ return 0;
++
++err_fail:
++ of_node_put(target_node);
++ devm_kfree(&pdev->dev, frag);
++
++ /* remove all in reverse */
++ list_for_each_prev_safe(lh, lhp, &priv->frag_list) {
++ frag = list_entry(lh, struct dt_fragment, node);
++ list_del(lh);
++
++ /* TODO: remove overlay */
++
++ of_node_put(frag->target_node);
++ devm_kfree(&pdev->dev, frag);
++ }
++ return ret;
++}
++
++static int __devexit dt_overlay_remove(struct platform_device *pdev)
++{
++ return -EINVAL; /* not supporting removal yet */
++}
++
++static struct platform_driver dt_overlay_driver = {
++ .probe = dt_overlay_probe,
++ .remove = __devexit_p(dt_overlay_remove),
++ .driver = {
++ .name = "dt-overlay",
++ .owner = THIS_MODULE,
++ .of_match_table = of_dt_overlay_match,
++ },
++};
++
+ /*
+ *
+ */
+@@ -263,6 +649,9 @@ static struct bone_capebus_pdev_driver pdev_drivers[] = {
+ .driver = &spi_dt_driver,
+ },
+ {
++ .driver = &dt_overlay_driver,
++ },
++ {
+ .driver = NULL,
+ }
+ };
+--
+1.7.7.6
+
View
142 patches/capebus/0030-Bug-fixes-pinctl-gpio-reset.patch
@@ -0,0 +1,142 @@
+From 49b8f7810b87dd4667a51f32c45b4b7661942795 Mon Sep 17 00:00:00 2001
+From: Pantelis Antoniou <panto@antoniou-consulting.com>
+Date: Fri, 30 Nov 2012 12:23:33 +0200
+Subject: [PATCH 30/30] Bug fixes, pinctl & gpio-reset
+
+---
+ arch/arm/plat-omap/include/plat/mmc.h | 3 ++
+ drivers/mmc/host/omap_hsmmc.c | 41 ++++++++++++++++++++++++++++++++-
+ 2 files changed, 43 insertions(+), 1 deletions(-)
+
+diff --git a/arch/arm/plat-omap/include/plat/mmc.h b/arch/arm/plat-omap/include/plat/mmc.h
+index 346af5b..594fc12 100644
+--- a/arch/arm/plat-omap/include/plat/mmc.h
++++ b/arch/arm/plat-omap/include/plat/mmc.h
+@@ -131,6 +131,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,
+diff --git a/drivers/mmc/host/omap_hsmmc.c b/drivers/mmc/host/omap_hsmmc.c
+index 7a1283c..8a15610 100644
+--- a/drivers/mmc/host/omap_hsmmc.c
++++ b/drivers/mmc/host/omap_hsmmc.c
+@@ -38,6 +38,8 @@
+ #include <linux/gpio.h>
+ #include <linux/regulator/consumer.h>
+ #include <linux/pm_runtime.h>
++#include <linux/pinctrl/consumer.h>
++#include <linux/err.h>
+ #include <mach/hardware.h>
+ #include <plat/mmc.h>
+ #include <plat/cpu.h>
+@@ -383,6 +385,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)
+@@ -412,6 +415,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:
+@@ -425,6 +446,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))
+@@ -779,7 +802,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);
+@@ -821,6 +844,8 @@ static void omap_hsmmc_request_done(struct omap_hsmmc_host *host, struct mmc_req
+ int dma_ch;
+ unsigned long flags;
+
++ BUG_ON(mrq == NULL);
++
+ spin_lock_irqsave(&host->irq_lock, flags);
+ host->req_in_progress = 0;
+ dma_ch = host->dma_ch;
+@@ -1704,6 +1729,7 @@ static struct omap_mmc_platform_data *of_get_hsmmc_pdata(struct device *dev)
+ struct omap_mmc_platform_data *pdata;
+ struct device_node *np = dev->of_node;
+ u32 bus_width;
++ enum of_gpio_flags reset_flags;
+
+ pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL);
+ if (!pdata)
+@@ -1716,6 +1742,14 @@ static struct omap_mmc_platform_data *of_get_hsmmc_pdata(struct device *dev)
+ pdata->nr_slots = 1;
+ pdata->slots[0].switch_pin = of_get_named_gpio(np, "cd-gpios", 0);
+ pdata->slots[0].gpio_wp = of_get_named_gpio(np, "wp-gpios", 0);
++ 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;
+@@ -1753,6 +1787,7 @@ static int __devinit omap_hsmmc_probe(struct platform_device *pdev)
+ const struct of_device_id *match;
+ dma_cap_mask_t mask;
+ unsigned tx_req, rx_req;
++ struct pinctrl *pinctrl;
+
+ match = of_match_device(of_match_ptr(omap_mmc_of_match), &pdev->dev);
+ if (match) {
+@@ -1773,6 +1808,10 @@ static int __devinit 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)
+--
+1.7.7.6
+

0 comments on commit fba444a

Please sign in to comment.
Something went wrong with that request. Please try again.