aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/mmc
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/mmc')
-rw-r--r--drivers/mmc/host/dw_mmc.c34
1 files changed, 34 insertions, 0 deletions
diff --git a/drivers/mmc/host/dw_mmc.c b/drivers/mmc/host/dw_mmc.c
index 90f7d990551b..df6207909fe7 100644
--- a/drivers/mmc/host/dw_mmc.c
+++ b/drivers/mmc/host/dw_mmc.c
@@ -34,6 +34,7 @@
34#include <linux/regulator/consumer.h> 34#include <linux/regulator/consumer.h>
35#include <linux/workqueue.h> 35#include <linux/workqueue.h>
36#include <linux/of.h> 36#include <linux/of.h>
37#include <linux/of_gpio.h>
37 38
38#include "dw_mmc.h" 39#include "dw_mmc.h"
39 40
@@ -75,6 +76,7 @@ struct idmac_desc {
75 * @mmc: The mmc_host representing this slot. 76 * @mmc: The mmc_host representing this slot.
76 * @host: The MMC controller this slot is using. 77 * @host: The MMC controller this slot is using.
77 * @quirks: Slot-level quirks (DW_MCI_SLOT_QUIRK_XXX) 78 * @quirks: Slot-level quirks (DW_MCI_SLOT_QUIRK_XXX)
79 * @wp_gpio: If gpio_is_valid() we'll use this to read write protect.
78 * @ctype: Card type for this slot. 80 * @ctype: Card type for this slot.
79 * @mrq: mmc_request currently being processed or waiting to be 81 * @mrq: mmc_request currently being processed or waiting to be
80 * processed, or NULL when the slot is idle. 82 * processed, or NULL when the slot is idle.
@@ -90,6 +92,7 @@ struct dw_mci_slot {
90 struct dw_mci *host; 92 struct dw_mci *host;
91 93
92 int quirks; 94 int quirks;
95 int wp_gpio;
93 96
94 u32 ctype; 97 u32 ctype;
95 98
@@ -838,6 +841,8 @@ static int dw_mci_get_ro(struct mmc_host *mmc)
838 read_only = 0; 841 read_only = 0;
839 else if (brd->get_ro) 842 else if (brd->get_ro)
840 read_only = brd->get_ro(slot->id); 843 read_only = brd->get_ro(slot->id);
844 else if (gpio_is_valid(slot->wp_gpio))
845 read_only = gpio_get_value(slot->wp_gpio);
841 else 846 else
842 read_only = 847 read_only =
843 mci_readl(slot->host, WRTPRT) & (1 << slot->id) ? 1 : 0; 848 mci_readl(slot->host, WRTPRT) & (1 << slot->id) ? 1 : 0;
@@ -1832,6 +1837,29 @@ static u32 dw_mci_of_get_bus_wd(struct device *dev, u8 slot)
1832 " as 1\n"); 1837 " as 1\n");
1833 return bus_wd; 1838 return bus_wd;
1834} 1839}
1840
1841/* find the write protect gpio for a given slot; or -1 if none specified */
1842static int dw_mci_of_get_wp_gpio(struct device *dev, u8 slot)
1843{
1844 struct device_node *np = dw_mci_of_find_slot_node(dev, slot);
1845 int gpio;
1846
1847 if (!np)
1848 return -EINVAL;
1849
1850 gpio = of_get_named_gpio(np, "wp-gpios", 0);
1851
1852 /* Having a missing entry is valid; return silently */
1853 if (!gpio_is_valid(gpio))
1854 return -EINVAL;
1855
1856 if (devm_gpio_request(dev, gpio, "dw-mci-wp")) {
1857 dev_warn(dev, "gpio [%d] request failed\n", gpio);
1858 return -EINVAL;
1859 }
1860
1861 return gpio;
1862}
1835#else /* CONFIG_OF */ 1863#else /* CONFIG_OF */
1836static int dw_mci_of_get_slot_quirks(struct device *dev, u8 slot) 1864static int dw_mci_of_get_slot_quirks(struct device *dev, u8 slot)
1837{ 1865{
@@ -1845,6 +1873,10 @@ static struct device_node *dw_mci_of_find_slot_node(struct device *dev, u8 slot)
1845{ 1873{
1846 return NULL; 1874 return NULL;
1847} 1875}
1876static int dw_mci_of_get_wp_gpio(struct device *dev, u8 slot)
1877{
1878 return -EINVAL;
1879}
1848#endif /* CONFIG_OF */ 1880#endif /* CONFIG_OF */
1849 1881
1850static int dw_mci_init_slot(struct dw_mci *host, unsigned int id) 1882static int dw_mci_init_slot(struct dw_mci *host, unsigned int id)
@@ -1962,6 +1994,8 @@ static int dw_mci_init_slot(struct dw_mci *host, unsigned int id)
1962 else 1994 else
1963 clear_bit(DW_MMC_CARD_PRESENT, &slot->flags); 1995 clear_bit(DW_MMC_CARD_PRESENT, &slot->flags);
1964 1996
1997 slot->wp_gpio = dw_mci_of_get_wp_gpio(host->dev, slot->id);
1998
1965 mmc_add_host(mmc); 1999 mmc_add_host(mmc);
1966 2000
1967#if defined(CONFIG_DEBUG_FS) 2001#if defined(CONFIG_DEBUG_FS)