Skip to content

Commit

Permalink
mmc: dw_mmc: Handle wp-gpios from device tree
Browse files Browse the repository at this point in the history
On some SoCs (like exynos5250) you need to use an external GPIO for
write protect.  Add support for wp-gpios to the core dw_mmc driver
since it could be useful across multiple SoCs.

With this change I am able to make use of the write protect for the
external SD slot on exynos5250-snow.

Signed-off-by: Doug Anderson <[email protected]>
Acked-by: Seungwon Jeon <[email protected]>
Acked-by: Olof Johansson <[email protected]>
Signed-off-by: Chris Ball <[email protected]>
  • Loading branch information
dianders authored and cjb committed Feb 24, 2013
1 parent 07b2404 commit 55a6ceb
Showing 1 changed file with 34 additions and 0 deletions.
34 changes: 34 additions & 0 deletions drivers/mmc/host/dw_mmc.c
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@
#include <linux/regulator/consumer.h>
#include <linux/workqueue.h>
#include <linux/of.h>
#include <linux/of_gpio.h>

#include "dw_mmc.h"

Expand Down Expand Up @@ -75,6 +76,7 @@ struct idmac_desc {
* @mmc: The mmc_host representing this slot.
* @host: The MMC controller this slot is using.
* @quirks: Slot-level quirks (DW_MCI_SLOT_QUIRK_XXX)
* @wp_gpio: If gpio_is_valid() we'll use this to read write protect.
* @ctype: Card type for this slot.
* @mrq: mmc_request currently being processed or waiting to be
* processed, or NULL when the slot is idle.
Expand All @@ -90,6 +92,7 @@ struct dw_mci_slot {
struct dw_mci *host;

int quirks;
int wp_gpio;

u32 ctype;

Expand Down Expand Up @@ -838,6 +841,8 @@ static int dw_mci_get_ro(struct mmc_host *mmc)
read_only = 0;
else if (brd->get_ro)
read_only = brd->get_ro(slot->id);
else if (gpio_is_valid(slot->wp_gpio))
read_only = gpio_get_value(slot->wp_gpio);
else
read_only =
mci_readl(slot->host, WRTPRT) & (1 << slot->id) ? 1 : 0;
Expand Down Expand Up @@ -1832,6 +1837,29 @@ static u32 dw_mci_of_get_bus_wd(struct device *dev, u8 slot)
" as 1\n");
return bus_wd;
}

/* find the write protect gpio for a given slot; or -1 if none specified */
static int dw_mci_of_get_wp_gpio(struct device *dev, u8 slot)
{
struct device_node *np = dw_mci_of_find_slot_node(dev, slot);
int gpio;

if (!np)
return -EINVAL;

gpio = of_get_named_gpio(np, "wp-gpios", 0);

/* Having a missing entry is valid; return silently */
if (!gpio_is_valid(gpio))
return -EINVAL;

if (devm_gpio_request(dev, gpio, "dw-mci-wp")) {
dev_warn(dev, "gpio [%d] request failed\n", gpio);
return -EINVAL;
}

return gpio;
}
#else /* CONFIG_OF */
static int dw_mci_of_get_slot_quirks(struct device *dev, u8 slot)
{
Expand All @@ -1845,6 +1873,10 @@ static struct device_node *dw_mci_of_find_slot_node(struct device *dev, u8 slot)
{
return NULL;
}
static int dw_mci_of_get_wp_gpio(struct device *dev, u8 slot)
{
return -EINVAL;
}
#endif /* CONFIG_OF */

static int dw_mci_init_slot(struct dw_mci *host, unsigned int id)
Expand Down Expand Up @@ -1962,6 +1994,8 @@ static int dw_mci_init_slot(struct dw_mci *host, unsigned int id)
else
clear_bit(DW_MMC_CARD_PRESENT, &slot->flags);

slot->wp_gpio = dw_mci_of_get_wp_gpio(host->dev, slot->id);

mmc_add_host(mmc);

#if defined(CONFIG_DEBUG_FS)
Expand Down

0 comments on commit 55a6ceb

Please sign in to comment.