* [RFC DT style 2/4] mtd: sh_flctl: Add device tree support
@ 2012-04-26 14:01 Bastian Hecht
0 siblings, 0 replies; only message in thread
From: Bastian Hecht @ 2012-04-26 14:01 UTC (permalink / raw)
To: linux-sh
The flctl can now be probed via device tree setup in addition to the existing
platform data way.
---
drivers/mtd/nand/sh_flctl.c | 155 ++++++++++++++++++++++++++++++++++++++++++-
1 files changed, 154 insertions(+), 1 deletions(-)
diff --git a/drivers/mtd/nand/sh_flctl.c b/drivers/mtd/nand/sh_flctl.c
index c6e072d..221a4d4 100644
--- a/drivers/mtd/nand/sh_flctl.c
+++ b/drivers/mtd/nand/sh_flctl.c
@@ -28,6 +28,11 @@
#include <linux/io.h>
#include <linux/platform_device.h>
#include <linux/pm_runtime.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/of_device.h>
+#include <linux/of_gpio.h>
+#include <linux/of_mtd.h>
#include <linux/slab.h>
#include <linux/mtd/mtd.h>
@@ -866,8 +871,147 @@ static irqreturn_t flctl_handle_flste(int irq, void *dev_id)
return IRQ_HANDLED;
}
-static int __devinit flctl_probe(struct platform_device *pdev)
+#if defined(CONFIG_OF)
+static const char const *of_part_type[] = {
+ "ofpart",
+ NULL
+};
+
+static int __devinit flctl_probe(struct platform_device *ofdev)
{
+ struct resource io_res;
+ struct sh_flctl *flctl;
+ struct mtd_info *flctl_mtd;
+ struct nand_chip *nand;
+ const __be32 *prop;
+ struct device_node *nand_ic;
+ struct mtd_part_parser_data ppdata;
+ int ret = -ENXIO;
+
+ flctl = kzalloc(sizeof(struct sh_flctl), GFP_KERNEL);
+ if (!flctl) {
+ dev_err(&ofdev->dev, "failed to allocate driver data\n");
+ return -ENOMEM;
+ }
+
+ platform_set_drvdata(ofdev, flctl);
+ flctl_mtd = &flctl->mtd;
+ nand = &flctl->chip;
+ flctl_mtd->priv = nand;
+ flctl->pdev = ofdev;
+
+ ret = of_address_to_resource(ofdev->dev.of_node, 0, &io_res);
+ if (ret) {
+ dev_err(&ofdev->dev, "failed to get I/O memory\n");
+ goto err_iomap;
+ }
+
+ flctl->reg = ioremap(io_res.start, resource_size(&io_res));
+ if (flctl->reg = NULL) {
+ dev_err(&ofdev->dev, "failed to remap I/O memory\n");
+ goto err_iomap;
+ }
+
+ flctl->flcmncr_base = TYPESEL_SET;
+
+ /* Parse the flctl host controller properties */
+ prop = of_get_property(ofdev->dev.of_node, "clk-scheme", NULL);
+ if (!prop) {
+ dev_err(&ofdev->dev, "no clocking scheme supplied\n");
+ goto err_clk;
+ } else
+ flctl->flcmncr_base |= be32_to_cpup(prop);
+
+ prop = of_get_property(ofdev->dev.of_node, "ext-bus-con", NULL);
+ if (prop)
+ flctl->flcmncr_base |= SHBUSSEL;
+
+ prop = of_get_property(ofdev->dev.of_node, "use-holden", NULL);
+ if (prop)
+ flctl->holden = true;
+
+ /*
+ * Parse the nand IC specific properties.
+ * Until now we support only 1 chip
+ */
+ nand_ic = of_get_next_child(ofdev->dev.of_node, NULL);
+ if (!nand_ic) {
+ dev_err(&ofdev->dev, "no nand chip data supplied\n");
+ goto err_clk;
+ }
+
+ ret = of_get_nand_ecc_mode(nand_ic);
+ if (ret < 0 || (ret != NAND_ECC_HW && ret != NAND_ECC_SOFT)) {
+ dev_err(&ofdev->dev, "no supported ECC mode selected\n");
+ if (ret >= 0)
+ ret = -EINVAL;
+ goto err_subnode;
+ }
+ flctl->hwecc = ret = NAND_ECC_HW ? 1 : 0;
+
+ ret = of_get_nand_bus_width(nand_ic);
+ if (ret = 16) {
+ flctl->flcmncr_base |= SEL_16BIT;
+ nand->options = NAND_BUSWIDTH_16;
+ nand->read_word = flctl_read_word;
+ } else if (ret != 8) {
+ dev_err(&ofdev->dev, "invalid bus width\n");
+ goto err_subnode;
+ } /* else we stick with the default 8 bit settings */
+
+ prop = of_get_property(nand_ic, "flctl-snand", NULL);
+ if (prop)
+ flctl->flcmncr_base |= SNAND_E;
+
+ /* Set address of hardware control function */
+ /* 20 us command delay time */
+ nand->chip_delay = 20;
+ nand->options |= NAND_NO_AUTOINCR;
+
+ nand->read_byte = flctl_read_byte;
+ nand->write_buf = flctl_write_buf;
+ nand->read_buf = flctl_read_buf;
+ nand->verify_buf = flctl_verify_buf;
+ nand->select_chip = flctl_select_chip;
+ nand->cmdfunc = flctl_cmdfunc;
+
+ pm_runtime_enable(&ofdev->dev);
+ pm_runtime_resume(&ofdev->dev);
+
+ ret = nand_scan_ident(flctl_mtd, 1, NULL);
+ if (ret)
+ goto err_chip;
+
+ ret = flctl_chip_init_tail(flctl_mtd);
+ if (ret)
+ goto err_chip;
+
+ ret = nand_scan_tail(flctl_mtd);
+ if (ret)
+ goto err_chip;
+
+ ppdata.of_node = nand_ic;
+ ret = mtd_device_parse_register
+ (flctl_mtd, of_part_type, &ppdata, NULL, 0);
+
+ of_node_put(nand_ic);
+
+ return ret;
+
+err_chip:
+ pm_runtime_disable(&ofdev->dev);
+err_subnode:
+ of_node_put(nand_ic);
+err_clk:
+ iounmap(flctl->reg);
+err_iomap:
+ kfree(flctl);
+
+ return ret;
+}
+
+#else /* CONFIG_OF */
+static int __devinit flctl_probe(struct platform_device *pdev)
struct resource *res;
struct sh_flctl *flctl;
struct mtd_info *flctl_mtd;
@@ -968,6 +1112,7 @@ err_iomap:
kfree(flctl);
return ret;
}
+#endif /* CONFIG_OF */
static int __devexit flctl_remove(struct platform_device *pdev)
{
@@ -982,11 +1127,19 @@ static int __devexit flctl_remove(struct platform_device *pdev)
return 0;
}
+static const struct of_device_id of_flctl_match[] = {
+ { .compatible = "renesas,rmobile-flctl" },
+ { .compatible = "renesas,shmobile-flctl" },
+ {},
+};
+MODULE_DEVICE_TABLE(of, of_flctl_match);
+
static struct platform_driver flctl_driver = {
.remove = flctl_remove,
.driver = {
.name = "sh_flctl",
.owner = THIS_MODULE,
+ .of_match_table = of_flctl_match,
},
};
--
1.7.5.4
^ permalink raw reply related [flat|nested] only message in thread
only message in thread, other threads:[~2012-04-26 14:01 UTC | newest]
Thread overview: (only message) (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2012-04-26 14:01 [RFC DT style 2/4] mtd: sh_flctl: Add device tree support Bastian Hecht
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).