* [PATCH 0/2] Add DMA and device tree support to the flash controller FLCTL @ 2012-10-02 13:12 Bastian Hecht 2012-10-02 13:12 ` [PATCH 1/2] mtd: sh_flctl: Add DMA capabilty Bastian Hecht 2012-10-02 13:12 ` [PATCH 2/2] mtd: sh_flctl: Add device tree support Bastian Hecht 0 siblings, 2 replies; 9+ messages in thread From: Bastian Hecht @ 2012-10-02 13:12 UTC (permalink / raw) To: linux-arm-kernel This mini-series consists of 2 separately posted patch-sets that shrunk to one patch each. It adds DMA support for the data part (not ECC) as well as device tree support to the FLCTL flash controller. As the 2nd patch is based on the 1st, I've decided to collect them here to avoid any confusion. The first set contained [PATCH 1/2] mtd: sh_flctl: Setup and release DMA channels [PATCH 2/2] mtd: sh_flctl: Use DMA for data fifo FLTDFIFO when available and was merged after 2 reviews to [PATCH] mtd: sh_flctl: Add DMA capabilty (same patch as in here) The second set contained [PATCH 1/3] mtd: sh_flctl: Probe SNAND_E flag from NAND chip [PATCH 2/3] mtd: sh_flctl: Add device tree support [PATCH 3/3] mtd: sh_flctl: Add sh7372 device tree config and is merged here to mtd: sh_flctl: Add device tree support Patch 1 can be omitted as SNAND_E is handled in the FLCTL source anyway correctly in set_cmd_regs() and the flag can be removed from existing board codes without this patch. Patch 2 without patch 3 may be confusing so I merged them too. Documentation is added as well. I've added linux-arm-kernel at lists.infradead.org as recipient for the device tree part. The patchset is based on l2-mtd git://git.infradead.org/users/dedekind/l2-mtd.git with reverted commit e26c113b4130aefa1d8446602bb5b05cfd646bfe. Bastian Hecht (2): mtd: sh_flctl: Add DMA capabilty mtd: sh_flctl: Add device tree support .../devicetree/bindings/mtd/flctl-nand.txt | 37 +++ drivers/mtd/nand/sh_flctl.c | 266 +++++++++++++++++++- include/linux/mtd/sh_flctl.h | 12 + 3 files changed, 305 insertions(+), 10 deletions(-) create mode 100644 Documentation/devicetree/bindings/mtd/flctl-nand.txt -- 1.7.5.4 ^ permalink raw reply [flat|nested] 9+ messages in thread
* [PATCH 1/2] mtd: sh_flctl: Add DMA capabilty 2012-10-02 13:12 [PATCH 0/2] Add DMA and device tree support to the flash controller FLCTL Bastian Hecht @ 2012-10-02 13:12 ` Bastian Hecht 2012-10-02 13:55 ` Guennadi Liakhovetski 2012-10-02 13:12 ` [PATCH 2/2] mtd: sh_flctl: Add device tree support Bastian Hecht 1 sibling, 1 reply; 9+ messages in thread From: Bastian Hecht @ 2012-10-02 13:12 UTC (permalink / raw) To: linux-arm-kernel The code probes if DMA channels can get allocated and tears them down at removal/failure if needed. If available it uses them to transfer the data part (not ECC). On failure we fall back to PIO mode. Based on Guennadi Liakhovetski's code from the sh_mmcif driver. Signed-off-by: Bastian Hecht <hechtb@gmail.com> --- drivers/mtd/nand/sh_flctl.c | 174 +++++++++++++++++++++++++++++++++++++++++- include/linux/mtd/sh_flctl.h | 12 +++ 2 files changed, 183 insertions(+), 3 deletions(-) diff --git a/drivers/mtd/nand/sh_flctl.c b/drivers/mtd/nand/sh_flctl.c index 4fbfe96..0fead2a 100644 --- a/drivers/mtd/nand/sh_flctl.c +++ b/drivers/mtd/nand/sh_flctl.c @@ -24,10 +24,13 @@ #include <linux/module.h> #include <linux/kernel.h> #include <linux/delay.h> +#include <linux/dmaengine.h> +#include <linux/dma-mapping.h> #include <linux/interrupt.h> #include <linux/io.h> #include <linux/platform_device.h> #include <linux/pm_runtime.h> +#include <linux/sh_dma.h> #include <linux/slab.h> #include <linux/string.h> @@ -106,6 +109,84 @@ static void wait_completion(struct sh_flctl *flctl) writeb(0x0, FLTRCR(flctl)); } +static void flctl_dma_complete(void *param) +{ + struct sh_flctl *flctl = param; + + complete(&flctl->dma_complete); +} + +static void flctl_release_dma(struct sh_flctl *flctl) +{ + if (flctl->chan_fifo0_rx) { + dma_release_channel(flctl->chan_fifo0_rx); + flctl->chan_fifo0_rx = NULL; + } + if (flctl->chan_fifo0_tx) { + dma_release_channel(flctl->chan_fifo0_tx); + flctl->chan_fifo0_tx = NULL; + } +} + +static void flctl_setup_dma(struct sh_flctl *flctl) +{ + dma_cap_mask_t mask; + struct dma_slave_config cfg; + struct platform_device *pdev = flctl->pdev; + struct sh_flctl_platform_data *pdata = pdev->dev.platform_data; + int ret; + + if (!pdata) + return; + + if (pdata->slave_id_fifo0_tx <= 0 || pdata->slave_id_fifo0_rx <= 0) + return; + + /* We can only either use DMA for both Tx and Rx or not use it@all */ + dma_cap_zero(mask); + dma_cap_set(DMA_SLAVE, mask); + + flctl->chan_fifo0_tx = dma_request_channel(mask, shdma_chan_filter, + (void *)pdata->slave_id_fifo0_tx); + dev_dbg(&pdev->dev, "%s: TX: got channel %p\n", __func__, + flctl->chan_fifo0_tx); + + if (!flctl->chan_fifo0_tx) + return; + + memset(&cfg, 0, sizeof(cfg)); + cfg.slave_id = pdata->slave_id_fifo0_tx; + cfg.direction = DMA_MEM_TO_DEV; + cfg.dst_addr = (dma_addr_t)FLDTFIFO(flctl); + cfg.src_addr = 0; + ret = dmaengine_slave_config(flctl->chan_fifo0_tx, &cfg); + if (ret < 0) + goto err; + + flctl->chan_fifo0_rx = dma_request_channel(mask, shdma_chan_filter, + (void *)pdata->slave_id_fifo0_rx); + dev_dbg(&pdev->dev, "%s: RX: got channel %p\n", __func__, + flctl->chan_fifo0_rx); + + if (!flctl->chan_fifo0_rx) + goto err; + + cfg.slave_id = pdata->slave_id_fifo0_rx; + cfg.direction = DMA_DEV_TO_MEM; + cfg.dst_addr = 0; + cfg.src_addr = (dma_addr_t)FLDTFIFO(flctl); + ret = dmaengine_slave_config(flctl->chan_fifo0_rx, &cfg); + if (ret < 0) + goto err; + + init_completion(&flctl->dma_complete); + + return; + +err: + flctl_release_dma(flctl); +} + static void set_addr(struct mtd_info *mtd, int column, int page_addr) { struct sh_flctl *flctl = mtd_to_flctl(mtd); @@ -261,6 +342,70 @@ static void wait_wecfifo_ready(struct sh_flctl *flctl) timeout_error(flctl, __func__); } +static int flctl_dma_fifo0_transfer(struct sh_flctl *flctl, unsigned long *buf, + int len, enum dma_data_direction dir) +{ + struct dma_async_tx_descriptor *desc = NULL; + struct dma_chan *chan; + enum dma_transfer_direction tr_dir; + dma_addr_t dma_addr; + dma_cookie_t cookie = -EINVAL; + uint32_t reg; + int ret; + + if (dir == DMA_FROM_DEVICE) { + chan = flctl->chan_fifo0_rx; + tr_dir = DMA_DEV_TO_MEM; + } else { + chan = flctl->chan_fifo0_tx; + tr_dir = DMA_MEM_TO_DEV; + } + + dma_addr = dma_map_single(chan->device->dev, buf, len, dir); + + if (dma_addr) + desc = dmaengine_prep_slave_single(chan, dma_addr, len, + tr_dir, DMA_PREP_INTERRUPT | DMA_CTRL_ACK); + + if (desc) { + reg = readl(FLINTDMACR(flctl)); + reg |= DREQ0EN; + writel(reg, FLINTDMACR(flctl)); + + desc->callback = flctl_dma_complete; + desc->callback_param = flctl; + cookie = dmaengine_submit(desc); + + dma_async_issue_pending(chan); + } else { + /* DMA failed, fall back to PIO */ + flctl_release_dma(flctl); + dev_warn(&flctl->pdev->dev, + "DMA failed, falling back to PIO\n"); + ret = -EIO; + goto out; + } + + ret = + wait_for_completion_timeout(&flctl->dma_complete, + msecs_to_jiffies(3000)); + + if (ret <= 0) { + chan->device->device_control(chan, DMA_TERMINATE_ALL, 0); + dev_err(&flctl->pdev->dev, "wait_for_completion_timeout\n"); + } + +out: + reg = readl(FLINTDMACR(flctl)); + reg &= ~DREQ0EN; + writel(reg, FLINTDMACR(flctl)); + + dma_unmap_single(chan->device->dev, dma_addr, len, dir); + + /* ret > 0 is success */ + return ret; +} + static void read_datareg(struct sh_flctl *flctl, int offset) { unsigned long data; @@ -279,11 +424,20 @@ static void read_fiforeg(struct sh_flctl *flctl, int rlen, int offset) len_4align = (rlen + 3) / 4; + /* initiate DMA transfer */ + if (flctl->chan_fifo0_rx && rlen >= 32 && + flctl_dma_fifo0_transfer(flctl, buf, rlen, DMA_DEV_TO_MEM) > 0) + goto convert; /* DMA success */ + + /* do polling transfer */ for (i = 0; i < len_4align; i++) { wait_rfifo_ready(flctl); buf[i] = readl(FLDTFIFO(flctl)); - buf[i] = be32_to_cpu(buf[i]); } + +convert: + for (i = 0; i < len_4align; i++) + buf[i] = be32_to_cpu(buf[i]); } static enum flctl_ecc_res_t read_ecfiforeg @@ -308,13 +462,23 @@ static enum flctl_ecc_res_t read_ecfiforeg static void write_fiforeg(struct sh_flctl *flctl, int rlen, int offset) { int i, len_4align; - unsigned long *data = (unsigned long *)&flctl->done_buff[offset]; + unsigned long *buf = (unsigned long *)&flctl->done_buff[offset]; void *fifo_addr = (void *)FLDTFIFO(flctl); len_4align = (rlen + 3) / 4; + + for (i = 0; i < len_4align; i++) + buf[i] = cpu_to_be32(buf[i]); + + /* initiate DMA transfer */ + if (flctl->chan_fifo0_tx && rlen >= 32 && + flctl_dma_fifo0_transfer(flctl, buf, rlen, DMA_MEM_TO_DEV) > 0) + return; /* DMA success */ + + /* do polling transfer */ for (i = 0; i < len_4align; i++) { wait_wfifo_ready(flctl); - writel(cpu_to_be32(data[i]), fifo_addr); + writel(buf[i], fifo_addr); } } @@ -930,6 +1094,8 @@ static int __devinit flctl_probe(struct platform_device *pdev) pm_runtime_enable(&pdev->dev); pm_runtime_resume(&pdev->dev); + flctl_setup_dma(flctl); + ret = nand_scan_ident(flctl_mtd, 1, NULL); if (ret) goto err_chip; @@ -947,6 +1113,7 @@ static int __devinit flctl_probe(struct platform_device *pdev) return 0; err_chip: + flctl_release_dma(flctl); pm_runtime_disable(&pdev->dev); free_irq(irq, flctl); err_flste: @@ -960,6 +1127,7 @@ static int __devexit flctl_remove(struct platform_device *pdev) { struct sh_flctl *flctl = platform_get_drvdata(pdev); + flctl_release_dma(flctl); nand_release(&flctl->mtd); pm_runtime_disable(&pdev->dev); free_irq(platform_get_irq(pdev, 0), flctl); diff --git a/include/linux/mtd/sh_flctl.h b/include/linux/mtd/sh_flctl.h index 01e4b15..e98fe7e 100644 --- a/include/linux/mtd/sh_flctl.h +++ b/include/linux/mtd/sh_flctl.h @@ -20,6 +20,7 @@ #ifndef __SH_FLCTL_H__ #define __SH_FLCTL_H__ +#include <linux/completion.h> #include <linux/mtd/mtd.h> #include <linux/mtd/nand.h> #include <linux/mtd/partitions.h> @@ -107,6 +108,7 @@ #define ESTERINTE (0x1 << 24) /* ECC error interrupt enable */ #define AC1CLR (0x1 << 19) /* ECC FIFO clear */ #define AC0CLR (0x1 << 18) /* Data FIFO clear */ +#define DREQ0EN (0x1 << 16) /* FLDTFIFODMA Request Enable */ #define ECERB (0x1 << 9) /* ECC error */ #define STERB (0x1 << 8) /* Status error */ #define STERINTE (0x1 << 4) /* Status error enable */ @@ -138,6 +140,8 @@ enum flctl_ecc_res_t { FL_TIMEOUT }; +struct dma_chan; + struct sh_flctl { struct mtd_info mtd; struct nand_chip chip; @@ -161,6 +165,11 @@ struct sh_flctl { unsigned hwecc:1; /* Hardware ECC (0 = disabled, 1 = enabled) */ unsigned holden:1; /* Hardware has FLHOLDCR and HOLDEN is set */ unsigned qos_request:1; /* QoS request to prevent deep power shutdown */ + + /* DMA related objects */ + struct dma_chan *chan_fifo0_rx; + struct dma_chan *chan_fifo0_tx; + struct completion dma_complete; }; struct sh_flctl_platform_data { @@ -170,6 +179,9 @@ struct sh_flctl_platform_data { unsigned has_hwecc:1; unsigned use_holden:1; + + unsigned int slave_id_fifo0_tx; + unsigned int slave_id_fifo0_rx; }; static inline struct sh_flctl *mtd_to_flctl(struct mtd_info *mtdinfo) -- 1.7.5.4 ^ permalink raw reply related [flat|nested] 9+ messages in thread
* [PATCH 1/2] mtd: sh_flctl: Add DMA capabilty 2012-10-02 13:12 ` [PATCH 1/2] mtd: sh_flctl: Add DMA capabilty Bastian Hecht @ 2012-10-02 13:55 ` Guennadi Liakhovetski 2012-10-04 10:12 ` Bastian Hecht 0 siblings, 1 reply; 9+ messages in thread From: Guennadi Liakhovetski @ 2012-10-02 13:55 UTC (permalink / raw) To: linux-arm-kernel On Tue, 2 Oct 2012, Bastian Hecht wrote: > The code probes if DMA channels can get allocated and tears them down at > removal/failure if needed. > If available it uses them to transfer the data part (not ECC). On > failure we fall back to PIO mode. > > Based on Guennadi Liakhovetski's code from the sh_mmcif driver. > > Signed-off-by: Bastian Hecht <hechtb@gmail.com> Looks mostly good to me, just a couple of cosmetic remarks below. They are not critical, so, I won't be upset, if you fix them later:-) In any case Reviewed-by: Guennadi Liakhovetski <g.liakhovetski@gmx.de> > --- > drivers/mtd/nand/sh_flctl.c | 174 +++++++++++++++++++++++++++++++++++++++++- > include/linux/mtd/sh_flctl.h | 12 +++ > 2 files changed, 183 insertions(+), 3 deletions(-) > > diff --git a/drivers/mtd/nand/sh_flctl.c b/drivers/mtd/nand/sh_flctl.c > index 4fbfe96..0fead2a 100644 > --- a/drivers/mtd/nand/sh_flctl.c > +++ b/drivers/mtd/nand/sh_flctl.c > @@ -24,10 +24,13 @@ > #include <linux/module.h> > #include <linux/kernel.h> > #include <linux/delay.h> > +#include <linux/dmaengine.h> > +#include <linux/dma-mapping.h> > #include <linux/interrupt.h> > #include <linux/io.h> > #include <linux/platform_device.h> > #include <linux/pm_runtime.h> > +#include <linux/sh_dma.h> > #include <linux/slab.h> > #include <linux/string.h> > > @@ -106,6 +109,84 @@ static void wait_completion(struct sh_flctl *flctl) > writeb(0x0, FLTRCR(flctl)); > } > > +static void flctl_dma_complete(void *param) > +{ > + struct sh_flctl *flctl = param; > + > + complete(&flctl->dma_complete); I think I mentioned in the first review, that it is good to include headers everywhere, where they are needed and not rely on pulling them in via other headers. So, it would be good to also include complete.h here directly. [snip] > @@ -308,13 +462,23 @@ static enum flctl_ecc_res_t read_ecfiforeg > static void write_fiforeg(struct sh_flctl *flctl, int rlen, int offset) > { > int i, len_4align; > - unsigned long *data = (unsigned long *)&flctl->done_buff[offset]; > + unsigned long *buf = (unsigned long *)&flctl->done_buff[offset]; > void *fifo_addr = (void *)FLDTFIFO(flctl); > > len_4align = (rlen + 3) / 4; > + > + for (i = 0; i < len_4align; i++) > + buf[i] = cpu_to_be32(buf[i]); indentation ran away here. Thanks Guennadi --- Guennadi Liakhovetski, Ph.D. Freelance Open-Source Software Developer http://www.open-technology.de/ ^ permalink raw reply [flat|nested] 9+ messages in thread
* [PATCH 1/2] mtd: sh_flctl: Add DMA capabilty 2012-10-02 13:55 ` Guennadi Liakhovetski @ 2012-10-04 10:12 ` Bastian Hecht 0 siblings, 0 replies; 9+ messages in thread From: Bastian Hecht @ 2012-10-04 10:12 UTC (permalink / raw) To: linux-arm-kernel Hey Guennadi, 2012/10/2 Guennadi Liakhovetski <g.liakhovetski@gmx.de>: > On Tue, 2 Oct 2012, Bastian Hecht wrote: > >> The code probes if DMA channels can get allocated and tears them down at >> removal/failure if needed. >> If available it uses them to transfer the data part (not ECC). On >> failure we fall back to PIO mode. >> >> Based on Guennadi Liakhovetski's code from the sh_mmcif driver. >> >> Signed-off-by: Bastian Hecht <hechtb@gmail.com> > > Looks mostly good to me, just a couple of cosmetic remarks below. They are > not critical, so, I won't be upset, if you fix them later:-) In any case > > Reviewed-by: Guennadi Liakhovetski <g.liakhovetski@gmx.de> Great, will add that to the next version! >> --- >> drivers/mtd/nand/sh_flctl.c | 174 +++++++++++++++++++++++++++++++++++++++++- >> include/linux/mtd/sh_flctl.h | 12 +++ >> 2 files changed, 183 insertions(+), 3 deletions(-) >> >> diff --git a/drivers/mtd/nand/sh_flctl.c b/drivers/mtd/nand/sh_flctl.c >> index 4fbfe96..0fead2a 100644 >> --- a/drivers/mtd/nand/sh_flctl.c >> +++ b/drivers/mtd/nand/sh_flctl.c >> @@ -24,10 +24,13 @@ >> #include <linux/module.h> >> #include <linux/kernel.h> >> #include <linux/delay.h> >> +#include <linux/dmaengine.h> >> +#include <linux/dma-mapping.h> >> #include <linux/interrupt.h> >> #include <linux/io.h> >> #include <linux/platform_device.h> >> #include <linux/pm_runtime.h> >> +#include <linux/sh_dma.h> >> #include <linux/slab.h> >> #include <linux/string.h> >> >> @@ -106,6 +109,84 @@ static void wait_completion(struct sh_flctl *flctl) >> writeb(0x0, FLTRCR(flctl)); >> } >> >> +static void flctl_dma_complete(void *param) >> +{ >> + struct sh_flctl *flctl = param; >> + >> + complete(&flctl->dma_complete); > > I think I mentioned in the first review, that it is good to include > headers everywhere, where they are needed and not rely on pulling them in > via other headers. So, it would be good to also include complete.h here > directly. Ok sure, I will include that as well. > [snip] >> @@ -308,13 +462,23 @@ static enum flctl_ecc_res_t read_ecfiforeg >> static void write_fiforeg(struct sh_flctl *flctl, int rlen, int offset) >> { >> int i, len_4align; >> - unsigned long *data = (unsigned long *)&flctl->done_buff[offset]; >> + unsigned long *buf = (unsigned long *)&flctl->done_buff[offset]; >> void *fifo_addr = (void *)FLDTFIFO(flctl); >> >> len_4align = (rlen + 3) / 4; >> + >> + for (i = 0; i < len_4align; i++) >> + buf[i] = cpu_to_be32(buf[i]); > > indentation ran away here. Ah nice, thanks for the hawk's eye ;) > Thanks > Guennadi Thanks! Bastian ^ permalink raw reply [flat|nested] 9+ messages in thread
* [PATCH 2/2] mtd: sh_flctl: Add device tree support 2012-10-02 13:12 [PATCH 0/2] Add DMA and device tree support to the flash controller FLCTL Bastian Hecht 2012-10-02 13:12 ` [PATCH 1/2] mtd: sh_flctl: Add DMA capabilty Bastian Hecht @ 2012-10-02 13:12 ` Bastian Hecht 2012-10-02 13:54 ` Arnd Bergmann 1 sibling, 1 reply; 9+ messages in thread From: Bastian Hecht @ 2012-10-02 13:12 UTC (permalink / raw) To: linux-arm-kernel The flctl can now be probed via device tree setup in addition to the existing platform data way. SoC specific setup data is set in the .data member of the OF match, so kept within the driver itself, while board/user specific setup - like partitioning - is taken from the device tree. Actual configuration is added for the SoC sh7372. Signed-off-by: Bastian Hecht <hechtb@gmail.com> --- .../devicetree/bindings/mtd/flctl-nand.txt | 37 ++++++++ drivers/mtd/nand/sh_flctl.c | 92 ++++++++++++++++++-- 2 files changed, 122 insertions(+), 7 deletions(-) create mode 100644 Documentation/devicetree/bindings/mtd/flctl-nand.txt diff --git a/Documentation/devicetree/bindings/mtd/flctl-nand.txt b/Documentation/devicetree/bindings/mtd/flctl-nand.txt new file mode 100644 index 0000000..f615031 --- /dev/null +++ b/Documentation/devicetree/bindings/mtd/flctl-nand.txt @@ -0,0 +1,37 @@ +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 + +The device tree may optionally contain sub-nodes describing partitions of the +address space. See partition.txt for more detail. + +Example: + + flctl at e6a30000 { + #address-cells = <1>; + #size-cells = <1>; + compatible = "renesas,shmobile-flctl-sh7372"; + reg = <0xe6a30000 0x100>; + interrupts = <0x0d80>; + + nand-bus-width = <16>; + + system at 0 { + label = "system"; + reg = <0x0 0x8000000>; + }; + + userdata at 8000000 { + label = "userdata"; + reg = <0x8000000 0x10000000>; + }; + + cache at 18000000 { + label = "cache"; + reg = <0x18000000 0x8000000>; + }; + }; diff --git a/drivers/mtd/nand/sh_flctl.c b/drivers/mtd/nand/sh_flctl.c index 0fead2a..4c7e542 100644 --- a/drivers/mtd/nand/sh_flctl.c +++ b/drivers/mtd/nand/sh_flctl.c @@ -28,6 +28,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> @@ -1020,6 +1023,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; @@ -1029,12 +1099,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) { @@ -1066,6 +1131,16 @@ 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"); + return -EINVAL; + } + platform_set_drvdata(pdev, flctl); flctl_mtd = &flctl->mtd; nand = &flctl->chip; @@ -1108,7 +1183,9 @@ 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; @@ -1142,6 +1219,7 @@ static struct platform_driver flctl_driver = { .driver = { .name = "sh_flctl", .owner = THIS_MODULE, + .of_match_table = of_flctl_match, }, }; -- 1.7.5.4 ^ permalink raw reply related [flat|nested] 9+ messages in thread
* [PATCH 2/2] mtd: sh_flctl: Add device tree support 2012-10-02 13:12 ` [PATCH 2/2] mtd: sh_flctl: Add device tree support Bastian Hecht @ 2012-10-02 13:54 ` Arnd Bergmann 2012-10-02 14:04 ` Guennadi Liakhovetski 0 siblings, 1 reply; 9+ messages in thread From: Arnd Bergmann @ 2012-10-02 13:54 UTC (permalink / raw) To: linux-arm-kernel On Tuesday 02 October 2012, Bastian Hecht wrote: > +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 > + > +The device tree may optionally contain sub-nodes describing partitions of the > +address space. See partition.txt for more detail. > + > +Example: > + > + flctl at e6a30000 { > + #address-cells = <1>; > + #size-cells = <1>; > + compatible = "renesas,shmobile-flctl-sh7372"; > + reg = <0xe6a30000 0x100>; > + interrupts = <0x0d80>; > + > + nand-bus-width = <16>; > + > + system at 0 { > + label = "system"; > + reg = <0x0 0x8000000>; > + }; > + > + userdata at 8000000 { > + label = "userdata"; > + reg = <0x8000000 0x10000000>; > + }; > + > + cache at 18000000 { > + label = "cache"; > + reg = <0x18000000 0x8000000>; > + }; > + }; Since you are also adding dma-engine support, I would suggest you specify a "dmas" and "dma-names" property as well, so the device can find the right dma channel. The code might not do that yet while you're still sorting out the dependencies (and the sh dmaengine code is not yet converted to DT), but I think it would be good to nail down the binding for this device. Arnd ^ permalink raw reply [flat|nested] 9+ messages in thread
* [PATCH 2/2] mtd: sh_flctl: Add device tree support 2012-10-02 13:54 ` Arnd Bergmann @ 2012-10-02 14:04 ` Guennadi Liakhovetski 2012-10-02 20:47 ` Arnd Bergmann 0 siblings, 1 reply; 9+ messages in thread From: Guennadi Liakhovetski @ 2012-10-02 14:04 UTC (permalink / raw) To: linux-arm-kernel Hi Arnd On Tue, 2 Oct 2012, Arnd Bergmann wrote: > On Tuesday 02 October 2012, Bastian Hecht wrote: > > +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 > > + > > +The device tree may optionally contain sub-nodes describing partitions of the > > +address space. See partition.txt for more detail. > > + > > +Example: > > + > > + flctl at e6a30000 { > > + #address-cells = <1>; > > + #size-cells = <1>; > > + compatible = "renesas,shmobile-flctl-sh7372"; > > + reg = <0xe6a30000 0x100>; > > + interrupts = <0x0d80>; > > + > > + nand-bus-width = <16>; > > + > > + system at 0 { > > + label = "system"; > > + reg = <0x0 0x8000000>; > > + }; > > + > > + userdata at 8000000 { > > + label = "userdata"; > > + reg = <0x8000000 0x10000000>; > > + }; > > + > > + cache at 18000000 { > > + label = "cache"; > > + reg = <0x18000000 0x8000000>; > > + }; > > + }; > > Since you are also adding dma-engine support, I would suggest you specify > a "dmas" and "dma-names" property as well, so the device can find the > right dma channel. The code might not do that yet while you're still > sorting out the dependencies (and the sh dmaengine code is not yet > converted to DT), but I think it would be good to nail down the binding > for this device. Have DMA DT bindings been accepted yet, are they fixed? Wouldn't it be better to wait until patches appear in a tree, at least with high probability heading towards the mainline, or have they already? Thanks Guennadi --- Guennadi Liakhovetski, Ph.D. Freelance Open-Source Software Developer http://www.open-technology.de/ ^ permalink raw reply [flat|nested] 9+ messages in thread
* [PATCH 2/2] mtd: sh_flctl: Add device tree support 2012-10-02 14:04 ` Guennadi Liakhovetski @ 2012-10-02 20:47 ` Arnd Bergmann 2012-10-04 10:07 ` Bastian Hecht 0 siblings, 1 reply; 9+ messages in thread From: Arnd Bergmann @ 2012-10-02 20:47 UTC (permalink / raw) To: linux-arm-kernel On Tuesday 02 October 2012, Guennadi Liakhovetski wrote: > > > > Since you are also adding dma-engine support, I would suggest you specify > > a "dmas" and "dma-names" property as well, so the device can find the > > right dma channel. The code might not do that yet while you're still > > sorting out the dependencies (and the sh dmaengine code is not yet > > converted to DT), but I think it would be good to nail down the binding > > for this device. > > Have DMA DT bindings been accepted yet, are they fixed? Wouldn't it be > better to wait until patches appear in a tree, at least with high > probability heading towards the mainline, or have they already? > I think they ended up not getting scheduled for 3.7, which is a bit disappointing after we got an agreement on the binding. However, I am rather confident that we won't change the binding again, at least I don't see how they would change in a way that would impact the binding document for a device using a DMA channel. Arnd ^ permalink raw reply [flat|nested] 9+ messages in thread
* [PATCH 2/2] mtd: sh_flctl: Add device tree support 2012-10-02 20:47 ` Arnd Bergmann @ 2012-10-04 10:07 ` Bastian Hecht 0 siblings, 0 replies; 9+ messages in thread From: Bastian Hecht @ 2012-10-04 10:07 UTC (permalink / raw) To: linux-arm-kernel Hi Arnd, hi Guennadi, 2012/10/2 Arnd Bergmann <arnd.bergmann@linaro.org>: > On Tuesday 02 October 2012, Guennadi Liakhovetski wrote: >> > >> > Since you are also adding dma-engine support, I would suggest you specify >> > a "dmas" and "dma-names" property as well, so the device can find the >> > right dma channel. The code might not do that yet while you're still >> > sorting out the dependencies (and the sh dmaengine code is not yet >> > converted to DT), but I think it would be good to nail down the binding >> > for this device. Ok good, so I will include these field in v2. The FLCTL has support for 4 channels, 2 for data read/write and 2 for ECC read/write. The driver currently supports only the data part. Should I include the ECC part nevertheless? Further would you prefer the naming - fifo0_rx fifo0_tx fifo1_rx fifo1_tx (close to the datasheet) or - data_rx data_tx ecc_rx ecc_tx Then the dmas field: If I get it right, we have 3 possible DMA controllers to use on the sh7372 and we specify the mid/rid value as second argument? So how about this to add to the docs: dmas = <&dma1 0x83 /* fifo0_rx */ &dma1 0x83 /* fifo0_tx */ &dma2 0x83 /* fifo0_rx */ &dma2 0x83 /* fifo0_tx */ &dma3 0x83 /* fifo0_rx */ &dma3 0x83>; /* fifo0_tx */ dma-names = "fifo0_rx", "fifo0_tx", fifo0_rx", "fifo0_tx", fifo0_rx", "fifo0_tx"; Many thanks for the help, Bastian ^ permalink raw reply [flat|nested] 9+ messages in thread
end of thread, other threads:[~2012-10-04 10:12 UTC | newest] Thread overview: 9+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2012-10-02 13:12 [PATCH 0/2] Add DMA and device tree support to the flash controller FLCTL Bastian Hecht 2012-10-02 13:12 ` [PATCH 1/2] mtd: sh_flctl: Add DMA capabilty Bastian Hecht 2012-10-02 13:55 ` Guennadi Liakhovetski 2012-10-04 10:12 ` Bastian Hecht 2012-10-02 13:12 ` [PATCH 2/2] mtd: sh_flctl: Add device tree support Bastian Hecht 2012-10-02 13:54 ` Arnd Bergmann 2012-10-02 14:04 ` Guennadi Liakhovetski 2012-10-02 20:47 ` Arnd Bergmann 2012-10-04 10:07 ` 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).