Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 347165
b: refs/heads/master
c: 7c8f680
h: refs/heads/master
i:
  347163: b0f8e1c
v: v3
  • Loading branch information
Bastian Hecht authored and Artem Bityutskiy committed Nov 15, 2012
1 parent c2815c5 commit 6bde490
Show file tree
Hide file tree
Showing 3 changed files with 137 additions and 8 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: 83738d87e3a0a4096e1419a65b8228130d183df6
refs/heads/master: 7c8f680e96edbd9896b13b5e6ff39bc5852dce2a
49 changes: 49 additions & 0 deletions trunk/Documentation/devicetree/bindings/mtd/flctl-nand.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
FLCTL NAND controller

Required properties:
- compatible : "renesas,shmobile-flctl-sh7372"
- reg : Address range of the FLCTL
- interrupts : flste IRQ number
- nand-bus-width : bus width to NAND chip

Optional properties:
- dmas: DMA specifier(s)
- dma-names: name for each DMA specifier. Valid names are
"data_tx", "data_rx", "ecc_tx", "ecc_rx"

The DMA fields are not used yet in the driver but are listed here for
completing the bindings.

The device tree may optionally contain sub-nodes describing partitions of the
address space. See partition.txt for more detail.

Example:

flctl@e6a30000 {
#address-cells = <1>;
#size-cells = <1>;
compatible = "renesas,shmobile-flctl-sh7372";
reg = <0xe6a30000 0x100>;
interrupts = <0x0d80>;

nand-bus-width = <16>;

dmas = <&dmac 1 /* data_tx */
&dmac 2;> /* data_rx */
dma-names = "data_tx", "data_rx";

system@0 {
label = "system";
reg = <0x0 0x8000000>;
};

userdata@8000000 {
label = "userdata";
reg = <0x8000000 0x10000000>;
};

cache@18000000 {
label = "cache";
reg = <0x18000000 0x8000000>;
};
};
94 changes: 87 additions & 7 deletions trunk/drivers/mtd/nand/sh_flctl.c
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,9 @@
#include <linux/dma-mapping.h>
#include <linux/interrupt.h>
#include <linux/io.h>
#include <linux/of.h>
#include <linux/of_device.h>
#include <linux/of_mtd.h>
#include <linux/platform_device.h>
#include <linux/pm_runtime.h>
#include <linux/sh_dma.h>
Expand Down Expand Up @@ -1016,6 +1019,73 @@ static irqreturn_t flctl_handle_flste(int irq, void *dev_id)
return IRQ_HANDLED;
}

#ifdef CONFIG_OF
struct flctl_soc_config {
unsigned long flcmncr_val;
unsigned has_hwecc:1;
unsigned use_holden:1;
};

static struct flctl_soc_config flctl_sh7372_config = {
.flcmncr_val = CLK_16B_12L_4H | TYPESEL_SET | SHBUSSEL,
.has_hwecc = 1,
.use_holden = 1,
};

static const struct of_device_id of_flctl_match[] = {
{ .compatible = "renesas,shmobile-flctl-sh7372",
.data = &flctl_sh7372_config },
{},
};
MODULE_DEVICE_TABLE(of, of_flctl_match);

static struct sh_flctl_platform_data *flctl_parse_dt(struct device *dev)
{
const struct of_device_id *match;
struct flctl_soc_config *config;
struct sh_flctl_platform_data *pdata;
struct device_node *dn = dev->of_node;
int ret;

match = of_match_device(of_flctl_match, dev);
if (match)
config = (struct flctl_soc_config *)match->data;
else {
dev_err(dev, "%s: no OF configuration attached\n", __func__);
return NULL;
}

pdata = devm_kzalloc(dev, sizeof(struct sh_flctl_platform_data),
GFP_KERNEL);
if (!pdata) {
dev_err(dev, "%s: failed to allocate config data\n", __func__);
return NULL;
}

/* set SoC specific options */
pdata->flcmncr_val = config->flcmncr_val;
pdata->has_hwecc = config->has_hwecc;
pdata->use_holden = config->use_holden;

/* parse user defined options */
ret = of_get_nand_bus_width(dn);
if (ret == 16)
pdata->flcmncr_val |= SEL_16BIT;
else if (ret != 8) {
dev_err(dev, "%s: invalid bus width\n", __func__);
return NULL;
}

return pdata;
}
#else /* CONFIG_OF */
#define of_flctl_match NULL
static struct sh_flctl_platform_data *flctl_parse_dt(struct device *dev)
{
return NULL;
}
#endif /* CONFIG_OF */

static int __devinit flctl_probe(struct platform_device *pdev)
{
struct resource *res;
Expand All @@ -1025,12 +1095,7 @@ static int __devinit flctl_probe(struct platform_device *pdev)
struct sh_flctl_platform_data *pdata;
int ret = -ENXIO;
int irq;

pdata = pdev->dev.platform_data;
if (pdata == NULL) {
dev_err(&pdev->dev, "no platform data defined\n");
return -EINVAL;
}
struct mtd_part_parser_data ppdata = {};

flctl = kzalloc(sizeof(struct sh_flctl), GFP_KERNEL);
if (!flctl) {
Expand Down Expand Up @@ -1062,6 +1127,17 @@ static int __devinit flctl_probe(struct platform_device *pdev)
goto err_flste;
}

if (pdev->dev.of_node)
pdata = flctl_parse_dt(&pdev->dev);
else
pdata = pdev->dev.platform_data;

if (!pdata) {
dev_err(&pdev->dev, "no setup data defined\n");
ret = -EINVAL;
goto err_pdata;
}

platform_set_drvdata(pdev, flctl);
flctl_mtd = &flctl->mtd;
nand = &flctl->chip;
Expand Down Expand Up @@ -1104,13 +1180,16 @@ static int __devinit flctl_probe(struct platform_device *pdev)
if (ret)
goto err_chip;

mtd_device_register(flctl_mtd, pdata->parts, pdata->nr_parts);
ppdata.of_node = pdev->dev.of_node;
ret = mtd_device_parse_register(flctl_mtd, NULL, &ppdata, pdata->parts,
pdata->nr_parts);

return 0;

err_chip:
flctl_release_dma(flctl);
pm_runtime_disable(&pdev->dev);
err_pdata:
free_irq(irq, flctl);
err_flste:
iounmap(flctl->reg);
Expand Down Expand Up @@ -1138,6 +1217,7 @@ static struct platform_driver flctl_driver = {
.driver = {
.name = "sh_flctl",
.owner = THIS_MODULE,
.of_match_table = of_flctl_match,
},
};

Expand Down

0 comments on commit 6bde490

Please sign in to comment.