Commit a70aaa64 authored by Doug Anderson's avatar Doug Anderson Committed by Chris Ball

mmc: dw_mmc: Add "disable-wp" device tree property

The "disable-wp" property is used to specify that a given SD card slot
doesn't have a concept of write protect.  This eliminates the need for
special case code for SD slots that should never be write protected
(like a micro SD slot or a dev board).

The dw_mmc driver is special in needing to specify "disable-wp"
because the lack of a "wp-gpios" property means to use the special
purpose write protect line.  On some other mmc devices the lack of
"wp-gpios" means that write protect should be disabled.
Signed-off-by: default avatarDoug Anderson <dianders@chromium.org>
Acked-by: default avatarSeungwon Jeon <tgih.jun@samsung.com>
Acked-by: default avatarWill Newton <will.newton@imgtec.com>
Acked-by: default avatarOlof Johansson <olof@lixom.net>
Signed-off-by: default avatarChris Ball <cjb@laptop.org>
parent c148e9ff
...@@ -26,8 +26,16 @@ Required Properties: ...@@ -26,8 +26,16 @@ Required Properties:
* bus-width: as documented in mmc core bindings. * bus-width: as documented in mmc core bindings.
* wp-gpios: specifies the write protect gpio line. The format of the * wp-gpios: specifies the write protect gpio line. The format of the
gpio specifier depends on the gpio controller. If the write-protect gpio specifier depends on the gpio controller. If a GPIO is not used
line is not available, this property is optional. for write-protect, this property is optional.
* disable-wp: If the wp-gpios property isn't present then (by default)
we'd assume that the write protect is hooked up directly to the
controller's special purpose write protect line (accessible via
the WRTPRT register). However, it's possible that we simply don't
want write protect. In that case specify 'disable-wp'.
NOTE: This property is not required for slots known to always
connect to eMMC or SDIO cards.
Optional properties: Optional properties:
......
...@@ -74,6 +74,7 @@ struct idmac_desc { ...@@ -74,6 +74,7 @@ struct idmac_desc {
* struct dw_mci_slot - MMC slot state * struct dw_mci_slot - MMC slot state
* @mmc: The mmc_host representing this slot. * @mmc: The mmc_host representing this slot.
* @host: The MMC controller this slot is using. * @host: The MMC controller this slot is using.
* @quirks: Slot-level quirks (DW_MCI_SLOT_QUIRK_XXX)
* @ctype: Card type for this slot. * @ctype: Card type for this slot.
* @mrq: mmc_request currently being processed or waiting to be * @mrq: mmc_request currently being processed or waiting to be
* processed, or NULL when the slot is idle. * processed, or NULL when the slot is idle.
...@@ -88,6 +89,8 @@ struct dw_mci_slot { ...@@ -88,6 +89,8 @@ struct dw_mci_slot {
struct mmc_host *mmc; struct mmc_host *mmc;
struct dw_mci *host; struct dw_mci *host;
int quirks;
u32 ctype; u32 ctype;
struct mmc_request *mrq; struct mmc_request *mrq;
...@@ -825,7 +828,13 @@ static int dw_mci_get_ro(struct mmc_host *mmc) ...@@ -825,7 +828,13 @@ static int dw_mci_get_ro(struct mmc_host *mmc)
struct dw_mci_board *brd = slot->host->pdata; struct dw_mci_board *brd = slot->host->pdata;
/* Use platform get_ro function, else try on board write protect */ /* Use platform get_ro function, else try on board write protect */
if (brd->quirks & DW_MCI_QUIRK_NO_WRITE_PROTECT)
/*
* NOTE: DW_MCI_QUIRK_NO_WRITE_PROTECT will be removed in a future
* patch in the series once reference to it is removed.
*/
if ((brd->quirks & DW_MCI_QUIRK_NO_WRITE_PROTECT) ||
(slot->quirks & DW_MCI_SLOT_QUIRK_NO_WRITE_PROTECT))
read_only = 0; read_only = 0;
else if (brd->get_ro) else if (brd->get_ro)
read_only = brd->get_ro(slot->id); read_only = brd->get_ro(slot->id);
...@@ -1785,6 +1794,30 @@ static struct device_node *dw_mci_of_find_slot_node(struct device *dev, u8 slot) ...@@ -1785,6 +1794,30 @@ static struct device_node *dw_mci_of_find_slot_node(struct device *dev, u8 slot)
return NULL; return NULL;
} }
static struct dw_mci_of_slot_quirks {
char *quirk;
int id;
} of_slot_quirks[] = {
{
.quirk = "disable-wp",
.id = DW_MCI_SLOT_QUIRK_NO_WRITE_PROTECT,
},
};
static int dw_mci_of_get_slot_quirks(struct device *dev, u8 slot)
{
struct device_node *np = dw_mci_of_find_slot_node(dev, slot);
int quirks = 0;
int idx;
/* get quirks */
for (idx = 0; idx < ARRAY_SIZE(of_slot_quirks); idx++)
if (of_get_property(np, of_slot_quirks[idx].quirk, NULL))
quirks |= of_slot_quirks[idx].id;
return quirks;
}
/* find out bus-width for a given slot */ /* find out bus-width for a given slot */
static u32 dw_mci_of_get_bus_wd(struct device *dev, u8 slot) static u32 dw_mci_of_get_bus_wd(struct device *dev, u8 slot)
{ {
...@@ -1800,6 +1833,10 @@ static u32 dw_mci_of_get_bus_wd(struct device *dev, u8 slot) ...@@ -1800,6 +1833,10 @@ static u32 dw_mci_of_get_bus_wd(struct device *dev, u8 slot)
return bus_wd; return bus_wd;
} }
#else /* CONFIG_OF */ #else /* CONFIG_OF */
static int dw_mci_of_get_slot_quirks(struct device *dev, u8 slot)
{
return 0;
}
static u32 dw_mci_of_get_bus_wd(struct device *dev, u8 slot) static u32 dw_mci_of_get_bus_wd(struct device *dev, u8 slot)
{ {
return 1; return 1;
...@@ -1828,6 +1865,8 @@ static int dw_mci_init_slot(struct dw_mci *host, unsigned int id) ...@@ -1828,6 +1865,8 @@ static int dw_mci_init_slot(struct dw_mci *host, unsigned int id)
slot->host = host; slot->host = host;
host->slot[id] = slot; host->slot[id] = slot;
slot->quirks = dw_mci_of_get_slot_quirks(host->dev, slot->id);
mmc->ops = &dw_mci_ops; mmc->ops = &dw_mci_ops;
mmc->f_min = DIV_ROUND_UP(host->bus_hz, 510); mmc->f_min = DIV_ROUND_UP(host->bus_hz, 510);
mmc->f_max = host->bus_hz; mmc->f_max = host->bus_hz;
......
...@@ -209,9 +209,18 @@ struct dw_mci_dma_ops { ...@@ -209,9 +209,18 @@ struct dw_mci_dma_ops {
#define DW_MCI_QUIRK_HIGHSPEED BIT(2) #define DW_MCI_QUIRK_HIGHSPEED BIT(2)
/* Unreliable card detection */ /* Unreliable card detection */
#define DW_MCI_QUIRK_BROKEN_CARD_DETECTION BIT(3) #define DW_MCI_QUIRK_BROKEN_CARD_DETECTION BIT(3)
/* Write Protect detection not available */ /* Write Protect detection not available */
/*
* NOTE: DW_MCI_QUIRK_NO_WRITE_PROTECT will be removed in a future
* patch in the series once reference to it is removed.
*/
#define DW_MCI_QUIRK_NO_WRITE_PROTECT BIT(4) #define DW_MCI_QUIRK_NO_WRITE_PROTECT BIT(4)
/* Slot level quirks */
/* This slot has no write protect */
#define DW_MCI_SLOT_QUIRK_NO_WRITE_PROTECT BIT(0)
struct dma_pdata; struct dma_pdata;
struct block_settings { struct block_settings {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment