Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 332792
b: refs/heads/master
c: e919fd2
h: refs/heads/master
v: v3
  • Loading branch information
Ludovic Desroches authored and Chris Ball committed Sep 4, 2012
1 parent 1ef9b84 commit 859e00c
Show file tree
Hide file tree
Showing 3 changed files with 152 additions and 3 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 77dcb3f4c344d4c9619803848f1aba4d271dac7b
refs/heads/master: e919fd200033e80b26f152d22c00a8fae7f8d548
68 changes: 68 additions & 0 deletions trunk/Documentation/devicetree/bindings/mmc/atmel-hsmci.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
* Atmel High Speed MultiMedia Card Interface

This controller on atmel products provides an interface for MMC, SD and SDIO
types of memory cards.

This file documents differences between the core properties described
by mmc.txt and the properties used by the atmel-mci driver.

1) MCI node

Required properties:
- compatible: should be "atmel,hsmci"
- #address-cells: should be one. The cell is the slot id.
- #size-cells: should be zero.
- at least one slot node

The node contains child nodes for each slot that the platform uses

Example MCI node:

mmc0: mmc@f0008000 {
compatible = "atmel,hsmci";
reg = <0xf0008000 0x600>;
interrupts = <12 4>;
#address-cells = <1>;
#size-cells = <0>;

[ child node definitions...]
};

2) slot nodes

Required properties:
- reg: should contain the slot id.
- bus-width: number of data lines connected to the controller

Optional properties:
- cd-gpios: specify GPIOs for card detection
- cd-inverted: invert the value of external card detect gpio line
- wp-gpios: specify GPIOs for write protection

Example slot node:

slot@0 {
reg = <0>;
bus-width = <4>;
cd-gpios = <&pioD 15 0>
cd-inverted;
};

Example full MCI node:
mmc0: mmc@f0008000 {
compatible = "atmel,hsmci";
reg = <0xf0008000 0x600>;
interrupts = <12 4>;
#address-cells = <1>;
#size-cells = <0>;
slot@0 {
reg = <0>;
bus-width = <4>;
cd-gpios = <&pioD 15 0>
cd-inverted;
};
slot@1 {
reg = <1>;
bus-width = <4>;
};
};
85 changes: 83 additions & 2 deletions trunk/drivers/mmc/host/atmel-mci.c
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,9 @@
#include <linux/interrupt.h>
#include <linux/ioport.h>
#include <linux/module.h>
#include <linux/of.h>
#include <linux/of_device.h>
#include <linux/of_gpio.h>
#include <linux/platform_device.h>
#include <linux/scatterlist.h>
#include <linux/seq_file.h>
Expand Down Expand Up @@ -500,6 +503,70 @@ static void atmci_init_debugfs(struct atmel_mci_slot *slot)
dev_err(&mmc->class_dev, "failed to initialize debugfs for slot\n");
}

#if defined(CONFIG_OF)
static const struct of_device_id atmci_dt_ids[] = {
{ .compatible = "atmel,hsmci" },
{ /* sentinel */ }
};

MODULE_DEVICE_TABLE(of, atmci_dt_ids);

static struct mci_platform_data __devinit*
atmci_of_init(struct platform_device *pdev)
{
struct device_node *np = pdev->dev.of_node;
struct device_node *cnp;
struct mci_platform_data *pdata;
u32 slot_id;

if (!np) {
dev_err(&pdev->dev, "device node not found\n");
return ERR_PTR(-EINVAL);
}

pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL);
if (!pdata) {
dev_err(&pdev->dev, "could not allocate memory for pdata\n");
return ERR_PTR(-ENOMEM);
}

for_each_child_of_node(np, cnp) {
if (of_property_read_u32(cnp, "reg", &slot_id)) {
dev_warn(&pdev->dev, "reg property is missing for %s\n",
cnp->full_name);
continue;
}

if (slot_id >= ATMCI_MAX_NR_SLOTS) {
dev_warn(&pdev->dev, "can't have more than %d slots\n",
ATMCI_MAX_NR_SLOTS);
break;
}

if (of_property_read_u32(cnp, "bus-width",
&pdata->slot[slot_id].bus_width))
pdata->slot[slot_id].bus_width = 1;

pdata->slot[slot_id].detect_pin =
of_get_named_gpio(cnp, "cd-gpios", 0);

pdata->slot[slot_id].detect_is_active_high =
of_property_read_bool(cnp, "cd-inverted");

pdata->slot[slot_id].wp_pin =
of_get_named_gpio(cnp, "wp-gpios", 0);
}

return pdata;
}
#else /* CONFIG_OF */
static inline struct mci_platform_data*
atmci_of_init(struct platform_device *dev)
{
return ERR_PTR(-EINVAL);
}
#endif

static inline unsigned int atmci_get_version(struct atmel_mci *host)
{
return atmci_readl(host, ATMCI_VERSION) & 0x00000fff;
Expand Down Expand Up @@ -2046,6 +2113,13 @@ static int __init atmci_init_slot(struct atmel_mci *host,
slot->sdc_reg = sdc_reg;
slot->sdio_irq = sdio_irq;

dev_dbg(&mmc->class_dev,
"slot[%u]: bus_width=%u, detect_pin=%d, "
"detect_is_active_high=%s, wp_pin=%d\n",
id, slot_data->bus_width, slot_data->detect_pin,
slot_data->detect_is_active_high ? "true" : "false",
slot_data->wp_pin);

mmc->ops = &atmci_ops;
mmc->f_min = DIV_ROUND_UP(host->bus_hz, 512);
mmc->f_max = host->bus_hz / 2;
Expand Down Expand Up @@ -2268,8 +2342,14 @@ static int __init atmci_probe(struct platform_device *pdev)
if (!regs)
return -ENXIO;
pdata = pdev->dev.platform_data;
if (!pdata)
return -ENXIO;
if (!pdata) {
pdata = atmci_of_init(pdev);
if (IS_ERR(pdata)) {
dev_err(&pdev->dev, "platform data not available\n");
return PTR_ERR(pdata);
}
}

irq = platform_get_irq(pdev, 0);
if (irq < 0)
return irq;
Expand Down Expand Up @@ -2487,6 +2567,7 @@ static struct platform_driver atmci_driver = {
.driver = {
.name = "atmel_mci",
.pm = ATMCI_PM_OPS,
.of_match_table = of_match_ptr(atmci_dt_ids),
},
};

Expand Down

0 comments on commit 859e00c

Please sign in to comment.